aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.vnet.ibm.com>2016-02-29 08:53:02 -0500
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2016-06-25 10:26:35 -0400
commit15516788e581eb32ec1c50e5f00aba3faf95d817 (patch)
treefc21e9a76367a73ba36b1e9315ca8fd741c544d8
parent3897cd9c8d1d1a9ff81fed893502911c2b9f4a79 (diff)
tpm: Replace device number bitmap with IDR
Replace the device number bitmap with IDR. Extend the number of devices we can create to 64k. Since an IDR allows us to associate a pointer with an ID, we use this now to rewrite tpm_chip_find_get() to simply look up the chip pointer by the given device ID. Protect the IDR calls with a mutex. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
-rw-r--r--drivers/char/tpm/tpm-chip.c84
-rw-r--r--drivers/char/tpm/tpm-interface.c1
-rw-r--r--drivers/char/tpm/tpm.h5
3 files changed, 48 insertions, 42 deletions
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 588037733107..f62c8518cd68 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -29,9 +29,8 @@
29#include "tpm.h" 29#include "tpm.h"
30#include "tpm_eventlog.h" 30#include "tpm_eventlog.h"
31 31
32static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); 32DEFINE_IDR(dev_nums_idr);
33static LIST_HEAD(tpm_chip_list); 33static DEFINE_MUTEX(idr_lock);
34static DEFINE_SPINLOCK(driver_lock);
35 34
36struct class *tpm_class; 35struct class *tpm_class;
37dev_t tpm_devt; 36dev_t tpm_devt;
@@ -88,20 +87,30 @@ EXPORT_SYMBOL_GPL(tpm_put_ops);
88 */ 87 */
89struct tpm_chip *tpm_chip_find_get(int chip_num) 88struct tpm_chip *tpm_chip_find_get(int chip_num)
90{ 89{
91 struct tpm_chip *pos, *chip = NULL; 90 struct tpm_chip *chip, *res = NULL;
91 int chip_prev;
92
93 mutex_lock(&idr_lock);
94
95 if (chip_num == TPM_ANY_NUM) {
96 chip_num = 0;
97 do {
98 chip_prev = chip_num;
99 chip = idr_get_next(&dev_nums_idr, &chip_num);
100 if (chip && !tpm_try_get_ops(chip)) {
101 res = chip;
102 break;
103 }
104 } while (chip_prev != chip_num);
105 } else {
106 chip = idr_find_slowpath(&dev_nums_idr, chip_num);
107 if (chip && !tpm_try_get_ops(chip))
108 res = chip;
109 }
92 110
93 rcu_read_lock(); 111 mutex_unlock(&idr_lock);
94 list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
95 if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
96 continue;
97 112
98 /* rcu prevents chip from being free'd */ 113 return res;
99 if (!tpm_try_get_ops(pos))
100 chip = pos;
101 break;
102 }
103 rcu_read_unlock();
104 return chip;
105} 114}
106 115
107/** 116/**
@@ -114,9 +123,10 @@ static void tpm_dev_release(struct device *dev)
114{ 123{
115 struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); 124 struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
116 125
117 spin_lock(&driver_lock); 126 mutex_lock(&idr_lock);
118 clear_bit(chip->dev_num, dev_mask); 127 idr_remove(&dev_nums_idr, chip->dev_num);
119 spin_unlock(&driver_lock); 128 mutex_unlock(&idr_lock);
129
120 kfree(chip); 130 kfree(chip);
121} 131}
122 132
@@ -142,21 +152,18 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
142 152
143 mutex_init(&chip->tpm_mutex); 153 mutex_init(&chip->tpm_mutex);
144 init_rwsem(&chip->ops_sem); 154 init_rwsem(&chip->ops_sem);
145 INIT_LIST_HEAD(&chip->list);
146 155
147 chip->ops = ops; 156 chip->ops = ops;
148 157
149 spin_lock(&driver_lock); 158 mutex_lock(&idr_lock);
150 chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); 159 rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
151 spin_unlock(&driver_lock); 160 mutex_unlock(&idr_lock);
152 161 if (rc < 0) {
153 if (chip->dev_num >= TPM_NUM_DEVICES) {
154 dev_err(dev, "No available tpm device numbers\n"); 162 dev_err(dev, "No available tpm device numbers\n");
155 kfree(chip); 163 kfree(chip);
156 return ERR_PTR(-ENOMEM); 164 return ERR_PTR(rc);
157 } 165 }
158 166 chip->dev_num = rc;
159 set_bit(chip->dev_num, dev_mask);
160 167
161 device_initialize(&chip->dev); 168 device_initialize(&chip->dev);
162 169
@@ -242,19 +249,28 @@ static int tpm_add_char_device(struct tpm_chip *chip)
242 return rc; 249 return rc;
243 } 250 }
244 251
252 /* Make the chip available. */
253 mutex_lock(&idr_lock);
254 idr_replace(&dev_nums_idr, chip, chip->dev_num);
255 mutex_unlock(&idr_lock);
256
245 return rc; 257 return rc;
246} 258}
247 259
248static void tpm_del_char_device(struct tpm_chip *chip) 260static void tpm_del_char_device(struct tpm_chip *chip)
249{ 261{
250 cdev_del(&chip->cdev); 262 cdev_del(&chip->cdev);
263 device_del(&chip->dev);
264
265 /* Make the chip unavailable. */
266 mutex_lock(&idr_lock);
267 idr_replace(&dev_nums_idr, NULL, chip->dev_num);
268 mutex_unlock(&idr_lock);
251 269
252 /* Make the driver uncallable. */ 270 /* Make the driver uncallable. */
253 down_write(&chip->ops_sem); 271 down_write(&chip->ops_sem);
254 chip->ops = NULL; 272 chip->ops = NULL;
255 up_write(&chip->ops_sem); 273 up_write(&chip->ops_sem);
256
257 device_del(&chip->dev);
258} 274}
259 275
260static int tpm1_chip_register(struct tpm_chip *chip) 276static int tpm1_chip_register(struct tpm_chip *chip)
@@ -309,11 +325,6 @@ int tpm_chip_register(struct tpm_chip *chip)
309 if (rc) 325 if (rc)
310 goto out_err; 326 goto out_err;
311 327
312 /* Make the chip available. */
313 spin_lock(&driver_lock);
314 list_add_tail_rcu(&chip->list, &tpm_chip_list);
315 spin_unlock(&driver_lock);
316
317 chip->flags |= TPM_CHIP_FLAG_REGISTERED; 328 chip->flags |= TPM_CHIP_FLAG_REGISTERED;
318 329
319 if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { 330 if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
@@ -350,11 +361,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
350 if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED)) 361 if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
351 return; 362 return;
352 363
353 spin_lock(&driver_lock);
354 list_del_rcu(&chip->list);
355 spin_unlock(&driver_lock);
356 synchronize_rcu();
357
358 if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) 364 if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
359 sysfs_remove_link(&chip->dev.parent->kobj, "ppi"); 365 sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
360 366
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 5caf15421ef7..5397b64b6c96 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1139,6 +1139,7 @@ static int __init tpm_init(void)
1139 1139
1140static void __exit tpm_exit(void) 1140static void __exit tpm_exit(void)
1141{ 1141{
1142 idr_destroy(&dev_nums_idr);
1142 class_destroy(tpm_class); 1143 class_destroy(tpm_class);
1143 unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); 1144 unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
1144} 1145}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 5fcf7885a4b9..928b47f58771 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -34,7 +34,7 @@
34enum tpm_const { 34enum tpm_const {
35 TPM_MINOR = 224, /* officially assigned */ 35 TPM_MINOR = 224, /* officially assigned */
36 TPM_BUFSIZE = 4096, 36 TPM_BUFSIZE = 4096,
37 TPM_NUM_DEVICES = 256, 37 TPM_NUM_DEVICES = 65536,
38 TPM_RETRY = 50, /* 5 seconds */ 38 TPM_RETRY = 50, /* 5 seconds */
39}; 39};
40 40
@@ -195,8 +195,6 @@ struct tpm_chip {
195 acpi_handle acpi_dev_handle; 195 acpi_handle acpi_dev_handle;
196 char ppi_version[TPM_PPI_VERSION_LEN + 1]; 196 char ppi_version[TPM_PPI_VERSION_LEN + 1];
197#endif /* CONFIG_ACPI */ 197#endif /* CONFIG_ACPI */
198
199 struct list_head list;
200}; 198};
201 199
202#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) 200#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -492,6 +490,7 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
492extern struct class *tpm_class; 490extern struct class *tpm_class;
493extern dev_t tpm_devt; 491extern dev_t tpm_devt;
494extern const struct file_operations tpm_fops; 492extern const struct file_operations tpm_fops;
493extern struct idr dev_nums_idr;
495 494
496ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); 495ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
497ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, 496ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,