aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tpm/tpm_tis.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 88de8fc41586..b97ce2b205d7 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -26,6 +26,7 @@
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/wait.h> 27#include <linux/wait.h>
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29#include <linux/freezer.h>
29#include "tpm.h" 30#include "tpm.h"
30 31
31#define TPM_HEADER_SIZE 10 32#define TPM_HEADER_SIZE 10
@@ -120,7 +121,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force)
120 121
121static int request_locality(struct tpm_chip *chip, int l) 122static int request_locality(struct tpm_chip *chip, int l)
122{ 123{
123 unsigned long stop; 124 unsigned long stop, timeout;
124 long rc; 125 long rc;
125 126
126 if (check_locality(chip, l) >= 0) 127 if (check_locality(chip, l) >= 0)
@@ -129,17 +130,25 @@ static int request_locality(struct tpm_chip *chip, int l)
129 iowrite8(TPM_ACCESS_REQUEST_USE, 130 iowrite8(TPM_ACCESS_REQUEST_USE,
130 chip->vendor.iobase + TPM_ACCESS(l)); 131 chip->vendor.iobase + TPM_ACCESS(l));
131 132
133 stop = jiffies + chip->vendor.timeout_a;
134
132 if (chip->vendor.irq) { 135 if (chip->vendor.irq) {
136again:
137 timeout = stop - jiffies;
138 if ((long)timeout <= 0)
139 return -1;
133 rc = wait_event_interruptible_timeout(chip->vendor.int_queue, 140 rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
134 (check_locality 141 (check_locality
135 (chip, l) >= 0), 142 (chip, l) >= 0),
136 chip->vendor.timeout_a); 143 timeout);
137 if (rc > 0) 144 if (rc > 0)
138 return l; 145 return l;
139 146 if (rc == -ERESTARTSYS && freezing(current)) {
147 clear_thread_flag(TIF_SIGPENDING);
148 goto again;
149 }
140 } else { 150 } else {
141 /* wait for burstcount */ 151 /* wait for burstcount */
142 stop = jiffies + chip->vendor.timeout_a;
143 do { 152 do {
144 if (check_locality(chip, l) >= 0) 153 if (check_locality(chip, l) >= 0)
145 return l; 154 return l;
@@ -196,15 +205,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
196 if ((status & mask) == mask) 205 if ((status & mask) == mask)
197 return 0; 206 return 0;
198 207
208 stop = jiffies + timeout;
209
199 if (chip->vendor.irq) { 210 if (chip->vendor.irq) {
211again:
212 timeout = stop - jiffies;
213 if ((long)timeout <= 0)
214 return -ETIME;
200 rc = wait_event_interruptible_timeout(*queue, 215 rc = wait_event_interruptible_timeout(*queue,
201 ((tpm_tis_status 216 ((tpm_tis_status
202 (chip) & mask) == 217 (chip) & mask) ==
203 mask), timeout); 218 mask), timeout);
204 if (rc > 0) 219 if (rc > 0)
205 return 0; 220 return 0;
221 if (rc == -ERESTARTSYS && freezing(current)) {
222 clear_thread_flag(TIF_SIGPENDING);
223 goto again;
224 }
206 } else { 225 } else {
207 stop = jiffies + timeout;
208 do { 226 do {
209 msleep(TPM_TIMEOUT); 227 msleep(TPM_TIMEOUT);
210 status = tpm_tis_status(chip); 228 status = tpm_tis_status(chip);