Added PPI interface to the character device. PPI interface is also kept
in the pdev for backwards compatibility.

Signed-off-by: Jarkko Sakkinen <[email protected]>
---
 drivers/char/tpm/tpm-chip.c      |  16 +++---
 drivers/char/tpm/tpm-interface.c |   1 +
 drivers/char/tpm/tpm.h           |   3 +-
 drivers/char/tpm/tpm_ppi.c       | 105 ++++++++++++++++++++++++++++++++-------
 4 files changed, 97 insertions(+), 28 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 283f00a..44f39be 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -181,12 +181,6 @@ static int tpm1_chip_register(struct tpm_chip *chip)
        if (rc)
                return rc;
 
-       rc = tpm_add_ppi(chip);
-       if (rc) {
-               tpm_sysfs_del_device(chip);
-               return rc;
-       }
-
        chip->bios_dir = tpm_bios_log_setup(chip->devname);
 
        return 0;
@@ -200,8 +194,6 @@ static void tpm1_chip_unregister(struct tpm_chip *chip)
        if (chip->bios_dir)
                tpm_bios_log_teardown(chip->bios_dir);
 
-       tpm_remove_ppi(chip);
-
        tpm_sysfs_del_device(chip);
 }
 
@@ -224,6 +216,10 @@ int tpm_chip_register(struct tpm_chip *chip)
        if (rc)
                return rc;
 
+       rc = tpm_add_ppi(chip);
+       if (rc)
+               goto out_err;
+
        rc = tpm_dev_add_device(chip);
        if (rc)
                goto out_err;
@@ -237,6 +233,7 @@ int tpm_chip_register(struct tpm_chip *chip)
 
        return 0;
 out_err:
+       tpm_remove_ppi(chip);
        tpm1_chip_unregister(chip);
        return rc;
 }
@@ -262,7 +259,8 @@ void tpm_chip_unregister(struct tpm_chip *chip)
        spin_unlock(&driver_lock);
        synchronize_rcu();
 
-       tpm1_chip_unregister(chip);
        tpm_dev_del_device(chip);
+       tpm_remove_ppi(chip);
+       tpm1_chip_unregister(chip);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_unregister);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e85d341..aa813ff 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1038,6 +1038,7 @@ static int __init tpm_init(void)
                return rc;
        }
 
+       tpm_ppi_init(tpm_class);
        return 0;
 }
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f8319a0..65872a5 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -182,7 +182,7 @@ struct tpm_chip {
        struct list_head list;
 };
 
-#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+#define to_tpm_chip(n) container_of(dev, struct tpm_chip, dev)
 
 static inline void tpm_chip_put(struct tpm_chip *chip)
 {
@@ -411,6 +411,7 @@ void tpm_sysfs_del_device(struct tpm_chip *chip);
 
 int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
 
+void tpm_ppi_init(struct class *tpm_class);
 #ifdef CONFIG_ACPI
 extern int tpm_add_ppi(struct tpm_chip *chip);
 extern void tpm_remove_ppi(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index 6ca9b5d..517a8b2 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -50,10 +50,23 @@ tpm_eval_dsm(acpi_handle ppi_handle, int func, 
acpi_object_type type,
                                       func, argv4, type);
 }
 
+static struct tpm_chip *ppi_dev_to_chip(struct device *dev)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       if (chip == NULL)
+               chip = to_tpm_chip(chip);
+
+       return chip;
+}
+
 static ssize_t tpm_show_ppi_version(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
 
        return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version);
 }
