Skip to content

Commit 8462dc1

Browse files
committed
tpm, tpm_tis: Only handle supported interrupts
JIRA: https://issues.redhat.com/browse/RHEL-72765 Upstream Status: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git commit e87fcf0 Author: Lino Sanfilippo <l.sanfilippo@kunbus.com> Date: Thu Nov 24 14:55:30 2022 +0100 tpm, tpm_tis: Only handle supported interrupts According to the TPM Interface Specification (TIS) support for "stsValid" and "commandReady" interrupts is only optional. This has to be taken into account when handling the interrupts in functions like wait_for_tpm_stat(). To determine the supported interrupts use the capability query. Also adjust wait_for_tpm_stat() to only wait for interrupt reported status changes. After that process all the remaining status changes by polling the status register. Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com> Tested-by: Michael Niewöhner <linux@mniewoehner.de> Tested-by: Jarkko Sakkinen <jarkko@kernel.org> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Štěpán Horáček <shoracek@redhat.com>
1 parent f5d7a01 commit 8462dc1

File tree

2 files changed

+73
-48
lines changed

2 files changed

+73
-48
lines changed

drivers/char/tpm/tpm_tis_core.c

Lines changed: 72 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -53,41 +53,63 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
5353
long rc;
5454
u8 status;
5555
bool canceled = false;
56+
u8 sts_mask = 0;
57+
int ret = 0;
5658

5759
/* check current status */
5860
status = chip->ops->status(chip);
5961
if ((status & mask) == mask)
6062
return 0;
6163

62-
stop = jiffies + timeout;
64+
/* check what status changes can be handled by irqs */
65+
if (priv->int_mask & TPM_INTF_STS_VALID_INT)
66+
sts_mask |= TPM_STS_VALID;
6367

64-
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
68+
if (priv->int_mask & TPM_INTF_DATA_AVAIL_INT)
69+
sts_mask |= TPM_STS_DATA_AVAIL;
70+
71+
if (priv->int_mask & TPM_INTF_CMD_READY_INT)
72+
sts_mask |= TPM_STS_COMMAND_READY;
73+
74+
sts_mask &= mask;
75+
76+
stop = jiffies + timeout;
77+
/* process status changes with irq support */
78+
if (sts_mask) {
79+
ret = -ETIME;
6580
again:
6681
timeout = stop - jiffies;
6782
if ((long)timeout <= 0)
6883
return -ETIME;
6984
rc = wait_event_interruptible_timeout(*queue,
70-
wait_for_tpm_stat_cond(chip, mask, check_cancel,
85+
wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
7186
&canceled),
7287
timeout);
7388
if (rc > 0) {
7489
if (canceled)
7590
return -ECANCELED;
76-
return 0;
91+
ret = 0;
7792
}
7893
if (rc == -ERESTARTSYS && freezing(current)) {
7994
clear_thread_flag(TIF_SIGPENDING);
8095
goto again;
8196
}
82-
} else {
83-
do {
84-
usleep_range(priv->timeout_min,
85-
priv->timeout_max);
86-
status = chip->ops->status(chip);
87-
if ((status & mask) == mask)
88-
return 0;
89-
} while (time_before(jiffies, stop));
9097
}
98+
99+
if (ret)
100+
return ret;
101+
102+
mask &= ~sts_mask;
103+
if (!mask) /* all done */
104+
return 0;
105+
/* process status changes without irq support */
106+
do {
107+
status = chip->ops->status(chip);
108+
if ((status & mask) == mask)
109+
return 0;
110+
usleep_range(priv->timeout_min,
111+
priv->timeout_max);
112+
} while (time_before(jiffies, stop));
91113
return -ETIME;
92114
}
93115

@@ -987,8 +1009,40 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
9871009
if (rc < 0)
9881010
goto out_err;
9891011

