diff options
| author | James Morris <james.l.morris@oracle.com> | 2015-02-15 21:41:46 -0500 |
|---|---|---|
| committer | James Morris <james.l.morris@oracle.com> | 2015-02-15 21:41:46 -0500 |
| commit | cd07db5f2770cf7f96b0202ef93533c8a9eee09f (patch) | |
| tree | 8bf3f95dbfc2aff804fed65d5069d23a63a57761 | |
| parent | 1fa185ebcbcefdc5229c783450c9f0439a69f0c1 (diff) | |
| parent | eb71f8a5e33fa1066fb92f0111ab366a341e1f6c (diff) | |
Merge https://github.com/PeterHuewe/linux-tpmdd into for-linus
| -rw-r--r-- | drivers/char/tpm/tpm-interface.c | 6 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.h | 5 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 59 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_crb.c | 20 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_ibmvtpm.c | 20 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis.c | 37 |
6 files changed, 85 insertions, 62 deletions
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index bf53a3771da5..e85d3416d899 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
| @@ -901,8 +901,10 @@ int tpm_pm_suspend(struct device *dev) | |||
| 901 | if (chip == NULL) | 901 | if (chip == NULL) |
| 902 | return -ENODEV; | 902 | return -ENODEV; |
| 903 | 903 | ||
| 904 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 904 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
| 905 | return tpm2_shutdown(chip, TPM2_SU_CLEAR); | 905 | tpm2_shutdown(chip, TPM2_SU_STATE); |
| 906 | return 0; | ||
| 907 | } | ||
| 906 | 908 | ||
| 907 | /* for buggy tpm, flush pcrs with extend to selected dummy */ | 909 | /* for buggy tpm, flush pcrs with extend to selected dummy */ |
| 908 | if (tpm_suspend_pcr) { | 910 | if (tpm_suspend_pcr) { |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 7b0727c5e803..f8319a0860fd 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -432,7 +432,8 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, | |||
| 432 | u32 *value, const char *desc); | 432 | u32 *value, const char *desc); |
| 433 | 433 | ||
| 434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); | 434 | extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); |
| 435 | extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); | 435 | extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); |
| 436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); | 436 | extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); |
| 437 | extern int tpm2_do_selftest(struct tpm_chip *chip); | 437 | extern int tpm2_do_selftest(struct tpm_chip *chip); |
| 438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet); | 438 | extern int tpm2_gen_interrupt(struct tpm_chip *chip); |
| 439 | extern int tpm2_probe(struct tpm_chip *chip); | ||
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 1abe6502219f..011909a9be96 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
| @@ -456,20 +456,23 @@ static const struct tpm_input_header tpm2_shutdown_header = { | |||
| 456 | * @chip: TPM chip to use. | 456 | * @chip: TPM chip to use. |
| 457 | * @shutdown_type shutdown type. The value is either | 457 | * @shutdown_type shutdown type. The value is either |
| 458 | * TPM_SU_CLEAR or TPM_SU_STATE. | 458 | * TPM_SU_CLEAR or TPM_SU_STATE. |
| 459 | * | ||
| 460 | * 0 is returned when the operation is successful. If a negative number is | ||
| 461 | * returned it remarks a POSIX error code. If a positive number is returned | ||
| 462 | * it remarks a TPM error. | ||
| 463 | */ | 459 | */ |
| 464 | int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) | 460 | void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) |
| 465 | { | 461 | { |
| 466 | struct tpm2_cmd cmd; | 462 | struct tpm2_cmd cmd; |
| 463 | int rc; | ||
| 467 | 464 | ||
| 468 | cmd.header.in = tpm2_shutdown_header; | 465 | cmd.header.in = tpm2_shutdown_header; |
| 469 | |||
| 470 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); | 466 | cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); |
| 471 | return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), | 467 | |
| 472 | "stopping the TPM"); | 468 | rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM"); |
| 469 | |||
| 470 | /* In places where shutdown command is sent there's no much we can do | ||
| 471 | * except print the error code on a system failure. | ||
| 472 | */ | ||
| 473 | if (rc < 0) | ||
| 474 | dev_warn(chip->pdev, "transmit returned %d while stopping the TPM", | ||
| 475 | rc); | ||
| 473 | } | 476 | } |
| 474 | EXPORT_SYMBOL_GPL(tpm2_shutdown); | 477 | EXPORT_SYMBOL_GPL(tpm2_shutdown); |
| 475 | 478 | ||
| @@ -598,20 +601,46 @@ EXPORT_SYMBOL_GPL(tpm2_do_selftest); | |||
| 598 | /** | 601 | /** |
| 599 | * tpm2_gen_interrupt() - generate an interrupt | 602 | * tpm2_gen_interrupt() - generate an interrupt |
| 600 | * @chip: TPM chip to use | 603 | * @chip: TPM chip to use |
| 601 | * @quiet: surpress the error message | ||
| 602 | * | 604 | * |
| 603 | * 0 is returned when the operation is successful. If a negative number is | 605 | * 0 is returned when the operation is successful. If a negative number is |
| 604 | * returned it remarks a POSIX error code. If a positive number is returned | 606 | * returned it remarks a POSIX error code. If a positive number is returned |
| 605 | * it remarks a TPM error. | 607 | * it remarks a TPM error. |
| 606 | */ | 608 | */ |
| 607 | int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet) | 609 | int tpm2_gen_interrupt(struct tpm_chip *chip) |
| 608 | { | 610 | { |
| 609 | const char *desc = NULL; | ||
| 610 | u32 dummy; | 611 | u32 dummy; |
| 611 | 612 | ||
| 612 | if (!quiet) | 613 | return tpm2_get_tpm_pt(chip, 0x100, &dummy, |
| 613 | desc = "attempting to generate an interrupt"; | 614 | "attempting to generate an interrupt"); |
| 614 | |||
| 615 | return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc); | ||
| 616 | } | 615 | } |
| 617 | EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); | 616 | EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); |
| 617 | |||
| 618 | /** | ||
| 619 | * tpm2_probe() - probe TPM 2.0 | ||
| 620 | * @chip: TPM chip to use | ||
| 621 | * | ||
| 622 | * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on | ||
| 623 | * the reply tag. | ||
| 624 | */ | ||
| 625 | int tpm2_probe(struct tpm_chip *chip) | ||
| 626 | { | ||
| 627 | struct tpm2_cmd cmd; | ||
| 628 | int rc; | ||
| 629 | |||
| 630 | cmd.header.in = tpm2_get_tpm_pt_header; | ||
| 631 | cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES); | ||
| 632 | cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); | ||
| 633 | cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); | ||
| 634 | |||
| 635 | rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd)); | ||
| 636 | if (rc < 0) | ||
| 637 | return rc; | ||
| 638 | else if (rc < TPM_HEADER_SIZE) | ||
| 639 | return -EFAULT; | ||
| 640 | |||
| 641 | if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS) | ||
| 642 | chip->flags |= TPM_CHIP_FLAG_TPM2; | ||
| 643 | |||
| 644 | return 0; | ||
| 645 | } | ||
| 646 | EXPORT_SYMBOL_GPL(tpm2_probe); | ||
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 3dd23cfae4fe..b26ceee3585e 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c | |||
| @@ -95,21 +95,7 @@ struct crb_priv { | |||
| 95 | u8 __iomem *rsp; | 95 | u8 __iomem *rsp; |
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | #ifdef CONFIG_PM_SLEEP | 98 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume); |
| 99 | static int crb_resume(struct device *dev) | ||
| 100 | { | ||
| 101 | int rc; | ||
| 102 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
| 103 | |||
| 104 | rc = tpm2_shutdown(chip, TPM2_SU_STATE); | ||
| 105 | if (!rc) | ||
| 106 | rc = tpm2_do_selftest(chip); | ||
| 107 | |||
| 108 | return rc; | ||
| 109 | } | ||
| 110 | #endif | ||
| 111 | |||
| 112 | static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume); | ||
| 113 | 99 | ||
| 114 | static u8 crb_status(struct tpm_chip *chip) | 100 | static u8 crb_status(struct tpm_chip *chip) |
| 115 | { | 101 | { |
| @@ -326,6 +312,10 @@ static int crb_acpi_remove(struct acpi_device *device) | |||
| 326 | struct tpm_chip *chip = dev_get_drvdata(dev); | 312 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 327 | 313 | ||
| 328 | tpm_chip_unregister(chip); | 314 | tpm_chip_unregister(chip); |
| 315 | |||
| 316 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 317 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
| 318 | |||
| 329 | return 0; | 319 | return 0; |
| 330 | } | 320 | } |
| 331 | 321 | ||
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 0840347e251c..b1e53e3aece5 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c | |||
| @@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 148 | crq.len = (u16)count; | 148 | crq.len = (u16)count; |
| 149 | crq.data = ibmvtpm->rtce_dma_handle; | 149 | crq.data = ibmvtpm->rtce_dma_handle; |
| 150 | 150 | ||
| 151 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); | 151 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]), |
| 152 | cpu_to_be64(word[1])); | ||
| 152 | if (rc != H_SUCCESS) { | 153 | if (rc != H_SUCCESS) { |
| 153 | dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); | 154 | dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); |
| 154 | rc = 0; | 155 | rc = 0; |
| @@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm) | |||
| 186 | crq.valid = (u8)IBMVTPM_VALID_CMD; | 187 | crq.valid = (u8)IBMVTPM_VALID_CMD; |
| 187 | crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; | 188 | crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; |
| 188 | 189 | ||
| 189 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | 190 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| 191 | cpu_to_be64(buf[1])); | ||
| 190 | if (rc != H_SUCCESS) | 192 | if (rc != H_SUCCESS) |
| 191 | dev_err(ibmvtpm->dev, | 193 | dev_err(ibmvtpm->dev, |
| 192 | "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); | 194 | "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); |
| @@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm) | |||
| 212 | crq.valid = (u8)IBMVTPM_VALID_CMD; | 214 | crq.valid = (u8)IBMVTPM_VALID_CMD; |
| 213 | crq.msg = (u8)VTPM_GET_VERSION; | 215 | crq.msg = (u8)VTPM_GET_VERSION; |
| 214 | 216 | ||
| 215 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | 217 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| 218 | cpu_to_be64(buf[1])); | ||
| 216 | if (rc != H_SUCCESS) | 219 | if (rc != H_SUCCESS) |
| 217 | dev_err(ibmvtpm->dev, | 220 | dev_err(ibmvtpm->dev, |
| 218 | "ibmvtpm_crq_get_version failed rc=%d\n", rc); | 221 | "ibmvtpm_crq_get_version failed rc=%d\n", rc); |
| @@ -336,7 +339,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev) | |||
| 336 | crq.valid = (u8)IBMVTPM_VALID_CMD; | 339 | crq.valid = (u8)IBMVTPM_VALID_CMD; |
| 337 | crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; | 340 | crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; |
| 338 | 341 | ||
| 339 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | 342 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| 343 | cpu_to_be64(buf[1])); | ||
| 340 | if (rc != H_SUCCESS) | 344 | if (rc != H_SUCCESS) |
| 341 | dev_err(ibmvtpm->dev, | 345 | dev_err(ibmvtpm->dev, |
| 342 | "tpm_ibmvtpm_suspend failed rc=%d\n", rc); | 346 | "tpm_ibmvtpm_suspend failed rc=%d\n", rc); |
| @@ -481,11 +485,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, | |||
| 481 | case IBMVTPM_VALID_CMD: | 485 | case IBMVTPM_VALID_CMD: |
| 482 | switch (crq->msg) { | 486 | switch (crq->msg) { |
| 483 | case VTPM_GET_RTCE_BUFFER_SIZE_RES: | 487 | case VTPM_GET_RTCE_BUFFER_SIZE_RES: |
| 484 | if (crq->len <= 0) { | 488 | if (be16_to_cpu(crq->len) <= 0) { |
| 485 | dev_err(ibmvtpm->dev, "Invalid rtce size\n"); | 489 | dev_err(ibmvtpm->dev, "Invalid rtce size\n"); |
| 486 | return; | 490 | return; |
| 487 | } | 491 | } |
| 488 | ibmvtpm->rtce_size = crq->len; | 492 | ibmvtpm->rtce_size = be16_to_cpu(crq->len); |
| 489 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, | 493 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, |
| 490 | GFP_KERNEL); | 494 | GFP_KERNEL); |
| 491 | if (!ibmvtpm->rtce_buf) { | 495 | if (!ibmvtpm->rtce_buf) { |
| @@ -506,11 +510,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, | |||
| 506 | 510 | ||
| 507 | return; | 511 | return; |
| 508 | case VTPM_GET_VERSION_RES: | 512 | case VTPM_GET_VERSION_RES: |
| 509 | ibmvtpm->vtpm_version = crq->data; | 513 | ibmvtpm->vtpm_version = be32_to_cpu(crq->data); |
| 510 | return; | 514 | return; |
| 511 | case VTPM_TPM_COMMAND_RES: | 515 | case VTPM_TPM_COMMAND_RES: |
| 512 | /* len of the data in rtce buffer */ | 516 | /* len of the data in rtce buffer */ |
| 513 | ibmvtpm->res_len = crq->len; | 517 | ibmvtpm->res_len = be16_to_cpu(crq->len); |
| 514 | wake_up_interruptible(&ibmvtpm->wq); | 518 | wake_up_interruptible(&ibmvtpm->wq); |
| 515 | return; | 519 | return; |
| 516 | default: | 520 | default: |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 6725bef7cb96..f2dffa770b8e 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
| @@ -588,6 +588,9 @@ MODULE_PARM_DESC(interrupts, "Enable interrupts"); | |||
| 588 | 588 | ||
| 589 | static void tpm_tis_remove(struct tpm_chip *chip) | 589 | static void tpm_tis_remove(struct tpm_chip *chip) |
| 590 | { | 590 | { |
| 591 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | ||
| 592 | tpm2_shutdown(chip, TPM2_SU_CLEAR); | ||
| 593 | |||
| 591 | iowrite32(~TPM_GLOBAL_INT_ENABLE & | 594 | iowrite32(~TPM_GLOBAL_INT_ENABLE & |
| 592 | ioread32(chip->vendor.iobase + | 595 | ioread32(chip->vendor.iobase + |
| 593 | TPM_INT_ENABLE(chip->vendor. | 596 | TPM_INT_ENABLE(chip->vendor. |
| @@ -639,12 +642,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
| 639 | goto out_err; | 642 | goto out_err; |
| 640 | } | 643 | } |
| 641 | 644 | ||
| 642 | /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. | 645 | rc = tpm2_probe(chip); |
| 643 | * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. | 646 | if (rc) |
| 644 | */ | 647 | goto out_err; |
| 645 | rc = tpm2_gen_interrupt(chip, true); | ||
| 646 | if (rc == 0 || rc == TPM2_RC_INITIALIZE) | ||
| 647 | chip->flags |= TPM_CHIP_FLAG_TPM2; | ||
| 648 | 648 | ||
| 649 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); | 649 | vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); |
| 650 | chip->vendor.manufacturer_id = vendor; | 650 | chip->vendor.manufacturer_id = vendor; |
| @@ -747,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, | |||
| 747 | 747 | ||
| 748 | /* Generate Interrupts */ | 748 | /* Generate Interrupts */ |
| 749 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 749 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
| 750 | tpm2_gen_interrupt(chip, false); | 750 | tpm2_gen_interrupt(chip); |
| 751 | else | 751 | else |
| 752 | tpm_gen_interrupt(chip); | 752 | tpm_gen_interrupt(chip); |
| 753 | 753 | ||
| @@ -865,25 +865,22 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |||
| 865 | static int tpm_tis_resume(struct device *dev) | 865 | static int tpm_tis_resume(struct device *dev) |
| 866 | { | 866 | { |
| 867 | struct tpm_chip *chip = dev_get_drvdata(dev); | 867 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 868 | int ret = 0; | 868 | int ret; |
| 869 | 869 | ||
| 870 | if (chip->vendor.irq) | 870 | if (chip->vendor.irq) |
| 871 | tpm_tis_reenable_interrupts(chip); | 871 | tpm_tis_reenable_interrupts(chip); |
| 872 | 872 | ||
| 873 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 873 | ret = tpm_pm_resume(dev); |
| 874 | /* NOP if firmware properly does this. */ | 874 | if (ret) |
| 875 | tpm2_startup(chip, TPM2_SU_STATE); | 875 | return ret; |
| 876 | 876 | ||
| 877 | ret = tpm2_shutdown(chip, TPM2_SU_STATE); | 877 | /* TPM 1.2 requires self-test on resume. This function actually returns |
| 878 | if (!ret) | 878 | * an error code but for unknown reason it isn't handled. |
| 879 | ret = tpm2_do_selftest(chip); | 879 | */ |
| 880 | } else { | 880 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) |
| 881 | ret = tpm_pm_resume(dev); | 881 | tpm_do_selftest(chip); |
| 882 | if (!ret) | ||
| 883 | tpm_do_selftest(chip); | ||
| 884 | } | ||
| 885 | 882 | ||
| 886 | return ret; | 883 | return 0; |
| 887 | } | 884 | } |
| 888 | #endif | 885 | #endif |
| 889 | 886 | ||
