From: Kylene Hall <kjhall@us.ibm.com>

This patch provides the logic to check if an operation has been canceled while
waiting for the response to arrive.

Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/char/tpm/tpm.c       |   32 ++++++++++++++++++++------------
 drivers/char/tpm/tpm.h       |    1 +
 drivers/char/tpm/tpm_atmel.c |    1 +
 drivers/char/tpm/tpm_nsc.c   |    1 +
 4 files changed, 23 insertions(+), 12 deletions(-)

diff -puN drivers/char/tpm/tpm_atmel.c~fix-tpm-driver-add-cancel-function drivers/char/tpm/tpm_atmel.c
--- 25/drivers/char/tpm/tpm_atmel.c~fix-tpm-driver-add-cancel-function	2005-05-31 02:44:31.000000000 -0700
+++ 25-akpm/drivers/char/tpm/tpm_atmel.c	2005-05-31 02:44:31.000000000 -0700
@@ -147,6 +147,7 @@ static struct tpm_vendor_specific tpm_at
 	.cancel = tpm_atml_cancel,
 	.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
 	.req_complete_val = ATML_STATUS_DATA_AVAIL,
+	.req_canceled = ATML_STATUS_READY,
 	.base = TPM_ATML_BASE,
 	.attr_group = &atmel_attr_grp,
 	.miscdev = { .fops = &atmel_ops, },
diff -puN drivers/char/tpm/tpm.c~fix-tpm-driver-add-cancel-function drivers/char/tpm/tpm.c
--- 25/drivers/char/tpm/tpm.c~fix-tpm-driver-add-cancel-function	2005-05-31 02:44:31.000000000 -0700
+++ 25-akpm/drivers/char/tpm/tpm.c	2005-05-31 02:44:31.000000000 -0700
@@ -141,7 +141,7 @@ EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
 static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
 			    size_t bufsiz)
 {
-	ssize_t len;
+	ssize_t rc;
 	u32 count;
 	unsigned long stop;
 
@@ -157,10 +157,10 @@ static ssize_t tpm_transmit(struct tpm_c
 
 	down(&chip->tpm_mutex);
 
-	if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
 		dev_err(&chip->pci_dev->dev,
-			"tpm_transmit: tpm_send: error %zd\n", len);
-		return len;
+			"tpm_transmit: tpm_send: error %zd\n", rc);
+		goto out;
 	}
 
 	stop = jiffies + 2 * 60 * HZ;
@@ -170,23 +170,31 @@ static ssize_t tpm_transmit(struct tpm_c
 		    chip->vendor->req_complete_val) {
 			goto out_recv;
 		}
-		msleep(TPM_TIMEOUT); /* CHECK */
+
+		if ((status == chip->vendor->req_canceled)) {
+			dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+			rc = -ECANCELED;
+			goto out;
+		}
+
+		msleep(TPM_TIMEOUT);	/* CHECK */
 		rmb();
 	} while (time_before(jiffies, stop));
 
 
 	chip->vendor->cancel(chip);
-	dev_err(&chip->pci_dev->dev, "Time expired\n");
-	up(&chip->tpm_mutex);
-	return -EIO;
+	dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+	rc = -ETIME;
+	goto out;
 
 out_recv:
-	len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
-	if (len < 0)
+	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+	if (rc < 0)
 		dev_err(&chip->pci_dev->dev,
-			"tpm_transmit: tpm_recv: error %zd\n", len);
+			"tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
 	up(&chip->tpm_mutex);
-	return len;
+	return rc;
 }
 
 #define TPM_DIGEST_SIZE 20
diff -puN drivers/char/tpm/tpm.h~fix-tpm-driver-add-cancel-function drivers/char/tpm/tpm.h
--- 25/drivers/char/tpm/tpm.h~fix-tpm-driver-add-cancel-function	2005-05-31 02:44:31.000000000 -0700
+++ 25-akpm/drivers/char/tpm/tpm.h	2005-05-31 02:44:31.000000000 -0700
@@ -49,6 +49,7 @@ struct tpm_chip;
 struct tpm_vendor_specific {
 	u8 req_complete_mask;
 	u8 req_complete_val;
+	u8 req_canceled;
 	u16 base;		/* TPM base address */
 
 	int (*recv) (struct tpm_chip *, u8 *, size_t);
diff -puN drivers/char/tpm/tpm_nsc.c~fix-tpm-driver-add-cancel-function drivers/char/tpm/tpm_nsc.c
--- 25/drivers/char/tpm/tpm_nsc.c~fix-tpm-driver-add-cancel-function	2005-05-31 02:44:31.000000000 -0700
+++ 25-akpm/drivers/char/tpm/tpm_nsc.c	2005-05-31 02:44:31.000000000 -0700
@@ -245,6 +245,7 @@ static struct tpm_vendor_specific tpm_ns
 	.cancel = tpm_nsc_cancel,
 	.req_complete_mask = NSC_STATUS_OBF,
 	.req_complete_val = NSC_STATUS_OBF,
+	.req_canceled = NSC_STATUS_RDY,
 	.base = TPM_NSC_BASE,
 	.attr_group = &nsc_attr_grp,
 	.miscdev = { .fops = &nsc_ops, },
_