aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-27 22:26:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-27 22:26:38 -0400
commit95b6886526bb510b8370b625a49bc0ab3b8ff10f (patch)
tree2862606224820d200be12d2092dcd26df1654b80 /drivers/char
parent22712200e175e0df5c7f9edfe6c6bf5c94c23b83 (diff)
parent29412f0f6a19e34336368f13eab848091c343952 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (54 commits) tpm_nsc: Fix bug when loading multiple TPM drivers tpm: Move tpm_tis_reenable_interrupts out of CONFIG_PNP block tpm: Fix compilation warning when CONFIG_PNP is not defined TOMOYO: Update kernel-doc. tpm: Fix a typo tpm_tis: Probing function for Intel iTPM bug tpm_tis: Fix the probing for interrupts tpm_tis: Delay ACPI S3 suspend while the TPM is busy tpm_tis: Re-enable interrupts upon (S3) resume tpm: Fix display of data in pubek sysfs entry tpm_tis: Add timeouts sysfs entry tpm: Adjust interface timeouts if they are too small tpm: Use interface timeouts returned from the TPM tpm_tis: Introduce durations sysfs entry tpm: Adjust the durations if they are too small tpm: Use durations returned from TPM TOMOYO: Enable conditional ACL. TOMOYO: Allow using argv[]/envp[] of execve() as conditions. TOMOYO: Allow using executable's realpath and symlink's target as conditions. TOMOYO: Allow using owner/group etc. of file objects as conditions. ... Fix up trivial conflict in security/tomoyo/realpath.c
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm.c102
-rw-r--r--drivers/char/tpm/tpm.h7
-rw-r--r--drivers/char/tpm/tpm_nsc.c14
-rw-r--r--drivers/char/tpm/tpm_tis.c182
4 files changed, 250 insertions, 55 deletions
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7beb0e25f1e1..caf8012ef47c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
534 struct duration_t *duration_cap; 534 struct duration_t *duration_cap;
535 ssize_t rc; 535 ssize_t rc;
536 u32 timeout; 536 u32 timeout;
537 unsigned int scale = 1;
537 538
538 tpm_cmd.header.in = tpm_getcap_header; 539 tpm_cmd.header.in = tpm_getcap_header;
539 tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; 540 tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip)
545 if (rc) 546 if (rc)
546 goto duration; 547 goto duration;
547 548
548 if (be32_to_cpu(tpm_cmd.header.out.length) 549 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
549 != 4 * sizeof(u32)) 550 be32_to_cpu(tpm_cmd.header.out.length)
550 goto duration; 551 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
552 return;
551 553
552 timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; 554 timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
553 /* Don't overwrite default if value is 0 */ 555 /* Don't overwrite default if value is 0 */
554 timeout = be32_to_cpu(timeout_cap->a); 556 timeout = be32_to_cpu(timeout_cap->a);
557 if (timeout && timeout < 1000) {
558 /* timeouts in msec rather usec */
559 scale = 1000;
560 chip->vendor.timeout_adjusted = true;
561 }
555 if (timeout) 562 if (timeout)
556 chip->vendor.timeout_a = usecs_to_jiffies(timeout); 563 chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale);
557 timeout = be32_to_cpu(timeout_cap->b); 564 timeout = be32_to_cpu(timeout_cap->b);
558 if (timeout) 565 if (timeout)
559 chip->vendor.timeout_b = usecs_to_jiffies(timeout); 566 chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale);
560 timeout = be32_to_cpu(timeout_cap->c); 567 timeout = be32_to_cpu(timeout_cap->c);
561 if (timeout) 568 if (timeout)
562 chip->vendor.timeout_c = usecs_to_jiffies(timeout); 569 chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale);
563 timeout = be32_to_cpu(timeout_cap->d); 570 timeout = be32_to_cpu(timeout_cap->d);
564 if (timeout) 571 if (timeout)
565 chip->vendor.timeout_d = usecs_to_jiffies(timeout); 572 chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale);
566 573
567duration: 574duration:
568 tpm_cmd.header.in = tpm_getcap_header; 575 tpm_cmd.header.in = tpm_getcap_header;
@@ -575,23 +582,31 @@ duration:
575 if (rc) 582 if (rc)
576 return; 583 return;
577 584
578 if (be32_to_cpu(tpm_cmd.header.out.return_code) 585 if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
579 != 3 * sizeof(u32)) 586 be32_to_cpu(tpm_cmd.header.out.length)
587 != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
580 return; 588 return;
589
581 duration_cap = &tpm_cmd.params.getcap_out.cap.duration; 590 duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
582 chip->vendor.duration[TPM_SHORT] = 591 chip->vendor.duration[TPM_SHORT] =
583 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); 592 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
593 chip->vendor.duration[TPM_MEDIUM] =
594 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
595 chip->vendor.duration[TPM_LONG] =
596 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
597
584 /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above 598 /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
585 * value wrong and apparently reports msecs rather than usecs. So we 599 * value wrong and apparently reports msecs rather than usecs. So we
586 * fix up the resulting too-small TPM_SHORT value to make things work. 600 * fix up the resulting too-small TPM_SHORT value to make things work.
601 * We also scale the TPM_MEDIUM and -_LONG values by 1000.
587 */ 602 */
588 if (chip->vendor.duration[TPM_SHORT] < (HZ/100)) 603 if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
589 chip->vendor.duration[TPM_SHORT] = HZ; 604 chip->vendor.duration[TPM_SHORT] = HZ;
590 605 chip->vendor.duration[TPM_MEDIUM] *= 1000;
591 chip->vendor.duration[TPM_MEDIUM] = 606 chip->vendor.duration[TPM_LONG] *= 1000;
592 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); 607 chip->vendor.duration_adjusted = true;
593 chip->vendor.duration[TPM_LONG] = 608 dev_info(chip->dev, "Adjusting TPM timeout parameters.");
594 usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); 609 }
595} 610}
596EXPORT_SYMBOL_GPL(tpm_get_timeouts); 611EXPORT_SYMBOL_GPL(tpm_get_timeouts);
597 612
@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip)
600 u8 data[] = { 615 u8 data[] = {
601 0, 193, /* TPM_TAG_RQU_COMMAND */ 616 0, 193, /* TPM_TAG_RQU_COMMAND */
602 0, 0, 0, 10, /* length */ 617 0, 0, 0, 10, /* length */
603 0, 0, 0, 83, /* TPM_ORD_GetCapability */ 618 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
604 }; 619 };
605 620
606 tpm_transmit(chip, data, sizeof(data)); 621 tpm_transmit(chip, data, sizeof(data));
@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
863 data = tpm_cmd.params.readpubek_out_buffer; 878 data = tpm_cmd.params.readpubek_out_buffer;
864 str += 879 str +=
865 sprintf(str, 880 sprintf(str,
866 "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" 881 "Algorithm: %02X %02X %02X %02X\n"
867 "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X" 882 "Encscheme: %02X %02X\n"
868 " %02X %02X %02X %02X %02X %02X %02X %02X\n" 883 "Sigscheme: %02X %02X\n"
869 "Modulus length: %d\nModulus: \n", 884 "Parameters: %02X %02X %02X %02X "
870 data[10], data[11], data[12], data[13], data[14], 885 "%02X %02X %02X %02X "
871 data[15], data[16], data[17], data[22], data[23], 886 "%02X %02X %02X %02X\n"
872 data[24], data[25], data[26], data[27], data[28], 887 "Modulus length: %d\n"
873 data[29], data[30], data[31], data[32], data[33], 888 "Modulus:\n",
874 be32_to_cpu(*((__be32 *) (data + 34)))); 889 data[0], data[1], data[2], data[3],
890 data[4], data[5],
891 data[6], data[7],
892 data[12], data[13], data[14], data[15],
893 data[16], data[17], data[18], data[19],
894 data[20], data[21], data[22], data[23],
895 be32_to_cpu(*((__be32 *) (data + 24))));
875 896
876 for (i = 0; i < 256; i++) { 897 for (i = 0; i < 256; i++) {
877 str += sprintf(str, "%02X ", data[i + 38]); 898 str += sprintf(str, "%02X ", data[i + 28]);
878 if ((i + 1) % 16 == 0) 899 if ((i + 1) % 16 == 0)
879 str += sprintf(str, "\n"); 900 str += sprintf(str, "\n");
880 } 901 }
@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev,
937} 958}
938EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); 959EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
939 960
961ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
962 char *buf)
963{
964 struct tpm_chip *chip = dev_get_drvdata(dev);
965
966 return sprintf(buf, "%d %d %d [%s]\n",
967 jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
968 jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
969 jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
970 chip->vendor.duration_adjusted
971 ? "adjusted" : "original");
972}
973EXPORT_SYMBOL_GPL(tpm_show_durations);
974
975ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr,
976 char *buf)
977{
978 struct tpm_chip *chip = dev_get_drvdata(dev);
979
980 return sprintf(buf, "%d %d %d %d [%s]\n",
981 jiffies_to_usecs(chip->vendor.timeout_a),
982 jiffies_to_usecs(chip->vendor.timeout_b),
983 jiffies_to_usecs(chip->vendor.timeout_c),
984 jiffies_to_usecs(chip->vendor.timeout_d),
985 chip->vendor.timeout_adjusted
986 ? "adjusted" : "original");
987}
988EXPORT_SYMBOL_GPL(tpm_show_timeouts);
989
940ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, 990ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
941 const char *buf, size_t count) 991 const char *buf, size_t count)
942{ 992{
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 72ddb031b69a..9c4163cfa3ce 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
56 char *); 56 char *);
57extern ssize_t tpm_show_temp_deactivated(struct device *, 57extern ssize_t tpm_show_temp_deactivated(struct device *,
58 struct device_attribute *attr, char *); 58 struct device_attribute *attr, char *);
59extern ssize_t tpm_show_durations(struct device *,
60 struct device_attribute *attr, char *);
61extern ssize_t tpm_show_timeouts(struct device *,
62 struct device_attribute *attr, char *);
59 63
60struct tpm_chip; 64struct tpm_chip;
61 65
@@ -67,6 +71,7 @@ struct tpm_vendor_specific {
67 unsigned long base; /* TPM base address */ 71 unsigned long base; /* TPM base address */
68 72
69 int irq; 73 int irq;
74 int probed_irq;
70 75
71 int region_size; 76 int region_size;
72 int have_region; 77 int have_region;
@@ -81,7 +86,9 @@ struct tpm_vendor_specific {
81 struct list_head list; 86 struct list_head list;
82 int locality; 87 int locality;
83 unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ 88 unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
89 bool timeout_adjusted;
84 unsigned long duration[3]; /* jiffies */ 90 unsigned long duration[3]; /* jiffies */
91 bool duration_adjusted;
85 92
86 wait_queue_head_t read_queue; 93 wait_queue_head_t read_queue;
87 wait_queue_head_t int_queue; 94 wait_queue_head_t int_queue;
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index a605cb7dd898..82facc9104c7 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -330,12 +330,12 @@ static int __init init_nsc(void)
330 pdev->dev.driver = &nsc_drv.driver; 330 pdev->dev.driver = &nsc_drv.driver;
331 pdev->dev.release = tpm_nsc_remove; 331 pdev->dev.release = tpm_nsc_remove;
332 332
333 if ((rc = platform_device_register(pdev)) < 0) 333 if ((rc = platform_device_add(pdev)) < 0)
334 goto err_free_dev; 334 goto err_put_dev;
335 335
336 if (request_region(base, 2, "tpm_nsc0") == NULL ) { 336 if (request_region(base, 2, "tpm_nsc0") == NULL ) {
337 rc = -EBUSY; 337 rc = -EBUSY;
338 goto err_unreg_dev; 338 goto err_del_dev;
339 } 339 }
340 340
341 if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { 341 if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
@@ -382,10 +382,10 @@ static int __init init_nsc(void)
382 382
383err_rel_reg: 383err_rel_reg:
384 release_region(base, 2); 384 release_region(base, 2);
385err_unreg_dev: 385err_del_dev:
386 platform_device_unregister(pdev); 386 platform_device_del(pdev);
387err_free_dev: 387err_put_dev:
388 kfree(pdev); 388 platform_device_put(pdev);
389err_unreg_drv: 389err_unreg_drv:
390 platform_driver_unregister(&nsc_drv); 390 platform_driver_unregister(&nsc_drv);
391 return rc; 391 return rc;
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index dd21df55689d..7fc2f108f490 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -26,6 +26,7 @@
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/wait.h> 27#include <linux/wait.h>
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29#include <linux/freezer.h>
29#include "tpm.h" 30#include "tpm.h"
30 31
31#define TPM_HEADER_SIZE 10 32#define TPM_HEADER_SIZE 10
@@ -79,7 +80,7 @@ enum tis_defaults {
79static LIST_HEAD(tis_chips); 80static LIST_HEAD(tis_chips);
80static DEFINE_SPINLOCK(tis_lock); 81static DEFINE_SPINLOCK(tis_lock);
81 82
82#ifdef CONFIG_ACPI 83#ifdef CONFIG_PNP
83static int is_itpm(struct pnp_dev *dev) 84static int is_itpm(struct pnp_dev *dev)
84{ 85{
85 struct acpi_device *acpi = pnp_acpi_device(dev); 86 struct acpi_device *acpi = pnp_acpi_device(dev);
@@ -92,11 +93,6 @@ static int is_itpm(struct pnp_dev *dev)
92 93
93 return 0; 94 return 0;
94} 95}
95#else
96static int is_itpm(struct pnp_dev *dev)
97{
98 return 0;
99}
100#endif 96#endif
101 97
102static int check_locality(struct tpm_chip *chip, int l) 98static int check_locality(struct tpm_chip *chip, int l)
@@ -120,7 +116,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force)
120 116
121static int request_locality(struct tpm_chip *chip, int l) 117static int request_locality(struct tpm_chip *chip, int l)
122{ 118{
123 unsigned long stop; 119 unsigned long stop, timeout;
124 long rc; 120 long rc;
125 121
126 if (check_locality(chip, l) >= 0) 122 if (check_locality(chip, l) >= 0)
@@ -129,17 +125,25 @@ static int request_locality(struct tpm_chip *chip, int l)
129 iowrite8(TPM_ACCESS_REQUEST_USE, 125 iowrite8(TPM_ACCESS_REQUEST_USE,
130 chip->vendor.iobase + TPM_ACCESS(l)); 126 chip->vendor.iobase + TPM_ACCESS(l));
131 127
128 stop = jiffies + chip->vendor.timeout_a;
129
132 if (chip->vendor.irq) { 130 if (chip->vendor.irq) {
131again:
132 timeout = stop - jiffies;
133 if ((long)timeout <= 0)
134 return -1;
133 rc = wait_event_interruptible_timeout(chip->vendor.int_queue, 135 rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
134 (check_locality 136 (check_locality
135 (chip, l) >= 0), 137 (chip, l) >= 0),
136 chip->vendor.timeout_a); 138 timeout);
137 if (rc > 0) 139 if (rc > 0)
138 return l; 140 return l;
139 141 if (rc == -ERESTARTSYS && freezing(current)) {
142 clear_thread_flag(TIF_SIGPENDING);
143 goto again;
144 }
140 } else { 145 } else {
141 /* wait for burstcount */ 146 /* wait for burstcount */
142 stop = jiffies + chip->vendor.timeout_a;
143 do { 147 do {
144 if (check_locality(chip, l) >= 0) 148 if (check_locality(chip, l) >= 0)
145 return l; 149 return l;
@@ -196,15 +200,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
196 if ((status & mask) == mask) 200 if ((status & mask) == mask)
197 return 0; 201 return 0;
198 202
203 stop = jiffies + timeout;
204
199 if (chip->vendor.irq) { 205 if (chip->vendor.irq) {
206again:
207 timeout = stop - jiffies;
208 if ((long)timeout <= 0)
209 return -ETIME;
200 rc = wait_event_interruptible_timeout(*queue, 210 rc = wait_event_interruptible_timeout(*queue,
201 ((tpm_tis_status 211 ((tpm_tis_status
202 (chip) & mask) == 212 (chip) & mask) ==
203 mask), timeout); 213 mask), timeout);
204 if (rc > 0) 214 if (rc > 0)
205 return 0; 215 return 0;
216 if (rc == -ERESTARTSYS && freezing(current)) {
217 clear_thread_flag(TIF_SIGPENDING);
218 goto again;
219 }
206 } else { 220 } else {
207 stop = jiffies + timeout;
208 do { 221 do {
209 msleep(TPM_TIMEOUT); 222 msleep(TPM_TIMEOUT);
210 status = tpm_tis_status(chip); 223 status = tpm_tis_status(chip);
@@ -288,11 +301,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
288 * tpm.c can skip polling for the data to be available as the interrupt is 301 * tpm.c can skip polling for the data to be available as the interrupt is
289 * waited for here 302 * waited for here
290 */ 303 */
291static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) 304static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
292{ 305{
293 int rc, status, burstcnt; 306 int rc, status, burstcnt;
294 size_t count = 0; 307 size_t count = 0;
295 u32 ordinal;
296 308
297 if (request_locality(chip, 0) < 0) 309 if (request_locality(chip, 0) < 0)
298 return -EBUSY; 310 return -EBUSY;
@@ -327,8 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
327 339
328 /* write last byte */ 340 /* write last byte */
329 iowrite8(buf[count], 341 iowrite8(buf[count],
330 chip->vendor.iobase + 342 chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
331 TPM_DATA_FIFO(chip->vendor.locality));
332 wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, 343 wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
333 &chip->vendor.int_queue); 344 &chip->vendor.int_queue);
334 status = tpm_tis_status(chip); 345 status = tpm_tis_status(chip);
@@ -337,6 +348,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
337 goto out_err; 348 goto out_err;
338 } 349 }
339 350
351 return 0;
352
353out_err:
354 tpm_tis_ready(chip);
355 release_locality(chip, chip->vendor.locality, 0);
356 return rc;
357}
358
359/*
360 * If interrupts are used (signaled by an irq set in the vendor structure)
361 * tpm.c can skip polling for the data to be available as the interrupt is
362 * waited for here
363 */
364static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
365{
366 int rc;
367 u32 ordinal;
368
369 rc = tpm_tis_send_data(chip, buf, len);
370 if (rc < 0)
371 return rc;
372
340 /* go and do it */ 373 /* go and do it */
341 iowrite8(TPM_STS_GO, 374 iowrite8(TPM_STS_GO,
342 chip->vendor.iobase + TPM_STS(chip->vendor.locality)); 375 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
@@ -358,6 +391,47 @@ out_err:
358 return rc; 391 return rc;
359} 392}
360 393
394/*
395 * Early probing for iTPM with STS_DATA_EXPECT flaw.
396 * Try sending command without itpm flag set and if that
397 * fails, repeat with itpm flag set.
398 */
399static int probe_itpm(struct tpm_chip *chip)
400{
401 int rc = 0;
402 u8 cmd_getticks[] = {
403 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
404 0x00, 0x00, 0x00, 0xf1
405 };
406 size_t len = sizeof(cmd_getticks);
407 int rem_itpm = itpm;
408
409 itpm = 0;
410
411 rc = tpm_tis_send_data(chip, cmd_getticks, len);
412 if (rc == 0)
413 goto out;
414
415 tpm_tis_ready(chip);
416 release_locality(chip, chip->vendor.locality, 0);
417
418 itpm = 1;
419
420 rc = tpm_tis_send_data(chip, cmd_getticks, len);
421 if (rc == 0) {
422 dev_info(chip->dev, "Detected an iTPM.\n");
423 rc = 1;
424 } else
425 rc = -EFAULT;
426
427out:
428 itpm = rem_itpm;
429 tpm_tis_ready(chip);
430 release_locality(chip, chip->vendor.locality, 0);
431
432 return rc;
433}
434
361static const struct file_operations tis_ops = { 435static const struct file_operations tis_ops = {
362 .owner = THIS_MODULE, 436 .owner = THIS_MODULE,
363 .llseek = no_llseek, 437 .llseek = no_llseek,
@@ -376,6 +450,8 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
376 NULL); 450 NULL);
377static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); 451static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
378static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); 452static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
453static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
454static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
379 455
380static struct attribute *tis_attrs[] = { 456static struct attribute *tis_attrs[] = {
381 &dev_attr_pubek.attr, 457 &dev_attr_pubek.attr,
@@ -385,7 +461,9 @@ static struct attribute *tis_attrs[] = {
385 &dev_attr_owned.attr, 461 &dev_attr_owned.attr,
386 &dev_attr_temp_deactivated.attr, 462 &dev_attr_temp_deactivated.attr,
387 &dev_attr_caps.attr, 463 &dev_attr_caps.attr,
388 &dev_attr_cancel.attr, NULL, 464 &dev_attr_cancel.attr,
465 &dev_attr_durations.attr,
466 &dev_attr_timeouts.attr, NULL,
389}; 467};
390 468
391static struct attribute_group tis_attr_grp = { 469static struct attribute_group tis_attr_grp = {
@@ -416,7 +494,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id)
416 if (interrupt == 0) 494 if (interrupt == 0)
417 return IRQ_NONE; 495 return IRQ_NONE;
418 496
419 chip->vendor.irq = irq; 497 chip->vendor.probed_irq = irq;
420 498
421 /* Clear interrupts handled with TPM_EOI */ 499 /* Clear interrupts handled with TPM_EOI */
422 iowrite32(interrupt, 500 iowrite32(interrupt,
@@ -464,7 +542,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
464 resource_size_t len, unsigned int irq) 542 resource_size_t len, unsigned int irq)
465{ 543{
466 u32 vendor, intfcaps, intmask; 544 u32 vendor, intfcaps, intmask;
467 int rc, i; 545 int rc, i, irq_s, irq_e;
468 struct tpm_chip *chip; 546 struct tpm_chip *chip;
469 547
470 if (!(chip = tpm_register_hardware(dev, &tpm_tis))) 548 if (!(chip = tpm_register_hardware(dev, &tpm_tis)))
@@ -493,6 +571,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
493 "1.2 TPM (device-id 0x%X, rev-id %d)\n", 571 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
494 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); 572 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
495 573
574 if (!itpm) {
575 itpm = probe_itpm(chip);
576 if (itpm < 0) {
577 rc = -ENODEV;
578 goto out_err;
579 }
580 }
581
496 if (itpm) 582 if (itpm)
497 dev_info(dev, "Intel iTPM workaround enabled\n"); 583 dev_info(dev, "Intel iTPM workaround enabled\n");
498 584
@@ -522,6 +608,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
522 if (intfcaps & TPM_INTF_DATA_AVAIL_INT) 608 if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
523 dev_dbg(dev, "\tData Avail Int Support\n"); 609 dev_dbg(dev, "\tData Avail Int Support\n");
524 610
611 /* get the timeouts before testing for irqs */
612 tpm_get_timeouts(chip);
613
525 /* INTERRUPT Setup */ 614 /* INTERRUPT Setup */
526 init_waitqueue_head(&chip->vendor.read_queue); 615 init_waitqueue_head(&chip->vendor.read_queue);
527 init_waitqueue_head(&chip->vendor.int_queue); 616 init_waitqueue_head(&chip->vendor.int_queue);
@@ -540,13 +629,19 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
540 if (interrupts) 629 if (interrupts)
541 chip->vendor.irq = irq; 630 chip->vendor.irq = irq;
542 if (interrupts && !chip->vendor.irq) { 631 if (interrupts && !chip->vendor.irq) {
543 chip->vendor.irq = 632 irq_s =
544 ioread8(chip->vendor.iobase + 633 ioread8(chip->vendor.iobase +
545 TPM_INT_VECTOR(chip->vendor.locality)); 634 TPM_INT_VECTOR(chip->vendor.locality));
635 if (irq_s) {
636 irq_e = irq_s;
637 } else {
638 irq_s = 3;
639 irq_e = 15;
640 }
546 641
547 for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { 642 for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) {
548 iowrite8(i, chip->vendor.iobase + 643 iowrite8(i, chip->vendor.iobase +
549 TPM_INT_VECTOR(chip->vendor.locality)); 644 TPM_INT_VECTOR(chip->vendor.locality));
550 if (request_irq 645 if (request_irq
551 (i, tis_int_probe, IRQF_SHARED, 646 (i, tis_int_probe, IRQF_SHARED,
552 chip->vendor.miscdev.name, chip) != 0) { 647 chip->vendor.miscdev.name, chip) != 0) {
@@ -568,9 +663,22 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
568 chip->vendor.iobase + 663 chip->vendor.iobase +
569 TPM_INT_ENABLE(chip->vendor.locality)); 664 TPM_INT_ENABLE(chip->vendor.locality));
570 665
666 chip->vendor.probed_irq = 0;
667
571 /* Generate Interrupts */ 668 /* Generate Interrupts */
572 tpm_gen_interrupt(chip); 669 tpm_gen_interrupt(chip);
573 670
671 chip->vendor.irq = chip->vendor.probed_irq;
672
673 /* free_irq will call into tis_int_probe;
674 clear all irqs we haven't seen while doing
675 tpm_gen_interrupt */
676 iowrite32(ioread32
677 (chip->vendor.iobase +
678 TPM_INT_STATUS(chip->vendor.locality)),
679 chip->vendor.iobase +
680 TPM_INT_STATUS(chip->vendor.locality));
681
574 /* Turn off */ 682 /* Turn off */
575 iowrite32(intmask, 683 iowrite32(intmask,
576 chip->vendor.iobase + 684 chip->vendor.iobase +
@@ -609,7 +717,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
609 list_add(&chip->vendor.list, &tis_chips); 717 list_add(&chip->vendor.list, &tis_chips);
610 spin_unlock(&tis_lock); 718 spin_unlock(&tis_lock);
611 719
612 tpm_get_timeouts(chip);
613 tpm_continue_selftest(chip); 720 tpm_continue_selftest(chip);
614 721
615 return 0; 722 return 0;
@@ -619,6 +726,29 @@ out_err:
619 tpm_remove_hardware(chip->dev); 726 tpm_remove_hardware(chip->dev);
620 return rc; 727 return rc;
621} 728}
729
730static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
731{
732 u32 intmask;
733
734 /* reenable interrupts that device may have lost or
735 BIOS/firmware may have disabled */
736 iowrite8(chip->vendor.irq, chip->vendor.iobase +
737 TPM_INT_VECTOR(chip->vendor.locality));
738
739 intmask =
740 ioread32(chip->vendor.iobase +
741 TPM_INT_ENABLE(chip->vendor.locality));
742
743 intmask |= TPM_INTF_CMD_READY_INT
744 | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
745 | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
746
747 iowrite32(intmask,
748 chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
749}
750
751
622#ifdef CONFIG_PNP 752#ifdef CONFIG_PNP
623static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, 753static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
624 const struct pnp_device_id *pnp_id) 754 const struct pnp_device_id *pnp_id)
@@ -650,6 +780,9 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
650 struct tpm_chip *chip = pnp_get_drvdata(dev); 780 struct tpm_chip *chip = pnp_get_drvdata(dev);
651 int ret; 781 int ret;
652 782
783 if (chip->vendor.irq)
784 tpm_tis_reenable_interrupts(chip);
785
653 ret = tpm_pm_resume(&dev->dev); 786 ret = tpm_pm_resume(&dev->dev);
654 if (!ret) 787 if (!ret)
655 tpm_continue_selftest(chip); 788 tpm_continue_selftest(chip);
@@ -702,6 +835,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
702 835
703static int tpm_tis_resume(struct platform_device *dev) 836static int tpm_tis_resume(struct platform_device *dev)
704{ 837{
838 struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
839
840 if (chip->vendor.irq)
841 tpm_tis_reenable_interrupts(chip);
842
705 return tpm_pm_resume(&dev->dev); 843 return tpm_pm_resume(&dev->dev);
706} 844}
707static struct platform_driver tis_drv = { 845static struct platform_driver tis_drv = {