tpm: device class for tpm
authorJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Fri, 12 Dec 2014 19:46:37 +0000 (11:46 -0800)
committerPeter Huewe <peterhuewe@gmx.de>
Sat, 17 Jan 2015 13:00:10 +0000 (14:00 +0100)
Added own device class for TPM. Uses MISC_MAJOR:TPM_MINOR for the
first character device in order to retain backwards compatibility.
Added tpm_dev_release() back attached to the character device.

I've been running this code now for a while on my laptop (Lenovo
T430S) TrouSerS works perfectly without modifications. I don't
believe it breaks anything significantly.

The sysfs attributes that have been placed under the wrong place
and are against sysfs-rules.txt should be probably left to
stagnate under platform device directory and start defining
new sysfs attributes to the char device directory.

Guidelines for future TPM sysfs attributes should be probably
along the lines of

- Single flat set of mandatory sysfs attributes. For example,
  current PPI interface is way way too rich when you only want
  to use it to clear and activate the TPM.

- Define sysfs attribute if and only if there's no way to get
  the value from ring-3. No attributes for TPM properties. It's
  just unnecessary maintenance hurdle that we don't want.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Reviewed-by: Jasob Gunthorpe <jason.gunthorpe@obsidianresearch.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Tested-by: Scot Doyle <lkml14@scotdoyle.com>
Tested-by: Peter Huewe <peterhuewe@gmx.de>
Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
Documentation/ABI/stable/sysfs-class-tpm
drivers/char/tpm/tpm-chip.c
drivers/char/tpm/tpm-dev.c
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_i2c_nuvoton.c
drivers/char/tpm/tpm_tis.c

index a60b45e..9f790ee 100644 (file)
@@ -1,4 +1,4 @@
-What:          /sys/class/misc/tpmX/device/
+What:          /sys/class/tpm/tpmX/device/
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       tpmdd-devel@lists.sf.net
@@ -6,7 +6,7 @@ Description:    The device/ directory under a specific TPM instance exposes
                the properties of that TPM chip
 
 
-What:          /sys/class/misc/tpmX/device/active
+What:          /sys/class/tpm/tpmX/device/active
 Date:          April 2006
 KernelVersion: 2.6.17
 Contact:       tpmdd-devel@lists.sf.net
@@ -18,7 +18,7 @@ Description:  The "active" property prints a '1' if the TPM chip is accepting
                section 17 for more information on which commands are
                available.
 
-What:          /sys/class/misc/tpmX/device/cancel
+What:          /sys/class/tpm/tpmX/device/cancel
 Date:          June 2005
 KernelVersion: 2.6.13
 Contact:       tpmdd-devel@lists.sf.net
@@ -26,7 +26,7 @@ Description:  The "cancel" property allows you to cancel the currently
                pending TPM command. Writing any value to cancel will call the
                TPM vendor specific cancel operation.
 
-What:          /sys/class/misc/tpmX/device/caps
+What:          /sys/class/tpm/tpmX/device/caps
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       tpmdd-devel@lists.sf.net
@@ -43,7 +43,7 @@ Description:  The "caps" property contains TPM manufacturer and version info.
                the chip supports. Firmware version is that of the chip and
                is manufacturer specific.
 
-What:          /sys/class/misc/tpmX/device/durations
+What:          /sys/class/tpm/tpmX/device/durations
 Date:          March 2011
 KernelVersion: 3.1
 Contact:       tpmdd-devel@lists.sf.net
@@ -66,7 +66,7 @@ Description:  The "durations" property shows the 3 vendor-specific values
                scaled to be displayed in usecs. In this case "[adjusted]"
                will be displayed in place of "[original]".
 
-What:          /sys/class/misc/tpmX/device/enabled
+What:          /sys/class/tpm/tpmX/device/enabled
 Date:          April 2006
 KernelVersion: 2.6.17
 Contact:       tpmdd-devel@lists.sf.net
@@ -75,7 +75,7 @@ Description:  The "enabled" property prints a '1' if the TPM chip is enabled,
                may be visible but produce a '0' after some operation that
                disables the TPM.
 
