Skip to content

Commit f7e0f7f

Browse files
stefanbergergregkh
authored andcommitted
tpm: Replace device number bitmap with IDR
commit 15516788e581eb32ec1c50e5f00aba3faf95d817 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 7e78922 commit f7e0f7f

3 files changed

Lines changed: 49 additions & 42 deletions

File tree

drivers/char/tpm/tpm-chip.c

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
#include "tpm.h"
3030
#include "tpm_eventlog.h"
3131

32-
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
33-
static LIST_HEAD(tpm_chip_list);
34-
static DEFINE_SPINLOCK(driver_lock);
32+
DEFINE_IDR(dev_nums_idr);
33+
static DEFINE_MUTEX(idr_lock);
3534

3635
struct class *tpm_class;
3736
dev_t tpm_devt;
@@ -92,20 +91,30 @@ EXPORT_SYMBOL_GPL(tpm_put_ops);
9291
*/
9392
struct tpm_chip *tpm_chip_find_get(int chip_num)
9493
{
95-
struct tpm_chip *pos, *chip = NULL;
94+
struct tpm_chip *chip, *res = NULL;
95+
int chip_prev;
96+
97+
mutex_lock(&idr_lock);
98+
99+
if (chip_num == TPM_ANY_NUM) {
100+
chip_num = 0;
101+
do {
102+
chip_prev = chip_num;
103+
chip = idr_get_next(&dev_nums_idr, &chip_num);
104+
if (chip && !tpm_try_get_ops(chip)) {
105+
res = chip;
106+
break;
107+
}
108+
} while (chip_prev != chip_num);
109+
} else {
110+
chip = idr_find_slowpath(&dev_nums_idr, chip_num);
111+
if (chip && !tpm_try_get_ops(chip))
112+
res = chip;
113+
}
96114

97-
rcu_read_lock();
98-
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
99-
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
100-
continue;
115+
mutex_unlock(&idr_lock);
101116

102-
/* rcu prevents chip from being free'd */
103-
if (!tpm_try_get_ops(pos))
104-
chip = pos;
105-
break;
106-
}
107-
rcu_read_unlock();
108-
return chip;
117+
return res;
109118
}
110119

111120
/**
@@ -118,9 +127,10 @@ static void tpm_dev_release(struct device *dev)
118127
{
119128
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
120129

121-
spin_lock(&driver_lock);
122-
clear_bit(chip->dev_num, dev_mask);
123-
spin_unlock(&driver_lock);
130+
mutex_lock(&idr_lock);
131+
idr_remove(&dev_nums_idr, chip->dev_num);
132+
mutex_unlock(&idr_lock);
133+
124134
kfree(chip);
125135
}
126136

@@ -173,28 +183,26 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
173183
const struct tpm_class_ops *ops)
174184
{
175185
struct tpm_chip *chip;
186+
int rc;
176187

177188
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
178189
if (chip == NULL)
179190
return ERR_PTR(-ENOMEM);
180191

181192
mutex_init(&chip->tpm_mutex);
182193
init_rwsem(&chip->ops_sem);
183-
INIT_LIST_HEAD(&chip->list);
184194

185195
chip->ops = ops;
186196

187-
spin_lock(&driver_lock);
188-
chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
189-
spin_unlock(&driver_lock);
190-
191-
if (chip->dev_num >= TPM_NUM_DEVICES) {
197+
mutex_lock(&idr_lock);
198+
rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
199+
mutex_unlock(&idr_lock);
200+
if (rc < 0) {
192201
dev_err(dev, "No available tpm device numbers\n");
193202
kfree(chip);
194-
return ERR_PTR(-ENOMEM);
203+
return ERR_PTR(rc);
195204
}
196-
197-
set_bit(chip->dev_num, dev_mask);
205+
chip->dev_num = rc;
198206

199207
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
200208

@@ -252,19 +260,28 @@ static int tpm_add_char_device(struct tpm_chip *chip)
252260
return rc;
253261
}
254262

263+
/* Make the chip available. */
264+
mutex_lock(&idr_lock);
265+
idr_replace(&dev_nums_idr, chip, chip->dev_num);
266+
mutex_unlock(&idr_lock);
267+
255268
return rc;
256269
}
257270

258271
static void tpm_del_char_device(struct tpm_chip *chip)
259272
{
260273
cdev_del(&chip->cdev);
274+
device_del(&chip->dev);
275+
276+
/* Make the chip unavailable. */
277+
mutex_lock(&idr_lock);
278+
idr_replace(&dev_nums_idr, NULL, chip->dev_num);
279+
mutex_unlock(&idr_lock);
261280

262281
/* Make the driver uncallable. */
263282
down_write(&chip->ops_sem);
264283
chip->ops = NULL;
265284
up_write(&chip->ops_sem);
266-
267-
device_del(&chip->dev);
268285
}
269286

270287
static int tpm1_chip_register(struct tpm_chip *chip)
@@ -319,11 +336,6 @@ int tpm_chip_register(struct tpm_chip *chip)
319336
if (rc)
320337
goto out_err;
321338

322-
/* Make the chip available. */
323-
spin_lock(&driver_lock);
324-
list_add_tail_rcu(&chip->list, &tpm_chip_list);
325-
spin_unlock(&driver_lock);
326-
327339
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
328340

329341
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
@@ -360,11 +372,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
360372
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
361373
return;
362374

363-
spin_lock(&driver_lock);
364-
list_del_rcu(&chip->list);
365-
spin_unlock(&driver_lock);
366-
synchronize_rcu();
367-
368375
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
369376
sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
370377

drivers/char/tpm/tpm-interface.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,7 @@ static int __init tpm_init(void)
11271127

11281128
static void __exit tpm_exit(void)
11291129
{
1130+
idr_destroy(&dev_nums_idr);
11301131
class_destroy(tpm_class);
11311132
unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
11321133
}

drivers/char/tpm/tpm.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
enum tpm_const {
3535
TPM_MINOR = 224, /* officially assigned */
3636
TPM_BUFSIZE = 4096,
37-
TPM_NUM_DEVICES = 256,
37+
TPM_NUM_DEVICES = 65536,
3838
TPM_RETRY = 50, /* 5 seconds */
3939
};
4040

@@ -200,8 +200,6 @@ struct tpm_chip {
200200
acpi_handle acpi_dev_handle;
201201
char ppi_version[TPM_PPI_VERSION_LEN + 1];
202202
#endif /* CONFIG_ACPI */
203-
204-
struct list_head list;
205203
};
206204

207205
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -497,6 +495,7 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
497495
extern struct class *tpm_class;
498496
extern dev_t tpm_devt;
499497
extern const struct file_operations tpm_fops;
498+
extern struct idr dev_nums_idr;
500499

501500
enum tpm_transmit_flags {
502501
TPM_TRANSMIT_UNLOCKED = BIT(0),

0 commit comments

Comments
 (0)