Loading drivers/char/tpm/Kconfig +2 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ if TCG_TPM config TCG_TIS tristate "TPM Interface Specification 1.2 Interface" depends on X86 ---help--- If you have a TPM security chip that is compliant with the TCG TIS 1.2 TPM specification say Yes and it will be accessible Loading @@ -35,6 +36,7 @@ config TCG_TIS config TCG_NSC tristate "National Semiconductor TPM Interface" depends on X86 ---help--- If you have a TPM security chip from National Semiconductor say Yes and it will be accessible from within Linux. To Loading drivers/char/tpm/tpm.c +117 −20 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/slab.h> #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/freezer.h> #include "tpm.h" Loading Loading @@ -440,7 +441,6 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, } #define TPM_DIGEST_SIZE 20 #define TPM_ERROR_SIZE 10 #define TPM_RET_CODE_IDX 6 enum tpm_capabilities { Loading Loading @@ -469,13 +469,15 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, len = tpm_transmit(chip,(u8 *) cmd, len); if (len < 0) return len; if (len == TPM_ERROR_SIZE) { else if (len < TPM_HEADER_SIZE) return -EFAULT; err = be32_to_cpu(cmd->header.out.return_code); dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); if (err != 0) dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); return err; } return 0; } #define TPM_INTERNAL_RESULT_SIZE 200 #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) Loading Loading @@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_gen_interrupt); void tpm_get_timeouts(struct tpm_chip *chip) int tpm_get_timeouts(struct tpm_chip *chip) { struct tpm_cmd_t tpm_cmd; struct timeout_t *timeout_cap; Loading @@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) return; return -EINVAL; timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; /* Don't overwrite default if value is 0 */ Loading Loading @@ -583,12 +585,12 @@ void tpm_get_timeouts(struct tpm_chip *chip) rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the durations"); if (rc) return; return rc; if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) return; return -EINVAL; duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = Loading @@ -610,20 +612,36 @@ void tpm_get_timeouts(struct tpm_chip *chip) chip->vendor.duration_adjusted = true; dev_info(chip->dev, "Adjusting TPM timeout parameters."); } return 0; } EXPORT_SYMBOL_GPL(tpm_get_timeouts); void tpm_continue_selftest(struct tpm_chip *chip) { u8 data[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 10, /* length */ 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ #define TPM_ORD_CONTINUE_SELFTEST 83 #define CONTINUE_SELFTEST_RESULT_SIZE 10 static struct tpm_input_header continue_selftest_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(10), .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), }; tpm_transmit(chip, data, sizeof(data)); /** * tpm_continue_selftest -- run TPM's selftest * @chip: TPM chip to use * * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing * a TPM error code. */ static int tpm_continue_selftest(struct tpm_chip *chip) { int rc; struct tpm_cmd_t cmd; cmd.header.in = continue_selftest_header; rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, "continue selftest"); return rc; } EXPORT_SYMBOL_GPL(tpm_continue_selftest); ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) Loading Loading @@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = { .ordinal = TPM_ORDINAL_PCRREAD }; int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) { int rc; struct tpm_cmd_t cmd; Loading Loading @@ -798,6 +816,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) } EXPORT_SYMBOL_GPL(tpm_pcr_extend); /** * tpm_do_selftest - have the TPM continue its selftest and wait until it * can receive further commands * @chip: TPM chip to use * * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing * a TPM error code. */ int tpm_do_selftest(struct tpm_chip *chip) { int rc; u8 digest[TPM_DIGEST_SIZE]; unsigned int loops; unsigned int delay_msec = 1000; unsigned long duration; duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); loops = jiffies_to_msecs(duration) / delay_msec; rc = tpm_continue_selftest(chip); /* This may fail if there was no TPM driver during a suspend/resume * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) */ if (rc) return rc; do { rc = __tpm_pcr_read(chip, 0, digest); if (rc != TPM_WARN_DOING_SELFTEST) return rc; msleep(delay_msec); } while (--loops > 0); return rc; } EXPORT_SYMBOL_GPL(tpm_do_selftest); int tpm_send(u32 chip_num, void *cmd, size_t buflen) { struct tpm_chip *chip; Loading Loading @@ -1005,6 +1062,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 * Loading drivers/char/tpm/tpm.h +6 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ enum tpm_addr { TPM_ADDR = 0x4E, }; #define TPM_WARN_DOING_SELFTEST 0x802 #define TPM_HEADER_SIZE 10 extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, char *); extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, Loading Loading @@ -279,9 +281,9 @@ struct tpm_cmd_t { ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern void tpm_get_timeouts(struct tpm_chip *); extern int tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); extern void tpm_continue_selftest(struct tpm_chip *); extern int tpm_do_selftest(struct tpm_chip *); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); extern struct tpm_chip* tpm_register_hardware(struct device *, const struct tpm_vendor_specific *); Loading @@ -294,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 **); Loading drivers/char/tpm/tpm_tis.c +27 −57 Original line number Diff line number Diff line Loading @@ -29,8 +29,6 @@ #include <linux/freezer.h> #include "tpm.h" #define TPM_HEADER_SIZE 10 enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20, Loading Loading @@ -193,51 +191,11 @@ 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 = tpm_tis_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, ((tpm_tis_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 = tpm_tis_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, wait_for_tpm_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, chip->vendor.timeout_c, &chip->vendor.read_queue) Loading Loading @@ -282,7 +240,7 @@ 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, 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? */ Loading Loading @@ -317,7 +275,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; Loading @@ -333,7 +291,7 @@ 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, 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) { Loading @@ -345,7 +303,7 @@ 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, 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) { Loading Loading @@ -381,7 +339,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) { Loading Loading @@ -432,6 +390,9 @@ static int probe_itpm(struct tpm_chip *chip) out: itpm = rem_itpm; tpm_tis_ready(chip); /* some TPMs need a break here otherwise they will not work * correctly on the immediately subsequent command */ msleep(chip->vendor.timeout_b); release_locality(chip, chip->vendor.locality, 0); return rc; Loading Loading @@ -614,7 +575,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, dev_dbg(dev, "\tData Avail Int Support\n"); /* get the timeouts before testing for irqs */ tpm_get_timeouts(chip); if (tpm_get_timeouts(chip)) { dev_err(dev, "Could not get TPM timeouts and durations\n"); rc = -ENODEV; goto out_err; } if (tpm_do_selftest(chip)) { dev_err(dev, "TPM self test failed\n"); rc = -ENODEV; goto out_err; } /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); Loading Loading @@ -722,7 +693,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, list_add(&chip->vendor.list, &tis_chips); spin_unlock(&tis_lock); tpm_continue_selftest(chip); return 0; out_err: Loading Loading @@ -790,7 +760,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) ret = tpm_pm_resume(&dev->dev); if (!ret) tpm_continue_selftest(chip); tpm_do_selftest(chip); return ret; } Loading Loading
drivers/char/tpm/Kconfig +2 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ if TCG_TPM config TCG_TIS tristate "TPM Interface Specification 1.2 Interface" depends on X86 ---help--- If you have a TPM security chip that is compliant with the TCG TIS 1.2 TPM specification say Yes and it will be accessible Loading @@ -35,6 +36,7 @@ config TCG_TIS config TCG_NSC tristate "National Semiconductor TPM Interface" depends on X86 ---help--- If you have a TPM security chip from National Semiconductor say Yes and it will be accessible from within Linux. To Loading
drivers/char/tpm/tpm.c +117 −20 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/slab.h> #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/freezer.h> #include "tpm.h" Loading Loading @@ -440,7 +441,6 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, } #define TPM_DIGEST_SIZE 20 #define TPM_ERROR_SIZE 10 #define TPM_RET_CODE_IDX 6 enum tpm_capabilities { Loading Loading @@ -469,13 +469,15 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, len = tpm_transmit(chip,(u8 *) cmd, len); if (len < 0) return len; if (len == TPM_ERROR_SIZE) { else if (len < TPM_HEADER_SIZE) return -EFAULT; err = be32_to_cpu(cmd->header.out.return_code); dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); if (err != 0) dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); return err; } return 0; } #define TPM_INTERNAL_RESULT_SIZE 200 #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) Loading Loading @@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_gen_interrupt); void tpm_get_timeouts(struct tpm_chip *chip) int tpm_get_timeouts(struct tpm_chip *chip) { struct tpm_cmd_t tpm_cmd; struct timeout_t *timeout_cap; Loading @@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) return; return -EINVAL; timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; /* Don't overwrite default if value is 0 */ Loading Loading @@ -583,12 +585,12 @@ void tpm_get_timeouts(struct tpm_chip *chip) rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the durations"); if (rc) return; return rc; if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || be32_to_cpu(tpm_cmd.header.out.length) != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) return; return -EINVAL; duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = Loading @@ -610,20 +612,36 @@ void tpm_get_timeouts(struct tpm_chip *chip) chip->vendor.duration_adjusted = true; dev_info(chip->dev, "Adjusting TPM timeout parameters."); } return 0; } EXPORT_SYMBOL_GPL(tpm_get_timeouts); void tpm_continue_selftest(struct tpm_chip *chip) { u8 data[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 10, /* length */ 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ #define TPM_ORD_CONTINUE_SELFTEST 83 #define CONTINUE_SELFTEST_RESULT_SIZE 10 static struct tpm_input_header continue_selftest_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(10), .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), }; tpm_transmit(chip, data, sizeof(data)); /** * tpm_continue_selftest -- run TPM's selftest * @chip: TPM chip to use * * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing * a TPM error code. */ static int tpm_continue_selftest(struct tpm_chip *chip) { int rc; struct tpm_cmd_t cmd; cmd.header.in = continue_selftest_header; rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, "continue selftest"); return rc; } EXPORT_SYMBOL_GPL(tpm_continue_selftest); ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) Loading Loading @@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = { .ordinal = TPM_ORDINAL_PCRREAD }; int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) { int rc; struct tpm_cmd_t cmd; Loading Loading @@ -798,6 +816,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) } EXPORT_SYMBOL_GPL(tpm_pcr_extend); /** * tpm_do_selftest - have the TPM continue its selftest and wait until it * can receive further commands * @chip: TPM chip to use * * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing * a TPM error code. */ int tpm_do_selftest(struct tpm_chip *chip) { int rc; u8 digest[TPM_DIGEST_SIZE]; unsigned int loops; unsigned int delay_msec = 1000; unsigned long duration; duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); loops = jiffies_to_msecs(duration) / delay_msec; rc = tpm_continue_selftest(chip); /* This may fail if there was no TPM driver during a suspend/resume * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) */ if (rc) return rc; do { rc = __tpm_pcr_read(chip, 0, digest); if (rc != TPM_WARN_DOING_SELFTEST) return rc; msleep(delay_msec); } while (--loops > 0); return rc; } EXPORT_SYMBOL_GPL(tpm_do_selftest); int tpm_send(u32 chip_num, void *cmd, size_t buflen) { struct tpm_chip *chip; Loading Loading @@ -1005,6 +1062,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 * Loading
drivers/char/tpm/tpm.h +6 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,8 @@ enum tpm_addr { TPM_ADDR = 0x4E, }; #define TPM_WARN_DOING_SELFTEST 0x802 #define TPM_HEADER_SIZE 10 extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, char *); extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, Loading Loading @@ -279,9 +281,9 @@ struct tpm_cmd_t { ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern void tpm_get_timeouts(struct tpm_chip *); extern int tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); extern void tpm_continue_selftest(struct tpm_chip *); extern int tpm_do_selftest(struct tpm_chip *); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); extern struct tpm_chip* tpm_register_hardware(struct device *, const struct tpm_vendor_specific *); Loading @@ -294,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 **); Loading
drivers/char/tpm/tpm_tis.c +27 −57 Original line number Diff line number Diff line Loading @@ -29,8 +29,6 @@ #include <linux/freezer.h> #include "tpm.h" #define TPM_HEADER_SIZE 10 enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20, Loading Loading @@ -193,51 +191,11 @@ 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 = tpm_tis_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, ((tpm_tis_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 = tpm_tis_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, wait_for_tpm_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, chip->vendor.timeout_c, &chip->vendor.read_queue) Loading Loading @@ -282,7 +240,7 @@ 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, 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? */ Loading Loading @@ -317,7 +275,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; Loading @@ -333,7 +291,7 @@ 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, 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) { Loading @@ -345,7 +303,7 @@ 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, 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) { Loading Loading @@ -381,7 +339,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) { Loading Loading @@ -432,6 +390,9 @@ static int probe_itpm(struct tpm_chip *chip) out: itpm = rem_itpm; tpm_tis_ready(chip); /* some TPMs need a break here otherwise they will not work * correctly on the immediately subsequent command */ msleep(chip->vendor.timeout_b); release_locality(chip, chip->vendor.locality, 0); return rc; Loading Loading @@ -614,7 +575,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, dev_dbg(dev, "\tData Avail Int Support\n"); /* get the timeouts before testing for irqs */ tpm_get_timeouts(chip); if (tpm_get_timeouts(chip)) { dev_err(dev, "Could not get TPM timeouts and durations\n"); rc = -ENODEV; goto out_err; } if (tpm_do_selftest(chip)) { dev_err(dev, "TPM self test failed\n"); rc = -ENODEV; goto out_err; } /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); Loading Loading @@ -722,7 +693,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, list_add(&chip->vendor.list, &tis_chips); spin_unlock(&tis_lock); tpm_continue_selftest(chip); return 0; out_err: Loading Loading @@ -790,7 +760,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) ret = tpm_pm_resume(&dev->dev); if (!ret) tpm_continue_selftest(chip); tpm_do_selftest(chip); return ret; } Loading