-What:          /sys/class/misc/tpmX/device/owned
+What:          /sys/class/tpm/tpmX/device/owned
 Date:          April 2006
 KernelVersion: 2.6.17
 Contact:       tpmdd-devel@lists.sf.net
@@ -83,7 +83,7 @@ Description:  The "owned" property produces a '1' if the TPM_TakeOwnership
                ordinal has been executed successfully in the chip. A '0'
                indicates that ownership hasn't been taken.
 
-What:          /sys/class/misc/tpmX/device/pcrs
+What:          /sys/class/tpm/tpmX/device/pcrs
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       tpmdd-devel@lists.sf.net
@@ -106,7 +106,7 @@ Description:        The "pcrs" property will dump the current value of all Platform
                1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes
                long. Use the "caps" property to determine TPM version.
 
-What:          /sys/class/misc/tpmX/device/pubek
+What:          /sys/class/tpm/tpmX/device/pubek
 Date:          April 2005
 KernelVersion: 2.6.12
 Contact:       tpmdd-devel@lists.sf.net
@@ -158,7 +158,7 @@ Description:        The "pubek" property will return the TPM's public endorsement
                Modulus Length: 256 (bytes)
                Modulus:        The 256 byte Endorsement Key modulus
 
-What:          /sys/class/misc/tpmX/device/temp_deactivated
+What:          /sys/class/tpm/tpmX/device/temp_deactivated
 Date:          April 2006
 KernelVersion: 2.6.17
 Contact:       tpmdd-devel@lists.sf.net
@@ -167,7 +167,7 @@ Description:        The "temp_deactivated" property returns a '1' if the chip has
                cycle. Whether a warm boot (reboot) will clear a TPM chip
                from a temp_deactivated state is platform specific.
 
-What:          /sys/class/misc/tpmX/device/timeouts
+What:          /sys/class/tpm/tpmX/device/timeouts
 Date:          March 2011
 KernelVersion: 3.1
 Contact:       tpmdd-devel@lists.sf.net
index e72b042..7596eef 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/freezer.h>
+#include <linux/major.h>
 #include "tpm.h"
 #include "tpm_eventlog.h"
 
@@ -32,6 +33,9 @@ static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
 
+struct class *tpm_class;
+dev_t tpm_devt;
+
 /*
  * tpm_chip_find_get - return tpm_chip for a given chip number
  * @chip_num the device number for the chip
@@ -55,16 +59,14 @@ struct tpm_chip *tpm_chip_find_get(int chip_num)
 }
 
 /**
- * tpmm_chip_remove() - free chip memory and device number
- * @data: points to struct tpm_chip instance
+ * tpm_dev_release() - free chip memory and the device number
+ * @dev: the character device for the TPM chip
  *
- * This is used internally by tpmm_chip_alloc() and called by devres
- * when the device is released. This function does the opposite of
- * tpmm_chip_alloc() freeing memory and the device number.
+ * This is used as the release function for the character device.
  */
-static void tpmm_chip_remove(void *data)
+static void tpm_dev_release(struct device *dev)
 {
-       struct tpm_chip *chip = (struct tpm_chip *) data;
+       struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
 
        spin_lock(&driver_lock);
        clear_bit(chip->dev_num, dev_mask);
@@ -111,18 +113,68 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
        scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
 
        chip->pdev = dev;
-       devm_add_action(dev, tpmm_chip_remove, chip);
+
        dev_set_drvdata(dev, chip);
 
+       chip->dev.class = tpm_class;
+       chip->dev.release = tpm_dev_release;
+       chip->dev.parent = chip->pdev;
+
+       if (chip->dev_num == 0)
+               chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
+       else
+               chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
+
+       dev_set_name(&chip->dev, chip->devname);
+
+       device_initialize(&chip->dev);
+
+       chip->cdev.owner = chip->pdev->driver->owner;
+       cdev_init(&chip->cdev, &tpm_fops);
+
        return chip;
 }
 EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
 
