diff options
-rw-r--r-- | drivers/char/tpm/tpm.c | 41 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 3 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 64 |
3 files changed, 55 insertions, 53 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 2e12b3f98139..efd24bbb5cb1 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -27,6 +27,7 @@ #include <linux/slab.h> #include <linux/mutex.h> #include <linux/spinlock.h> +#include <linux/freezer.h> #include "tpm.h" @@ -1057,6 +1058,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, } EXPORT_SYMBOL_GPL(tpm_store_cancel); +int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + wait_queue_head_t *queue) +{ + unsigned long stop; + long rc; + u8 status; + + /* check current status */ + status = chip->vendor.status(chip); + if ((status & mask) == mask) + return 0; + + stop = jiffies + timeout; + + if (chip->vendor.irq) { +again: + timeout = stop - jiffies; + if ((long)timeout <= 0) + return -ETIME; + rc = wait_event_interruptible_timeout(*queue, + ((chip->vendor.status(chip) + & mask) == mask), + timeout); + if (rc > 0) + return 0; + if (rc == -ERESTARTSYS && freezing(current)) { + clear_thread_flag(TIF_SIGPENDING); + goto again; + } + } else { + do { + msleep(TPM_TIMEOUT); + status = chip->vendor.status(chip); + if ((status & mask) == mask) + return 0; + } while (time_before(jiffies, stop)); + } + return -ETIME; +} +EXPORT_SYMBOL_GPL(wait_for_tpm_stat); /* * Device file system interface to the TPM * diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e264de16285f..9deb65c0ab61 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -296,7 +296,8 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); extern void tpm_remove_hardware(struct device *); extern int tpm_pm_suspend(struct device *, pm_message_t); extern int tpm_pm_resume(struct device *); - +extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, + wait_queue_head_t *); #ifdef CONFIG_ACPI extern struct dentry ** tpm_bios_log_setup(char *); extern void tpm_bios_log_teardown(struct dentry **); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e4553eb6e542..92f9f34e88f7 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -193,54 +193,14 @@ static int get_burstcount(struct tpm_chip *chip) return -EBUSY; } -static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, - wait_queue_head_t *queue) -{ - unsigned long stop; - long rc; - u8 status; - - /* check current status */ - status = chip->vendor.status(chip); - if ((status & mask) == mask) - return 0; - - stop = jiffies + timeout; - - if (chip->vendor.irq) { -again: - timeout = stop - jiffies; - if ((long)timeout <= 0) - return -ETIME; - rc = wait_event_interruptible_timeout(*queue, - ((chip->vendor.status(chip) - & mask) == mask), - timeout); - if (rc > 0) - return 0; - if (rc == -ERESTARTSYS && freezing(current)) { - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - } else { - do { - msleep(TPM_TIMEOUT); - status = chip->vendor.status(chip); - if ((status & mask) == mask) - return 0; - } while (time_before(jiffies, stop)); - } - return -ETIME; -} - static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { int size = 0, burstcnt; while (size < count && - wait_for_stat(chip, - TPM_STS_DATA_AVAIL | TPM_STS_VALID, - chip->vendor.timeout_c, - &chip->vendor.read_queue) + wait_for_tpm_stat(chip, + TPM_STS_DATA_AVAIL | TPM_STS_VALID, + chip->vendor.timeout_c, + &chip->vendor.read_queue) == 0) { burstcnt = get_burstcount(chip); for (; burstcnt > 0 && size < count; burstcnt--) @@ -282,8 +242,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, + &chip->vendor.int_queue); status = tpm_tis_status(chip); if (status & TPM_STS_DATA_AVAIL) { /* retry? */ dev_err(chip->dev, "Error left over data\n"); @@ -317,7 +277,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) status = tpm_tis_status(chip); if ((status & TPM_STS_COMMAND_READY) == 0) { tpm_tis_ready(chip); - if (wait_for_stat + if (wait_for_tpm_stat (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, &chip->vendor.int_queue) < 0) { rc = -ETIME; @@ -333,8 +293,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) count++; } - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, + &chip->vendor.int_queue); status = tpm_tis_status(chip); if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; @@ -345,8 +305,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) /* write last byte */ iowrite8(buf[count], chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, - &chip->vendor.int_queue); + wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, + &chip->vendor.int_queue); status = tpm_tis_status(chip); if ((status & TPM_STS_DATA_EXPECT) != 0) { rc = -EIO; @@ -381,7 +341,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) if (chip->vendor.irq) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); - if (wait_for_stat + if (wait_for_tpm_stat (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm_calc_ordinal_duration(chip, ordinal), &chip->vendor.read_queue) < 0) { |