[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [TPM] Update the TPM drivers in the repository to a newer version



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.