* [PATCH v5 01/11] tpm: Get rid of chip->pdev
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 02/11] tpm: Get rid of devname Stefan Berger
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
This is a hold over from before the struct device conversion.
- All prints should be using &chip->dev, which is the Linux
standard. This changes prints to use tpm0 as the device name,
not the PnP/etc ID.
- The few places involving sysfs/modules that really do need the
parent just use chip->dev.parent instead
- We no longer need to get_device(pdev) in any places since it is no
longer used by any of the code. The kref on the parent is held
by the device core during device_add and dropped in device_del
Signed-off-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Tested-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/char/tpm/tpm-chip.c | 15 ++++++---------
drivers/char/tpm/tpm-dev.c | 4 +---
drivers/char/tpm/tpm-interface.c | 30 ++++++++++++++++--------------
drivers/char/tpm/tpm-sysfs.c | 6 +++---
drivers/char/tpm/tpm.h | 3 +--
drivers/char/tpm/tpm2-cmd.c | 8 ++++----
drivers/char/tpm/tpm_atmel.c | 14 +++++++-------
drivers/char/tpm/tpm_i2c_atmel.c | 16 ++++++++--------
drivers/char/tpm/tpm_i2c_infineon.c | 6 +++---
drivers/char/tpm/tpm_i2c_nuvoton.c | 22 +++++++++++-----------
drivers/char/tpm/tpm_infineon.c | 22 +++++++++++-----------
drivers/char/tpm/tpm_nsc.c | 20 ++++++++++----------
drivers/char/tpm/tpm_tis.c | 16 ++++++++--------
13 files changed, 89 insertions(+), 93 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 274dd01..12829dd 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -49,7 +49,7 @@ struct tpm_chip *tpm_chip_find_get(int chip_num)
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
continue;
- if (try_module_get(pos->pdev->driver->owner)) {
+ if (try_module_get(pos->dev.parent->driver->owner)) {
chip = pos;
break;
}
@@ -113,13 +113,11 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
- chip->pdev = dev;
-
dev_set_drvdata(dev, chip);
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
- chip->dev.parent = chip->pdev;
+ chip->dev.parent = dev;
#ifdef CONFIG_ACPI
chip->dev.groups = chip->groups;
#endif
@@ -134,7 +132,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
device_initialize(&chip->dev);
cdev_init(&chip->cdev, &tpm_fops);
- chip->cdev.owner = chip->pdev->driver->owner;
+ chip->cdev.owner = dev->driver->owner;
chip->cdev.kobj.parent = &chip->dev.kobj;
rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
@@ -241,9 +239,8 @@ int tpm_chip_register(struct tpm_chip *chip)
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
- rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
- &chip->dev.kobj,
- "ppi");
+ rc = __compat_only_sysfs_link_entry_to_kobj(
+ &chip->dev.parent->kobj, &chip->dev.kobj, "ppi");
if (rc && rc != -ENOENT) {
tpm_chip_unregister(chip);
return rc;
@@ -278,7 +275,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
synchronize_rcu();
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
- sysfs_remove_link(&chip->pdev->kobj, "ppi");
+ sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
tpm1_chip_unregister(chip);
tpm_del_char_device(chip);
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index de0337e..4009765 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -61,7 +61,7 @@ static int tpm_open(struct inode *inode, struct file *file)
* by the check of is_open variable, which is protected
* by driver_lock. */
if (test_and_set_bit(0, &chip->is_open)) {
- dev_dbg(chip->pdev, "Another process owns this TPM\n");
+ dev_dbg(&chip->dev, "Another process owns this TPM\n");
return -EBUSY;
}
@@ -79,7 +79,6 @@ static int tpm_open(struct inode *inode, struct file *file)
INIT_WORK(&priv->work, timeout_work);
file->private_data = priv;
- get_device(chip->pdev);
return 0;
}
@@ -166,7 +165,6 @@ static int tpm_release(struct inode *inode, struct file *file)
file->private_data = NULL;
atomic_set(&priv->data_pending, 0);
clear_bit(0, &priv->chip->is_open);
- put_device(priv->chip->pdev);
kfree(priv);
return 0;
}
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e2fa89c..483f86f 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -345,7 +345,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"invalid count value %x %zx\n", count, bufsiz);
return -E2BIG;
}
@@ -354,7 +354,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
rc = chip->ops->send(chip, (u8 *) buf, count);
if (rc < 0) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
@@ -373,7 +373,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
goto out_recv;
if (chip->ops->req_canceled(chip, status)) {
- dev_err(chip->pdev, "Operation Canceled\n");
+ dev_err(&chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
}
@@ -383,14 +383,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
} while (time_before(jiffies, stop));
chip->ops->cancel(chip);
- dev_err(chip->pdev, "Operation Timed out\n");
+ dev_err(&chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
out:
mutex_unlock(&chip->tpm_mutex);
@@ -416,7 +416,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd,
err = be32_to_cpu(header->return_code);
if (err != 0 && desc)
- dev_err(chip->pdev, "A TPM error (%d) occurred %s\n", err,
+ dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
desc);
return err;
@@ -527,7 +527,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
if (rc == TPM_ERR_INVALID_POSTINIT) {
/* The TPM is not started, we are the first to talk to it.
Execute a startup command. */
- dev_info(chip->pdev, "Issuing TPM_STARTUP");
+ dev_info(&chip->dev, "Issuing TPM_STARTUP");
if (tpm_startup(chip, TPM_ST_CLEAR))
return rc;
@@ -539,7 +539,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
NULL);
}
if (rc) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"A TPM error (%zd) occurred attempting to determine the timeouts\n",
rc);
goto duration;
@@ -578,7 +578,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
/* Report adjusted timeouts */
if (chip->vendor.timeout_adjusted) {
- dev_info(chip->pdev,
+ dev_info(&chip->dev,
HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
old_timeout[0], new_timeout[0],
old_timeout[1], new_timeout[1],
@@ -625,7 +625,7 @@ duration:
chip->vendor.duration[TPM_MEDIUM] *= 1000;
chip->vendor.duration[TPM_LONG] *= 1000;
chip->vendor.duration_adjusted = true;
- dev_info(chip->pdev, "Adjusting TPM timeout parameters.");
+ dev_info(&chip->dev, "Adjusting TPM timeout parameters.");
}
return 0;
}
@@ -815,7 +815,9 @@ int tpm_do_selftest(struct tpm_chip *chip)
* around 300ms while the self test is ongoing, keep trying
* until the self test duration expires. */
if (rc == -ETIME) {
- dev_info(chip->pdev, HW_ERR "TPM command timed out during continue self test");
+ dev_info(
+ &chip->dev, HW_ERR
+ "TPM command timed out during continue self test");
msleep(delay_msec);
continue;
}
@@ -825,7 +827,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
rc = be32_to_cpu(cmd.header.out.return_code);
if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
- dev_info(chip->pdev,
+ dev_info(&chip->dev,
"TPM is disabled/deactivated (0x%X)\n", rc);
/* TPM is disabled and/or deactivated; driver can
* proceed and TPM does handle commands for
@@ -978,10 +980,10 @@ int tpm_pm_suspend(struct device *dev)
}
if (rc)
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"Error (%d) sending savestate before suspend\n", rc);
else if (try > 0)
- dev_warn(chip->pdev, "TPM savestate took %dms\n",
+ dev_warn(&chip->dev, "TPM savestate took %dms\n",
try * TPM_TIMEOUT_RETRY);
return rc;
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index ee66fd4..d93736a 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -284,16 +284,16 @@ static const struct attribute_group tpm_dev_group = {
int tpm_sysfs_add_device(struct tpm_chip *chip)
{
int err;
- err = sysfs_create_group(&chip->pdev->kobj,
+ err = sysfs_create_group(&chip->dev.parent->kobj,
&tpm_dev_group);
if (err)
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"failed to create sysfs attributes, %d\n", err);
return err;
}
void tpm_sysfs_del_device(struct tpm_chip *chip)
{
- sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group);
+ sysfs_remove_group(&chip->dev.parent->kobj, &tpm_dev_group);
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 28b477e..9c9be6c 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -167,7 +167,6 @@ enum tpm_chip_flags {
};
struct tpm_chip {
- struct device *pdev; /* Device stuff */
struct device dev;
struct cdev cdev;
@@ -199,7 +198,7 @@ struct tpm_chip {
static inline void tpm_chip_put(struct tpm_chip *chip)
{
- module_put(chip->pdev->driver->owner);
+ module_put(chip->dev.parent->driver->owner);
}
static inline int tpm_read_index(int base, int index)
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index b28e4da..5fc0e7c 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -597,7 +597,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
if (rc) {
- dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n",
+ dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
handle);
return;
}
@@ -606,7 +606,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
if (rc)
- dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle,
+ dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
rc);
tpm_buf_destroy(&buf);
@@ -770,7 +770,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
* except print the error code on a system failure.
*/
if (rc < 0)
- dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
+ dev_warn(&chip->dev, "transmit returned %d while stopping the TPM",
rc);
}
EXPORT_SYMBOL_GPL(tpm2_shutdown);
@@ -837,7 +837,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
* immediately. This is a workaround for that.
*/
if (rc == TPM2_RC_TESTING) {
- dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n");
+ dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n");
rc = 0;
}
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index dfadad0..a48a878 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -49,7 +49,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
for (i = 0; i < 6; i++) {
status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
- dev_err(chip->pdev, "error reading header\n");
+ dev_err(&chip->dev, "error reading header\n");
return -EIO;
}
*buf++ = ioread8(chip->vendor.iobase);
@@ -60,12 +60,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size = be32_to_cpu(*native_size);
if (count < size) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */
status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
- dev_err(chip->pdev, "error reading data\n");
+ dev_err(&chip->dev, "error reading data\n");
return -EIO;
}
}
@@ -76,7 +76,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
for (; i < size; i++) {
status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
- dev_err(chip->pdev, "error reading data\n");
+ dev_err(&chip->dev, "error reading data\n");
return -EIO;
}
*buf++ = ioread8(chip->vendor.iobase);
@@ -86,7 +86,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
status = ioread8(chip->vendor.iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) {
- dev_err(chip->pdev, "data available is stuck\n");
+ dev_err(&chip->dev, "data available is stuck\n");
return -EIO;
}
@@ -97,9 +97,9 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
int i;
- dev_dbg(chip->pdev, "tpm_atml_send:\n");
+ dev_dbg(&chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) {
- dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
+ dev_dbg(&chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
iowrite8(buf[i], chip->vendor.iobase);
}
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
index 8dfb88b..dd8f0eb 100644
--- a/drivers/char/tpm/tpm_i2c_atmel.c
+++ b/drivers/char/tpm/tpm_i2c_atmel.c
@@ -52,7 +52,7 @@ struct priv_data {
static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct priv_data *priv = chip->vendor.priv;
- struct i2c_client *client = to_i2c_client(chip->pdev);
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
priv->len = 0;
@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
status = i2c_master_send(client, buf, len);
- dev_dbg(chip->pdev,
+ dev_dbg(&chip->dev,
"%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
(int)min_t(size_t, 64, len), buf, len, status);
return status;
@@ -71,7 +71,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct priv_data *priv = chip->vendor.priv;
- struct i2c_client *client = to_i2c_client(chip->pdev);
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
struct tpm_output_header *hdr =
(struct tpm_output_header *)priv->buffer;
u32 expected_len;
@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -ENOMEM;
if (priv->len >= expected_len) {
- dev_dbg(chip->pdev,
+ dev_dbg(&chip->dev,
"%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count,
expected_len);
@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
}
rc = i2c_master_recv(client, buf, expected_len);
- dev_dbg(chip->pdev,
+ dev_dbg(&chip->dev,
"%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count,
expected_len);
@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static void i2c_atmel_cancel(struct tpm_chip *chip)
{
- dev_err(chip->pdev, "TPM operation cancellation was requested, but is not supported");
+ dev_err(&chip->dev, "TPM operation cancellation was requested, but is not supported");
}
static u8 i2c_atmel_read_status(struct tpm_chip *chip)
{
struct priv_data *priv = chip->vendor.priv;
- struct i2c_client *client = to_i2c_client(chip->pdev);
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
int rc;
/* The TPM fails the I2C read until it is ready, so we do the entire
@@ -125,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip)
/* Once the TPM has completed the command the command remains readable
* until another command is issued. */
rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
- dev_dbg(chip->pdev,
+ dev_dbg(&chip->dev,
"%s: sts=%d", __func__, rc);
if (rc <= 0)
return 0;
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 63d5d22..f2aa99e 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -446,7 +446,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read first 10 bytes, including tag, paramsize, and result */
size = recv_data(chip, buf, TPM_HEADER_SIZE);
if (size < TPM_HEADER_SIZE) {
- dev_err(chip->pdev, "Unable to read header\n");
+ dev_err(&chip->dev, "Unable to read header\n");
goto out;
}
@@ -459,14 +459,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size += recv_data(chip, &buf[TPM_HEADER_SIZE],
expected - TPM_HEADER_SIZE);
if (size < expected) {
- dev_err(chip->pdev, "Unable to read remainder of result\n");
+ dev_err(&chip->dev, "Unable to read remainder of result\n");
size = -ETIME;
goto out;
}
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
- dev_err(chip->pdev, "Error left over data\n");
+ dev_err(&chip->dev, "Error left over data\n");
size = -EIO;
goto out;
}
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
index 847f159..a1e1474 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -96,13 +96,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size,
/* read TPM_STS register */
static u8 i2c_nuvoton_read_status(struct tpm_chip *chip)
{
- struct i2c_client *client = to_i2c_client(chip->pdev);
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
u8 data;
status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data);
if (status <= 0) {
- dev_err(chip->pdev, "%s() error return %d\n", __func__,
+ dev_err(&chip->dev, "%s() error return %d\n", __func__,
status);
data = TPM_STS_ERR_VAL;
}
@@ -127,13 +127,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data)
/* write commandReady to TPM_STS register */
static void i2c_nuvoton_ready(struct tpm_chip *chip)
{
- struct i2c_client *client = to_i2c_client(chip->pdev);
+ struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
/* this causes the current command to be aborted */
status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY);
if (status < 0)
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"%s() fail to write TPM_STS.commandReady\n", __func__);
}
@@ -212,7 +212,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
return 0;
} while (time_before(jiffies, stop));
}
- dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
+ dev_err(&chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
value);
return -ETIMEDOUT;
}
@@ -240,7 +240,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
&chip->vendor.read_queue) == 0) {
burst_count = i2c_nuvoton_get_burstcount(client, chip);
if (burst_count < 0) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"%s() fail to read burstCount=%d\n", __func__,
burst_count);
return -EIO;
@@ -249,12 +249,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R,
bytes2read, &buf[size]);
if (rc < 0) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"%s() fail on i2c_nuvoton_read_buf()=%d\n",
__func__, rc);
return -EIO;
}
- dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read);
+ dev_dbg(&chip->dev, "%s(%d):", __func__, bytes2read);
size += bytes2read;
}
@@ -264,7 +264,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
/* Read TPM command results */
static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
- struct device *dev = chip->pdev;
+ struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
s32 rc;
int expected, status, burst_count, retries, size = 0;
@@ -334,7 +334,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
break;
}
i2c_nuvoton_ready(chip);
- dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size);
+ dev_dbg(&chip->dev, "%s() -> %d\n", __func__, size);
return size;
}
@@ -347,7 +347,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
*/
static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
- struct device *dev = chip->pdev;
+ struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 6c488e6..e3cf9f3 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
}
if (i == TPM_MAX_TRIES) { /* timeout occurs */
if (wait_for_bit == STAT_XFE)
- dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n");
+ dev_err(&chip->dev, "Timeout in wait(STAT_XFE)\n");
if (wait_for_bit == STAT_RDA)
- dev_err(chip->pdev, "Timeout in wait(STAT_RDA)\n");
+ dev_err(&chip->dev, "Timeout in wait(STAT_RDA)\n");
return -EIO;
}
return 0;
@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
static void tpm_wtx(struct tpm_chip *chip)
{
number_of_wtx++;
- dev_info(chip->pdev, "Granting WTX (%02d / %02d)\n",
+ dev_info(&chip->dev, "Granting WTX (%02d / %02d)\n",
number_of_wtx, TPM_MAX_WTX_PACKAGES);
wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX);
@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip)
static void tpm_wtx_abort(struct tpm_chip *chip)
{
- dev_info(chip->pdev, "Aborting WTX\n");
+ dev_info(&chip->dev, "Aborting WTX\n");
wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX_ABORT);
wait_and_send(chip, 0x00);
@@ -257,7 +257,7 @@ recv_begin:
}
if (buf[0] != TPM_VL_VER) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"Wrong transport protocol implementation!\n");
return -EIO;
}
@@ -272,7 +272,7 @@ recv_begin:
}
if ((size == 0x6D00) && (buf[1] == 0x80)) {
- dev_err(chip->pdev, "Error handling on vendor layer!\n");
+ dev_err(&chip->dev, "Error handling on vendor layer!\n");
return -EIO;
}
@@ -284,7 +284,7 @@ recv_begin:
}
if (buf[1] == TPM_CTRL_WTX) {
- dev_info(chip->pdev, "WTX-package received\n");
+ dev_info(&chip->dev, "WTX-package received\n");
if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
tpm_wtx(chip);
goto recv_begin;
@@ -295,14 +295,14 @@ recv_begin:
}
if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
- dev_info(chip->pdev, "WTX-abort acknowledged\n");
+ dev_info(&chip->dev, "WTX-abort acknowledged\n");
return size;
}
if (buf[1] == TPM_CTRL_ERROR) {
- dev_err(chip->pdev, "ERROR-package received:\n");
+ dev_err(&chip->dev, "ERROR-package received:\n");
if (buf[4] == TPM_INF_NAK)
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"-> Negative acknowledgement"
" - retransmit command!\n");
return -EIO;
@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
ret = empty_fifo(chip, 1);
if (ret) {
- dev_err(chip->pdev, "Timeout while clearing FIFO\n");
+ dev_err(&chip->dev, "Timeout while clearing FIFO\n");
return -EIO;
}
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 289389e..766370b 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -113,7 +113,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
}
while (time_before(jiffies, stop));
- dev_info(chip->pdev, "wait for ready failed\n");
+ dev_info(&chip->dev, "wait for ready failed\n");
return -EBUSY;
}
@@ -129,12 +129,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
- dev_err(chip->pdev, "F0 timeout\n");
+ dev_err(&chip->dev, "F0 timeout\n");
return -EIO;
}
if ((data =
inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
- dev_err(chip->pdev, "not in normal mode (0x%x)\n",
+ dev_err(&chip->dev, "not in normal mode (0x%x)\n",
data);
return -EIO;
}
@@ -143,7 +143,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
for (p = buffer; p < &buffer[count]; p++) {
if (wait_for_stat
(chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"OBF timeout (while reading data)\n");
return -EIO;
}
@@ -154,11 +154,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
if ((data & NSC_STATUS_F0) == 0 &&
(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
- dev_err(chip->pdev, "F0 not set\n");
+ dev_err(&chip->dev, "F0 not set\n");
return -EIO;
}
if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"expected end of command(0x%x)\n", data);
return -EIO;
}
@@ -189,19 +189,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
return -EIO;
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
- dev_err(chip->pdev, "IBF timeout\n");
+ dev_err(&chip->dev, "IBF timeout\n");
return -EIO;
}
outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
- dev_err(chip->pdev, "IBR timeout\n");
+ dev_err(&chip->dev, "IBR timeout\n");
return -EIO;
}
for (i = 0; i < count; i++) {
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
- dev_err(chip->pdev,
+ dev_err(&chip->dev,
"IBF timeout (while writing data)\n");
return -EIO;
}
@@ -209,7 +209,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
- dev_err(chip->pdev, "IBF timeout\n");
+ dev_err(&chip->dev, "IBF timeout\n");
return -EIO;
}
outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index a507006..0a9aee9 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -260,7 +260,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read first 10 bytes, including tag, paramsize, and result */
if ((size =
recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
- dev_err(chip->pdev, "Unable to read header\n");
+ dev_err(&chip->dev, "Unable to read header\n");
goto out;
}
@@ -273,7 +273,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
if ((size +=
recv_data(chip, &buf[TPM_HEADER_SIZE],
expected - TPM_HEADER_SIZE)) < expected) {
- dev_err(chip->pdev, "Unable to read remainder of result\n");
+ dev_err(&chip->dev, "Unable to read remainder of result\n");
size = -ETIME;
goto out;
}
@@ -282,7 +282,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
&chip->vendor.int_queue, false);
status = tpm_tis_status(chip);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
- dev_err(chip->pdev, "Error left over data\n");
+ dev_err(&chip->dev, "Error left over data\n");
size = -EIO;
goto out;
}
@@ -368,7 +368,7 @@ static void disable_interrupts(struct tpm_chip *chip)
iowrite32(intmask,
chip->vendor.iobase +
TPM_INT_ENABLE(chip->vendor.locality));
- devm_free_irq(chip->pdev, chip->vendor.irq, chip);
+ devm_free_irq(&chip->dev, chip->vendor.irq, chip);
chip->vendor.irq = 0;
}
@@ -497,7 +497,7 @@ static int probe_itpm(struct tpm_chip *chip)
rc = tpm_tis_send_data(chip, cmd_getticks, len);
if (rc == 0) {
- dev_info(chip->pdev, "Detected an iTPM.\n");
+ dev_info(&chip->dev, "Detected an iTPM.\n");
rc = 1;
} else
rc = -EFAULT;
@@ -576,9 +576,9 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
struct priv_data *priv = chip->vendor.priv;
u8 original_int_vec;
- if (devm_request_irq(chip->pdev, irq, tis_int_handler, flags,
+ if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
chip->devname, chip) != 0) {
- dev_info(chip->pdev, "Unable to request irq: %d for probe\n",
+ dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
irq);
return -1;
}
@@ -779,7 +779,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
tpm_info->irq);
if (!chip->vendor.irq)
- dev_err(chip->pdev, FW_BUG
+ dev_err(&chip->dev, FW_BUG
"TPM interrupt not working, polling instead\n");
} else
tpm_tis_probe_irq(chip, intmask);
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 02/11] tpm: Get rid of devname
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2016-03-07 12:25 ` [PATCH v5 01/11] tpm: Get rid of chip->pdev Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 03/11] tpm: Provide strong locking for device removal Stefan Berger
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Now that we have a proper struct device just use dev_name() to
access this value instead of keeping two copies.
Signed-off-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/char/tpm/tpm-chip.c | 18 +++++++++++-------
drivers/char/tpm/tpm.h | 1 -
drivers/char/tpm/tpm_eventlog.c | 2 +-
drivers/char/tpm/tpm_eventlog.h | 2 +-
drivers/char/tpm/tpm_i2c_nuvoton.c | 2 +-
drivers/char/tpm/tpm_tis.c | 2 +-
6 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 12829dd..c21d81c 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -111,7 +111,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
set_bit(chip->dev_num, dev_mask);
- scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
+ device_initialize(&chip->dev);
dev_set_drvdata(dev, chip);
@@ -127,9 +127,9 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
else
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
- dev_set_name(&chip->dev, "%s", chip->devname);
-
- device_initialize(&chip->dev);
+ rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
+ if (rc)
+ goto out;
cdev_init(&chip->cdev, &tpm_fops);
chip->cdev.owner = dev->driver->owner;
@@ -142,6 +142,10 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
}
return chip;
+
+out:
+ put_device(&chip->dev);
+ return ERR_PTR(rc);
}
EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
@@ -153,7 +157,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
if (rc) {
dev_err(&chip->dev,
"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
- chip->devname, MAJOR(chip->dev.devt),
+ dev_name(&chip->dev), MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc);
return rc;
@@ -163,7 +167,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
if (rc) {
dev_err(&chip->dev,
"unable to device_register() %s, major %d, minor %d, err=%d\n",
- chip->devname, MAJOR(chip->dev.devt),
+ dev_name(&chip->dev), MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc);
cdev_del(&chip->cdev);
@@ -190,7 +194,7 @@ static int tpm1_chip_register(struct tpm_chip *chip)
if (rc)
return rc;
- chip->bios_dir = tpm_bios_log_setup(chip->devname);
+ chip->bios_dir = tpm_bios_log_setup(dev_name(&chip->dev));
return 0;
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 9c9be6c..5d33ba5 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -174,7 +174,6 @@ struct tpm_chip {
unsigned int flags;
int dev_num; /* /dev/tpm# */
- char devname[7];
unsigned long is_open; /* only one allowed */
int time_expired;
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c
index 4e6940a..e722886 100644
--- a/drivers/char/tpm/tpm_eventlog.c
+++ b/drivers/char/tpm/tpm_eventlog.c
@@ -403,7 +403,7 @@ static int is_bad(void *p)
return 0;
}
-struct dentry **tpm_bios_log_setup(char *name)
+struct dentry **tpm_bios_log_setup(const char *name)
{
struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
index 267bfbd..cc9672f 100644
--- a/drivers/char/tpm/tpm_eventlog.h
+++ b/drivers/char/tpm/tpm_eventlog.h
@@ -77,7 +77,7 @@ int read_log(struct tpm_bios_log *log);
#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
defined(CONFIG_ACPI)
-extern struct dentry **tpm_bios_log_setup(char *);
+extern struct dentry **tpm_bios_log_setup(const char *);
extern void tpm_bios_log_teardown(struct dentry **);
#else
static inline struct dentry **tpm_bios_log_setup(char *name)
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
index a1e1474..d61d43f 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -560,7 +560,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
rc = devm_request_irq(dev, chip->vendor.irq,
i2c_nuvoton_int_handler,
IRQF_TRIGGER_LOW,
- chip->devname,
+ dev_name(&chip->dev),
chip);
if (rc) {
dev_err(dev, "%s() Unable to request irq: %d for use\n",
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 0a9aee9..eed3bf5 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -577,7 +577,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
u8 original_int_vec;
if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
- chip->devname, chip) != 0) {
+ dev_name(&chip->dev), chip) != 0) {
dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
irq);
return -1;
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 03/11] tpm: Provide strong locking for device removal
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2016-03-07 12:25 ` [PATCH v5 01/11] tpm: Get rid of chip->pdev Stefan Berger
2016-03-07 12:25 ` [PATCH v5 02/11] tpm: Get rid of devname Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 04/11] tpm: Get rid of module locking Stefan Berger
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Add a read/write semaphore around the ops function pointers so
ops can be set to null when the driver un-registers.
Previously the tpm core expected module locking to be enough to
ensure that tpm_unregister could not be called during certain times,
however that hasn't been sufficient for a long time.
Introduce a read/write semaphore around 'ops' so the core can set
it to null when unregistering. This provides a strong fence around
the driver callbacks, guaranteeing to the driver that no callbacks
are running or will run again.
For now the ops_lock is placed very high in the call stack, it could
be pushed down and made more granular in future if necessary.
Signed-off-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Reviewed-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/char/tpm/tpm-chip.c | 72 ++++++++++++++++++++++++++++++++++++----
drivers/char/tpm/tpm-dev.c | 11 +++++-
drivers/char/tpm/tpm-interface.c | 19 ++++++-----
drivers/char/tpm/tpm-sysfs.c | 5 +++
drivers/char/tpm/tpm.h | 14 +++++---
5 files changed, 100 insertions(+), 21 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index c21d81c..5793ea1 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -36,10 +36,60 @@ 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
+/**
+ * tpm_try_get_ops() - Get a ref to the tpm_chip
+ * @chip: Chip to ref
+ *
+ * The caller must already have some kind of locking to ensure that chip is
+ * valid. This function will lock the chip so that the ops member can be
+ * accessed safely. The locking prevents tpm_chip_unregister from
+ * completing, so it should not be held for long periods.
+ *
+ * Returns -ERRNO if the chip could not be got.
*/
+int tpm_try_get_ops(struct tpm_chip *chip)
+{
+ int rc = -EIO;
+
+ get_device(&chip->dev);
+
+ down_read(&chip->ops_sem);
+ if (!chip->ops)
+ goto out_lock;
+
+ if (!try_module_get(chip->dev.parent->driver->owner))
+ goto out_lock;
+
+ return 0;
+out_lock:
+ up_read(&chip->ops_sem);
+ put_device(&chip->dev);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_try_get_ops);
+
+/**
+ * tpm_put_ops() - Release a ref to the tpm_chip
+ * @chip: Chip to put
+ *
+ * This is the opposite pair to tpm_try_get_ops(). After this returns chip may
+ * be kfree'd.
+ */
+void tpm_put_ops(struct tpm_chip *chip)
+{
+ module_put(chip->dev.parent->driver->owner);
+ up_read(&chip->ops_sem);
+ put_device(&chip->dev);
+}
+EXPORT_SYMBOL_GPL(tpm_put_ops);
+
+/**
+ * tpm_chip_find_get() - return tpm_chip for a given chip number
+ * @chip_num: id to find
+ *
+ * The return'd chip has been tpm_try_get_ops'd and must be released via
+ * tpm_put_ops
+ */
struct tpm_chip *tpm_chip_find_get(int chip_num)
{
struct tpm_chip *pos, *chip = NULL;
@@ -49,10 +99,10 @@ struct tpm_chip *tpm_chip_find_get(int chip_num)
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
continue;
- if (try_module_get(pos->dev.parent->driver->owner)) {
+ /* rcu prevents chip from being free'd */
+ if (!tpm_try_get_ops(pos))
chip = pos;
- break;
- }
+ break;
}
rcu_read_unlock();
return chip;
@@ -95,6 +145,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
return ERR_PTR(-ENOMEM);
mutex_init(&chip->tpm_mutex);
+ init_rwsem(&chip->ops_sem);
INIT_LIST_HEAD(&chip->list);
chip->ops = ops;
@@ -180,6 +231,12 @@ static int tpm_add_char_device(struct tpm_chip *chip)
static void tpm_del_char_device(struct tpm_chip *chip)
{
cdev_del(&chip->cdev);
+
+ /* Make the driver uncallable. */
+ down_write(&chip->ops_sem);
+ chip->ops = NULL;
+ up_write(&chip->ops_sem);
+
device_del(&chip->dev);
}
@@ -265,6 +322,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
* Takes the chip first away from the list of available TPM chips and then
* cleans up all the resources reserved by tpm_chip_register().
*
+ * Once this function returns the driver call backs in 'op's will not be
+ * running and will no longer start.
+ *
* NOTE: This function should be only called before deinitializing chip
* resources.
*/
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 4009765..f5d4521 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -136,9 +136,18 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
return -EFAULT;
}
- /* atomic tpm command send and result receive */
+ /* atomic tpm command send and result receive. We only hold the ops
+ * lock during this period so that the tpm can be unregistered even if
+ * the char dev is held open.
+ */
+ if (tpm_try_get_ops(priv->chip)) {
+ mutex_unlock(&priv->buffer_mutex);
+ return -EPIPE;
+ }
out_size = tpm_transmit(priv->chip, priv->data_buffer,
sizeof(priv->data_buffer));
+
+ tpm_put_ops(priv->chip);
if (out_size < 0) {
mutex_unlock(&priv->buffer_mutex);
return out_size;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 483f86f..5caf154 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -700,7 +700,7 @@ int tpm_is_tpm2(u32 chip_num)
rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return rc;
}
@@ -729,7 +729,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
else
rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf);
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_pcr_read);
@@ -764,7 +764,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
rc = tpm2_pcr_extend(chip, pcr_idx, hash);
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return rc;
}
@@ -774,7 +774,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
"attempting extend a PCR value");
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_pcr_extend);
@@ -855,7 +855,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_send);
@@ -1037,7 +1037,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
err = tpm2_get_random(chip, out, max);
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return err;
}
@@ -1059,7 +1059,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
num_bytes -= recd;
} while (retries-- && total < max);
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return total ? total : -EIO;
}
EXPORT_SYMBOL_GPL(tpm_get_random);
@@ -1085,7 +1085,7 @@ int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
rc = tpm2_seal_trusted(chip, payload, options);
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_seal_trusted);
@@ -1111,7 +1111,8 @@ int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
rc = tpm2_unseal_trusted(chip, payload, options);
- tpm_chip_put(chip);
+ tpm_put_ops(chip);
+
return rc;
}
EXPORT_SYMBOL_GPL(tpm_unseal_trusted);
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index d93736a..34e7fc7 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -295,5 +295,10 @@ int tpm_sysfs_add_device(struct tpm_chip *chip)
void tpm_sysfs_del_device(struct tpm_chip *chip)
{
+ /* The sysfs routines rely on an implicit tpm_try_get_ops, this
+ * function is called before ops is null'd and the sysfs core
+ * synchronizes this removal so that no callbacks are running or can
+ * run again
+ */
sysfs_remove_group(&chip->dev.parent->kobj, &tpm_dev_group);
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 5d33ba5..c6376b1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -170,7 +170,13 @@ struct tpm_chip {
struct device dev;
struct cdev cdev;
+ /* A driver callback under ops cannot be run unless ops_sem is held
+ * (sometimes implicitly, eg for the sysfs code). ops becomes null
+ * when the driver is unregistered, see tpm_try_get_ops.
+ */
+ struct rw_semaphore ops_sem;
const struct tpm_class_ops *ops;
+
unsigned int flags;
int dev_num; /* /dev/tpm# */
@@ -195,11 +201,6 @@ struct tpm_chip {
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
-static inline void tpm_chip_put(struct tpm_chip *chip)
-{
- module_put(chip->dev.parent->driver->owner);
-}
-
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
@@ -507,6 +508,9 @@ extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
wait_queue_head_t *, bool);
struct tpm_chip *tpm_chip_find_get(int chip_num);
+__must_check int tpm_try_get_ops(struct tpm_chip *chip);
+void tpm_put_ops(struct tpm_chip *chip);
+
extern struct tpm_chip *tpmm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops);
extern int tpm_chip_register(struct tpm_chip *chip);
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 04/11] tpm: Get rid of module locking
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (2 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 03/11] tpm: Provide strong locking for device removal Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 05/11] tpm: Split out the devm stuff from tpmm_chip_alloc Stefan Berger
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Now that the tpm core has strong locking around 'ops' it is possible
to remove a TPM driver, module and all, even while user space still
has things like /dev/tpmX open. For consistency and simplicity, drop
the module locking entirely.
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/char/tpm/tpm-chip.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 5793ea1..6636728 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -57,9 +57,6 @@ int tpm_try_get_ops(struct tpm_chip *chip)
if (!chip->ops)
goto out_lock;
- if (!try_module_get(chip->dev.parent->driver->owner))
- goto out_lock;
-
return 0;
out_lock:
up_read(&chip->ops_sem);
@@ -77,7 +74,6 @@ EXPORT_SYMBOL_GPL(tpm_try_get_ops);
*/
void tpm_put_ops(struct tpm_chip *chip)
{
- module_put(chip->dev.parent->driver->owner);
up_read(&chip->ops_sem);
put_device(&chip->dev);
}
@@ -183,7 +179,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
goto out;
cdev_init(&chip->cdev, &tpm_fops);
- chip->cdev.owner = dev->driver->owner;
+ chip->cdev.owner = THIS_MODULE;
chip->cdev.kobj.parent = &chip->dev.kobj;
rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 05/11] tpm: Split out the devm stuff from tpmm_chip_alloc
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (3 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 04/11] tpm: Get rid of module locking Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 06/11] tpm: Replace device number bitmap with IDR Stefan Berger
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
From: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
tpm_chip_alloc becomes a typical subsystem allocate call.
Signed-off-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Reviewed-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Tested-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/char/tpm/tpm-chip.c | 49 ++++++++++++++++++++++++++++++++-------------
drivers/char/tpm/tpm.h | 4 +++-
2 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 6636728..5880377 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -121,17 +121,17 @@ static void tpm_dev_release(struct device *dev)
}
/**
- * tpmm_chip_alloc() - allocate a new struct tpm_chip instance
- * @dev: device to which the chip is associated
+ * tpm_chip_alloc() - allocate a new struct tpm_chip instance
+ * @pdev: device to which the chip is associated
+ * At this point pdev mst be initialized, but does not have to
+ * be registered
* @ops: struct tpm_class_ops instance
*
* Allocates a new struct tpm_chip instance and assigns a free
- * device number for it. Caller does not have to worry about
- * freeing the allocated resources. When the devices is removed
- * devres calls tpmm_chip_remove() to do the job.
+ * device number for it. Must be paired with put_device(&chip->dev).
*/
-struct tpm_chip *tpmm_chip_alloc(struct device *dev,
- const struct tpm_class_ops *ops)
+struct tpm_chip *tpm_chip_alloc(struct device *dev,
+ const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
int rc;
@@ -160,8 +160,6 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
device_initialize(&chip->dev);
- dev_set_drvdata(dev, chip);
-
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
chip->dev.parent = dev;
@@ -182,17 +180,40 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
chip->cdev.owner = THIS_MODULE;
chip->cdev.kobj.parent = &chip->dev.kobj;
- rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
+ return chip;
+
+out:
+ put_device(&chip->dev);
+ return ERR_PTR(rc);
+}
+EXPORT_SYMBOL_GPL(tpm_chip_alloc);
+
+/**
+ * tpmm_chip_alloc() - allocate a new struct tpm_chip instance
+ * @pdev: parent device to which the chip is associated
+ * @ops: struct tpm_class_ops instance
+ *
+ * Same as tpm_chip_alloc except devm is used to do the put_device
+ */
+struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
+ const struct tpm_class_ops *ops)
+{
+ struct tpm_chip *chip;
+ int rc;
+
+ chip = tpm_chip_alloc(pdev, ops);
+ if (IS_ERR(chip))
+ return chip;
+
+ rc = devm_add_action(pdev, (void (*)(void *)) put_device, &chip->dev);
if (rc) {
put_device(&chip->dev);
return ERR_PTR(rc);
}
- return chip;
+ dev_set_drvdata(pdev, chip);
-out:
- put_device(&chip->dev);
- return ERR_PTR(rc);
+ return chip;
}
EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index c6376b1..5fcf788 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -511,7 +511,9 @@ struct tpm_chip *tpm_chip_find_get(int chip_num);
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);
-extern struct tpm_chip *tpmm_chip_alloc(struct device *dev,
+extern struct tpm_chip *tpm_chip_alloc(struct device *dev,
+ const struct tpm_class_ops *ops);
+extern struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops);
extern int tpm_chip_register(struct tpm_chip *chip);
extern void tpm_chip_unregister(struct tpm_chip *chip);
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 06/11] tpm: Replace device number bitmap with IDR
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (4 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 05/11] tpm: Split out the devm stuff from tpmm_chip_alloc Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 07/11] tpm: Introduce TPM_CHIP_FLAG_VIRTUAL Stefan Berger
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
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-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
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
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 07/11] tpm: Introduce TPM_CHIP_FLAG_VIRTUAL
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (5 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 06/11] tpm: Replace device number bitmap with IDR Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 08/11] tpm: Driver for supporting multiple emulated TPMs Stefan Berger
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Introduce TPM_CHIP_FLAG_VIRTUAL to be used when the chip device has no
parent device. Also adapt tpm_chip_alloc so that it can be called with
parent device being NULL.
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Reviewed-by: Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
drivers/char/tpm/tpm-chip.c | 9 +++++----
drivers/char/tpm/tpm-sysfs.c | 15 +++++++++++----
drivers/char/tpm/tpm.h | 5 +++--
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index f62c851..e4e1fad 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -170,9 +170,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
chip->dev.parent = dev;
-#ifdef CONFIG_ACPI
chip->dev.groups = chip->groups;
-#endif
if (chip->dev_num == 0)
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
@@ -183,6 +181,9 @@ struct tpm_chip *tpm_chip_alloc(struct device *dev,
if (rc)
goto out;
+ if (!dev)
+ chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
+
cdev_init(&chip->cdev, &tpm_fops);
chip->cdev.owner = THIS_MODULE;
chip->cdev.kobj.parent = &chip->dev.kobj;
@@ -327,7 +328,7 @@ int tpm_chip_register(struct tpm_chip *chip)
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
- if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
+ if (!(chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL))) {
rc = __compat_only_sysfs_link_entry_to_kobj(
&chip->dev.parent->kobj, &chip->dev.kobj, "ppi");
if (rc && rc != -ENOENT) {
@@ -361,7 +362,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
return;
- if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+ if (!(chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL)))
sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
tpm1_chip_unregister(chip);
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 34e7fc7..9ee0f4d 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -283,9 +283,15 @@ static const struct attribute_group tpm_dev_group = {
int tpm_sysfs_add_device(struct tpm_chip *chip)
{
- int err;
- err = sysfs_create_group(&chip->dev.parent->kobj,
- &tpm_dev_group);
+ int err = 0;
+
+ if (!(chip->flags & TPM_CHIP_FLAG_VIRTUAL))
+ err = sysfs_create_group(&chip->dev.parent->kobj,
+ &tpm_dev_group);
+ else {
+ dev_set_drvdata(&chip->dev, chip);
+ chip->groups[chip->groups_cnt++] = &tpm_dev_group;
+ }
if (err)
dev_err(&chip->dev,
@@ -300,5 +306,6 @@ void tpm_sysfs_del_device(struct tpm_chip *chip)
* synchronizes this removal so that no callbacks are running or can
* run again
*/
- sysfs_remove_group(&chip->dev.parent->kobj, &tpm_dev_group);
+ if (!(chip->flags & TPM_CHIP_FLAG_VIRTUAL))
+ sysfs_remove_group(&chip->dev.parent->kobj, &tpm_dev_group);
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 928b47f..f197eef 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -164,6 +164,7 @@ struct tpm_vendor_specific {
enum tpm_chip_flags {
TPM_CHIP_FLAG_REGISTERED = BIT(0),
TPM_CHIP_FLAG_TPM2 = BIT(1),
+ TPM_CHIP_FLAG_VIRTUAL = BIT(2),
};
struct tpm_chip {
@@ -189,9 +190,9 @@ struct tpm_chip {
struct dentry **bios_dir;
-#ifdef CONFIG_ACPI
- const struct attribute_group *groups[2];
+ const struct attribute_group *groups[3];
unsigned int groups_cnt;
+#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 08/11] tpm: Driver for supporting multiple emulated TPMs
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (6 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 07/11] tpm: Introduce TPM_CHIP_FLAG_VIRTUAL Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 09/11] tpm: Initialize TPM and get durations and timeouts Stefan Berger
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA,
jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/, Stefan Berger,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA
This patch implements a driver for supporting multiple emulated TPMs in a
system.
The driver implements a device /dev/vtpmx that is used to created
a client device pair /dev/tpmX (e.g., /dev/tpm10) and a server side that
is accessed using a file descriptor returned by an ioctl.
The device /dev/tpmX is the usual TPM device created by the core TPM
driver. Applications or kernel subsystems can send TPM commands to it
and the corresponding server-side file descriptor receives these
commands and delivers them to an emulated TPM.
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
CC: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
drivers/char/tpm/Kconfig | 10 +
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/tpm_vtpm.c | 566 ++++++++++++++++++++++++++++++++++++++++++++
include/uapi/linux/Kbuild | 1 +
include/uapi/linux/vtpm.h | 41 ++++
5 files changed, 619 insertions(+)
create mode 100644 drivers/char/tpm/tpm_vtpm.c
create mode 100644 include/uapi/linux/vtpm.h
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 3b84a8b..4c4e843 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -122,5 +122,15 @@ config TCG_CRB
from within Linux. To compile this driver as a module, choose
M here; the module will be called tpm_crb.
+config TCG_VTPM
+ tristate "VTPM Interface"
+ depends on TCG_TPM
+ ---help---
+ This driver supports an emulated TPM (vTPM) running in userspace.
+ A device /dev/vtpmx is provided that creates a device pair
+ /dev/vtpmX and a server-side file descriptor on which the vTPM
+ can receive commands.
+
+
source "drivers/char/tpm/st33zp24/Kconfig"
endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 56e8f1f..1a409c57 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -23,3 +23,4 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
+obj-$(CONFIG_TCG_VTPM) += tpm_vtpm.o
diff --git a/drivers/char/tpm/tpm_vtpm.c b/drivers/char/tpm/tpm_vtpm.c
new file mode 100644
index 0000000..245ce91
--- /dev/null
+++ b/drivers/char/tpm/tpm_vtpm.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2015, 2016 IBM Corporation
+ *
+ * Author: Stefan Berger <stefanb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+ *
+ * Device driver for vTPM.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/miscdevice.h>
+#include <linux/vtpm.h>
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
+#include <linux/poll.h>
+#include <linux/compat.h>
+
+#include "tpm.h"
+
+#define VTPM_REQ_COMPLETE_FLAG BIT(0)
+
+struct vtpm_dev {
+ struct tpm_chip *chip;
+
+ u32 flags; /* public API flags */
+
+ wait_queue_head_t wq;
+
+ struct mutex buf_lock; /* protect buffer and flags */
+
+ long state; /* internal state */
+#define STATE_OPENED_FLAG BIT(0)
+#define STATE_WAIT_RESPONSE_FLAG BIT(1) /* waiting for emulator response */
+
+ size_t req_len; /* length of queued TPM request */
+ size_t resp_len; /* length of queued TPM response */
+ u8 buffer[TPM_BUFSIZE]; /* request/response buffer */
+};
+
+
+static void vtpm_delete_device(struct vtpm_dev *vtpm_dev);
+
+/*
+ * Functions related to 'server side'
+ */
+
+/**
+ * vtpm_fops_read - Read TPM commands on 'server side'
+ *
+ * Return value:
+ * Number of bytes read or negative error code
+ */
+static ssize_t vtpm_fops_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct vtpm_dev *vtpm_dev = filp->private_data;
+ size_t len;
+ int sig, rc;
+
+ sig = wait_event_interruptible(vtpm_dev->wq, vtpm_dev->req_len != 0);
+ if (sig)
+ return -EINTR;
+
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ len = vtpm_dev->req_len;
+
+ if (count < len) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ pr_debug("Invalid size in recv: count=%zd, req_len=%zd\n",
+ count, len);
+ return -EIO;
+ }
+
+ rc = copy_to_user(buf, vtpm_dev->buffer, len);
+ memset(vtpm_dev->buffer, 0, len);
+ vtpm_dev->req_len = 0;
+
+ if (!rc)
+ vtpm_dev->state |= STATE_WAIT_RESPONSE_FLAG;
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ if (rc)
+ return -EFAULT;
+
+ return len;
+}
+
+/**
+ * vtpm_fops_write - Write TPM responses on 'server side'
+ *
+ * Return value:
+ * Number of bytes read or negative error value
+ */
+static ssize_t vtpm_fops_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ struct vtpm_dev *vtpm_dev = filp->private_data;
+
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ if (count > sizeof(vtpm_dev->buffer) ||
+ !(vtpm_dev->state & STATE_WAIT_RESPONSE_FLAG)) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ return -EIO;
+ }
+
+ vtpm_dev->state &= ~STATE_WAIT_RESPONSE_FLAG;
+
+ vtpm_dev->req_len = 0;
+
+ if (copy_from_user(vtpm_dev->buffer, buf, count)) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ return -EFAULT;
+ }
+
+ vtpm_dev->resp_len = count;
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ wake_up_interruptible(&vtpm_dev->wq);
+
+ return count;
+}
+
+/*
+ * vtpm_fops_poll: Poll status on 'server side'
+ *
+ * Return value:
+ * Poll flags
+ */
+static unsigned int vtpm_fops_poll(struct file *filp, poll_table *wait)
+{
+ struct vtpm_dev *vtpm_dev = filp->private_data;
+ unsigned ret;
+
+ poll_wait(filp, &vtpm_dev->wq, wait);
+
+ ret = POLLOUT;
+
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ if (vtpm_dev->req_len)
+ ret |= POLLIN | POLLRDNORM;
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ return ret;
+}
+
+/*
+ * vtpm_fops_open - Open vTPM device on 'server side'
+ *
+ * Called when setting up the anonymous file descriptor
+ */
+static void vtpm_fops_open(struct file *filp)
+{
+ struct vtpm_dev *vtpm_dev = filp->private_data;
+
+ vtpm_dev->state |= STATE_OPENED_FLAG;
+}
+
+/**
+ * vtpm_fops_undo_open - counter-part to vtpm_fops_open
+ *
+ * Call to undo vtpm_fops_open
+ */
+static void vtpm_fops_undo_open(struct vtpm_dev *vtpm_dev)
+{
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ vtpm_dev->state &= ~STATE_OPENED_FLAG;
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ /* no more TPM responses -- wake up anyone waiting for them */
+ wake_up_interruptible(&vtpm_dev->wq);
+}
+
+/*
+ * vtpm_fops_release: Close 'server side'
+ *
+ * Return value:
+ * Always returns 0.
+ */
+static int vtpm_fops_release(struct inode *inode, struct file *filp)
+{
+ struct vtpm_dev *vtpm_dev = filp->private_data;
+
+ filp->private_data = NULL;
+
+ vtpm_delete_device(vtpm_dev);
+
+ return 0;
+}
+
+static const struct file_operations vtpm_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = vtpm_fops_read,
+ .write = vtpm_fops_write,
+ .poll = vtpm_fops_poll,
+ .release = vtpm_fops_release,
+};
+
+/*
+ * Functions invoked by the core TPM driver to send TPM commands to
+ * 'server side' and receive responses from there.
+ */
+
+/*
+ * Called when core TPM driver reads TPM responses from 'server side'
+ *
+ * Return value:
+ * Number of TPM response bytes read, negative error value otherwise
+ */
+static int vtpm_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ struct vtpm_dev *vtpm_dev = chip->vendor.priv;
+ size_t len;
+
+ if (!vtpm_dev)
+ return -EIO;
+
+ /* process gone ? */
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ if (!(vtpm_dev->state & STATE_OPENED_FLAG)) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ return -EPIPE;
+ }
+
+ len = vtpm_dev->resp_len;
+ if (count < len) {
+ dev_err(&chip->dev,
+ "Invalid size in recv: count=%zd, resp_len=%zd\n",
+ count, len);
+ len = -EIO;
+ goto out;
+ }
+
+ memcpy(buf, vtpm_dev->buffer, len);
+ vtpm_dev->resp_len = 0;
+
+out:
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ return len;
+}
+
+/*
+ * Called when core TPM driver forwards TPM requests to 'server side'.
+ *
+ * Return value:
+ * 0 in case of success, negative error value otherwise.
+ */
+static int vtpm_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+ struct vtpm_dev *vtpm_dev = chip->vendor.priv;
+ int rc = 0;
+
+ if (!vtpm_dev)
+ return -EIO;
+
+ if (count > sizeof(vtpm_dev->buffer)) {
+ dev_err(&chip->dev,
+ "Invalid size in send: count=%zd, buffer size=%zd\n",
+ count, sizeof(vtpm_dev->buffer));
+ return -EIO;
+ }
+
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ if (!(vtpm_dev->state & STATE_OPENED_FLAG)) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ return -EPIPE;
+ }
+
+ vtpm_dev->resp_len = 0;
+
+ vtpm_dev->req_len = count;
+ memcpy(vtpm_dev->buffer, buf, count);
+
+ vtpm_dev->state &= ~STATE_WAIT_RESPONSE_FLAG;
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ wake_up_interruptible(&vtpm_dev->wq);
+
+ return rc;
+}
+
+static void vtpm_tpm_op_cancel(struct tpm_chip *chip)
+{
+ /* not supported */
+}
+
+static u8 vtpm_tpm_op_status(struct tpm_chip *chip)
+{
+ struct vtpm_dev *vtpm_dev = chip->vendor.priv;
+
+ if (vtpm_dev->resp_len)
+ return VTPM_REQ_COMPLETE_FLAG;
+
+ return 0;
+}
+
+static bool vtpm_tpm_req_canceled(struct tpm_chip *chip, u8 status)
+{
+ struct vtpm_dev *vtpm_dev = chip->vendor.priv;
+ bool ret;
+
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ ret = !(vtpm_dev->state & STATE_OPENED_FLAG);
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
+ return ret;
+}
+
+static const struct tpm_class_ops vtpm_tpm_ops = {
+ .recv = vtpm_tpm_op_recv,
+ .send = vtpm_tpm_op_send,
+ .cancel = vtpm_tpm_op_cancel,
+ .status = vtpm_tpm_op_status,
+ .req_complete_mask = VTPM_REQ_COMPLETE_FLAG,
+ .req_complete_val = VTPM_REQ_COMPLETE_FLAG,
+ .req_canceled = vtpm_tpm_req_canceled,
+};
+
+/*
+ * Code related to creation and deletion of device pairs
+ */
+static struct vtpm_dev *vtpm_create_vtpm_dev(void)
+{
+ struct vtpm_dev *vtpm_dev;
+ struct tpm_chip *chip;
+ int err;
+
+ vtpm_dev = kzalloc(sizeof(*vtpm_dev), GFP_KERNEL);
+ if (vtpm_dev == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ init_waitqueue_head(&vtpm_dev->wq);
+ mutex_init(&vtpm_dev->buf_lock);
+
+ chip = tpm_chip_alloc(NULL, &vtpm_tpm_ops);
+ if (IS_ERR(chip)) {
+ err = PTR_ERR(chip);
+ goto err_vtpm_dev_free;
+ }
+ chip->vendor.priv = vtpm_dev;
+
+ vtpm_dev->chip = chip;
+
+ return vtpm_dev;
+
+err_vtpm_dev_free:
+ kfree(vtpm_dev);
+
+ return ERR_PTR(err);
+}
+
+/*
+ * Undo what has been done in vtpm_create_vtpm_dev
+ */
+static inline void vtpm_delete_vtpm_dev(struct vtpm_dev *vtpm_dev)
+{
+ put_device(&vtpm_dev->chip->dev); /* frees chip */
+ kfree(vtpm_dev);
+}
+
+/*
+ * Create a /dev/tpm%d and 'server side' file descriptor pair
+ *
+ * Return value:
+ * Returns file pointer on success, an error value otherwise
+ */
+static struct file *vtpm_create_device(
+ struct vtpm_new_dev *vtpm_new_dev)
+{
+ struct vtpm_dev *vtpm_dev;
+ int rc, fd;
+ struct file *file;
+
+ if (vtpm_new_dev->flags & ~VTPM_FLAGS_ALL)
+ return ERR_PTR(-ENOSYS);
+
+ vtpm_dev = vtpm_create_vtpm_dev();
+ if (IS_ERR(vtpm_dev))
+ return ERR_CAST(vtpm_dev);
+
+ vtpm_dev->flags = vtpm_new_dev->flags;
+
+ /* setup an anonymous file for the server-side */
+ fd = get_unused_fd_flags(O_RDWR);
+ if (fd < 0) {
+ rc = fd;
+ goto err_delete_vtpm_dev;
+ }
+
+ file = anon_inode_getfile("[vtpms]", &vtpm_fops, vtpm_dev, O_RDWR);
+ if (IS_ERR(file)) {
+ rc = PTR_ERR(file);
+ goto err_put_unused_fd;
+ }
+
+ /* from now on we can unwind with put_unused_fd() + fput() */
+ /* simulate an open() on the server side */
+ vtpm_fops_open(file);
+
+ if (vtpm_dev->flags & VTPM_FLAG_TPM2)
+ vtpm_dev->chip->flags |= TPM_CHIP_FLAG_TPM2;
+
+ rc = tpm_chip_register(vtpm_dev->chip);
+ if (rc)
+ goto err_vtpm_fput;
+
+ vtpm_new_dev->fd = fd;
+ vtpm_new_dev->major = MAJOR(vtpm_dev->chip->dev.devt);
+ vtpm_new_dev->minor = MINOR(vtpm_dev->chip->dev.devt);
+ vtpm_new_dev->dev_num = vtpm_dev->chip->dev_num;
+
+ return file;
+
+err_vtpm_fput:
+ put_unused_fd(fd);
+ fput(file);
+
+ return ERR_PTR(rc);
+
+err_put_unused_fd:
+ put_unused_fd(fd);
+
+err_delete_vtpm_dev:
+ vtpm_delete_vtpm_dev(vtpm_dev);
+
+ return ERR_PTR(rc);
+}
+
+/*
+ * Counter part to vtpm_create_device.
+ */
+static void vtpm_delete_device(struct vtpm_dev *vtpm_dev)
+{
+ tpm_chip_unregister(vtpm_dev->chip);
+
+ vtpm_fops_undo_open(vtpm_dev);
+
+ vtpm_delete_vtpm_dev(vtpm_dev);
+}
+
+/*
+ * Code related to the control device /dev/vtpmx
+ */
+
+/*
+ * vtpmx_fops_ioctl: ioctl on /dev/vtpmx
+ *
+ * Return value:
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct vtpm_new_dev *vtpm_new_dev_p;
+ struct vtpm_new_dev vtpm_new_dev;
+ struct file *file;
+
+ switch (ioctl) {
+ case VTPM_NEW_DEV:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ vtpm_new_dev_p = argp;
+ if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p,
+ sizeof(vtpm_new_dev)))
+ return -EFAULT;
+ file = vtpm_create_device(&vtpm_new_dev);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+ if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev,
+ sizeof(vtpm_new_dev))) {
+ put_unused_fd(vtpm_new_dev.fd);
+ fput(file);
+ return -EFAULT;
+ }
+
+ fd_install(vtpm_new_dev.fd, file);
+ return 0;
+
+ default:
+ return -ENOSYS;
+ }
+}
+
+#ifdef CONFIG_COMPAT
+static long vtpmx_fops_compat_ioctl(struct file *f, unsigned int ioctl,
+ unsigned long arg)
+{
+ return vtpmx_fops_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations vtpmx_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = vtpmx_fops_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = vtpmx_fops_compat_ioctl,
+#endif
+ .llseek = noop_llseek,
+};
+
+static struct miscdevice vtpmx_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "vtpmx",
+ .fops = &vtpmx_fops,
+};
+
+static int vtpmx_init(void)
+{
+ return misc_register(&vtpmx_miscdev);
+}
+
+static void vtpmx_cleanup(void)
+{
+ misc_deregister(&vtpmx_miscdev);
+}
+
+static int __init vtpm_module_init(void)
+{
+ int rc;
+
+ rc = vtpmx_init();
+ if (rc) {
+ pr_err("couldn't create vtpmx device\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit vtpm_module_exit(void)
+{
+ vtpmx_cleanup();
+}
+
+module_init(vtpm_module_init);
+module_exit(vtpm_module_exit);
+
+MODULE_AUTHOR("Stefan Berger (stefanb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org)");
+MODULE_DESCRIPTION("vTPM Driver");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index ebd10e6..3a602c9 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -449,6 +449,7 @@ header-y += virtio_scsi.h
header-y += virtio_types.h
header-y += vm_sockets.h
header-y += vt.h
+header-y += vtpm.h
header-y += wait.h
header-y += wanrouter.h
header-y += watchdog.h
diff --git a/include/uapi/linux/vtpm.h b/include/uapi/linux/vtpm.h
new file mode 100644
index 0000000..4adc486
--- /dev/null
+++ b/include/uapi/linux/vtpm.h
@@ -0,0 +1,41 @@
+/*
+ * Definitions for the VTPM interface
+ * Copyright (c) 2015, 2016, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _UAPI_LINUX_VTPM_H
+#define _UAPI_LINUX_VTPM_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+/* ioctls */
+
+struct vtpm_new_dev {
+ __u32 flags; /* input */
+ __u32 dev_num; /* output */
+ __u32 fd; /* output */
+ __u32 major; /* output */
+ __u32 minor; /* output */
+};
+
+/* above flags */
+#define VTPM_FLAG_TPM2 1 /* emulator is TPM 2 */
+
+/* all supported flags */
+#define VTPM_FLAGS_ALL (VTPM_FLAG_TPM2)
+
+#define VTPM_TPM 0xa0
+
+#define VTPM_NEW_DEV _IOW(VTPM_TPM, 0x00, struct vtpm_new_dev)
+
+#endif /* _UAPI_LINUX_VTPM_H */
--
2.4.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 09/11] tpm: Initialize TPM and get durations and timeouts
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (7 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 08/11] tpm: Driver for supporting multiple emulated TPMs Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 10/11] tpm: Add documentation for the tpm_vtpm device driver Stefan Berger
2016-03-07 12:25 ` [PATCH v5 11/11] A test program for vTPM device creation Stefan Berger
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add the retrieval of TPM 1.2 durations and timeouts. Since this requires
the startup of the TPM, do this for TPM 1.2 and TPM 2.
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
CC: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
drivers/char/tpm/tpm_vtpm.c | 94 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 85 insertions(+), 9 deletions(-)
diff --git a/drivers/char/tpm/tpm_vtpm.c b/drivers/char/tpm/tpm_vtpm.c
index 245ce91..b048898 100644
--- a/drivers/char/tpm/tpm_vtpm.c
+++ b/drivers/char/tpm/tpm_vtpm.c
@@ -45,8 +45,11 @@ struct vtpm_dev {
size_t req_len; /* length of queued TPM request */
size_t resp_len; /* length of queued TPM response */
u8 buffer[TPM_BUFSIZE]; /* request/response buffer */
+
+ struct work_struct work; /* task that retrieves TPM timeouts */
};
+static struct workqueue_struct *workqueue;
static void vtpm_delete_device(struct vtpm_dev *vtpm_dev);
@@ -67,6 +70,15 @@ static ssize_t vtpm_fops_read(struct file *filp, char __user *buf,
size_t len;
int sig, rc;
+ mutex_lock(&vtpm_dev->buf_lock);
+
+ if (!(vtpm_dev->state & STATE_OPENED_FLAG)) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ return -EPIPE;
+ }
+
+ mutex_unlock(&vtpm_dev->buf_lock);
+
sig = wait_event_interruptible(vtpm_dev->wq, vtpm_dev->req_len != 0);
if (sig)
return -EINTR;
@@ -110,6 +122,11 @@ static ssize_t vtpm_fops_write(struct file *filp, const char __user *buf,
mutex_lock(&vtpm_dev->buf_lock);
+ if (!(vtpm_dev->state & STATE_OPENED_FLAG)) {
+ mutex_unlock(&vtpm_dev->buf_lock);
+ return -EPIPE;
+ }
+
if (count > sizeof(vtpm_dev->buffer) ||
!(vtpm_dev->state & STATE_WAIT_RESPONSE_FLAG)) {
mutex_unlock(&vtpm_dev->buf_lock);
@@ -154,6 +171,9 @@ static unsigned int vtpm_fops_poll(struct file *filp, poll_table *wait)
if (vtpm_dev->req_len)
ret |= POLLIN | POLLRDNORM;
+ if (!(vtpm_dev->state & STATE_OPENED_FLAG))
+ ret |= POLLHUP;
+
mutex_unlock(&vtpm_dev->buf_lock);
return ret;
@@ -341,6 +361,54 @@ static const struct tpm_class_ops vtpm_tpm_ops = {
};
/*
+ * Code related to the startup of the TPM 2 and startup of TPM 1.2 +
+ * retrieval of timeouts and durations.
+ */
+
+static void vtpm_dev_work(struct work_struct *work)
+{
+ struct vtpm_dev *vtpm_dev = container_of(work, struct vtpm_dev, work);
+ int rc;
+
+ if (vtpm_dev->flags & VTPM_FLAG_TPM2)
+ rc = tpm2_startup(vtpm_dev->chip, TPM2_SU_CLEAR);
+ else
+ rc = tpm_get_timeouts(vtpm_dev->chip);
+
+ if (rc)
+ goto err;
+
+ rc = tpm_chip_register(vtpm_dev->chip);
+ if (rc)
+ goto err;
+
+ return;
+
+err:
+ vtpm_fops_undo_open(vtpm_dev);
+}
+
+/*
+ * vtpm_dev_work_stop: make sure the work has finished
+ *
+ * This function is useful when user space closed the fd
+ * while the driver still determines timeouts.
+ */
+static void vtpm_dev_work_stop(struct vtpm_dev *vtpm_dev)
+{
+ vtpm_fops_undo_open(vtpm_dev);
+ flush_work(&vtpm_dev->work);
+}
+
+/*
+ * vtpm_dev_work_start: Schedule the work for TPM 1.2 & 2 initialization
+ */
+static inline void vtpm_dev_work_start(struct vtpm_dev *vtpm_dev)
+{
+ queue_work(workqueue, &vtpm_dev->work);
+}
+
+/*
* Code related to creation and deletion of device pairs
*/
static struct vtpm_dev *vtpm_create_vtpm_dev(void)
@@ -355,6 +423,7 @@ static struct vtpm_dev *vtpm_create_vtpm_dev(void)
init_waitqueue_head(&vtpm_dev->wq);
mutex_init(&vtpm_dev->buf_lock);
+ INIT_WORK(&vtpm_dev->work, vtpm_dev_work);
chip = tpm_chip_alloc(NULL, &vtpm_tpm_ops);
if (IS_ERR(chip)) {
@@ -424,9 +493,7 @@ static struct file *vtpm_create_device(
if (vtpm_dev->flags & VTPM_FLAG_TPM2)
vtpm_dev->chip->flags |= TPM_CHIP_FLAG_TPM2;
- rc = tpm_chip_register(vtpm_dev->chip);
- if (rc)
- goto err_vtpm_fput;
+ vtpm_dev_work_start(vtpm_dev);
vtpm_new_dev->fd = fd;
vtpm_new_dev->major = MAJOR(vtpm_dev->chip->dev.devt);
@@ -435,12 +502,6 @@ static struct file *vtpm_create_device(
return file;
-err_vtpm_fput:
- put_unused_fd(fd);
- fput(file);
-
- return ERR_PTR(rc);
-
err_put_unused_fd:
put_unused_fd(fd);
@@ -455,6 +516,8 @@ err_delete_vtpm_dev:
*/
static void vtpm_delete_device(struct vtpm_dev *vtpm_dev)
{
+ vtpm_dev_work_stop(vtpm_dev);
+
tpm_chip_unregister(vtpm_dev->chip);
vtpm_fops_undo_open(vtpm_dev);
@@ -549,11 +612,24 @@ static int __init vtpm_module_init(void)
return rc;
}
+ workqueue = create_workqueue("tpm-vtpm");
+ if (!workqueue) {
+ pr_err("couldn't create workqueue\n");
+ rc = -ENOMEM;
+ goto err_vtpmx_cleanup;
+ }
+
return 0;
+
+err_vtpmx_cleanup:
+ vtpmx_cleanup();
+
+ return rc;
}
static void __exit vtpm_module_exit(void)
{
+ destroy_workqueue(workqueue);
vtpmx_cleanup();
}
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 10/11] tpm: Add documentation for the tpm_vtpm device driver
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (8 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 09/11] tpm: Initialize TPM and get durations and timeouts Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
2016-03-07 12:25 ` [PATCH v5 11/11] A test program for vTPM device creation Stefan Berger
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Cc: linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Add documentation for the tpm_vtpm device driver that implements
support for providing TPM functionality to Linux containers.
Parts of this documentation were recycled from the Xen vTPM
device driver documentation.
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
CC: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
Documentation/tpm/tpm_vtpm.txt | 53 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
create mode 100644 Documentation/tpm/tpm_vtpm.txt
diff --git a/Documentation/tpm/tpm_vtpm.txt b/Documentation/tpm/tpm_vtpm.txt
new file mode 100644
index 0000000..7746c0d
--- /dev/null
+++ b/Documentation/tpm/tpm_vtpm.txt
@@ -0,0 +1,53 @@
+Virtual TPM Device Driver for Linux Containers
+
+Authors: Stefan Berger (IBM)
+
+This document describes the virtual Trusted Platform Module (vTPM) device
+driver for Linux containers.
+
+INTRODUCTION
+------------
+
+The goal of this work is to provide TPM functionality to each Linux
+container. This allows programs to interact with a TPM in a container
+the same way they interact with a TPM on the physical system. Each
+container gets its own unique, emulated, software TPM.
+
+
+DESIGN
+------
+
+To make an emulated software TPM available to each container, the container
+management stack needs to create a device pair consisting of a client TPM
+character device /dev/tpmX (with X=0,1,2...) and a 'server side' file
+descriptor. The former is moved into the container by creating a character
+device with the appropriate major and minor numbers while the file descriptor
+is passed to the TPM emulator. Software inside the container can then send
+TPM commands using the character device and the emulator will receive the
+commands via the file descriptor and use it for sending back responses.
+
+To support this, the virtual TPM device driver provides a device /dev/vtpmx
+that is used to create device pairs using an ioctl. The ioctl takes as
+an input flags for configuring the device. The flags for example indicate
+whether TPM 1.2 or TPM 2 functionality is supported by the TPM emulator.
+The result of the ioctl are the file descriptor for the 'server side'
+as well as the major and minor numbers of the character device that was created.
+Besides that the number of the TPM character device is return. If for
+example /dev/tpm10 was created, the number (dev_num) 10 is returned.
+
+The following is the data structure of the VTPM_NEW_DEV ioctl:
+
+struct vtpm_new_dev {
+ __u32 flags; /* input */
+ __u32 dev_num; /* output */
+ __u32 fd; /* output */
+ __u32 major; /* output */
+ __u32 minor; /* output */
+};
+
+Note that if unsupported flags are passed to the device driver, the ioctl will
+fail and errno will be set to ENOSYS. Similarly, if an unsupported ioctl is
+called on the device driver, the ioctl will fail and errno will be set to ENOSYS.
+
+See /usr/include/linux/vtpm.h for definitions related to the public interface
+of this vTPM device driver.
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH v5 11/11] A test program for vTPM device creation
[not found] ` <1457353514-2509-1-git-send-email-stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
` (9 preceding siblings ...)
2016-03-07 12:25 ` [PATCH v5 10/11] tpm: Add documentation for the tpm_vtpm device driver Stefan Berger
@ 2016-03-07 12:25 ` Stefan Berger
10 siblings, 0 replies; 12+ messages in thread
From: Stefan Berger @ 2016-03-07 12:25 UTC (permalink / raw)
To: tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
This patch provides a program that is for testing purposes only.
Build it using the following commands:
make headers_install ARCH=x86_64 INSTALL_HDR_PATH=/usr
gcc vtpmctrl.c -o vtpmctrl
To use it:
To create a device pair and have vtpmctrl listen for commands, display
them and respond with TPM success messages do:
Created TPM device /dev/tpm0; vTPM device has fd 4, major/minor = 10/224.
In another shell do
00000000 00 c4 00 00 00 0a 00 00 00 00
00000012
Signed-off-by: Stefan Berger <stefanb-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
vtpmctrl.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 163 insertions(+)
create mode 100644 vtpmctrl.c
diff --git a/vtpmctrl.c b/vtpmctrl.c
new file mode 100644
index 0000000..071be45
--- /dev/null
+++ b/vtpmctrl.c
@@ -0,0 +1,163 @@
+/*
+ * vtpmctrl.c -- Linux vTPM driver control program
+ *
+ * (c) Copyright IBM Corporation 2015.
+ *
+ * Author: Stefan Berger <stefanb-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the names of the IBM Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <linux/vtpm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <endian.h>
+#include <stdint.h>
+
+int vtpmctrl_create(void)
+{
+ int fd, n, option, li, serverfd, nn;
+ struct vtpm_new_dev vtpm_new_dev = {
+ .flags = 0,
+ };
+ char tpmdev[16];
+ unsigned char buffer[4096];
+ const unsigned char tpm_startup_resp[] = {
+ 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00
+ };
+ const unsigned char timeout_req[] = {
+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x65,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x01, 0x15
+ };
+ const unsigned char timeout_res[] = {
+ 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x00,
+ };
+ const unsigned char duration_req[] = {
+ 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x65,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x01, 0x20
+ };
+ const unsigned char duration_res[] = {
+ 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00,
+ 0x00, 0x03, 0x00, 0x00,
+ };
+ uint32_t ordinal;
+
+ fd = open("/dev/vtpmx", O_RDWR);
+ if (fd < 0) {
+ perror("Could not open /dev/vtpmx");
+ return 1;
+ }
+
+ n = ioctl(fd, VTPM_NEW_DEV, &vtpm_new_dev);
+ if (n != 0) {
+ perror("ioctl to create new device failed");
+ close(fd);
+ return 1;
+ }
+
+ snprintf(tpmdev, sizeof(tpmdev), "/dev/tpm%u",
+ vtpm_new_dev.dev_num);
+
+ serverfd = vtpm_new_dev.fd;
+
+ printf("Created TPM device %s; vTPM device has fd %d, "
+ "major/minor = %u/%u.\n",
+ tpmdev, serverfd, vtpm_new_dev.major, vtpm_new_dev.minor);
+
+ close(fd);
+
+ while (1) {
+ n = read(serverfd, buffer, sizeof(buffer));
+ if (n > 0) {
+ printf("Request with %d bytes:\n", n);
+ nn = 0;
+ while (nn < n) {
+ printf("0x%02x ", buffer[nn]);
+ nn++;
+ if (nn % 16 == 0)
+ printf("\n");
+ }
+ printf("\n");
+ ordinal = be32toh(*(uint32_t *)&(buffer[6]));
+ switch (ordinal) {
+ case 0x99:
+ n = write(serverfd, tpm_startup_resp, sizeof(tpm_startup_resp));
+ break;
+ case 0x65:
+ if (!memcmp(timeout_req, buffer, sizeof(timeout_req))) {
+ n = write(serverfd, timeout_res, sizeof(timeout_res));
+
+ } else if (!memcmp(duration_req, buffer, sizeof(duration_req))) {
+ n = write(serverfd, duration_res, sizeof(duration_res));
+ } else {
+ n = write(serverfd, tpm_startup_resp, sizeof(tpm_startup_resp));
+ }
+ break;
+ default:
+ n = write(serverfd, tpm_startup_resp, sizeof(tpm_startup_resp));
+ break;
+ }
+ if (n < 0) {
+ printf("Error from writing the response: %s\n",
+ strerror(errno));
+ break;
+ } else {
+ printf("Sent response with %d bytes.\n", n);
+ }
+ } else {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ return vtpmctrl_create();
+}
--
2.4.3
------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
^ permalink raw reply related [flat|nested] 12+ messages in thread