WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [TPM] Update the TPM drivers in the repos

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [TPM] Update the TPM drivers in the repository to a newer version
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 30 Jun 2006 15:40:18 +0000
Delivery-date: Fri, 30 Jun 2006 08:42:39 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [TPM] Update the TPM drivers in the repository to a newer version, Xen patchbot-unstable <=