990-
intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
991-
TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
1012+
/* Figure out the capabilities */
1013+
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
1014+
if (rc < 0)
1015+
goto out_err;
1016+
1017+
dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
1018+
intfcaps);
1019+
if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
1020+
dev_dbg(dev, "\tBurst Count Static\n");
1021+
if (intfcaps & TPM_INTF_CMD_READY_INT) {
1022+
intmask |= TPM_INTF_CMD_READY_INT;
1023+
dev_dbg(dev, "\tCommand Ready Int Support\n");
1024+
}
1025+
if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
1026+
dev_dbg(dev, "\tInterrupt Edge Falling\n");
1027+
if (intfcaps & TPM_INTF_INT_EDGE_RISING)
1028+
dev_dbg(dev, "\tInterrupt Edge Rising\n");
1029+
if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
1030+
dev_dbg(dev, "\tInterrupt Level Low\n");
1031+
if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
1032+
dev_dbg(dev, "\tInterrupt Level High\n");
1033+
if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
1034+
intmask |= TPM_INTF_LOCALITY_CHANGE_INT;
1035+
dev_dbg(dev, "\tLocality Change Int Support\n");
1036+
}
1037+
if (intfcaps & TPM_INTF_STS_VALID_INT) {
1038+
intmask |= TPM_INTF_STS_VALID_INT;
1039+
dev_dbg(dev, "\tSts Valid Int Support\n");
1040+
}
1041+
if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
1042+
intmask |= TPM_INTF_DATA_AVAIL_INT;
1043+
dev_dbg(dev, "\tData Avail Int Support\n");
1044+
}
1045+
9921046
intmask &= ~TPM_GLOBAL_INT_ENABLE;
9931047

9941048
rc = request_locality(chip, 0);
@@ -1022,32 +1076,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
10221076
goto out_err;
10231077
}
10241078

1025-
/* Figure out the capabilities */
1026-
rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
1027-
if (rc < 0)
1028-
goto out_err;
1029-
1030-
dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
1031-
intfcaps);
1032-
if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
1033-
dev_dbg(dev, "\tBurst Count Static\n");
1034-
if (intfcaps & TPM_INTF_CMD_READY_INT)
1035-
dev_dbg(dev, "\tCommand Ready Int Support\n");
1036-
if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
1037-
dev_dbg(dev, "\tInterrupt Edge Falling\n");
1038-
if (intfcaps & TPM_INTF_INT_EDGE_RISING)
1039-
dev_dbg(dev, "\tInterrupt Edge Rising\n");
1040-
if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
1041-
dev_dbg(dev, "\tInterrupt Level Low\n");
1042-
if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
1043-
dev_dbg(dev, "\tInterrupt Level High\n");
1044-
if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
1045-
dev_dbg(dev, "\tLocality Change Int Support\n");
1046-
if (intfcaps & TPM_INTF_STS_VALID_INT)
1047-
dev_dbg(dev, "\tSts Valid Int Support\n");
1048-
if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
1049-
dev_dbg(dev, "\tData Avail Int Support\n");
1050-
10511079
/* INTERRUPT Setup */
10521080
init_waitqueue_head(&priv->read_queue);
10531081
init_waitqueue_head(&priv->int_queue);
@@ -1083,7 +1111,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
10831111
else
10841112
tpm_tis_probe_irq(chip, intmask);
10851113

1086-
if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
1114+
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
1115+
priv->int_mask = intmask;
1116+
} else {
10871117
dev_err(&chip->dev, FW_BUG
10881118
"TPM interrupt not working, polling instead\n");
10891119

@@ -1130,13 +1160,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
11301160
if (rc < 0)
11311161
goto out;
11321162

1133-
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
1134-
if (rc < 0)
1135-
goto out;
1136-
1137-
intmask |= TPM_INTF_CMD_READY_INT
1138-
| TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
1139-
| TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
1163+
intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;
11401164

11411165
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
11421166

drivers/char/tpm/tpm_tis_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ struct tpm_tis_data {
9393
u16 manufacturer_id;
9494
int locality;
9595
int irq;
96+
unsigned int int_mask;
9697
unsigned long flags;
9798
void __iomem *ilb_base_addr;
9899
u16 clkrun_enabled;

0 commit comments

Comments
 (0)