@@ -63,7 +76,10 @@ static ssize_t tpm_show_ppi_request(struct device *dev,
 {
        ssize_t size = -EINVAL;
        union acpi_object *obj;
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
 
        obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ,
                           ACPI_TYPE_PACKAGE, NULL);
@@ -100,7 +116,10 @@ static ssize_t tpm_store_ppi_request(struct device *dev,
        int func = TPM_PPI_FN_SUBREQ;
        union acpi_object *obj, tmp;
        union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp);
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
 
        /*
         * the function to submit TPM operation request to pre-os environment
@@ -156,7 +175,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device 
*dev,
                .buffer.length = 0,
                .buffer.pointer = NULL
        };
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
 
        static char *info[] = {
                "None",
@@ -166,6 +185,9 @@ static ssize_t tpm_show_ppi_transition_action(struct device 
*dev,
                "Error",
        };
 
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
+
        /*
         * PPI spec defines params[3].type as empty package, but some platforms
         * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
@@ -197,7 +219,10 @@ static ssize_t tpm_show_ppi_response(struct device *dev,
        acpi_status status = -EINVAL;
        union acpi_object *obj, *ret_obj;
        u64 req, res;
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
 
        obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP,
                           ACPI_TYPE_PACKAGE, NULL);
@@ -251,7 +276,7 @@ cleanup:
        return status;
 }
 
-static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 
start,
+static ssize_t show_ppi_operations(struct tpm_chip *chip, char *buf, u32 start,
                                   u32 end)
 {
        int i;
@@ -268,14 +293,17 @@ static ssize_t show_ppi_operations(acpi_handle 
dev_handle, char *buf, u32 start,
                "User not required",
        };
 
-       if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID,
-                           1 << TPM_PPI_FN_GETOPR))
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
+
+       if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid,
+                           TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_GETOPR))
                return -EPERM;
 
        tmp.integer.type = ACPI_TYPE_INTEGER;
        for (i = start; i <= end; i++) {
                tmp.integer.value = i;
-               obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR,
+               obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETOPR,
                                   ACPI_TYPE_INTEGER, &argv);
                if (!obj) {
                        return -ENOMEM;
@@ -296,22 +324,57 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device 
*dev,
                                           struct device_attribute *attr,
                                           char *buf)
 {
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
 
-       return show_ppi_operations(chip->acpi_dev_handle, buf, 0,
-                                  PPI_TPM_REQ_MAX);
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
+
+       return show_ppi_operations(chip, buf, 0, PPI_TPM_REQ_MAX);
 }
 
 static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
                                          struct device_attribute *attr,
                                          char *buf)
 {
-       struct tpm_chip *chip = dev_get_drvdata(dev);
+       struct tpm_chip *chip = ppi_dev_to_chip(dev);
+
+       if (!(chip->flags & TPM_CHIP_FLAG_PPI))
+               return -EINVAL;
+
+       return show_ppi_operations(chip, buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
+}
+
+static DEVICE_ATTR(ppi_version, S_IRUGO, tpm_show_ppi_version, NULL);
+static DEVICE_ATTR(ppi_request, S_IRUGO | S_IWUSR | S_IWGRP,
+                  tpm_show_ppi_request, tpm_store_ppi_request);
+static DEVICE_ATTR(ppi_transition_action, S_IRUGO,
+                  tpm_show_ppi_transition_action, NULL);
+static DEVICE_ATTR(ppi_response, S_IRUGO, tpm_show_ppi_response, NULL);
+static DEVICE_ATTR(ppi_tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations,
+                  NULL);
+static DEVICE_ATTR(ppi_vs_operations, S_IRUGO, tpm_show_ppi_vs_operations,
+                  NULL);
+
+static struct attribute *tpm_attrs[] = {
+       &dev_attr_ppi_version.attr,
+       &dev_attr_ppi_request.attr,
+       &dev_attr_ppi_transition_action.attr,
+       &dev_attr_ppi_response.attr,
+       &dev_attr_ppi_tcg_operations.attr,
+       &dev_attr_ppi_vs_operations.attr,
+       NULL,
+};
+ATTRIBUTE_GROUPS(tpm);
 
-       return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START,
-                                  PPI_VS_REQ_END);
+void __init tpm_ppi_init(struct class *tpm_class)
+{
+       tpm_class->dev_groups = tpm_groups;
 }
 
+/* Legacy attributes and operations for backwards compatibility. These are
+ * only for TPM 1.x and are attached to the platform device.
+ */
+
 static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
 static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
                   tpm_show_ppi_request, tpm_store_ppi_request);
@@ -327,8 +390,10 @@ static struct attribute *ppi_attrs[] = {
        &dev_attr_transition_action.attr,
        &dev_attr_response.attr,
        &dev_attr_tcg_operations.attr,
-       &dev_attr_vs_operations.attr, NULL,
+       &dev_attr_vs_operations.attr,
+       NULL,
 };
+
 static struct attribute_group ppi_attr_grp = {
        .name = "ppi",
        .attrs = ppi_attrs
@@ -337,7 +402,7 @@ static struct attribute_group ppi_attr_grp = {
 int tpm_add_ppi(struct tpm_chip *chip)
 {
        union acpi_object *obj;
-       int rc;
+       int rc = 0;
 
        if (!chip->acpi_dev_handle)
                return 0;
@@ -356,7 +421,8 @@ int tpm_add_ppi(struct tpm_chip *chip)
                ACPI_FREE(obj);
        }
 
-       rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp);
+       if (!(chip->flags &  TPM_CHIP_FLAG_TPM2))
+               rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp);
 
        if (!rc)
                chip->flags |= TPM_CHIP_FLAG_PPI;
@@ -366,6 +432,9 @@ int tpm_add_ppi(struct tpm_chip *chip)
 
 void tpm_remove_ppi(struct tpm_chip *chip)
 {
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               return;
+
        if (chip->flags & TPM_CHIP_FLAG_PPI)
                sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp);
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to