hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/char/tpm/tpm_tis_core.c
....@@ -136,16 +136,27 @@
136136 return false;
137137 }
138138
139
-static int release_locality(struct tpm_chip *chip, int l)
139
+static int __tpm_tis_relinquish_locality(struct tpm_tis_data *priv, int l)
140140 {
141
- struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
142
-
143141 tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
144142
145143 return 0;
146144 }
147145
148
-static int request_locality(struct tpm_chip *chip, int l)
146
+static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l)
147
+{
148
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
149
+
150
+ mutex_lock(&priv->locality_count_mutex);
151
+ priv->locality_count--;
152
+ if (priv->locality_count == 0)
153
+ __tpm_tis_relinquish_locality(priv, l);
154
+ mutex_unlock(&priv->locality_count_mutex);
155
+
156
+ return 0;
157
+}
158
+
159
+static int __tpm_tis_request_locality(struct tpm_chip *chip, int l)
149160 {
150161 struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
151162 unsigned long stop, timeout;
....@@ -184,6 +195,20 @@
184195 } while (time_before(jiffies, stop));
185196 }
186197 return -1;
198
+}
199
+
200
+static int tpm_tis_request_locality(struct tpm_chip *chip, int l)
201
+{
202
+ struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
203
+ int ret = 0;
204
+
205
+ mutex_lock(&priv->locality_count_mutex);
206
+ if (priv->locality_count == 0)
207
+ ret = __tpm_tis_request_locality(chip, l);
208
+ if (!ret)
209
+ priv->locality_count++;
210
+ mutex_unlock(&priv->locality_count_mutex);
211
+ return ret;
187212 }
188213
189214 static u8 tpm_tis_status(struct tpm_chip *chip)
....@@ -289,6 +314,7 @@
289314 int size = 0;
290315 int status;
291316 u32 expected;
317
+ int rc;
292318
293319 if (count < TPM_HEADER_SIZE) {
294320 size = -EIO;
....@@ -308,8 +334,13 @@
308334 goto out;
309335 }
310336
311
- size += recv_data(chip, &buf[TPM_HEADER_SIZE],
312
- expected - TPM_HEADER_SIZE);
337
+ rc = recv_data(chip, &buf[TPM_HEADER_SIZE],
338
+ expected - TPM_HEADER_SIZE);
339
+ if (rc < 0) {
340
+ size = rc;
341
+ goto out;
342
+ }
343
+ size += rc;
313344 if (size < expected) {
314345 dev_err(&chip->dev, "Unable to read remainder of result\n");
315346 size = -ETIME;
....@@ -438,10 +469,17 @@
438469 int rc;
439470 u32 ordinal;
440471 unsigned long dur;
472
+ unsigned int try;
441473
442
- rc = tpm_tis_send_data(chip, buf, len);
443
- if (rc < 0)
444
- return rc;
474
+ for (try = 0; try < TPM_RETRY; try++) {
475
+ rc = tpm_tis_send_data(chip, buf, len);
476
+ if (rc >= 0)
477
+ /* Data transfer done successfully */
478
+ break;
479
+ else if (rc != -EIO)
480
+ /* Data transfer failed, not recoverable */
481
+ return rc;
482
+ }
445483
446484 /* go and do it */
447485 rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
....@@ -638,7 +676,7 @@
638676 if (vendor != TPM_VID_INTEL)
639677 return 0;
640678
641
- if (request_locality(chip, 0) != 0)
679
+ if (tpm_tis_request_locality(chip, 0) != 0)
642680 return -EBUSY;
643681
644682 rc = tpm_tis_send_data(chip, cmd_getticks, len);
....@@ -659,7 +697,7 @@
659697
660698 out:
661699 tpm_tis_ready(chip);
662
- release_locality(chip, priv->locality);
700
+ tpm_tis_relinquish_locality(chip, priv->locality);
663701
664702 return rc;
665703 }
....@@ -706,7 +744,9 @@
706744 wake_up_interruptible(&priv->int_queue);
707745
708746 /* Clear interrupts handled with TPM_EOI */
747
+ tpm_tis_request_locality(chip, 0);
709748 rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt);
749
+ tpm_tis_relinquish_locality(chip, 0);
710750 if (rc < 0)
711751 return IRQ_NONE;
712752
....@@ -714,25 +754,17 @@
714754 return IRQ_HANDLED;
715755 }
716756
717
-static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
757
+static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
718758 {
719759 const char *desc = "attempting to generate an interrupt";
720760 u32 cap2;
721761 cap_t cap;
722762 int ret;
723763
724
- ret = request_locality(chip, 0);
725
- if (ret < 0)
726
- return ret;
727
-
728764 if (chip->flags & TPM_CHIP_FLAG_TPM2)
729765 ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
730766 else
731767 ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
732
-
733
- release_locality(chip, 0);
734
-
735
- return ret;
736768 }
737769
738770 /* Register the IRQ and issue a command that will cause an interrupt. If an
....@@ -747,60 +779,66 @@
747779 int rc;
748780 u32 int_status;
749781
750
- if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags,
751
- dev_name(&chip->dev), chip) != 0) {
782
+
783
+ rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
784
+ tis_int_handler, IRQF_ONESHOT | flags,
785
+ dev_name(&chip->dev), chip);
786
+ if (rc) {
752787 dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
753788 irq);
754789 return -1;
755790 }
756791 priv->irq = irq;
757792
758
- rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
759
- &original_int_vec);
793
+ rc = tpm_tis_request_locality(chip, 0);
760794 if (rc < 0)
761795 return rc;
796
+
797
+ rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality),
798
+ &original_int_vec);
799
+ if (rc < 0) {
800
+ tpm_tis_relinquish_locality(chip, priv->locality);
801
+ return rc;
802
+ }
762803
763804 rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
764805 if (rc < 0)
765
- return rc;
806
+ goto restore_irqs;
766807
767808 rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
768809 if (rc < 0)
769
- return rc;
810
+ goto restore_irqs;
770811
771812 /* Clear all existing */
772813 rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
773814 if (rc < 0)
774
- return rc;
775
-
815
+ goto restore_irqs;
776816 /* Turn on */
777817 rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
778818 intmask | TPM_GLOBAL_INT_ENABLE);
779819 if (rc < 0)
780
- return rc;
820
+ goto restore_irqs;
781821
782822 priv->irq_tested = false;
783823
784824 /* Generate an interrupt by having the core call through to
785825 * tpm_tis_send
786826 */
787
- rc = tpm_tis_gen_interrupt(chip);
788
- if (rc < 0)
789
- return rc;
827
+ tpm_tis_gen_interrupt(chip);
790828
829
+restore_irqs:
791830 /* tpm_tis_send will either confirm the interrupt is working or it
792831 * will call disable_irq which undoes all of the above.
793832 */
794833 if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
795
- rc = tpm_tis_write8(priv, original_int_vec,
796
- TPM_INT_VECTOR(priv->locality));
797
- if (rc < 0)
798
- return rc;
799
-
800
- return 1;
834
+ tpm_tis_write8(priv, original_int_vec,
835
+ TPM_INT_VECTOR(priv->locality));
836
+ rc = -1;
801837 }
802838
803
- return 0;
839
+ tpm_tis_relinquish_locality(chip, priv->locality);
840
+
841
+ return rc;
804842 }
805843
806844 /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
....@@ -914,8 +952,8 @@
914952 .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
915953 .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
916954 .req_canceled = tpm_tis_req_canceled,
917
- .request_locality = request_locality,
918
- .relinquish_locality = release_locality,
955
+ .request_locality = tpm_tis_request_locality,
956
+ .relinquish_locality = tpm_tis_relinquish_locality,
919957 .clk_enable = tpm_tis_clkrun_enable,
920958 };
921959
....@@ -949,6 +987,8 @@
949987 priv->timeout_min = TPM_TIMEOUT_USECS_MIN;
950988 priv->timeout_max = TPM_TIMEOUT_USECS_MAX;
951989 priv->phy_ops = phy_ops;
990
+ priv->locality_count = 0;
991
+ mutex_init(&priv->locality_count_mutex);
952992
953993 dev_set_drvdata(&chip->dev, priv);
954994
....@@ -995,14 +1035,14 @@
9951035 TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
9961036 intmask &= ~TPM_GLOBAL_INT_ENABLE;
9971037
998
- rc = request_locality(chip, 0);
1038
+ rc = tpm_tis_request_locality(chip, 0);
9991039 if (rc < 0) {
10001040 rc = -ENODEV;
10011041 goto out_err;
10021042 }
10031043
10041044 tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
1005
- release_locality(chip, 0);
1045
+ tpm_tis_relinquish_locality(chip, 0);
10061046
10071047 rc = tpm_chip_start(chip);
10081048 if (rc)
....@@ -1062,13 +1102,13 @@
10621102 * proper timeouts for the driver.
10631103 */
10641104
1065
- rc = request_locality(chip, 0);
1105
+ rc = tpm_tis_request_locality(chip, 0);
10661106 if (rc < 0)
10671107 goto out_err;
10681108
10691109 rc = tpm_get_timeouts(chip);
10701110
1071
- release_locality(chip, 0);
1111
+ tpm_tis_relinquish_locality(chip, 0);
10721112
10731113 if (rc) {
10741114 dev_err(dev, "Could not get TPM timeouts and durations\n");
....@@ -1076,17 +1116,21 @@
10761116 goto out_err;
10771117 }
10781118
1079
- if (irq) {
1119
+ if (irq)
10801120 tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
10811121 irq);
1082
- if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
1083
- dev_err(&chip->dev, FW_BUG
1122
+ else
1123
+ tpm_tis_probe_irq(chip, intmask);
1124
+
1125
+ if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
1126
+ dev_err(&chip->dev, FW_BUG
10841127 "TPM interrupt not working, polling instead\n");
10851128
1086
- disable_interrupts(chip);
1087
- }
1088
- } else {
1089
- tpm_tis_probe_irq(chip, intmask);
1129
+ rc = tpm_tis_request_locality(chip, 0);
1130
+ if (rc < 0)
1131
+ goto out_err;
1132
+ disable_interrupts(chip);
1133
+ tpm_tis_relinquish_locality(chip, 0);
10901134 }
10911135 }
10921136
....@@ -1147,28 +1191,27 @@
11471191 struct tpm_chip *chip = dev_get_drvdata(dev);
11481192 int ret;
11491193
1194
+ ret = tpm_tis_request_locality(chip, 0);
1195
+ if (ret < 0)
1196
+ return ret;
1197
+
11501198 if (chip->flags & TPM_CHIP_FLAG_IRQ)
11511199 tpm_tis_reenable_interrupts(chip);
11521200
11531201 ret = tpm_pm_resume(dev);
11541202 if (ret)
1155
- return ret;
1203
+ goto out;
11561204
11571205 /*
11581206 * TPM 1.2 requires self-test on resume. This function actually returns
11591207 * an error code but for unknown reason it isn't handled.
11601208 */
1161
- if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
1162
- ret = request_locality(chip, 0);
1163
- if (ret < 0)
1164
- return ret;
1165
-
1209
+ if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
11661210 tpm1_do_selftest(chip);
1211
+out:
1212
+ tpm_tis_relinquish_locality(chip, 0);
11671213
1168
- release_locality(chip, 0);
1169
- }
1170
-
1171
- return 0;
1214
+ return ret;
11721215 }
11731216 EXPORT_SYMBOL_GPL(tpm_tis_resume);
11741217 #endif