aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm_i2c_stm_st33.c
diff options
context:
space:
mode:
authorChristophe Ricard <christophe.ricard@gmail.com>2014-12-01 13:32:58 -0500
committerPeter Huewe <peterhuewe@gmx.de>2015-01-17 08:00:08 -0500
commitc3804b8cdbd2abb50cf87318b13660dff46b7fe8 (patch)
tree46d42a57c7b6b7e1a9590ddc5241ba56649a92ce /drivers/char/tpm/tpm_i2c_stm_st33.c
parent8dcd19874f31b7a806a2a2b129e94882918c3aaf (diff)
tpm/tpm_i2c_stm_st33: Interrupt management improvement
Improve the irq management by using a new function wait_for_stat. Instead of using a completion struct, we rely on the waitqueue read_queue and int_queue from chip->vendor field. Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
Diffstat (limited to 'drivers/char/tpm/tpm_i2c_stm_st33.c')
-rw-r--r--drivers/char/tpm/tpm_i2c_stm_st33.c197
1 files changed, 109 insertions, 88 deletions
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
index a444cd3cb17d..eb0244a2ec9d 100644
--- a/drivers/char/tpm/tpm_i2c_stm_st33.c
+++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
@@ -38,6 +38,7 @@
38#include <linux/kernel.h> 38#include <linux/kernel.h>
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/wait.h> 40#include <linux/wait.h>
41#include <linux/freezer.h>
41#include <linux/string.h> 42#include <linux/string.h>
42#include <linux/interrupt.h> 43#include <linux/interrupt.h>
43#include <linux/sysfs.h> 44#include <linux/sysfs.h>
@@ -102,9 +103,9 @@ enum tis_defaults {
102 103
103struct tpm_stm_dev { 104struct tpm_stm_dev {
104 struct i2c_client *client; 105 struct i2c_client *client;
105 struct completion irq_detection;
106 struct tpm_chip *chip; 106 struct tpm_chip *chip;
107 u8 buf[TPM_BUFSIZE + 1]; 107 u8 buf[TPM_BUFSIZE + 1];
108 u32 intrs;
108 int io_lpcpd; 109 int io_lpcpd;
109}; 110};
110 111
@@ -174,61 +175,18 @@ static int read8_reg(struct tpm_stm_dev *tpm_dev, u8 tpm_register,
174 * clear_interruption 175 * clear_interruption
175 * clear the TPM interrupt register. 176 * clear the TPM interrupt register.
176 * @param: tpm, the chip description 177 * @param: tpm, the chip description
178 * @return: the TPM_INT_STATUS value
177 */ 179 */
178static void clear_interruption(struct tpm_stm_dev *tpm_dev) 180static u8 clear_interruption(struct tpm_stm_dev *tpm_dev)
179{ 181{
180 u8 interrupt; 182 u8 interrupt;
181 183
182 I2C_READ_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1); 184 I2C_READ_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1);
183 I2C_WRITE_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1); 185 I2C_WRITE_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1);
184 I2C_READ_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1); 186 return interrupt;
185} /* clear_interruption() */ 187} /* clear_interruption() */
186 188
187/* 189/*
188 * _wait_for_interrupt_serirq_timeout
189 * @param: tpm, the chip description
190 * @param: timeout, the timeout of the interrupt
191 * @return: the status of the interruption.
192 */
193static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip,
194 unsigned long timeout)
195{
196 long status;
197 struct i2c_client *client;
198 struct tpm_stm_dev *tpm_dev;
199
200 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
201 client = tpm_dev->client;
202
203 status = wait_for_completion_interruptible_timeout(
204 &tpm_dev->irq_detection,
205 timeout);
206 if (status > 0)
207 enable_irq(client->irq);
208
209 return status;
210} /* wait_for_interrupt_serirq_timeout() */
211
212static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition,
213 unsigned long timeout)
214{
215 int status = 2;
216 struct tpm_stm_dev *tpm_dev;
217
218 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
219
220 status = _wait_for_interrupt_serirq_timeout(chip, timeout);
221 if (!status) {
222 status = -EBUSY;
223 } else {
224 clear_interruption(tpm_dev);
225 if (condition)
226 status = 1;
227 }
228 return status;
229} /* wait_for_serirq_timeout() */
230
231/*
232 * tpm_stm_i2c_cancel, cancel is not implemented. 190 * tpm_stm_i2c_cancel, cancel is not implemented.
233 * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h 191 * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
234 */ 192 */
@@ -241,8 +199,6 @@ static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
241 199
242 data = TPM_STS_COMMAND_READY; 200 data = TPM_STS_COMMAND_READY;
243 I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1); 201 I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1);
244 if (chip->vendor.irq)
245 wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a);
246} /* tpm_stm_i2c_cancel() */ 202} /* tpm_stm_i2c_cancel() */
247 203
248/* 204/*
@@ -297,30 +253,24 @@ static int request_locality(struct tpm_chip *chip)
297 struct tpm_stm_dev *tpm_dev; 253 struct tpm_stm_dev *tpm_dev;
298 u8 data; 254 u8 data;
299 255
300 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
301
302 if (check_locality(chip) == chip->vendor.locality) 256 if (check_locality(chip) == chip->vendor.locality)
303 return chip->vendor.locality; 257 return chip->vendor.locality;
304 258
259 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
260
305 data = TPM_ACCESS_REQUEST_USE; 261 data = TPM_ACCESS_REQUEST_USE;
306 ret = I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1); 262 ret = I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1);
307 if (ret < 0) 263 if (ret < 0)
308 goto end; 264 goto end;
309 265
310 if (chip->vendor.irq) { 266 stop = jiffies + chip->vendor.timeout_a;
311 ret = wait_for_serirq_timeout(chip, (check_locality 267
312 (chip) >= 0), 268 /* Request locality is usually effective after the request */
313 chip->vendor.timeout_a); 269 do {
314 if (ret > 0) 270 if (check_locality(chip) >= 0)
315 return chip->vendor.locality; 271 return chip->vendor.locality;
316 } else { 272 msleep(TPM_TIMEOUT);
317 stop = jiffies + chip->vendor.timeout_a; 273 } while (time_before(jiffies, stop));
318 do {
319 if (check_locality(chip) >= 0)
320 return chip->vendor.locality;
321 msleep(TPM_TIMEOUT);
322 } while (time_before(jiffies, stop));
323 }
324 ret = -EACCES; 274 ret = -EACCES;
325end: 275end:
326 return ret; 276 return ret;
@@ -378,36 +328,107 @@ end:
378 return -EBUSY; 328 return -EBUSY;
379} /* get_burstcount() */ 329} /* get_burstcount() */
380 330
331static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
332 bool check_cancel, bool *canceled)
333{
334 u8 status = chip->ops->status(chip);
335
336 *canceled = false;
337 if ((status & mask) == mask)
338 return true;
339 if (check_cancel && chip->ops->req_canceled(chip, status)) {
340 *canceled = true;
341 return true;
342 }
343 return false;
344}
345
346/*
347 * interrupt_to_status
348 * @param: irq_mask, the irq mask value to wait
349 * @return: the corresponding tpm_sts value
350 */
351static u8 interrupt_to_status(u8 irq_mask)
352{
353 u8 status = 0;
354
355 if ((irq_mask & TPM_INTF_STS_VALID_INT) == TPM_INTF_STS_VALID_INT)
356 status |= TPM_STS_VALID;
357 if ((irq_mask & TPM_INTF_DATA_AVAIL_INT) == TPM_INTF_DATA_AVAIL_INT)
358 status |= TPM_STS_DATA_AVAIL;
359 if ((irq_mask & TPM_INTF_CMD_READY_INT) == TPM_INTF_CMD_READY_INT)
360 status |= TPM_STS_COMMAND_READY;
361
362 return status;
363} /* status_to_interrupt() */
364
381/* 365/*
382 * wait_for_stat wait for a TPM_STS value 366 * wait_for_stat wait for a TPM_STS value
383 * @param: chip, the tpm chip description 367 * @param: chip, the tpm chip description
384 * @param: mask, the value mask to wait 368 * @param: mask, the value mask to wait
385 * @param: timeout, the timeout 369 * @param: timeout, the timeout
386 * @param: queue, the wait queue. 370 * @param: queue, the wait queue.
371 * @param: check_cancel, does the command can be cancelled ?
387 * @return: the tpm status, 0 if success, -ETIME if timeout is reached. 372 * @return: the tpm status, 0 if success, -ETIME if timeout is reached.
388 */ 373 */
389static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, 374static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
390 wait_queue_head_t *queue) 375 wait_queue_head_t *queue, bool check_cancel)
391{ 376{
392 unsigned long stop; 377 unsigned long stop;
393 long ret; 378 int r;
394 u8 status; 379 bool canceled = false;
380 bool condition;
381 u32 cur_intrs;
382 u8 interrupt, status;
383 struct tpm_stm_dev *tpm_dev;
384
385 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
386
387 /* check current status */
388 status = tpm_stm_i2c_status(chip);
389 if ((status & mask) == mask)
390 return 0;
391
392 stop = jiffies + timeout;
395 393
396 if (chip->vendor.irq) { 394 if (chip->vendor.irq) {
397 ret = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status 395 cur_intrs = tpm_dev->intrs;
398 (chip) & mask) == 396 interrupt = clear_interruption(tpm_dev);
399 mask), timeout); 397 enable_irq(chip->vendor.irq);
400 if (ret > 0) 398
399again:
400 timeout = stop - jiffies;
401 if ((long) timeout <= 0)
402 return -1;
403
404 r = wait_event_interruptible_timeout(*queue,
405 cur_intrs != tpm_dev->intrs, timeout);
406
407 interrupt |= clear_interruption(tpm_dev);
408 status = interrupt_to_status(interrupt);
409 condition = wait_for_tpm_stat_cond(chip, mask,
410 check_cancel, &canceled);
411
412 if (r >= 0 && condition) {
413 if (canceled)
414 return -ECANCELED;
401 return 0; 415 return 0;
416 }
417 if (r == -ERESTARTSYS && freezing(current)) {
418 clear_thread_flag(TIF_SIGPENDING);
419 goto again;
420 }
421 disable_irq_nosync(chip->vendor.irq);
422
402 } else { 423 } else {
403 stop = jiffies + timeout;
404 do { 424 do {
405 msleep(TPM_TIMEOUT); 425 msleep(TPM_TIMEOUT);
406 status = tpm_stm_i2c_status(chip); 426 status = chip->ops->status(chip);
407 if ((status & mask) == mask) 427 if ((status & mask) == mask)
408 return 0; 428 return 0;
409 } while (time_before(jiffies, stop)); 429 } while (time_before(jiffies, stop));
410 } 430 }
431
411 return -ETIME; 432 return -ETIME;
412} /* wait_for_stat() */ 433} /* wait_for_stat() */
413 434
@@ -429,7 +450,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
429 wait_for_stat(chip, 450 wait_for_stat(chip,
430 TPM_STS_DATA_AVAIL | TPM_STS_VALID, 451 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
431 chip->vendor.timeout_c, 452 chip->vendor.timeout_c,
432 &chip->vendor.read_queue) == 0) { 453 &chip->vendor.read_queue, true) == 0) {
433 burstcnt = get_burstcount(chip); 454 burstcnt = get_burstcount(chip);
434 if (burstcnt < 0) 455 if (burstcnt < 0)
435 return burstcnt; 456 return burstcnt;
@@ -449,15 +470,14 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
449static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) 470static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
450{ 471{
451 struct tpm_chip *chip = dev_id; 472 struct tpm_chip *chip = dev_id;
452 struct i2c_client *client;
453 struct tpm_stm_dev *tpm_dev; 473 struct tpm_stm_dev *tpm_dev;
454 474
455 disable_irq_nosync(irq);
456
457 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip); 475 tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
458 client = tpm_dev->client;
459 476
460 complete(&tpm_dev->irq_detection); 477 tpm_dev->intrs++;
478 wake_up_interruptible(&chip->vendor.read_queue);
479 disable_irq_nosync(chip->vendor.irq);
480
461 return IRQ_HANDLED; 481 return IRQ_HANDLED;
462} /* tpm_ioserirq_handler() */ 482} /* tpm_ioserirq_handler() */
463 483
@@ -500,7 +520,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
500 tpm_stm_i2c_cancel(chip); 520 tpm_stm_i2c_cancel(chip);
501 if (wait_for_stat 521 if (wait_for_stat
502 (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, 522 (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
503 &chip->vendor.int_queue) < 0) { 523 &chip->vendor.read_queue, false) < 0) {
504 ret = -ETIME; 524 ret = -ETIME;
505 goto out_err; 525 goto out_err;
506 } 526 }
@@ -743,7 +763,10 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
743 chip->vendor.locality = LOCALITY0; 763 chip->vendor.locality = LOCALITY0;
744 764
745 if (client->irq) { 765 if (client->irq) {
746 init_completion(&tpm_dev->irq_detection); 766 /* INTERRUPT Setup */
767 init_waitqueue_head(&chip->vendor.read_queue);
768 tpm_dev->intrs = 0;
769
747 if (request_locality(chip) != LOCALITY0) { 770 if (request_locality(chip) != LOCALITY0) {
748 ret = -ENODEV; 771 ret = -ENODEV;
749 goto _tpm_clean_answer; 772 goto _tpm_clean_answer;
@@ -765,9 +788,6 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
765 goto _tpm_clean_answer; 788 goto _tpm_clean_answer;
766 789
767 intmask |= TPM_INTF_CMD_READY_INT 790 intmask |= TPM_INTF_CMD_READY_INT
768 | TPM_INTF_FIFO_AVALAIBLE_INT
769 | TPM_INTF_WAKE_UP_READY_INT
770 | TPM_INTF_LOCALITY_CHANGE_INT
771 | TPM_INTF_STS_VALID_INT 791 | TPM_INTF_STS_VALID_INT
772 | TPM_INTF_DATA_AVAIL_INT; 792 | TPM_INTF_DATA_AVAIL_INT;
773 793
@@ -787,6 +807,8 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
787 807
788 chip->vendor.irq = client->irq; 808 chip->vendor.irq = client->irq;
789 809
810 disable_irq_nosync(chip->vendor.irq);
811
790 tpm_gen_interrupt(chip); 812 tpm_gen_interrupt(chip);
791 } 813 }
792 814
@@ -852,10 +874,9 @@ static int tpm_stm_i2c_pm_resume(struct device *dev)
852 874
853 if (gpio_is_valid(pin_infos->io_lpcpd)) { 875 if (gpio_is_valid(pin_infos->io_lpcpd)) {
854 gpio_set_value(pin_infos->io_lpcpd, 1); 876 gpio_set_value(pin_infos->io_lpcpd, 1);
855 ret = wait_for_serirq_timeout(chip, 877 ret = wait_for_stat(chip,
856 (chip->ops->status(chip) & 878 TPM_STS_VALID, chip->vendor.timeout_b,
857 TPM_STS_VALID) == TPM_STS_VALID, 879 &chip->vendor.read_queue, false);
858 chip->vendor.timeout_b);
859 } else { 880 } else {
860 ret = tpm_pm_resume(dev); 881 ret = tpm_pm_resume(dev);
861 if (!ret) 882 if (!ret)