Skip to content

Commit 33bafe9

Browse files
snitsJarkko Sakkinen
authored andcommitted
tpm_tis: verify locality released before returning from release_locality
For certain tpm chips releasing locality can take long enough that a subsequent call to request_locality will see the locality as being active when the access register is read in check_locality. So check that the locality has been released before returning from release_locality. Cc: Jarkko Sakkinen <[email protected]> Cc: Peter Huewe <[email protected]> Cc: Jason Gunthorpe <[email protected]> Reported-by: Laurent Bigonville <[email protected]> Signed-off-by: Jerry Snitselaar <[email protected]> Tested-by: Laurent Bigonville <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent 1fbad30 commit 33bafe9

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

drivers/char/tpm/tpm_tis_core.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,58 @@ static bool check_locality(struct tpm_chip *chip, int l)
143143
return false;
144144
}
145145

146+
static bool locality_inactive(struct tpm_chip *chip, int l)
147+
{
148+
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
149+
int rc;
150+
u8 access;
151+
152+
rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
153+
if (rc < 0)
154+
return false;
155+
156+
if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
157+
== TPM_ACCESS_VALID)
158+
return true;
159+
160+
return false;
161+
}
162+
146163
static int release_locality(struct tpm_chip *chip, int l)
147164
{
148165
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
166+
unsigned long stop, timeout;
167+
long rc;
149168

150169
tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
151170

152-
return 0;
171+
stop = jiffies + chip->timeout_a;
172+
173+
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
174+
again:
175+
timeout = stop - jiffies;
176+
if ((long)timeout <= 0)
177+
return -1;
178+
179+
rc = wait_event_interruptible_timeout(priv->int_queue,
180+
(locality_inactive(chip, l)),
181+
timeout);
182+
183+
if (rc > 0)
184+
return 0;
185+
186+
if (rc == -ERESTARTSYS && freezing(current)) {
187+
clear_thread_flag(TIF_SIGPENDING);
188+
goto again;
189+
}
190+
} else {
191+
do {
192+
if (locality_inactive(chip, l))
193+
return 0;
194+
tpm_msleep(TPM_TIMEOUT);
195+
} while (time_before(jiffies, stop));
196+
}
197+
return -1;
153198
}
154199

155200
static int request_locality(struct tpm_chip *chip, int l)

0 commit comments

Comments
 (0)