Skip to content

Commit 313d21e

Browse files
Jarkko SakkinenPeterHuewe
Jarkko Sakkinen
authored andcommitted
tpm: device class for tpm
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 <[email protected]> Reviewed-by: Jasob Gunthorpe <[email protected]> Reviewed-by: Stefan Berger <[email protected]> Tested-by: Scot Doyle <[email protected]> Tested-by: Peter Huewe <[email protected]> Signed-off-by: Peter Huewe <[email protected]>
1 parent 71ed848 commit 313d21e

File tree

7 files changed

+116
-61
lines changed

7 files changed

+116
-61
lines changed

Documentation/ABI/stable/sysfs-class-tpm

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
What: /sys/class/misc/tpmX/device/
1+
What: /sys/class/tpm/tpmX/device/
22
Date: April 2005
33
KernelVersion: 2.6.12
44
55
Description: The device/ directory under a specific TPM instance exposes
66
the properties of that TPM chip
77

88

9-
What: /sys/class/misc/tpmX/device/active
9+
What: /sys/class/tpm/tpmX/device/active
1010
Date: April 2006
1111
KernelVersion: 2.6.17
1212
@@ -18,15 +18,15 @@ Description: The "active" property prints a '1' if the TPM chip is accepting
1818
section 17 for more information on which commands are
1919
available.
2020

21-
What: /sys/class/misc/tpmX/device/cancel
21+
What: /sys/class/tpm/tpmX/device/cancel
2222
Date: June 2005
2323
KernelVersion: 2.6.13
2424
2525
Description: The "cancel" property allows you to cancel the currently
2626
pending TPM command. Writing any value to cancel will call the
2727
TPM vendor specific cancel operation.
2828

29-
What: /sys/class/misc/tpmX/device/caps
29+
What: /sys/class/tpm/tpmX/device/caps
3030
Date: April 2005
3131
KernelVersion: 2.6.12
3232
@@ -43,7 +43,7 @@ Description: The "caps" property contains TPM manufacturer and version info.
4343
the chip supports. Firmware version is that of the chip and
4444
is manufacturer specific.
4545

46-
What: /sys/class/misc/tpmX/device/durations
46+
What: /sys/class/tpm/tpmX/device/durations
4747
Date: March 2011
4848
KernelVersion: 3.1
4949
@@ -66,7 +66,7 @@ Description: The "durations" property shows the 3 vendor-specific values
6666
scaled to be displayed in usecs. In this case "[adjusted]"
6767
will be displayed in place of "[original]".
6868

69-
What: /sys/class/misc/tpmX/device/enabled
69+
What: /sys/class/tpm/tpmX/device/enabled
7070
Date: April 2006
7171
KernelVersion: 2.6.17
7272
@@ -75,15 +75,15 @@ Description: The "enabled" property prints a '1' if the TPM chip is enabled,
7575
may be visible but produce a '0' after some operation that
7676
disables the TPM.
7777

78-
What: /sys/class/misc/tpmX/device/owned
78+
What: /sys/class/tpm/tpmX/device/owned
7979
Date: April 2006
8080
KernelVersion: 2.6.17
8181
8282
Description: The "owned" property produces a '1' if the TPM_TakeOwnership
8383
ordinal has been executed successfully in the chip. A '0'
8484
indicates that ownership hasn't been taken.
8585

86-
What: /sys/class/misc/tpmX/device/pcrs
86+
What: /sys/class/tpm/tpmX/device/pcrs
8787
Date: April 2005
8888
KernelVersion: 2.6.12
8989
@@ -106,7 +106,7 @@ Description: The "pcrs" property will dump the current value of all Platform
106106
1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes
107107
long. Use the "caps" property to determine TPM version.
108108

109-
What: /sys/class/misc/tpmX/device/pubek
109+
What: /sys/class/tpm/tpmX/device/pubek
110110
Date: April 2005
111111
KernelVersion: 2.6.12
112112
@@ -158,7 +158,7 @@ Description: The "pubek" property will return the TPM's public endorsement
158158
Modulus Length: 256 (bytes)
159159
Modulus: The 256 byte Endorsement Key modulus
160160

161-
What: /sys/class/misc/tpmX/device/temp_deactivated
161+
What: /sys/class/tpm/tpmX/device/temp_deactivated
162162
Date: April 2006
163163
KernelVersion: 2.6.17
164164
@@ -167,7 +167,7 @@ Description: The "temp_deactivated" property returns a '1' if the chip has
167167
cycle. Whether a warm boot (reboot) will clear a TPM chip
168168
from a temp_deactivated state is platform specific.
169169

170-
What: /sys/class/misc/tpmX/device/timeouts
170+
What: /sys/class/tpm/tpmX/device/timeouts
171171
Date: March 2011
172172
KernelVersion: 3.1
173173

drivers/char/tpm/tpm-chip.c

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@
2525
#include <linux/mutex.h>
2626
#include <linux/spinlock.h>
2727
#include <linux/freezer.h>
28+
#include <linux/major.h>
2829
#include "tpm.h"
2930
#include "tpm_eventlog.h"
3031

