From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To: tpmdd-devel@lists.sourceforge.net
Cc: jarkko.sakkinen@linux.intel.com, jgunthorpe@obsidianresearch.com,
linux-security-module@vger.kernel.org,
linux-kernel@vger.kernel.org,
Stefan Berger <stefanb@linux.vnet.ibm.com>
Subject: [PATCH v8 06/10] tpm: Replace device number bitmap with IDR
Date: Sun, 13 Mar 2016 18:54:36 -0400 [thread overview]
Message-ID: <1457909680-14085-7-git-send-email-stefanb@linux.vnet.ibm.com> (raw)
In-Reply-To: <1457909680-14085-1-git-send-email-stefanb@linux.vnet.ibm.com>
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>
---
drivers/char/tpm/tpm-chip.c | 84 +++++++++++++++++++++-------------------
drivers/char/tpm/tpm-interface.c | 1 +
drivers/char/tpm/tpm.h | 5 +--
3 files changed, 48 insertions(+), 42 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 5880377..f62c851 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -29,9 +29,8 @@
#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);
+DEFINE_IDR(dev_nums_idr);
+static DEFINE_MUTEX(idr_lock);
struct class *tpm_class;
dev_t tpm_devt;
@@ -88,20 +87,30 @@ EXPORT_SYMBOL_GPL(tpm_put_ops);
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
{
- struct tpm_chip *pos, *chip = NULL;
+ struct tpm_chip *chip, *res = NULL;
+ int chip_prev;
+
+ mutex_lock(&idr_lock);
+
+ if (chip_num == TPM_ANY_NUM) {
+ chip_num = 0;
+ do {
+ chip_prev = chip_num;
+ chip = idr_get_next(&dev_nums_idr, &chip_num);
+ if (chip && !tpm_try_get_ops(chip)) {
+ res = chip;
+ break;
+ }
+ } while (chip_prev != chip_num);
+ } else {
+ chip = idr_find_slowpath(&dev_nums_idr, chip_num);
+ if (chip && !tpm_try_get_ops(chip))
+ res = chip;
+ }
- 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;
+ mutex_unlock(&idr_lock);
- /* rcu prevents chip from being free'd */
- if (!tpm_try_get_ops(pos))
- chip = pos;
- break;
- }
- rcu_read_unlock();
- return chip;
+ return res;
}
/**
@@ -114,9 +123,10 @@ static void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
- spin_lock(&driver_lock);
- clear_bit(chip->dev_num, dev_mask);
- spin_unlock(&driver_lock);
+ mutex_lock(&idr_lock);
+ idr_remove(&dev_nums_idr, chip->dev_num);
+ mutex_unlock(&idr_lock);
+
kfree(chip);
}
@@ -142,21 +152,18 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
mutex_init(&chip->tpm_mutex);
init_rwsem(&chip->ops_sem);
- INIT_LIST_HEAD(&chip->list);
chip->ops = ops;
- spin_lock(&driver_lock);
- chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
- spin_unlock(&driver_lock);
-
- if (chip->dev_num >= TPM_NUM_DEVICES) {
+ mutex_lock(&idr_lock);
+ rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
+ mutex_unlock(&idr_lock);
+ if (rc < 0) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
- return ERR_PTR(-ENOMEM);
+ return ERR_PTR(rc);
}
-
- set_bit(chip->dev_num, dev_mask);
+ chip->dev_num = rc;
device_initialize(&chip->dev);
@@ -242,19 +249,28 @@ static int tpm_add_char_device(struct tpm_chip *chip)
return rc;
}
+ /* Make the chip available. */
+ mutex_lock(&idr_lock);
+ idr_replace(&dev_nums_idr, chip, chip->dev_num);
+ mutex_unlock(&idr_lock);
+
return rc;
}
static void tpm_del_char_device(struct tpm_chip *chip)
{
cdev_del(&chip->cdev);
+ device_del(&chip->dev);
+
+ /* Make the chip unavailable. */
+ mutex_lock(&idr_lock);
+ idr_replace(&dev_nums_idr, NULL, chip->dev_num);
+ mutex_unlock(&idr_lock);
/* Make the driver uncallable. */
down_write(&chip->ops_sem);
chip->ops = NULL;
up_write(&chip->ops_sem);
-
- device_del(&chip->dev);
}
static int tpm1_chip_register(struct tpm_chip *chip)
@@ -309,11 +325,6 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
goto out_err;
- /* Make the chip available. */
- spin_lock(&driver_lock);
- list_add_tail_rcu(&chip->list, &tpm_chip_list);
- spin_unlock(&driver_lock);
-
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
@@ -350,11 +361,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
return;
- spin_lock(&driver_lock);
- list_del_rcu(&chip->list);
- spin_unlock(&driver_lock);
- synchronize_rcu();
-
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 5caf154..5397b64 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)
static void __exit tpm_exit(void)
{
+ idr_destroy(&dev_nums_idr);
class_destroy(tpm_class);
unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 5fcf788..928b47f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -34,7 +34,7 @@
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 4096,
- TPM_NUM_DEVICES = 256,
+ TPM_NUM_DEVICES = 65536,
TPM_RETRY = 50, /* 5 seconds */
};
@@ -195,8 +195,6 @@ struct tpm_chip {
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
-
- struct list_head list;
};
#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)
extern struct class *tpm_class;
extern dev_t tpm_devt;
extern const struct file_operations tpm_fops;
+extern struct idr dev_nums_idr;
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
--
2.4.3
next prev parent reply other threads:[~2016-03-13 22:55 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-13 22:54 [PATCH v8 00/10] Multi-instance vTPM proxy driver Stefan Berger
2016-03-13 22:54 ` [PATCH v8 01/10] tpm: Get rid of chip->pdev Stefan Berger
2016-03-13 22:54 ` [PATCH v8 02/10] tpm: Get rid of devname Stefan Berger
2016-03-13 22:54 ` [PATCH v8 03/10] tpm: Provide strong locking for device removal Stefan Berger
2016-03-13 22:54 ` [PATCH v8 04/10] tpm: Get rid of module locking Stefan Berger
2016-03-13 22:54 ` [PATCH v8 05/10] tpm: Split out the devm stuff from tpmm_chip_alloc Stefan Berger
2016-03-13 22:54 ` Stefan Berger [this message]
2016-03-15 5:58 ` [PATCH v8 06/10] tpm: Replace device number bitmap with IDR Jarkko Sakkinen
2016-03-13 22:54 ` [PATCH v8 07/10] tpm: Introduce TPM_CHIP_FLAG_VIRTUAL Stefan Berger
2016-03-13 22:54 ` [PATCH v8 08/10] tpm: Proxy driver for supporting multiple emulated TPMs Stefan Berger
2016-03-14 16:26 ` Jarkko Sakkinen
2016-03-16 12:09 ` Jarkko Sakkinen
2016-03-16 13:49 ` Stefan Berger
2016-03-16 17:49 ` Jason Gunthorpe
2016-03-16 20:37 ` Jarkko Sakkinen
2016-03-16 20:42 ` Jarkko Sakkinen
2016-03-17 17:45 ` Stefan Berger
2016-03-18 8:52 ` Jarkko Sakkinen
2016-03-18 13:06 ` Jarkko Sakkinen
2016-03-13 22:54 ` [PATCH v8 09/10] tpm: Initialize TPM and get durations and timeouts Stefan Berger
2016-03-22 6:34 ` [v8,09/10] " Jarkko Sakkinen
2016-03-22 10:54 ` Stefan Berger
2016-03-29 15:31 ` [v8,09/10] tpm: Initialize TPM and get durations and timeoutsg Jarkko Sakkinen
2016-03-29 15:53 ` Stefan Berger
2016-03-13 22:54 ` [PATCH v8 10/10] tpm: Add documentation for the tpm_vtpm device driver Stefan Berger
2016-03-29 16:24 ` [PATCH v8 00/10] Multi-instance vTPM proxy driver Jarkko Sakkinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1457909680-14085-7-git-send-email-stefanb@linux.vnet.ibm.com \
--to=stefanb@linux.vnet.ibm.com \
--cc=jarkko.sakkinen@linux.intel.com \
--cc=jgunthorpe@obsidianresearch.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=tpmdd-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).