# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID da8da6e1e1d609b1ceedb552475b72684e8461f5
# Parent 1d17ddd9e45d25e1b5fc21e558a4973b70572334
[TPM] Update the TPM drivers in the repository to a newer version
and also fixes the following:
- a problem introduced by a recent change to the xenbus_driver structure
requires driver-specific data to be stored in another data structures
- removes the #define'd MIN by min/min_t
- moves the sysfs entry to /sys/devices/xen/<vtpm-%d>
- fixes a bug occurring during cancellation of requests
- updates the default configuration to also compile the TPM V1.2 driver
submitted in part 2 of this patch
- all changes made to the generic TPM driver are surrounded by #ifdef
CONFIG_XEN's.
Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
buildconfigs/linux-defconfig_xen_x86_32 | 1
buildconfigs/linux-defconfig_xen_x86_64 | 1
linux-2.6-xen-sparse/drivers/char/tpm/Kconfig | 13
linux-2.6-xen-sparse/drivers/char/tpm/Makefile | 1
linux-2.6-xen-sparse/drivers/char/tpm/tpm.c | 873 +++++++++++++++++++----
linux-2.6-xen-sparse/drivers/char/tpm/tpm.h | 74 +
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c | 183 ++--
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h | 42 -
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c | 60 -
9 files changed, 972 insertions(+), 276 deletions(-)
diff -r 1d17ddd9e45d -r da8da6e1e1d6 buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32 Wed Jun 28 16:15:36 2006 +0100
+++ b/buildconfigs/linux-defconfig_xen_x86_32 Wed Jun 28 16:20:29 2006 +0100
@@ -1902,6 +1902,7 @@ CONFIG_HANGCHECK_TIMER=m
# TPM devices
#
CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
diff -r 1d17ddd9e45d -r da8da6e1e1d6 buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64 Wed Jun 28 16:15:36 2006 +0100
+++ b/buildconfigs/linux-defconfig_xen_x86_64 Wed Jun 28 16:20:29 2006 +0100
@@ -1765,6 +1765,7 @@ CONFIG_HANGCHECK_TIMER=m
# TPM devices
#
CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
diff -r 1d17ddd9e45d -r da8da6e1e1d6
linux-2.6-xen-sparse/drivers/char/tpm/Kconfig
--- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Wed Jun 28 16:20:29
2006 +0100
@@ -20,9 +20,18 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
+config TCG_TIS
+ tristate "TPM Interface Specification 1.2 Interface"
+ depends on TCG_TPM
+ ---help---
+ If you have a TPM security chip that is compliant with the
+ TCG TIS 1.2 TPM specification say Yes and it will be accessible
+ from within Linux. To compile this driver as a module, choose
+ M here; the module will be called tpm_tis.
+
config TCG_NSC
tristate "National Semiconductor TPM Interface"
- depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST
+ depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from National Semicondutor
say Yes and it will be accessible from within Linux. To
@@ -31,7 +40,7 @@ config TCG_NSC
config TCG_ATMEL
tristate "Atmel TPM Interface"
- depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST
+ depends on TCG_TPM
---help---
If you have a TPM security chip from Atmel say Yes and it
will be accessible from within Linux. To compile this driver
diff -r 1d17ddd9e45d -r da8da6e1e1d6
linux-2.6-xen-sparse/drivers/char/tpm/Makefile
--- a/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Wed Jun 28 16:20:29
2006 +0100
@@ -5,6 +5,7 @@ ifdef CONFIG_ACPI
ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
endif
+obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff -r 1d17ddd9e45d -r da8da6e1e1d6 linux-2.6-xen-sparse/drivers/char/tpm/tpm.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Wed Jun 28 16:20:29
2006 +0100
@@ -30,15 +30,295 @@
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
- TPM_MIN_BUFSIZE = 2048,
- TPM_MAX_BUFSIZE = 64 * 1024,
+#ifndef CONFIG_XEN
+ TPM_BUFSIZE = 2048,
+#endif
TPM_NUM_DEVICES = 256,
- TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
};
+
+enum tpm_duration {
+ TPM_SHORT = 0,
+ TPM_MEDIUM = 1,
+ TPM_LONG = 2,
+ TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[TPM_NUM_MASK_ENTRIES];
+static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result. The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_LONG,
+ TPM_MEDIUM, /* 15 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT, /* 20 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT, /* 25 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 30 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 35 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 40 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 45 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_MEDIUM, /* 50 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 55 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 60 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 65 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 70 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 75 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 80 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 85 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 90 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 95 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 100 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 105 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 110 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 115 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 120 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 125 */
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 130 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 135 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 140 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 145 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 150 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 155 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 160 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 165 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 170 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 175 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 180 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM, /* 185 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 190 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 195 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 200 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 205 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 210 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 215 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 220 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 225 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 230 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 235 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 240 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+};
static void user_reader_timeout(unsigned long ptr)
{
@@ -47,28 +327,58 @@ static void user_reader_timeout(unsigned
schedule_work(&chip->work);
}
-static void timeout_work(void * ptr)
+static void timeout_work(void *ptr)
{
struct tpm_chip *chip = ptr;
down(&chip->buffer_mutex);
atomic_set(&chip->data_pending, 0);
+#ifndef CONFIG_XEN
+ memset(chip->data_buffer, 0, TPM_BUFSIZE);
+#else
memset(chip->data_buffer, 0, get_chip_buffersize(chip));
+#endif
up(&chip->buffer_mutex);
}
+
+/*
+ * Returns max number of jiffies to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+ u32 ordinal)
+{
+ int duration_idx = TPM_UNDEFINED;
+ int duration = 0;
+
+ if (ordinal < TPM_MAX_ORDINAL)
+ duration_idx = tpm_ordinal_duration[ordinal];
+ else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+ TPM_MAX_PROTECTED_ORDINAL)
+ duration_idx =
+ tpm_protected_ordinal_duration[ordinal &
+ TPM_PROTECTED_ORDINAL_MASK];
+
+ if (duration_idx != TPM_UNDEFINED)
+ duration = chip->vendor.duration[duration_idx];
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
/*
* Internal kernel interface to transmit TPM commands
*/
-static ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf,
+static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
ssize_t rc;
- u32 count;
+ u32 count, ordinal;
unsigned long stop;
count = be32_to_cpu(*((__be32 *) (buf + 2)));
-
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
@@ -79,21 +389,23 @@ static ssize_t tpm_transmit(struct tpm_c
down(&chip->tpm_mutex);
- if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
dev_err(chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
- stop = jiffies + 2 * 60 * HZ;
+ if (chip->vendor.irq)
+ goto out_recv;
+
+ stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
- u8 status = chip->vendor->status(chip);
- if ((status & chip->vendor->req_complete_mask) ==
- chip->vendor->req_complete_val) {
+ u8 status = chip->vendor.status(chip);
+ if ((status & chip->vendor.req_complete_mask) ==
+ chip->vendor.req_complete_val)
goto out_recv;
- }
-
- if ((status == chip->vendor->req_canceled)) {
+
+ if ((status == chip->vendor.req_canceled)) {
dev_err(chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
@@ -103,14 +415,13 @@ static ssize_t tpm_transmit(struct tpm_c
rmb();
} while (time_before(jiffies, stop));
-
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
dev_err(chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
- rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
dev_err(chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
@@ -120,17 +431,247 @@ out:
}
#define TPM_DIGEST_SIZE 20
-#define CAP_PCR_RESULT_SIZE 18
-static const u8 cap_pcr[] = {
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+#define TPM_GET_CAP_RET_SIZE_IDX 10
+#define TPM_GET_CAP_RET_UINT32_1_IDX 14
+#define TPM_GET_CAP_RET_UINT32_2_IDX 18
+#define TPM_GET_CAP_RET_UINT32_3_IDX 22
+#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
+
+#define TPM_CAP_IDX 13
+#define TPM_CAP_SUBCAP_IDX 21
+
+enum tpm_capabilities {
+ TPM_CAP_FLAG = 4,
+ TPM_CAP_PROP = 5,
+};
+
+enum tpm_sub_capabilities {
+ TPM_CAP_PROP_PCR = 0x1,
+ TPM_CAP_PROP_MANUFACTURER = 0x3,
+ TPM_CAP_FLAG_PERM = 0x8,
+ TPM_CAP_FLAG_VOL = 0x9,
+ TPM_CAP_PROP_OWNER = 0x11,
+ TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+ TPM_CAP_PROP_TIS_DURATION = 0x20,
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tpm_cap[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 1
+ 0, 0, 0, 0, /* TPM_CAP_<TYPE> */
+ 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */
+ 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */
};
-#define READ_PCR_RESULT_SIZE 30
+static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
+ char *desc)
+{
+ int err;
+
+ len = tpm_transmit(chip, data, len);
+ if (len < 0)
+ return len;
+ if (len == TPM_ERROR_SIZE) {
+ err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+ dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+ ssize_t rc;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)];
+ ssize_t rc;
+ u32 timeout;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+ if (rc)
+ goto duration;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = msecs_to_jiffies(timeout);
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = msecs_to_jiffies(timeout);
+
+duration:
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the durations");
+ if (rc)
+ return;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TPM_SHORT] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_1_IDX))));
+ chip->vendor.duration[TPM_MEDIUM] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_2_IDX))));
+ chip->vendor.duration[TPM_LONG] =
+ msecs_to_jiffies(be32_to_cpu
+ (*((__be32 *) (data +
+ TPM_GET_CAP_RET_UINT32_3_IDX))));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+void tpm_continue_selftest(struct tpm_chip *chip)
+{
+ u8 data[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* length */
+ 0, 0, 0, 83, /* TPM_ORD_GetCapability */
+ };
+
+ tpm_transmit(chip, data, sizeof(data));
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_enabled);
+
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_active);
+
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the owner state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_owned);
+
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the temporary state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
+
static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
@@ -141,8 +682,8 @@ ssize_t tpm_show_pcrs(struct device *dev
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[READ_PCR_RESULT_SIZE];
- ssize_t len;
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)];
+ ssize_t rc;
int i, j, num_pcrs;
__be32 index;
char *str = buf;
@@ -151,29 +692,24 @@ ssize_t tpm_show_pcrs(struct device *dev
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_pcr, sizeof(cap_pcr));
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to determine the number of PCRS\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the number of PCRS");
+ if (rc)
return 0;
- }
num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
-
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE){
- dev_dbg(chip->dev, "A TPM error (%d) occurred"
- " attempting to read PCR %d of %d\n",
- be32_to_cpu(*((__be32 *) (data + 6))),
- i, num_pcrs);
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read a PCR");
+ if (rc)
goto out;
- }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -195,7 +731,7 @@ ssize_t tpm_show_pubek(struct device *de
char *buf)
{
u8 *data;
- ssize_t len;
+ ssize_t err;
int i, rc;
char *str = buf;
@@ -209,14 +745,10 @@ ssize_t tpm_show_pubek(struct device *de
memcpy(data, readpubek, sizeof(readpubek));
- if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
- READ_PUBEK_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to read the PUBEK\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
- rc = 0;
+ err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+ "attempting to read the PUBEK");
+ if (err)
goto out;
- }
/*
ignore header 10 bytes
@@ -246,66 +778,109 @@ ssize_t tpm_show_pubek(struct device *de
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
+out:
rc = str - buf;
-out:
kfree(data);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_show_pubek);
-#define CAP_VER_RESULT_SIZE 18
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
+#define CAP_VERSION_IDX 13
static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 18, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 6,
+ 0, 0, 0, 0,
0, 0, 0, 0
};
-#define CAP_MANUFACTURER_RESULT_SIZE 18
-static const u8 cap_manufacturer[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 22, /* length */
- 0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 3
-};
-
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[sizeof(cap_manufacturer)];
- ssize_t len;
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)),
30)];
+ ssize_t rc;
char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
-
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_MANUFACTURER_RESULT_SIZE)
- return len;
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*((__be32 *) (data + 14))));
+ be32_to_cpu(*((__be32 *) (data +
TPM_GET_CAP_RET_UINT32_1_IDX))));
memcpy(data, cap_version, sizeof(cap_version));
-
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_VER_RESULT_SIZE)
- return len;
-
- str +=
- sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
- (int) data[14], (int) data[15], (int) data[16],
- (int) data[17]);
-
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the 1.1 version");
+ if (rc)
+ goto out;
+
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+
+out:
return str - buf;
}
EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_show_caps_1_2(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)),
30)];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the manufacturer\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ return 0;
+ }
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *) (data +
TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_err(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the 1.2 version\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto out;
+ }
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[16], (int) data[17], (int) data[18],
+ (int) data[19]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -314,7 +889,7 @@ ssize_t tpm_store_cancel(struct device *
if (chip == NULL)
return 0;
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
return count;
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
@@ -330,7 +905,7 @@ int tpm_open(struct inode *inode, struct
spin_lock(&driver_lock);
list_for_each_entry(pos, &tpm_chip_list, list) {
- if (pos->vendor->miscdev.minor == minor) {
+ if (pos->vendor.miscdev.minor == minor) {
chip = pos;
break;
}
@@ -352,7 +927,12 @@ int tpm_open(struct inode *inode, struct
spin_unlock(&driver_lock);
- chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8),
GFP_KERNEL);
+#ifndef CONFIG_XEN
+ chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+#else
+ chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8),
+ GFP_KERNEL);
+#endif
if (chip->data_buffer == NULL) {
chip->num_opens--;
put_device(chip->dev);
@@ -388,7 +968,7 @@ EXPORT_SYMBOL_GPL(tpm_release);
EXPORT_SYMBOL_GPL(tpm_release);
ssize_t tpm_write(struct file *file, const char __user *buf,
- size_t size, loff_t * off)
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int in_size = size, out_size;
@@ -400,8 +980,13 @@ ssize_t tpm_write(struct file *file, con
down(&chip->buffer_mutex);
+#ifndef CONFIG_XEN
+ if (in_size > TPM_BUFSIZE)
+ in_size = TPM_BUFSIZE;
+#else
if (in_size > get_chip_buffersize(chip))
in_size = get_chip_buffersize(chip);
+#endif
if (copy_from_user
(chip->data_buffer, (void __user *) buf, in_size)) {
@@ -410,11 +995,17 @@ ssize_t tpm_write(struct file *file, con
}
/* atomic tpm command send and result receive */
- out_size = tpm_transmit(chip, chip->data_buffer,
+#ifndef CONFIG_XEN
+ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+#else
+ out_size = tpm_transmit(chip, chip->data_buffer,
get_chip_buffersize(chip));
+#endif
atomic_set(&chip->data_pending, out_size);
+#ifdef CONFIG_XEN
atomic_set(&chip->data_position, 0);
+#endif
up(&chip->buffer_mutex);
/* Set a timeout by which the reader must come claim the result */
@@ -422,42 +1013,59 @@ ssize_t tpm_write(struct file *file, con
return in_size;
}
-
EXPORT_SYMBOL_GPL(tpm_write);
-ssize_t tpm_read(struct file * file, char __user *buf,
- size_t size, loff_t * off)
+ssize_t tpm_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int ret_size;
+#ifdef CONFIG_XEN
int pos, pending = 0;
-
+#endif
+
+#ifndef CONFIG_XEN
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ flush_scheduled_work();
+#endif
ret_size = atomic_read(&chip->data_pending);
+#ifndef CONFIG_XEN
+ atomic_set(&chip->data_pending, 0);
+#endif
if (ret_size > 0) { /* relay data */
if (size < ret_size)
ret_size = size;
+#ifdef CONFIG_XEN
pos = atomic_read(&chip->data_position);
-
+#endif
down(&chip->buffer_mutex);
+#ifndef CONFIG_XEN
+ if (copy_to_user(buf, chip->data_buffer, ret_size))
+#else
if (copy_to_user(buf, &chip->data_buffer[pos], ret_size)) {
+#endif
ret_size = -EFAULT;
+#ifdef CONFIG_XEN
} else {
pending = atomic_read(&chip->data_pending) - ret_size;
if ( pending ) {
- atomic_set( &chip->data_pending, pending );
- atomic_set( &chip->data_position, pos+ret_size
);
+ atomic_set(&chip->data_pending, pending);
+ atomic_set(&chip->data_position,
+ pos+ret_size);
}
}
+#endif
up(&chip->buffer_mutex);
}
-
- if ( ret_size <= 0 || pending == 0 ) {
- atomic_set( &chip->data_pending, 0 );
+
+#ifdef CONFIG_XEN
+ if ( ret_size <= 0 || pending == 0 ) {
+ atomic_set(&chip->data_pending, 0);
del_singleshot_timer_sync(&chip->user_read_timer);
flush_scheduled_work();
}
-
+#endif
return ret_size;
}
EXPORT_SYMBOL_GPL(tpm_read);
@@ -478,14 +1086,13 @@ void tpm_remove_hardware(struct device *
spin_unlock(&driver_lock);
dev_set_drvdata(dev, NULL);
- misc_deregister(&chip->vendor->miscdev);
- kfree(chip->vendor->miscdev.name);
-
- sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+ misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
+
+ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
- dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
- ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+ clear_bit(chip->dev_num, dev_mask);
kfree(chip);
@@ -536,18 +1143,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
-int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific
*entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev, const struct
tpm_vendor_specific
+ *entry)
{
#define DEVNAME_SIZE 7
char *devname;
struct tpm_chip *chip;
- int i, j;
/* Driver specific per-device data */
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
- return -ENOMEM;
+ return NULL;
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
@@ -559,51 +1166,37 @@ int tpm_register_hardware(struct device
chip->user_read_timer.function = user_reader_timeout;
chip->user_read_timer.data = (unsigned long) chip;
- chip->vendor = entry;
-
- if (entry->buffersize < TPM_MIN_BUFSIZE) {
- entry->buffersize = TPM_MIN_BUFSIZE;
- } else if (entry->buffersize > TPM_MAX_BUFSIZE) {
- entry->buffersize = TPM_MAX_BUFSIZE;
- }
-
- chip->dev_num = -1;
-
- for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
- for (j = 0; j < 8 * sizeof(int); j++)
- if ((dev_mask[i] & (1 << j)) == 0) {
- chip->dev_num =
- i * TPM_NUM_MASK_ENTRIES + j;
- dev_mask[i] |= 1 << j;
- goto dev_num_search_complete;
- }
-
-dev_num_search_complete:
- if (chip->dev_num < 0) {
+ memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
+
+ chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
+
+ if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
- return -ENODEV;
+ return NULL;
} else if (chip->dev_num == 0)
- chip->vendor->miscdev.minor = TPM_MINOR;
+ chip->vendor.miscdev.minor = TPM_MINOR;
else
- chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
+
+ set_bit(chip->dev_num, dev_mask);
devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
- chip->vendor->miscdev.name = devname;
-
- chip->vendor->miscdev.dev = dev;
+ chip->vendor.miscdev.name = devname;
+
+ chip->vendor.miscdev.dev = dev;
chip->dev = get_device(dev);
- if (misc_register(&chip->vendor->miscdev)) {
+ if (misc_register(&chip->vendor.miscdev)) {
dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
- chip->vendor->miscdev.name,
- chip->vendor->miscdev.minor);
+ chip->vendor.miscdev.name,
+ chip->vendor.miscdev.minor);
put_device(dev);
+ clear_bit(chip->dev_num, dev_mask);
kfree(chip);
- dev_mask[i] &= !(1 << j);
- return -ENODEV;
+ return NULL;
}
spin_lock(&driver_lock);
@@ -614,11 +1207,11 @@ dev_num_search_complete:
spin_unlock(&driver_lock);
- sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
chip->bios_dir = tpm_bios_log_setup(devname);
- return 0;
+ return chip;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff -r 1d17ddd9e45d -r da8da6e1e1d6 linux-2.6-xen-sparse/drivers/char/tpm/tpm.h
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Wed Jun 28 16:20:29
2006 +0100
@@ -24,6 +24,14 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#ifdef CONFIG_XEN
+enum tpm_bufsize {
+ TPM_MIN_BUFFERSIZE = 2048,
+ TPM_MAX_BUFFERSIZE = 64 * 1024,
+};
+#endif
enum tpm_timeout {
TPM_TIMEOUT = 5, /* msecs */
@@ -41,18 +49,32 @@ extern ssize_t tpm_show_pcrs(struct devi
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute
*attr,
+ char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
+extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_temp_deactivated(struct device *,
+ struct device_attribute *attr, char *);
struct tpm_chip;
struct tpm_vendor_specific {
- u8 req_complete_mask;
- u8 req_complete_val;
- u8 req_canceled;
+ const u8 req_complete_mask;
+ const u8 req_complete_val;
+ const u8 req_canceled;
+#ifdef CONFIG_XEN
u32 buffersize;
+#endif
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
+
+ int irq;
int region_size;
int have_region;
@@ -63,6 +85,13 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ struct list_head list;
+ int locality;
+ unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
+ unsigned long duration[3]; /* jiffies */
+
+ wait_queue_head_t read_queue;
+ wait_queue_head_t int_queue;
};
struct tpm_chip {
@@ -75,19 +104,26 @@ struct tpm_chip {
/* Data passed to and from the tpm via the read/write calls */
u8 *data_buffer;
atomic_t data_pending;
+#ifdef CONFIG_XEN
atomic_t data_position;
+#endif
struct semaphore buffer_mutex;
struct timer_list user_read_timer; /* user needs to claim result */
struct work_struct work;
struct semaphore tpm_mutex; /* tpm is processing */
- struct tpm_vendor_specific *vendor;
+ struct tpm_vendor_specific vendor;
struct dentry **bios_dir;
struct list_head list;
+#ifdef CONFIG_XEN
+ void *priv;
+#endif
};
+
+#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
static inline int tpm_read_index(int base, int index)
{
@@ -101,13 +137,35 @@ static inline void tpm_write_index(int b
outb(value & 0xFF, base+1);
}
+#ifdef CONFIG_XEN
static inline u32 get_chip_buffersize(struct tpm_chip *chip)
{
- return chip->vendor->buffersize;
+ u32 size = chip->vendor.buffersize;
+ if (size > TPM_MAX_BUFFERSIZE) {
+ return TPM_MAX_BUFFERSIZE;
+ } else if (size < TPM_MIN_BUFFERSIZE) {
+ return TPM_MIN_BUFFERSIZE;
+ }
+ return size;
}
-extern int tpm_register_hardware(struct device *,
- struct tpm_vendor_specific *);
+static inline void *chip_get_private(const struct tpm_chip *chip)
+{
+ return chip->priv;
+}
+
+static inline void chip_set_private(struct tpm_chip *chip, void *priv)
+{
+ chip->priv = priv;
+}
+#endif
+
+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
+extern void tpm_continue_selftest(struct tpm_chip *);
+extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
+extern struct tpm_chip* tpm_register_hardware(struct device *,
+ const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
@@ -121,7 +179,7 @@ extern struct dentry ** tpm_bios_log_set
extern struct dentry ** tpm_bios_log_setup(char *);
extern void tpm_bios_log_teardown(struct dentry **);
#else
-static inline struct dentry* tpm_bios_log_setup(char *name)
+static inline struct dentry ** tpm_bios_log_setup(char *name)
{
return NULL;
}
diff -r 1d17ddd9e45d -r da8da6e1e1d6
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Wed Jun 28 16:20:29
2006 +0100
@@ -29,8 +29,6 @@ enum {
STATUS_READY = 0x04
};
-#define MIN(x,y) ((x) < (y)) ? (x) : (y)
-
struct transmission {
struct list_head next;
@@ -49,26 +47,6 @@ enum {
TRANSMISSION_FLAG_WAS_QUEUED = 0x1
};
-struct vtpm_state {
- struct transmission *current_request;
- spinlock_t req_list_lock;
- wait_queue_head_t req_wait_queue;
-
- struct list_head queued_requests;
-
- struct transmission *current_response;
- spinlock_t resp_list_lock;
- wait_queue_head_t resp_wait_queue; // processes waiting for
responses
-
- struct transmission *req_cancelled; // if a cancellation was
encounterd
-
- u8 vd_status;
- u8 flags;
-
- unsigned long disconnect_time;
-
- struct tpm_virtual_device *tpmvd;
-};
enum {
DATAEX_FLAG_QUEUED_ONLY = 0x1
@@ -76,7 +54,6 @@ enum {
/* local variables */
-static struct vtpm_state *vtpms;
/* local function prototypes */
static int _vtpm_send_queued(struct tpm_chip *chip);
@@ -160,11 +137,16 @@ static inline void transmission_free(str
/*
* Lower layer uses this function to make a response available.
*/
-int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr)
+int vtpm_vd_recv(const struct tpm_chip *chip,
+ const unsigned char *buffer, size_t count,
+ void *ptr)
{
unsigned long flags;
int ret_size = 0;
struct transmission *t;
+ struct vtpm_state *vtpms;
+
+ vtpms = (struct vtpm_state *)chip_get_private(chip);
/*
* The list with requests must contain one request
@@ -173,26 +155,11 @@ int vtpm_vd_recv(const unsigned char *bu
*/
spin_lock_irqsave(&vtpms->resp_list_lock, flags);
if (vtpms->current_request != ptr) {
- printk("WARNING: The request pointer is different than the "
- "pointer the shared memory driver returned to me. "
- "%p != %p\n",
- vtpms->current_request, ptr);
- }
-
- /*
- * If the request has been cancelled, just quit here
- */
- if (vtpms->req_cancelled == (struct transmission *)ptr) {
- if (vtpms->current_request == vtpms->req_cancelled) {
- vtpms->current_request = NULL;
- }
- transmission_free(vtpms->req_cancelled);
- vtpms->req_cancelled = NULL;
spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
return 0;
}
- if (NULL != (t = vtpms->current_request)) {
+ if ((t = vtpms->current_request)) {
transmission_free(t);
vtpms->current_request = NULL;
}
@@ -217,8 +184,12 @@ int vtpm_vd_recv(const unsigned char *bu
/*
* Lower layer indicates its status (connected/disconnected)
*/
-void vtpm_vd_status(u8 vd_status)
-{
+void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status)
+{
+ struct vtpm_state *vtpms;
+
+ vtpms = (struct vtpm_state *)chip_get_private(chip);
+
vtpms->vd_status = vd_status;
if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) {
vtpms->disconnect_time = jiffies;
@@ -233,6 +204,9 @@ static int vtpm_recv(struct tpm_chip *ch
{
int rc = 0;
unsigned long flags;
+ struct vtpm_state *vtpms;
+
+ vtpms = (struct vtpm_state *)chip_get_private(chip);
/*
* Check if the previous operation only queued the command
@@ -251,7 +225,7 @@ static int vtpm_recv(struct tpm_chip *ch
* Return a response of up to 30 '0's.
*/
- count = MIN(count, 30);
+ count = min_t(size_t, count, 30);
memset(buf, 0x0, count);
return count;
}
@@ -270,7 +244,7 @@ static int vtpm_recv(struct tpm_chip *ch
if (vtpms->current_response) {
struct transmission *t = vtpms->current_response;
vtpms->current_response = NULL;
- rc = MIN(count, t->response_len);
+ rc = min(count, t->response_len);
memcpy(buf, t->response, rc);
transmission_free(t);
}
@@ -284,6 +258,9 @@ static int vtpm_send(struct tpm_chip *ch
int rc = 0;
unsigned long flags;
struct transmission *t = transmission_alloc();
+ struct vtpm_state *vtpms;
+
+ vtpms = (struct vtpm_state *)chip_get_private(chip);
if (!t)
return -ENOMEM;
@@ -327,8 +304,7 @@ static int vtpm_send(struct tpm_chip *ch
vtpms->current_request = t;
- rc = vtpm_vd_send(chip,
- vtpms->tpmvd->tpm_private,
+ rc = vtpm_vd_send(vtpms->tpm_private,
buf,
count,
t);
@@ -373,6 +349,8 @@ static int _vtpm_send_queued(struct tpm_
int error = 0;
long flags;
unsigned char buffer[1];
+ struct vtpm_state *vtpms;
+ vtpms = (struct vtpm_state *)chip_get_private(chip);
spin_lock_irqsave(&vtpms->req_list_lock, flags);
@@ -387,8 +365,7 @@ static int _vtpm_send_queued(struct tpm_
vtpms->current_request = qt;
spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
- rc = vtpm_vd_send(chip,
- vtpms->tpmvd->tpm_private,
+ rc = vtpm_vd_send(vtpms->tpm_private,
qt->request,
qt->request_len,
qt);
@@ -427,9 +404,21 @@ static void vtpm_cancel(struct tpm_chip
static void vtpm_cancel(struct tpm_chip *chip)
{
unsigned long flags;
+ struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip);
+
spin_lock_irqsave(&vtpms->resp_list_lock,flags);
- vtpms->req_cancelled = vtpms->current_request;
+ if (!vtpms->current_response && vtpms->current_request) {
+ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
+ interruptible_sleep_on(&vtpms->resp_wait_queue);
+ spin_lock_irqsave(&vtpms->resp_list_lock,flags);
+ }
+
+ if (vtpms->current_response) {
+ struct transmission *t = vtpms->current_response;
+ vtpms->current_response = NULL;
+ transmission_free(t);
+ }
spin_unlock_irqrestore(&vtpms->resp_list_lock,flags);
}
@@ -438,6 +427,9 @@ static u8 vtpm_status(struct tpm_chip *c
{
u8 rc = 0;
unsigned long flags;
+ struct vtpm_state *vtpms;
+
+ vtpms = (struct vtpm_state *)chip_get_private(chip);
spin_lock_irqsave(&vtpms->resp_list_lock, flags);
/*
@@ -449,7 +441,10 @@ static u8 vtpm_status(struct tpm_chip *c
if (vtpms->current_response ||
0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) {
rc = STATUS_DATA_AVAIL;
- }
+ } else if (!vtpms->current_response && !vtpms->current_request) {
+ rc = STATUS_READY;
+ }
+
spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
return rc;
}
@@ -465,18 +460,29 @@ static struct file_operations vtpm_ops =
static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+ NULL);
static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
static struct attribute *vtpm_attrs[] = {
&dev_attr_pubek.attr,
&dev_attr_pcrs.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_active.attr,
+ &dev_attr_owned.attr,
+ &dev_attr_temp_deactivated.attr,
&dev_attr_caps.attr,
&dev_attr_cancel.attr,
NULL,
};
static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs };
+
+#define TPM_LONG_TIMEOUT (10 * 60 * HZ)
static struct tpm_vendor_specific tpm_vtpm = {
.recv = vtpm_recv,
@@ -486,61 +492,56 @@ static struct tpm_vendor_specific tpm_vt
.req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
.req_complete_val = STATUS_DATA_AVAIL,
.req_canceled = STATUS_READY,
- .base = 0,
.attr_group = &vtpm_attr_grp,
.miscdev = {
.fops = &vtpm_ops,
},
-};
-
-static struct platform_device *pdev;
-
-int __init init_vtpm(struct tpm_virtual_device *tvd)
-{
- int rc;
-
- /* vtpms is global - only allow one user */
- if (vtpms)
- return -EBUSY;
+ .duration = {
+ TPM_LONG_TIMEOUT,
+ TPM_LONG_TIMEOUT,
+ TPM_LONG_TIMEOUT,
+ },
+};
+
+struct tpm_chip *init_vtpm(struct device *dev,
+ struct tpm_virtual_device *tvd,
+ struct tpm_private *tp)
+{
+ long rc;
+ struct tpm_chip *chip;
+ struct vtpm_state *vtpms;
vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL);
if (!vtpms)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
vtpm_state_init(vtpms);
vtpms->tpmvd = tvd;
-
- pdev = platform_device_register_simple("tpm_vtpm", -1, NULL, 0);
- if (IS_ERR(pdev)) {
- rc = PTR_ERR(pdev);
- goto err_free_mem;
- }
+ vtpms->tpm_private = tp;
if (tvd)
tpm_vtpm.buffersize = tvd->max_tx_size;
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_vtpm)) < 0) {
- goto err_unreg_pdev;
- }
-
- return 0;
-
-err_unreg_pdev:
- platform_device_unregister(pdev);
+ chip = tpm_register_hardware(dev, &tpm_vtpm);
+ if (!chip) {
+ rc = -ENODEV;
+ goto err_free_mem;
+ }
+
+ chip_set_private(chip, vtpms);
+
+ return chip;
+
err_free_mem:
kfree(vtpms);
- vtpms = NULL;
-
- return rc;
-}
-
-void __exit cleanup_vtpm(void)
-{
- struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
- if (chip) {
- tpm_remove_hardware(chip->dev);
- platform_device_unregister(pdev);
- }
+
+ return ERR_PTR(rc);
+}
+
+void cleanup_vtpm(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip);
+ tpm_remove_hardware(dev);
kfree(vtpms);
- vtpms = NULL;
-}
+}
diff -r 1d17ddd9e45d -r da8da6e1e1d6
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Wed Jun 28 16:20:29
2006 +0100
@@ -12,6 +12,26 @@ struct tpm_virtual_device {
* for allocation of buffers.
*/
unsigned int max_tx_size;
+};
+
+struct vtpm_state {
+ struct transmission *current_request;
+ spinlock_t req_list_lock;
+ wait_queue_head_t req_wait_queue;
+
+ struct list_head queued_requests;
+
+ struct transmission *current_response;
+ spinlock_t resp_list_lock;
+ wait_queue_head_t resp_wait_queue; // processes waiting for
responses
+
+ u8 vd_status;
+ u8 flags;
+
+ unsigned long disconnect_time;
+
+ struct tpm_virtual_device *tpmvd;
+
/*
* The following is a private structure of the underlying
* driver. It is passed as parameter in the send function.
@@ -19,20 +39,30 @@ struct tpm_virtual_device {
struct tpm_private *tpm_private;
};
+
enum vdev_status {
TPM_VD_STATUS_DISCONNECTED = 0x0,
TPM_VD_STATUS_CONNECTED = 0x1
};
/* this function is called from tpm_vtpm.c */
-int vtpm_vd_send(struct tpm_chip *tc,
- struct tpm_private * tp,
+int vtpm_vd_send(struct tpm_private * tp,
const u8 * buf, size_t count, void *ptr);
/* these functions are offered by tpm_vtpm.c */
-int __init init_vtpm(struct tpm_virtual_device *);
-void __exit cleanup_vtpm(void);
-int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr);
-void vtpm_vd_status(u8 status);
+struct tpm_chip *init_vtpm(struct device *,
+ struct tpm_virtual_device *,
+ struct tpm_private *);
+void cleanup_vtpm(struct device *);
+int vtpm_vd_recv(const struct tpm_chip* chip,
+ const unsigned char *buffer, size_t count, void *ptr);
+void vtpm_vd_status(const struct tpm_chip *, u8 status);
+
+static inline struct tpm_private *tpm_private_from_dev(struct device *dev)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ struct vtpm_state *vtpms = chip_get_private(chip);
+ return vtpms->tpm_private;
+}
#endif
diff -r 1d17ddd9e45d -r da8da6e1e1d6
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Wed Jun 28 16:15:36
2006 +0100
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Wed Jun 28 16:20:29
2006 +0100
@@ -34,6 +34,7 @@
*/
#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -41,12 +42,15 @@
#include <xen/interface/grant_table.h>
#include <xen/interface/io/tpmif.h>
#include <xen/xenbus.h>
+#include "tpm.h"
#include "tpm_vtpm.h"
#undef DEBUG
/* local structures */
struct tpm_private {
+ struct tpm_chip *chip;
+
tpmif_tx_interface_t *tx;
atomic_t refcnt;
unsigned int evtchn;
@@ -60,6 +64,7 @@ struct tpm_private {
atomic_t tx_busy;
void *tx_remember;
+
domid_t backend_id;
wait_queue_head_t wait_q;
@@ -95,6 +100,7 @@ static int tpm_xmit(struct tpm_private *
const u8 * buf, size_t count, int userbuffer,
void *remember);
static void destroy_tpmring(struct tpm_private *tp);
+void __exit tpmif_exit(void);
#define DPRINTK(fmt, args...) \
pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
@@ -199,8 +205,7 @@ static DEFINE_MUTEX(suspend_lock);
/*
* Send data via this module by calling this function
*/
-int vtpm_vd_send(struct tpm_chip *chip,
- struct tpm_private *tp,
+int vtpm_vd_send(struct tpm_private *tp,
const u8 * buf, size_t count, void *ptr)
{
int sent;
@@ -331,7 +336,7 @@ static void backend_changed(struct xenbu
static void backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
- struct tpm_private *tp = dev->dev.driver_data;
+ struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
DPRINTK("\n");
switch (backend_state) {
@@ -358,6 +363,9 @@ static void backend_changed(struct xenbu
}
}
+struct tpm_virtual_device tvd = {
+ .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE,
+};
static int tpmfront_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id)
@@ -368,6 +376,12 @@ static int tpmfront_probe(struct xenbus_
if (!tp)
return -ENOMEM;
+
+ tp->chip = init_vtpm(&dev->dev, &tvd, tp);
+
+ if (IS_ERR(tp->chip)) {
+ return PTR_ERR(tp->chip);
+ }
err = xenbus_scanf(XBT_NIL, dev->nodename,
"handle", "%i", &handle);
@@ -380,12 +394,10 @@ static int tpmfront_probe(struct xenbus_
}
tp->dev = dev;
- dev->dev.driver_data = tp;
err = talk_to_backend(dev, tp);
if (err) {
tpm_private_put();
- dev->dev.driver_data = NULL;
return err;
}
return 0;
@@ -394,16 +406,16 @@ static int tpmfront_probe(struct xenbus_
static int tpmfront_remove(struct xenbus_device *dev)
{
- struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data;
+ struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
destroy_tpmring(tp);
+ cleanup_vtpm(&dev->dev);
return 0;
}
static int tpmfront_suspend(struct xenbus_device *dev)
{
- struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data;
+ struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
u32 ctr;
-
/* lock, so no app can send */
mutex_lock(&suspend_lock);
tp->is_suspended = 1;
@@ -431,7 +443,7 @@ static int tpmfront_suspend(struct xenbu
static int tpmfront_resume(struct xenbus_device *dev)
{
- struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data;
+ struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
destroy_tpmring(tp);
return talk_to_backend(dev, tp);
}
@@ -548,7 +560,7 @@ static void tpmif_rx_action(unsigned lon
offset += tocopy;
}
- vtpm_vd_recv(buffer, received, tp->tx_remember);
+ vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
kfree(buffer);
exit:
@@ -638,6 +650,7 @@ static int tpm_xmit(struct tpm_private *
atomic_set(&tp->tx_busy, 1);
tp->tx_remember = remember;
+
mb();
DPRINTK("Notifying backend via event channel %d\n",
@@ -657,9 +670,9 @@ static void tpmif_notify_upperlayer(stru
* to the BE.
*/
if (tp->is_connected) {
- vtpm_vd_status(TPM_VD_STATUS_CONNECTED);
+ vtpm_vd_status(tp->chip, TPM_VD_STATUS_CONNECTED);
} else {
- vtpm_vd_status(TPM_VD_STATUS_DISCONNECTED);
+ vtpm_vd_status(tp->chip, TPM_VD_STATUS_DISCONNECTED);
}
}
@@ -699,13 +712,10 @@ static void tpmif_set_connected_state(st
* =================================================================
*/
-struct tpm_virtual_device tvd = {
- .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE,
-};
static int __init tpmif_init(void)
{
- int rc;
+ long rc = 0;
struct tpm_private *tp;
if ((xen_start_info->flags & SIF_INITDOMAIN)) {
@@ -717,11 +727,6 @@ static int __init tpmif_init(void)
rc = -ENOMEM;
goto failexit;
}
-
- tvd.tpm_private = tp;
- rc = init_vtpm(&tvd);
- if (rc)
- goto init_vtpm_failed;
IPRINTK("Initialising the vTPM driver.\n");
if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE,
@@ -734,19 +739,16 @@ static int __init tpmif_init(void)
return 0;
gnttab_alloc_failed:
- cleanup_vtpm();
-init_vtpm_failed:
tpm_private_put();
failexit:
- return rc;
-}
-
-
-static void __exit tpmif_exit(void)
+ return (int)rc;
+}
+
+
+void __exit tpmif_exit(void)
{
exit_tpm_xenbus();
- cleanup_vtpm();
tpm_private_put();
gnttab_free_grant_references(gref_head);
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|