+static int tpm_dev_add_device(struct tpm_chip *chip)
+{
+       int rc;
+
+       rc = device_add(&chip->dev);
+       if (rc) {
+               dev_err(&chip->dev,
+                       "unable to device_register() %s, major %d, minor %d, err=%d\n",
+                       chip->devname, MAJOR(chip->dev.devt),
+                       MINOR(chip->dev.devt), rc);
+
+               return rc;
+       }
+
+       rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
+       if (rc) {
+               dev_err(&chip->dev,
+                       "unable to cdev_add() %s, major %d, minor %d, err=%d\n",
+                       chip->devname, MAJOR(chip->dev.devt),
+                       MINOR(chip->dev.devt), rc);
+
+               device_unregister(&chip->dev);
+               return rc;
+       }
+
+       return rc;
+}
+
+static void tpm_dev_del_device(struct tpm_chip *chip)
+{
+       cdev_del(&chip->cdev);
+       device_unregister(&chip->dev);
+}
+
 /*
- * tpm_chip_register() - create a misc driver for the TPM chip
+ * tpm_chip_register() - create a character device for the TPM chip
  * @chip: TPM chip to use.
  *
- * Creates a misc driver for the TPM chip and adds sysfs interfaces for
+ * Creates a character device for the TPM chip and adds sysfs interfaces for
  * the device, PPI and TCPA. As the last step this function adds the
  * chip to the list of TPM chips available for use.
  *
index 3568321..de0337e 100644 (file)
@@ -17,7 +17,6 @@
  * License.
  *
  */
-#include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include "tpm.h"
@@ -54,9 +53,8 @@ static void timeout_work(struct work_struct *work)
 
 static int tpm_open(struct inode *inode, struct file *file)
 {
-       struct miscdevice *misc = file->private_data;
-       struct tpm_chip *chip = container_of(misc, struct tpm_chip,
-                                            vendor.miscdev);
+       struct tpm_chip *chip =
+               container_of(inode->i_cdev, struct tpm_chip, cdev);
        struct file_priv *priv;
 
        /* It's assured that the chip will be opened just once,
@@ -173,7 +171,7 @@ static int tpm_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations tpm_fops = {
+const struct file_operations tpm_fops = {
        .owner = THIS_MODULE,
        .llseek = no_llseek,
        .open = tpm_open,
@@ -182,32 +180,4 @@ static const struct file_operations tpm_fops = {
        .release = tpm_release,
 };
 
-int tpm_dev_add_device(struct tpm_chip *chip)
-{
-       int rc;
 
-       chip->vendor.miscdev.fops = &tpm_fops;
-       if (chip->dev_num == 0)
-               chip->vendor.miscdev.minor = TPM_MINOR;
-       else
-               chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
-
-       chip->vendor.miscdev.name = chip->devname;
-       chip->vendor.miscdev.parent = chip->pdev;
-
-       rc = misc_register(&chip->vendor.miscdev);
-       if (rc) {
-               chip->vendor.miscdev.name = NULL;
-               dev_err(chip->pdev,
-                       "unable to misc_register %s, minor %d err=%d\n",
-                       chip->vendor.miscdev.name,
-                       chip->vendor.miscdev.minor, rc);
-       }
-       return rc;
-}
-
-void tpm_dev_del_device(struct tpm_chip *chip)
-{
-       if (chip->vendor.miscdev.name)
-               misc_deregister(&chip->vendor.miscdev);
-}
index e2af28f..b6f6b17 100644 (file)
@@ -997,6 +997,35 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
 }
 EXPORT_SYMBOL_GPL(tpm_get_random);
 
+static int __init tpm_init(void)
+{
+       int rc;
+
+       tpm_class = class_create(THIS_MODULE, "tpm");
+       if (IS_ERR(tpm_class)) {
+               pr_err("couldn't create tpm class\n");
+               return PTR_ERR(tpm_class);
+       }
+
+       rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
+       if (rc < 0) {
+               pr_err("tpm: failed to allocate char dev region\n");
+               class_destroy(tpm_class);
+               return rc;
+       }
+
+       return 0;
+}
+
+static void __exit tpm_exit(void)
+{
+       class_destroy(tpm_class);
+       unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
+}
+
+subsys_initcall(tpm_init);
+module_exit(tpm_exit);
+
 MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
 MODULE_DESCRIPTION("TPM Driver");
 MODULE_VERSION("2.0");
Simple merge
Simple merge
Simple merge