* Separated allocation and registeration into two functions:
  * tpm_chip_alloc()
  * tpm_chip_register()
* Modified tpm_register_hardware() to call tpm_chip_alloc/register().
* Added tpm2 boolean flag to struct tpm_chip.
* If a chip has tpm2 flag set TCPA log is not initialized in
  tpm_chip_register().

The rationale is to introduce TPM2 support without existing drivers
getting harmed.

Signed-off-by: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
---
 drivers/char/tpm/Makefile        |   2 +-
 drivers/char/tpm/tpm-chip.c      | 169 +++++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm-interface.c | 120 ++-------------------------
 drivers/char/tpm/tpm.h           |   9 +++
 4 files changed, 187 insertions(+), 113 deletions(-)
 create mode 100644 drivers/char/tpm/tpm-chip.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 4d85dd6..837da04 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the kernel tpm device drivers.
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
-tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o
+tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o
 
 ifdef CONFIG_ACPI
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
new file mode 100644
index 0000000..128942b
--- /dev/null
+++ b/drivers/char/tpm/tpm-chip.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Authors:
+ * Jarkko Sakkinen <jarkko.sakki...@linux.intel.com>
+ * Leendert van Doorn <leend...@watson.ibm.com>
+ * Dave Safford <saff...@watson.ibm.com>
+ * Reiner Sailer <sai...@watson.ibm.com>
+ * Kylene Hall <kjh...@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-de...@lists.sourceforge.net>
+ *
+ * TPM chip management routines.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/freezer.h>
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+static LIST_HEAD(tpm_chip_list);
+static DEFINE_SPINLOCK(driver_lock);
+
+/*
+ * tpm_chip_find_get - return tpm_chip for given chip number
+ */
+struct tpm_chip *tpm_chip_find_get(int chip_num)
+{
+       struct tpm_chip *pos, *chip = NULL;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
+               if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
+                       continue;
+
+               if (try_module_get(pos->dev->driver->owner)) {
+                       chip = pos;
+                       break;
+               }
+       }
+       rcu_read_unlock();
+       return chip;
+}
+
+
+/* In case vendor provided release function, call it too.*/
+
+void tpm_dev_vendor_release(struct tpm_chip *chip)
+{
+       if (!chip)
+               return;
+
+       clear_bit(chip->dev_num, dev_mask);
+}
+EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
+
+/*
+ * Once all references to platform device are down to 0,
+ * release all allocated structures.
+ */
+static void tpm_dev_release(struct device *dev)
+{
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+
+       if (!chip)
+               return;
+
+       tpm_dev_vendor_release(chip);
+
+       chip->release(dev);
+       kfree(chip);
+}
+
+struct tpm_chip *tpm_chip_alloc(struct device *dev,
+                               const struct tpm_class_ops *ops)
+{
+       struct tpm_chip *chip;
+
+       /* Driver specific per-device data */
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+
+       if (chip == NULL)
+               return NULL;
+
+       mutex_init(&chip->tpm_mutex);
+       INIT_LIST_HEAD(&chip->list);
+
+       chip->ops = ops;
+       chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
+
+       if (chip->dev_num >= TPM_NUM_DEVICES) {
+               dev_err(dev, "No available tpm device numbers\n");
+               kfree(chip);
+               return NULL;
+       }
+
+       set_bit(chip->dev_num, dev_mask);
+
+       scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm",
+                 chip->dev_num);
+
+       chip->dev = get_device(dev);
+       chip->release = dev->release;
+       dev->release = tpm_dev_release;
+       dev_set_drvdata(dev, chip);
+
+       return chip;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_alloc);
+
+int tpm_chip_register(struct tpm_chip *chip)
+{
+       int rc;
+
+       rc = tpm_dev_add_device(chip);
+       if (rc)
+               return rc;
+
+       rc = tpm_sysfs_add_device(chip);
+       if (rc)
+               goto del_misc;
+
+       rc = tpm_add_ppi(&chip->dev->kobj);
+       if (rc)
+               goto del_sysfs;
+
+       if (!chip->tpm2)
+               chip->bios_dir = tpm_bios_log_setup(chip->devname);
+
+       /* Make chip available */
+       spin_lock(&driver_lock);
+       list_add_rcu(&chip->list, &tpm_chip_list);
+       spin_unlock(&driver_lock);
+
+       return 0;
+del_sysfs:
+       tpm_sysfs_del_device(chip);
+del_misc:
+       tpm_dev_del_device(chip);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_register);
+
+void tpm_chip_unregister(struct tpm_chip *chip)
+{
+       spin_lock(&driver_lock);
+       list_del_rcu(&chip->list);
+       spin_unlock(&driver_lock);
+       synchronize_rcu();
+
+       tpm_dev_del_device(chip);
+       tpm_sysfs_del_device(chip);
+       tpm_remove_ppi(&chip->dev->kobj);
+
+       if (!chip->tpm2)
+               tpm_bios_log_teardown(chip->bios_dir);
+}
+EXPORT_SYMBOL_GPL(tpm_chip_unregister);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index f638f9d..3c54570 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -47,10 +47,6 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
 MODULE_PARM_DESC(suspend_pcr,
                 "PCR to use for dummy writes to faciltate flush on suspend.");
 
