diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-11 00:51:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-11 00:51:23 -0500 |
commit | e7691a1ce341c80ed9504244a36b31c025217391 (patch) | |
tree | e9941bb350f64a726130e299c411821da6f41a53 /drivers/char | |
parent | 5cd9599bba428762025db6027764f1c59d0b1e1b (diff) | |
parent | 8fcc99549522fc7a0bbaeb5755855ab0d9a59ce8 (diff) |
Merge branch 'for-linus' of git://selinuxproject.org/~jmorris/linux-security
* 'for-linus' of git://selinuxproject.org/~jmorris/linux-security: (32 commits)
ima: fix invalid memory reference
ima: free duplicate measurement memory
security: update security_file_mmap() docs
selinux: Casting (void *) value returned by kmalloc is useless
apparmor: fix module parameter handling
Security: tomoyo: add .gitignore file
tomoyo: add missing rcu_dereference()
apparmor: add missing rcu_dereference()
evm: prevent racing during tfm allocation
evm: key must be set once during initialization
mpi/mpi-mpow: NULL dereference on allocation failure
digsig: build dependency fix
KEYS: Give key types their own lockdep class for key->sem
TPM: fix transmit_cmd error logic
TPM: NSC and TIS drivers X86 dependency fix
TPM: Export wait_for_stat for other vendor specific drivers
TPM: Use vendor specific function for status probe
tpm_tis: add delay after aborting command
tpm_tis: Check return code from getting timeouts/durations
tpm: Introduce function to poll for result of self test
...
Fix up trivial conflict in lib/Makefile due to addition of CONFIG_MPI
and SIGSIG next to CONFIG_DQL addition.
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 137 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 9 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 84 |
4 files changed, 152 insertions, 80 deletions
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index fa567f1158c2..7fc75e47e6d0 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -27,6 +27,7 @@ if TCG_TPM | |||
27 | 27 | ||
28 | config TCG_TIS | 28 | config TCG_TIS |
29 | tristate "TPM Interface Specification 1.2 Interface" | 29 | tristate "TPM Interface Specification 1.2 Interface" |
30 | depends on X86 | ||
30 | ---help--- | 31 | ---help--- |
31 | If you have a TPM security chip that is compliant with the | 32 | If you have a TPM security chip that is compliant with the |
32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 33 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
@@ -35,6 +36,7 @@ config TCG_TIS | |||
35 | 36 | ||
36 | config TCG_NSC | 37 | config TCG_NSC |
37 | tristate "National Semiconductor TPM Interface" | 38 | tristate "National Semiconductor TPM Interface" |
39 | depends on X86 | ||
38 | ---help--- | 40 | ---help--- |
39 | If you have a TPM security chip from National Semiconductor | 41 | If you have a TPM security chip from National Semiconductor |
40 | say Yes and it will be accessible from within Linux. To | 42 | say Yes and it will be accessible from within Linux. To |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 361a1dff8f77..6a8771f47a55 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/freezer.h> | ||
30 | 31 | ||
31 | #include "tpm.h" | 32 | #include "tpm.h" |
32 | 33 | ||
@@ -440,7 +441,6 @@ out: | |||
440 | } | 441 | } |
441 | 442 | ||
442 | #define TPM_DIGEST_SIZE 20 | 443 | #define TPM_DIGEST_SIZE 20 |
443 | #define TPM_ERROR_SIZE 10 | ||
444 | #define TPM_RET_CODE_IDX 6 | 444 | #define TPM_RET_CODE_IDX 6 |
445 | 445 | ||
446 | enum tpm_capabilities { | 446 | enum tpm_capabilities { |
@@ -469,12 +469,14 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | |||
469 | len = tpm_transmit(chip,(u8 *) cmd, len); | 469 | len = tpm_transmit(chip,(u8 *) cmd, len); |
470 | if (len < 0) | 470 | if (len < 0) |
471 | return len; | 471 | return len; |
472 | if (len == TPM_ERROR_SIZE) { | 472 | else if (len < TPM_HEADER_SIZE) |
473 | err = be32_to_cpu(cmd->header.out.return_code); | 473 | return -EFAULT; |
474 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | 474 | |
475 | return err; | 475 | err = be32_to_cpu(cmd->header.out.return_code); |
476 | } | 476 | if (err != 0) |
477 | return 0; | 477 | dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); |
478 | |||
479 | return err; | ||
478 | } | 480 | } |
479 | 481 | ||
480 | #define TPM_INTERNAL_RESULT_SIZE 200 | 482 | #define TPM_INTERNAL_RESULT_SIZE 200 |
@@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) | |||
530 | } | 532 | } |
531 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 533 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
532 | 534 | ||
533 | void tpm_get_timeouts(struct tpm_chip *chip) | 535 | int tpm_get_timeouts(struct tpm_chip *chip) |
534 | { | 536 | { |
535 | struct tpm_cmd_t tpm_cmd; | 537 | struct tpm_cmd_t tpm_cmd; |
536 | struct timeout_t *timeout_cap; | 538 | struct timeout_t *timeout_cap; |
@@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) | |||
552 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || | 554 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
553 | be32_to_cpu(tpm_cmd.header.out.length) | 555 | be32_to_cpu(tpm_cmd.header.out.length) |
554 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) | 556 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) |
555 | return; | 557 | return -EINVAL; |
556 | 558 | ||
557 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; | 559 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; |
558 | /* Don't overwrite default if value is 0 */ | 560 | /* Don't overwrite default if value is 0 */ |
@@ -583,12 +585,12 @@ duration: | |||
583 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 585 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
584 | "attempting to determine the durations"); | 586 | "attempting to determine the durations"); |
585 | if (rc) | 587 | if (rc) |
586 | return; | 588 | return rc; |
587 | 589 | ||
588 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || | 590 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
589 | be32_to_cpu(tpm_cmd.header.out.length) | 591 | be32_to_cpu(tpm_cmd.header.out.length) |
590 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) | 592 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) |
591 | return; | 593 | return -EINVAL; |
592 | 594 | ||
593 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; | 595 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; |
594 | chip->vendor.duration[TPM_SHORT] = | 596 | chip->vendor.duration[TPM_SHORT] = |
@@ -610,20 +612,36 @@ duration: | |||
610 | chip->vendor.duration_adjusted = true; | 612 | chip->vendor.duration_adjusted = true; |
611 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); | 613 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); |
612 | } | 614 | } |
615 | return 0; | ||
613 | } | 616 | } |
614 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | 617 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); |
615 | 618 | ||
616 | void tpm_continue_selftest(struct tpm_chip *chip) | 619 | #define TPM_ORD_CONTINUE_SELFTEST 83 |
620 | #define CONTINUE_SELFTEST_RESULT_SIZE 10 | ||
621 | |||
622 | static struct tpm_input_header continue_selftest_header = { | ||
623 | .tag = TPM_TAG_RQU_COMMAND, | ||
624 | .length = cpu_to_be32(10), | ||
625 | .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), | ||
626 | }; | ||
627 | |||
628 | /** | ||
629 | * tpm_continue_selftest -- run TPM's selftest | ||
630 | * @chip: TPM chip to use | ||
631 | * | ||
632 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
633 | * a TPM error code. | ||
634 | */ | ||
635 | static int tpm_continue_selftest(struct tpm_chip *chip) | ||
617 | { | 636 | { |
618 | u8 data[] = { | 637 | int rc; |
619 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 638 | struct tpm_cmd_t cmd; |
620 | 0, 0, 0, 10, /* length */ | ||
621 | 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ | ||
622 | }; | ||
623 | 639 | ||
624 | tpm_transmit(chip, data, sizeof(data)); | 640 | cmd.header.in = continue_selftest_header; |
641 | rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, | ||
642 | "continue selftest"); | ||
643 | return rc; | ||
625 | } | 644 | } |
626 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | ||
627 | 645 | ||
628 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 646 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
629 | char *buf) | 647 | char *buf) |
@@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = { | |||
718 | .ordinal = TPM_ORDINAL_PCRREAD | 736 | .ordinal = TPM_ORDINAL_PCRREAD |
719 | }; | 737 | }; |
720 | 738 | ||
721 | int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | 739 | static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
722 | { | 740 | { |
723 | int rc; | 741 | int rc; |
724 | struct tpm_cmd_t cmd; | 742 | struct tpm_cmd_t cmd; |
@@ -798,6 +816,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
798 | } | 816 | } |
799 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); | 817 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); |
800 | 818 | ||
819 | /** | ||
820 | * tpm_do_selftest - have the TPM continue its selftest and wait until it | ||
821 | * can receive further commands | ||
822 | * @chip: TPM chip to use | ||
823 | * | ||
824 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
825 | * a TPM error code. | ||
826 | */ | ||
827 | int tpm_do_selftest(struct tpm_chip *chip) | ||
828 | { | ||
829 | int rc; | ||
830 | u8 digest[TPM_DIGEST_SIZE]; | ||
831 | unsigned int loops; | ||
832 | unsigned int delay_msec = 1000; | ||
833 | unsigned long duration; | ||
834 | |||
835 | duration = tpm_calc_ordinal_duration(chip, | ||
836 | TPM_ORD_CONTINUE_SELFTEST); | ||
837 | |||
838 | loops = jiffies_to_msecs(duration) / delay_msec; | ||
839 | |||
840 | rc = tpm_continue_selftest(chip); | ||
841 | /* This may fail if there was no TPM driver during a suspend/resume | ||
842 | * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) | ||
843 | */ | ||
844 | if (rc) | ||
845 | return rc; | ||
846 | |||
847 | do { | ||
848 | rc = __tpm_pcr_read(chip, 0, digest); | ||
849 | if (rc != TPM_WARN_DOING_SELFTEST) | ||
850 | return rc; | ||
851 | msleep(delay_msec); | ||
852 | } while (--loops > 0); | ||
853 | |||
854 | return rc; | ||
855 | } | ||
856 | EXPORT_SYMBOL_GPL(tpm_do_selftest); | ||
857 | |||
801 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) | 858 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) |
802 | { | 859 | { |
803 | struct tpm_chip *chip; | 860 | struct tpm_chip *chip; |
@@ -1005,6 +1062,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | |||
1005 | } | 1062 | } |
1006 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | 1063 | EXPORT_SYMBOL_GPL(tpm_store_cancel); |
1007 | 1064 | ||
1065 | int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
1066 | wait_queue_head_t *queue) | ||
1067 | { | ||
1068 | unsigned long stop; | ||
1069 | long rc; | ||
1070 | u8 status; | ||
1071 | |||
1072 | /* check current status */ | ||
1073 | status = chip->vendor.status(chip); | ||
1074 | if ((status & mask) == mask) | ||
1075 | return 0; | ||
1076 | |||
1077 | stop = jiffies + timeout; | ||
1078 | |||
1079 | if (chip->vendor.irq) { | ||
1080 | again: | ||
1081 | timeout = stop - jiffies; | ||
1082 | if ((long)timeout <= 0) | ||
1083 | return -ETIME; | ||
1084 | rc = wait_event_interruptible_timeout(*queue, | ||
1085 | ((chip->vendor.status(chip) | ||
1086 | & mask) == mask), | ||
1087 | timeout); | ||
1088 | if (rc > 0) | ||
1089 | return 0; | ||
1090 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
1091 | clear_thread_flag(TIF_SIGPENDING); | ||
1092 | goto again; | ||
1093 | } | ||
1094 | } else { | ||
1095 | do { | ||
1096 | msleep(TPM_TIMEOUT); | ||
1097 | status = chip->vendor.status(chip); | ||
1098 | if ((status & mask) == mask) | ||
1099 | return 0; | ||
1100 | } while (time_before(jiffies, stop)); | ||
1101 | } | ||
1102 | return -ETIME; | ||
1103 | } | ||
1104 | EXPORT_SYMBOL_GPL(wait_for_tpm_stat); | ||
1008 | /* | 1105 | /* |
1009 | * Device file system interface to the TPM | 1106 | * Device file system interface to the TPM |
1010 | * | 1107 | * |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9c4163cfa3ce..8c1df302fbb6 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -38,6 +38,8 @@ enum tpm_addr { | |||
38 | TPM_ADDR = 0x4E, | 38 | TPM_ADDR = 0x4E, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | #define TPM_WARN_DOING_SELFTEST 0x802 | ||
42 | #define TPM_HEADER_SIZE 10 | ||
41 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, | 43 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, |
42 | char *); | 44 | char *); |
43 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | 45 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, |
@@ -279,9 +281,9 @@ struct tpm_cmd_t { | |||
279 | 281 | ||
280 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | 282 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); |
281 | 283 | ||
282 | extern void tpm_get_timeouts(struct tpm_chip *); | 284 | extern int tpm_get_timeouts(struct tpm_chip *); |
283 | extern void tpm_gen_interrupt(struct tpm_chip *); | 285 | extern void tpm_gen_interrupt(struct tpm_chip *); |
284 | extern void tpm_continue_selftest(struct tpm_chip *); | 286 | extern int tpm_do_selftest(struct tpm_chip *); |
285 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | 287 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); |
286 | extern struct tpm_chip* tpm_register_hardware(struct device *, | 288 | extern struct tpm_chip* tpm_register_hardware(struct device *, |
287 | const struct tpm_vendor_specific *); | 289 | const struct tpm_vendor_specific *); |
@@ -294,7 +296,8 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); | |||
294 | extern void tpm_remove_hardware(struct device *); | 296 | extern void tpm_remove_hardware(struct device *); |
295 | extern int tpm_pm_suspend(struct device *, pm_message_t); | 297 | extern int tpm_pm_suspend(struct device *, pm_message_t); |
296 | extern int tpm_pm_resume(struct device *); | 298 | extern int tpm_pm_resume(struct device *); |
297 | 299 | extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, | |
300 | wait_queue_head_t *); | ||
298 | #ifdef CONFIG_ACPI | 301 | #ifdef CONFIG_ACPI |
299 | extern struct dentry ** tpm_bios_log_setup(char *); | 302 | extern struct dentry ** tpm_bios_log_setup(char *); |
300 | extern void tpm_bios_log_teardown(struct dentry **); | 303 | 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 3f4051a7c5a7..10cc44ceb5d1 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <linux/freezer.h> | 29 | #include <linux/freezer.h> |
30 | #include "tpm.h" | 30 | #include "tpm.h" |
31 | 31 | ||
32 | #define TPM_HEADER_SIZE 10 | ||
33 | |||
34 | enum tis_access { | 32 | enum tis_access { |
35 | TPM_ACCESS_VALID = 0x80, | 33 | TPM_ACCESS_VALID = 0x80, |
36 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | 34 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, |
@@ -193,54 +191,14 @@ static int get_burstcount(struct tpm_chip *chip) | |||
193 | return -EBUSY; | 191 | return -EBUSY; |
194 | } | 192 | } |
195 | 193 | ||
196 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
197 | wait_queue_head_t *queue) | ||
198 | { | ||
199 | unsigned long stop; | ||
200 | long rc; | ||
201 | u8 status; | ||
202 | |||
203 | /* check current status */ | ||
204 | status = tpm_tis_status(chip); | ||
205 | if ((status & mask) == mask) | ||
206 | return 0; | ||
207 | |||
208 | stop = jiffies + timeout; | ||
209 | |||
210 | if (chip->vendor.irq) { | ||
211 | again: | ||
212 | timeout = stop - jiffies; | ||
213 | if ((long)timeout <= 0) | ||
214 | return -ETIME; | ||
215 | rc = wait_event_interruptible_timeout(*queue, | ||
216 | ((tpm_tis_status | ||
217 | (chip) & mask) == | ||
218 | mask), timeout); | ||
219 | if (rc > 0) | ||
220 | return 0; | ||
221 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
222 | clear_thread_flag(TIF_SIGPENDING); | ||
223 | goto again; | ||
224 | } | ||
225 | } else { | ||
226 | do { | ||
227 | msleep(TPM_TIMEOUT); | ||
228 | status = tpm_tis_status(chip); | ||
229 | if ((status & mask) == mask) | ||
230 | return 0; | ||
231 | } while (time_before(jiffies, stop)); | ||
232 | } | ||
233 | return -ETIME; | ||
234 | } | ||
235 | |||
236 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | 194 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) |
237 | { | 195 | { |
238 | int size = 0, burstcnt; | 196 | int size = 0, burstcnt; |
239 | while (size < count && | 197 | while (size < count && |
240 | wait_for_stat(chip, | 198 | wait_for_tpm_stat(chip, |
241 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 199 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
242 | chip->vendor.timeout_c, | 200 | chip->vendor.timeout_c, |
243 | &chip->vendor.read_queue) | 201 | &chip->vendor.read_queue) |
244 | == 0) { | 202 | == 0) { |
245 | burstcnt = get_burstcount(chip); | 203 | burstcnt = get_burstcount(chip); |
246 | for (; burstcnt > 0 && size < count; burstcnt--) | 204 | for (; burstcnt > 0 && size < count; burstcnt--) |
@@ -282,8 +240,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
282 | goto out; | 240 | goto out; |
283 | } | 241 | } |
284 | 242 | ||
285 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 243 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
286 | &chip->vendor.int_queue); | 244 | &chip->vendor.int_queue); |
287 | status = tpm_tis_status(chip); | 245 | status = tpm_tis_status(chip); |
288 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | 246 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ |
289 | dev_err(chip->dev, "Error left over data\n"); | 247 | dev_err(chip->dev, "Error left over data\n"); |
@@ -317,7 +275,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
317 | status = tpm_tis_status(chip); | 275 | status = tpm_tis_status(chip); |
318 | if ((status & TPM_STS_COMMAND_READY) == 0) { | 276 | if ((status & TPM_STS_COMMAND_READY) == 0) { |
319 | tpm_tis_ready(chip); | 277 | tpm_tis_ready(chip); |
320 | if (wait_for_stat | 278 | if (wait_for_tpm_stat |
321 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | 279 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, |
322 | &chip->vendor.int_queue) < 0) { | 280 | &chip->vendor.int_queue) < 0) { |
323 | rc = -ETIME; | 281 | rc = -ETIME; |
@@ -333,8 +291,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
333 | count++; | 291 | count++; |
334 | } | 292 | } |
335 | 293 | ||
336 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 294 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
337 | &chip->vendor.int_queue); | 295 | &chip->vendor.int_queue); |
338 | status = tpm_tis_status(chip); | 296 | status = tpm_tis_status(chip); |
339 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { | 297 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { |
340 | rc = -EIO; | 298 | rc = -EIO; |
@@ -345,8 +303,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
345 | /* write last byte */ | 303 | /* write last byte */ |
346 | iowrite8(buf[count], | 304 | iowrite8(buf[count], |
347 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); | 305 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); |
348 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 306 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
349 | &chip->vendor.int_queue); | 307 | &chip->vendor.int_queue); |
350 | status = tpm_tis_status(chip); | 308 | status = tpm_tis_status(chip); |
351 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | 309 | if ((status & TPM_STS_DATA_EXPECT) != 0) { |
352 | rc = -EIO; | 310 | rc = -EIO; |
@@ -381,7 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
381 | 339 | ||
382 | if (chip->vendor.irq) { | 340 | if (chip->vendor.irq) { |
383 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | 341 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
384 | if (wait_for_stat | 342 | if (wait_for_tpm_stat |
385 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 343 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
386 | tpm_calc_ordinal_duration(chip, ordinal), | 344 | tpm_calc_ordinal_duration(chip, ordinal), |
387 | &chip->vendor.read_queue) < 0) { | 345 | &chip->vendor.read_queue) < 0) { |
@@ -432,6 +390,9 @@ static int probe_itpm(struct tpm_chip *chip) | |||
432 | out: | 390 | out: |
433 | itpm = rem_itpm; | 391 | itpm = rem_itpm; |
434 | tpm_tis_ready(chip); | 392 | tpm_tis_ready(chip); |
393 | /* some TPMs need a break here otherwise they will not work | ||
394 | * correctly on the immediately subsequent command */ | ||
395 | msleep(chip->vendor.timeout_b); | ||
435 | release_locality(chip, chip->vendor.locality, 0); | 396 | release_locality(chip, chip->vendor.locality, 0); |
436 | 397 | ||
437 | return rc; | 398 | return rc; |
@@ -614,7 +575,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
614 | dev_dbg(dev, "\tData Avail Int Support\n"); | 575 | dev_dbg(dev, "\tData Avail Int Support\n"); |
615 | 576 | ||
616 | /* get the timeouts before testing for irqs */ | 577 | /* get the timeouts before testing for irqs */ |
617 | tpm_get_timeouts(chip); | 578 | if (tpm_get_timeouts(chip)) { |
579 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | ||
580 | rc = -ENODEV; | ||
581 | goto out_err; | ||
582 | } | ||
583 | |||
584 | if (tpm_do_selftest(chip)) { | ||
585 | dev_err(dev, "TPM self test failed\n"); | ||
586 | rc = -ENODEV; | ||
587 | goto out_err; | ||
588 | } | ||
618 | 589 | ||
619 | /* INTERRUPT Setup */ | 590 | /* INTERRUPT Setup */ |
620 | init_waitqueue_head(&chip->vendor.read_queue); | 591 | init_waitqueue_head(&chip->vendor.read_queue); |
@@ -722,7 +693,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
722 | list_add(&chip->vendor.list, &tis_chips); | 693 | list_add(&chip->vendor.list, &tis_chips); |
723 | spin_unlock(&tis_lock); | 694 | spin_unlock(&tis_lock); |
724 | 695 | ||
725 | tpm_continue_selftest(chip); | ||
726 | 696 | ||
727 | return 0; | 697 | return 0; |
728 | out_err: | 698 | out_err: |
@@ -790,7 +760,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) | |||
790 | 760 | ||
791 | ret = tpm_pm_resume(&dev->dev); | 761 | ret = tpm_pm_resume(&dev->dev); |
792 | if (!ret) | 762 | if (!ret) |
793 | tpm_continue_selftest(chip); | 763 | tpm_do_selftest(chip); |
794 | 764 | ||
795 | return ret; | 765 | return ret; |
796 | } | 766 | } |