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>
This commit is contained in:
committed by
Kent Yoder
parent
1f86605729
commit
78f09cc248
+24
-5
@@ -1102,12 +1102,28 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tpm_store_cancel);
|
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,
|
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;
|
unsigned long stop;
|
||||||
long rc;
|
long rc;
|
||||||
u8 status;
|
u8 status;
|
||||||
|
bool canceled = false;
|
||||||
|
|
||||||
/* check current status */
|
/* check current status */
|
||||||
status = chip->vendor.status(chip);
|
status = chip->vendor.status(chip);
|
||||||
@@ -1122,11 +1138,14 @@ again:
|
|||||||
if ((long)timeout <= 0)
|
if ((long)timeout <= 0)
|
||||||
return -ETIME;
|
return -ETIME;
|
||||||
rc = wait_event_interruptible_timeout(*queue,
|
rc = wait_event_interruptible_timeout(*queue,
|
||||||
((chip->vendor.status(chip)
|
wait_for_tpm_stat_cond(chip, mask, check_cancel,
|
||||||
& mask) == mask),
|
&canceled),
|
||||||
timeout);
|
timeout);
|
||||||
if (rc > 0)
|
if (rc > 0) {
|
||||||
|
if (canceled)
|
||||||
|
return -ECANCELED;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (rc == -ERESTARTSYS && freezing(current)) {
|
if (rc == -ERESTARTSYS && freezing(current)) {
|
||||||
clear_thread_flag(TIF_SIGPENDING);
|
clear_thread_flag(TIF_SIGPENDING);
|
||||||
goto again;
|
goto again;
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ extern void tpm_remove_hardware(struct device *);
|
|||||||
extern int tpm_pm_suspend(struct device *);
|
extern int tpm_pm_suspend(struct device *);
|
||||||
extern int tpm_pm_resume(struct device *);
|
extern int tpm_pm_resume(struct device *);
|
||||||
extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
|
extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
|
||||||
wait_queue_head_t *);
|
wait_queue_head_t *, bool);
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
extern int tpm_add_ppi(struct kobject *);
|
extern int tpm_add_ppi(struct kobject *);
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
|
|||||||
wait_for_tpm_stat(chip,
|
wait_for_tpm_stat(chip,
|
||||||
TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
chip->vendor.timeout_c,
|
chip->vendor.timeout_c,
|
||||||
&chip->vendor.read_queue)
|
&chip->vendor.read_queue, true)
|
||||||
== 0) {
|
== 0) {
|
||||||
burstcnt = get_burstcount(chip);
|
burstcnt = get_burstcount(chip);
|
||||||
for (; burstcnt > 0 && size < count; burstcnt--)
|
for (; burstcnt > 0 && size < count; burstcnt--)
|
||||||
@@ -241,7 +241,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
||||||
&chip->vendor.int_queue);
|
&chip->vendor.int_queue, false);
|
||||||
status = tpm_tis_status(chip);
|
status = tpm_tis_status(chip);
|
||||||
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
|
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
|
||||||
dev_err(chip->dev, "Error left over data\n");
|
dev_err(chip->dev, "Error left over data\n");
|
||||||
@@ -277,7 +277,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
|
|||||||
tpm_tis_ready(chip);
|
tpm_tis_ready(chip);
|
||||||
if (wait_for_tpm_stat
|
if (wait_for_tpm_stat
|
||||||
(chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
|
(chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
|
||||||
&chip->vendor.int_queue) < 0) {
|
&chip->vendor.int_queue, false) < 0) {
|
||||||
rc = -ETIME;
|
rc = -ETIME;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
@@ -292,7 +292,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
||||||
&chip->vendor.int_queue);
|
&chip->vendor.int_queue, false);
|
||||||
status = tpm_tis_status(chip);
|
status = tpm_tis_status(chip);
|
||||||
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
|
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
@@ -304,7 +304,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
|
|||||||
iowrite8(buf[count],
|
iowrite8(buf[count],
|
||||||
chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
|
chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
|
||||||
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
|
||||||
&chip->vendor.int_queue);
|
&chip->vendor.int_queue, false);
|
||||||
status = tpm_tis_status(chip);
|
status = tpm_tis_status(chip);
|
||||||
if ((status & TPM_STS_DATA_EXPECT) != 0) {
|
if ((status & TPM_STS_DATA_EXPECT) != 0) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
@@ -342,7 +342,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
|||||||
if (wait_for_tpm_stat
|
if (wait_for_tpm_stat
|
||||||
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||||
tpm_calc_ordinal_duration(chip, ordinal),
|
tpm_calc_ordinal_duration(chip, ordinal),
|
||||||
&chip->vendor.read_queue) < 0) {
|
&chip->vendor.read_queue, false) < 0) {
|
||||||
rc = -ETIME;
|
rc = -ETIME;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user