-static LIST_HEAD(tpm_chip_list);
-static DEFINE_SPINLOCK(driver_lock);
-static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
-
 /*
  * Array with one entry per ordinal defining the maximum amount
  * of time the chip could take to return the result.  The ordinal
@@ -636,27 +632,6 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
        return rc;
 }
 
-/*
- * tpm_chip_find_get - return tpm_chip for given chip number
- */
-static struct tpm_chip *tpm_chip_find_get(int chip_num)
-{
-       struct tpm_chip *pos, *chip = NULL;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
-               if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
-                       continue;
-
-               if (try_module_get(pos->dev->driver->owner)) {
-                       chip = pos;
-                       break;
-               }
-       }
-       rcu_read_unlock();
-       return chip;
-}
-
 #define TPM_ORDINAL_PCRREAD cpu_to_be32(21)
 #define READ_PCR_RESULT_SIZE 30
 static struct tpm_input_header pcrread_header = {
@@ -893,15 +868,7 @@ void tpm_remove_hardware(struct device *dev)
                return;
        }
 
-       spin_lock(&driver_lock);
-       list_del_rcu(&chip->list);
-       spin_unlock(&driver_lock);
-       synchronize_rcu();
-
-       tpm_dev_del_device(chip);
-       tpm_sysfs_del_device(chip);
-       tpm_remove_ppi(&dev->kobj);
-       tpm_bios_log_teardown(chip->bios_dir);
+       tpm_chip_unregister(chip);
 
        /* write it this way to be explicit (chip->dev == dev) */
        put_device(chip->dev);
@@ -1041,35 +1008,6 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 }
 EXPORT_SYMBOL_GPL(tpm_get_random);
 
-/* In case vendor provided release function, call it too.*/
-
-void tpm_dev_vendor_release(struct tpm_chip *chip)
-{
-       if (!chip)
-               return;
-
-       clear_bit(chip->dev_num, dev_mask);
-}
-EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
-
-
-/*
- * Once all references to platform device are down to 0,
- * release all allocated structures.
- */
-static void tpm_dev_release(struct device *dev)
-{
-       struct tpm_chip *chip = dev_get_drvdata(dev);
-
-       if (!chip)
-               return;
-
-       tpm_dev_vendor_release(chip);
-
-       chip->release(dev);
-       kfree(chip);
-}
-
 /*
  * Called from tpm_<specific>.c probe function only for devices
  * the driver has determined it should claim.  Prior to calling
@@ -1081,61 +1019,19 @@ struct tpm_chip *tpm_register_hardware(struct device 
*dev,
                                       const struct tpm_class_ops *ops)
 {
        struct tpm_chip *chip;
+       int rc;
 
-       /* Driver specific per-device data */
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-
-       if (chip == NULL)
+       chip = tpm_chip_alloc(dev, ops);
+       if (!chip)
                return NULL;
 
-       mutex_init(&chip->tpm_mutex);
-       INIT_LIST_HEAD(&chip->list);
-
-       chip->ops = ops;
-       chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
-
-       if (chip->dev_num >= TPM_NUM_DEVICES) {
-               dev_err(dev, "No available tpm device numbers\n");
-               goto out_free;
+       rc = tpm_chip_register(chip);
+       if (rc) {
+               put_device(chip->dev);
+               kfree(chip);
        }
 
-       set_bit(chip->dev_num, dev_mask);
-
-       scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm",
-                 chip->dev_num);
-
-       chip->dev = get_device(dev);
-       chip->release = dev->release;
-       dev->release = tpm_dev_release;
-       dev_set_drvdata(dev, chip);
-
-       if (tpm_dev_add_device(chip))
-               goto put_device;
-
-       if (tpm_sysfs_add_device(chip))
-               goto del_misc;
-
-       if (tpm_add_ppi(&dev->kobj))
-               goto del_sysfs;
-
-       chip->bios_dir = tpm_bios_log_setup(chip->devname);
-
-       /* Make chip available */
-       spin_lock(&driver_lock);
-       list_add_rcu(&chip->list, &tpm_chip_list);
-       spin_unlock(&driver_lock);
-
        return chip;
-
-del_sysfs:
-       tpm_sysfs_del_device(chip);
-del_misc:
-       tpm_dev_del_device(chip);
-put_device:
-       put_device(chip->dev);
-out_free:
-       kfree(chip);
-       return NULL;
 }
 EXPORT_SYMBOL_GPL(tpm_register_hardware);
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index d893335..cc95a52 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -109,6 +109,8 @@ struct tpm_chip {
 
        struct dentry **bios_dir;
 
+       bool tpm2; /* is this a TPM2 chip? */
+
        struct list_head list;
        void (*release) (struct device *);
 };
@@ -332,6 +334,13 @@ extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
                             wait_queue_head_t *, bool);
 
+struct tpm_chip *tpm_chip_find_get(int chip_num);
+extern void tpm_dev_vendor_release(struct tpm_chip *);
+extern struct tpm_chip *tpm_chip_alloc(struct device *dev,
+                                      const struct tpm_class_ops *ops);
+extern int tpm_chip_register(struct tpm_chip *chip);
+extern void tpm_chip_unregister(struct tpm_chip *chip);
+
 int tpm_dev_add_device(struct tpm_chip *chip);
 void tpm_dev_del_device(struct tpm_chip *chip);
 int tpm_sysfs_add_device(struct tpm_chip *chip);
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
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