Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tpm/tpm_crb: Use start method value from ACPI table directly

This patch gets rid of dealing with intermediate flag for start method
and use start method value from ACPI table directly.

For ARM64, the locality is handled by Trust Zone in FW. The layout
does not have crb_regs_head. It is hitting the following line.
dev_warn(dev, FW_BUG "Bad ACPI memory layout");

Current code excludes CRB_FL_ACPI_START for this check. Now since
ARM64 support for TPM CRB is added, CRB_FL_CRB_SMC_START should also be
excluded from this check.

For goIdle and cmdReady where code was excluding CRB_FL_ACPI_START only
(do nothing for ACPI start method), CRB_FL_CRB_SMC_START was also
excluded as ARM64 SMC start method does not have TPM_CRB_CTRL_REQ.

However with special PPT workaround requiring CRB_FL_CRB_START to be
set in addition to CRB_FL_ACPI_START and the addition flag of SMC
start method CRB_FL_CRB_SMC_START, the code has become difficult to
maintain and undrestand. It is better to make code deal with start
method value from ACPI table directly.

Signed-off-by: Jiandi An <anjiandi@codeaurora.org>
Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

authored by

Jiandi An and committed by
Jarkko Sakkinen
f5357413 c37fbc09

+29 -30
+29 -30
drivers/char/tpm/tpm_crb.c
··· 92 92 CRB_DRV_STS_COMPLETE = BIT(0), 93 93 }; 94 94 95 - enum crb_flags { 96 - CRB_FL_ACPI_START = BIT(0), 97 - CRB_FL_CRB_START = BIT(1), 98 - CRB_FL_CRB_SMC_START = BIT(2), 99 - }; 100 - 101 95 struct crb_priv { 102 - unsigned int flags; 96 + u32 sm; 97 + const char *hid; 103 98 void __iomem *iobase; 104 99 struct crb_regs_head __iomem *regs_h; 105 100 struct crb_regs_tail __iomem *regs_t; ··· 123 128 * Anyhow, we do not wait here as a consequent CMD_READY request 124 129 * will be handled correctly even if idle was not completed. 125 130 * 126 - * The function does nothing for devices with ACPI-start method. 131 + * The function does nothing for devices with ACPI-start method 132 + * or SMC-start method. 127 133 * 128 134 * Return: 0 always 129 135 */ 130 136 static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv) 131 137 { 132 - if ((priv->flags & CRB_FL_ACPI_START) || 133 - (priv->flags & CRB_FL_CRB_SMC_START)) 138 + if ((priv->sm == ACPI_TPM2_START_METHOD) || 139 + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || 140 + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) 134 141 return 0; 135 142 136 143 iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req); ··· 171 174 * The device should respond within TIMEOUT_C. 172 175 * 173 176 * The function does nothing for devices with ACPI-start method 177 + * or SMC-start method. 174 178 * 175 179 * Return: 0 on success -ETIME on timeout; 176 180 */ 177 181 static int __maybe_unused crb_cmd_ready(struct device *dev, 178 182 struct crb_priv *priv) 179 183 { 180 - if ((priv->flags & CRB_FL_ACPI_START) || 181 - (priv->flags & CRB_FL_CRB_SMC_START)) 184 + if ((priv->sm == ACPI_TPM2_START_METHOD) || 185 + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || 186 + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC)) 182 187 return 0; 183 188 184 189 iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->regs_t->ctrl_req); ··· 324 325 /* Make sure that cmd is populated before issuing start. */ 325 326 wmb(); 326 327 327 - if (priv->flags & CRB_FL_CRB_START) 328 + /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs 329 + * report only ACPI start but in practice seems to require both 330 + * CRB start, hence invoking CRB start method if hid == MSFT0101. 331 + */ 332 + if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || 333 + (priv->sm == ACPI_TPM2_MEMORY_MAPPED) || 334 + (!strcmp(priv->hid, "MSFT0101"))) 328 335 iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); 329 336 330 - if (priv->flags & CRB_FL_ACPI_START) 337 + if ((priv->sm == ACPI_TPM2_START_METHOD) || 338 + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) 331 339 rc = crb_do_acpi_start(chip); 332 340 333 - if (priv->flags & CRB_FL_CRB_SMC_START) { 341 + if (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { 334 342 iowrite32(CRB_START_INVOKE, &priv->regs_t->ctrl_start); 335 343 rc = tpm_crb_smc_start(&chip->dev, priv->smc_func_id); 336 344 } ··· 351 345 352 346 iowrite32(CRB_CANCEL_INVOKE, &priv->regs_t->ctrl_cancel); 353 347 354 - if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) 348 + if (((priv->sm == ACPI_TPM2_START_METHOD) || 349 + (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD)) && 350 + crb_do_acpi_start(chip)) 355 351 dev_err(&chip->dev, "ACPI Start failed\n"); 356 352 } 357 353 ··· 466 458 * the control area, as one nice sane region except for some older 467 459 * stuff that puts the control area outside the ACPI IO region. 468 460 */ 469 - if (!(priv->flags & CRB_FL_ACPI_START)) { 461 + if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) || 462 + (priv->sm == ACPI_TPM2_MEMORY_MAPPED)) { 470 463 if (buf->control_address == io_res.start + 471 464 sizeof(*priv->regs_h)) 472 465 priv->regs_h = priv->iobase; ··· 561 552 if (!priv) 562 553 return -ENOMEM; 563 554 564 - /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs 565 - * report only ACPI start but in practice seems to require both 566 - * ACPI start and CRB start. 567 - */ 568 - if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED || 569 - !strcmp(acpi_device_hid(device), "MSFT0101")) 570 - priv->flags |= CRB_FL_CRB_START; 571 - 572 - if (sm == ACPI_TPM2_START_METHOD || 573 - sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) 574 - priv->flags |= CRB_FL_ACPI_START; 575 - 576 555 if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) { 577 556 if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) { 578 557 dev_err(dev, ··· 571 574 } 572 575 crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf)); 573 576 priv->smc_func_id = crb_smc->smc_func_id; 574 - priv->flags |= CRB_FL_CRB_SMC_START; 575 577 } 578 + 579 + priv->sm = sm; 580 + priv->hid = acpi_device_hid(device); 576 581 577 582 rc = crb_map_io(device, priv, buf); 578 583 if (rc)