3132
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
3233
static LIST_HEAD(tpm_chip_list);
3334
static DEFINE_SPINLOCK(driver_lock);
3435

36+
struct class *tpm_class;
37+
dev_t tpm_devt;
38+
3539
/*
3640
* tpm_chip_find_get - return tpm_chip for a given chip number
3741
* @chip_num the device number for the chip
@@ -55,16 +59,14 @@ struct tpm_chip *tpm_chip_find_get(int chip_num)
5559
}
5660

5761
/**
58-
* tpmm_chip_remove() - free chip memory and device number
59-
* @data: points to struct tpm_chip instance
62+
* tpm_dev_release() - free chip memory and the device number
63+
* @dev: the character device for the TPM chip
6064
*
61-
* This is used internally by tpmm_chip_alloc() and called by devres
62-
* when the device is released. This function does the opposite of
63-
* tpmm_chip_alloc() freeing memory and the device number.
65+
* This is used as the release function for the character device.
6466
*/
65-
static void tpmm_chip_remove(void *data)
67+
static void tpm_dev_release(struct device *dev)
6668
{
67-
struct tpm_chip *chip = (struct tpm_chip *) data;
69+
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
6870

6971
spin_lock(&driver_lock);
7072
clear_bit(chip->dev_num, dev_mask);
@@ -111,18 +113,68 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
111113
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
112114

113115
chip->pdev = dev;
114-
devm_add_action(dev, tpmm_chip_remove, chip);
116+
115117
dev_set_drvdata(dev, chip);
116118

119+
chip->dev.class = tpm_class;
120+
chip->dev.release = tpm_dev_release;
121+
chip->dev.parent = chip->pdev;
122+
123+
if (chip->dev_num == 0)
124+
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
125+
else
126+
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
127+
128+
dev_set_name(&chip->dev, chip->devname);
129+
130+
device_initialize(&chip->dev);
131+
132+
chip->cdev.owner = chip->pdev->driver->owner;
133+
cdev_init(&chip->cdev, &tpm_fops);
134+
117135
return chip;
118136
}
119137
EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
120138

139+
static int tpm_dev_add_device(struct tpm_chip *chip)
140+
{
141+
int rc;
142+
143+
rc = device_add(&chip->dev);
144+
if (rc) {
145+
dev_err(&chip->dev,
146+
"unable to device_register() %s, major %d, minor %d, err=%d\n",
147+
chip->devname, MAJOR(chip->dev.devt),
148+
MINOR(chip->dev.devt), rc);
149+
150+
return rc;
151+
}
152+
153+
rc = cdev_add(&chip->cdev, chip->dev.devt, 1);
154+
if (rc) {
155+
dev_err(&chip->dev,
156+
"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
157+
chip->devname, MAJOR(chip->dev.devt),
158+
MINOR(chip->dev.devt), rc);
159+
160+
device_unregister(&chip->dev);
161+
return rc;
162+
}
163+
164+
return rc;
165+
}
166+
167+
static void tpm_dev_del_device(struct tpm_chip *chip)
168+
{
169+
cdev_del(&chip->cdev);
170+
device_unregister(&chip->dev);
171+
}
172+
121173
/*
122-
* tpm_chip_register() - create a misc driver for the TPM chip
174+
* tpm_chip_register() - create a character device for the TPM chip
123175
* @chip: TPM chip to use.
124176
*
125-
* Creates a misc driver for the TPM chip and adds sysfs interfaces for
177+
* Creates a character device for the TPM chip and adds sysfs interfaces for
126178
* the device, PPI and TCPA. As the last step this function adds the
127179
* chip to the list of TPM chips available for use.
128180
*

drivers/char/tpm/tpm-dev.c

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
* License.
1818
*
1919
*/
20-
#include <linux/miscdevice.h>
2120
#include <linux/slab.h>
2221
#include <linux/uaccess.h>
2322
#include "tpm.h"
@@ -54,9 +53,8 @@ static void timeout_work(struct work_struct *work)
5453

