Skip to content

Commit

Permalink
tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume
Browse files Browse the repository at this point in the history
[ Upstream commit 1398aa8 ]

Before sending a TPM command, CLKRUN protocol must be disabled. This is not
done in the case of tpm1_do_selftest() call site inside tpm_tis_resume().

Address this by decorating the calls with tpm_chip_{start,stop}, which
should be always used to arm and disarm the TPM chip for transmission.

Finally, move the call to the main TPM driver callback as the last step
because it should arm the chip by itself, if it needs that type of
functionality.

Cc: stable@vger.kernel.org
Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
Closes: https://lore.kernel.org/linux-integrity/CS68AWILHXS4.3M36M1EKZLUMS@suppilovahvero/
Fixes: a3fbfae ("tpm: take TPM chip power gating out of tpm_transmit()")
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
jarkkojs authored and gregkh committed May 30, 2023
1 parent d6c5a69 commit e09bf4b
Showing 1 changed file with 19 additions and 24 deletions.
43 changes: 19 additions & 24 deletions drivers/char/tpm/tpm_tis_core.c
Expand Up @@ -1190,53 +1190,48 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
u32 intmask;
int rc;

if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, true);

/* reenable interrupts that device may have lost or
* BIOS/firmware may have disabled
/*
* Re-enable interrupts that device may have lost or BIOS/firmware may
* have disabled.
*/
rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq);
if (rc < 0)
goto out;
if (rc < 0) {
dev_err(&chip->dev, "Setting IRQ failed.\n");
return;
}

intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;

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

out:
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);

return;
rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
if (rc < 0)
dev_err(&chip->dev, "Enabling interrupts failed.\n");
}

int tpm_tis_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
int ret;

ret = tpm_tis_request_locality(chip, 0);
if (ret < 0)
ret = tpm_chip_start(chip);
if (ret)
return ret;

if (chip->flags & TPM_CHIP_FLAG_IRQ)
tpm_tis_reenable_interrupts(chip);

ret = tpm_pm_resume(dev);
if (ret)
goto out;

/*
* TPM 1.2 requires self-test on resume. This function actually returns
* an error code but for unknown reason it isn't handled.
*/
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
tpm1_do_selftest(chip);
out:
tpm_tis_relinquish_locality(chip, 0);

return ret;
tpm_chip_stop(chip);

ret = tpm_pm_resume(dev);
if (ret)
return ret;

return 0;
}
EXPORT_SYMBOL_GPL(tpm_tis_resume);
#endif
Expand Down

0 comments on commit e09bf4b

Please sign in to comment.