diff options
author | Stefan Berger <stefanb@linux.vnet.ibm.com> | 2013-01-22 23:57:53 +0400 |
---|---|---|
committer | Kent Yoder <key@linux.vnet.ibm.com> | 2013-02-05 19:38:24 +0400 |
commit | 78f09cc248731716633c0ef219613e762a9c4f2e (patch) | |
tree | e0c1f2197bff7a5ad3f566cdd6ca2389c8e7cb31 /drivers/char/tpm/tpm.c | |
parent | 1f866057291fc00f14e4962473bd7724ffa8f578 (diff) | |
download | linux-78f09cc248731716633c0ef219613e762a9c4f2e.tar.xz |
tpm: Fix cancellation of TPM commands (interrupt mode)
Support cancellation of TPM commands when driver is used in interrupt
mode.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
Diffstat (limited to 'drivers/char/tpm/tpm.c')
-rw-r--r-- | drivers/char/tpm/tpm.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index a244cd3e7dbc..0d2e82f95577 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1102,12 +1102,28 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, } EXPORT_SYMBOL_GPL(tpm_store_cancel); +static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, bool check_cancel, + bool *canceled) +{ + u8 status = chip->vendor.status(chip); + + *canceled = false; + if ((status & mask) == mask) + return true; + if (check_cancel && chip->vendor.req_canceled(chip, status)) { + *canceled = true; + return true; + } + return false; +} + int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - wait_queue_head_t *queue) + wait_queue_head_t *queue, bool check_cancel) { unsigned long stop; long rc; u8 status; + bool canceled = false; /* check current status */ status = chip->vendor.status(chip); @@ -1122,11 +1138,14 @@ again: if ((long)timeout <= 0) return -ETIME; rc = wait_event_interruptible_timeout(*queue, - ((chip->vendor.status(chip) - & mask) == mask), - timeout); - if (rc > 0) + wait_for_tpm_stat_cond(chip, mask, check_cancel, + &canceled), + timeout); + if (rc > 0) { + if (canceled) + return -ECANCELED; return 0; + } if (rc == -ERESTARTSYS && freezing(current)) { clear_thread_flag(TIF_SIGPENDING); goto again; |