5554
static int tpm_open(struct inode *inode, struct file *file)
5655
{
57-
struct miscdevice *misc = file->private_data;
58-
struct tpm_chip *chip = container_of(misc, struct tpm_chip,
59-
vendor.miscdev);
56+
struct tpm_chip *chip =
57+
container_of(inode->i_cdev, struct tpm_chip, cdev);
6058
struct file_priv *priv;
6159

6260
/* 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)
173171
return 0;
174172
}
175173

176-
static const struct file_operations tpm_fops = {
174+
const struct file_operations tpm_fops = {
177175
.owner = THIS_MODULE,
178176
.llseek = no_llseek,
179177
.open = tpm_open,
@@ -182,32 +180,4 @@ static const struct file_operations tpm_fops = {
182180
.release = tpm_release,
183181
};
184182

185-
int tpm_dev_add_device(struct tpm_chip *chip)
186-
{
187-
int rc;
188183

189-
chip->vendor.miscdev.fops = &tpm_fops;
190-
if (chip->dev_num == 0)
191-
chip->vendor.miscdev.minor = TPM_MINOR;
192-
else
193-
chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
194-
195-
chip->vendor.miscdev.name = chip->devname;
196-
chip->vendor.miscdev.parent = chip->pdev;
197-
198-
rc = misc_register(&chip->vendor.miscdev);
199-
if (rc) {
200-
chip->vendor.miscdev.name = NULL;
201-
dev_err(chip->pdev,
202-
"unable to misc_register %s, minor %d err=%d\n",
203-
chip->vendor.miscdev.name,
204-
chip->vendor.miscdev.minor, rc);
205-
}
206-
return rc;
207-
}
208-
209-
void tpm_dev_del_device(struct tpm_chip *chip)
210-
{
211-
if (chip->vendor.miscdev.name)
212-
misc_deregister(&chip->vendor.miscdev);
213-
}

drivers/char/tpm/tpm-interface.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,35 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
997997
}
998998
EXPORT_SYMBOL_GPL(tpm_get_random);
999999

1000+
static int __init tpm_init(void)
1001+
{
1002+
int rc;
1003+
1004+
tpm_class = class_create(THIS_MODULE, "tpm");
1005+
if (IS_ERR(tpm_class)) {
1006+
pr_err("couldn't create tpm class\n");
1007+
return PTR_ERR(tpm_class);
1008+
}
1009+
1010+
rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
1011+
if (rc < 0) {
1012+
pr_err("tpm: failed to allocate char dev region\n");
1013+
class_destroy(tpm_class);
1014+
return rc;
1015+
}
1016+
1017+
return 0;
1018+
}
1019+
1020+
static void __exit tpm_exit(void)
1021+
{
1022+
class_destroy(tpm_class);
1023+
unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
1024+
}
1025+
1026+
subsys_initcall(tpm_init);
1027+
module_exit(tpm_exit);
1028+
10001029
MODULE_AUTHOR("Leendert van Doorn ([email protected])");
10011030
MODULE_DESCRIPTION("TPM Driver");
10021031
MODULE_VERSION("2.0");

drivers/char/tpm/tpm.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
#include <linux/fs.h>
2424
#include <linux/mutex.h>
2525
#include <linux/sched.h>
26-
#include <linux/miscdevice.h>
2726
#include <linux/platform_device.h>
2827
#include <linux/io.h>
2928
#include <linux/tpm.h>
3029
#include <linux/acpi.h>
30+
#include <linux/cdev.h>
3131

3232
enum tpm_const {
3333
TPM_MINOR = 224, /* officially assigned */
@@ -74,7 +74,6 @@ struct tpm_vendor_specific {
7474
int region_size;
7575
int have_region;
7676

77-
struct miscdevice miscdev;
7877
struct list_head list;
7978
int locality;
8079
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
@@ -104,6 +103,9 @@ enum tpm_chip_flags {
104103

105104
struct tpm_chip {
106105
struct device *pdev; /* Device stuff */
106+
struct device dev;
107+
struct cdev cdev;
108+
107109
const struct tpm_class_ops *ops;
108110
unsigned int flags;
109111

@@ -326,6 +328,10 @@ struct tpm_cmd_t {
326328
tpm_cmd_params params;
327329
} __packed;
328330

331+
extern struct class *tpm_class;
332+
extern dev_t tpm_devt;
333+
extern const struct file_operations tpm_fops;
334+
329335
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
330336
ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
331337
size_t bufsiz);
@@ -346,8 +352,6 @@ extern struct tpm_chip *tpmm_chip_alloc(struct device *dev,
346352
extern int tpm_chip_register(struct tpm_chip *chip);
347353
extern void tpm_chip_unregister(struct tpm_chip *chip);
348354

349-
int tpm_dev_add_device(struct tpm_chip *chip);
350-
void tpm_dev_del_device(struct tpm_chip *chip);
351355
int tpm_sysfs_add_device(struct tpm_chip *chip);
352356
void tpm_sysfs_del_device(struct tpm_chip *chip);
353357

drivers/char/tpm/tpm_i2c_nuvoton.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
560560
rc = devm_request_irq(dev, chip->vendor.irq,
561561
i2c_nuvoton_int_handler,
562562
IRQF_TRIGGER_LOW,
563-
chip->vendor.miscdev.name,
563+
chip->devname,
564564
chip);
565565
if (rc) {
566566
dev_err(dev, "%s() Unable to request irq: %d for use\n",

drivers/char/tpm/tpm_tis.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
698698
TPM_INT_VECTOR(chip->vendor.locality));
699699
if (devm_request_irq
700700
(dev, i, tis_int_probe, IRQF_SHARED,
701-
chip->vendor.miscdev.name, chip) != 0) {
701+
chip->devname, chip) != 0) {
702702
dev_info(chip->pdev,
703703
"Unable to request irq: %d for probe\n",
704704
i);
@@ -745,7 +745,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
745745
TPM_INT_VECTOR(chip->vendor.locality));
746746
if (devm_request_irq
747747
(dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED,
748-
chip->vendor.miscdev.name, chip) != 0) {
748+
chip->devname, chip) != 0) {
749749
dev_info(chip->pdev,
750750
"Unable to request irq: %d for use\n",
751751
chip->vendor.irq);

0 commit comments

Comments
 (0)