Merge https://github.com/PeterHuewe/linux-tpmdd into for-linus
authorJames Morris <james.l.morris@oracle.com>
Mon, 16 Feb 2015 02:41:46 +0000 (13:41 +1100)
committerJames Morris <james.l.morris@oracle.com>
Mon, 16 Feb 2015 02:41:46 +0000 (13:41 +1100)
drivers/char/tpm/tpm-interface.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_crb.c
drivers/char/tpm/tpm_ibmvtpm.c
drivers/char/tpm/tpm_tis.c

index bf53a3771da5308ea227094acfe5611569ac59e7..e85d3416d89918e4050eeec8dd32233f2589dc44 100644 (file)
@@ -901,8 +901,10 @@ int tpm_pm_suspend(struct device *dev)
        if (chip == NULL)
                return -ENODEV;
 
-       if (chip->flags & TPM_CHIP_FLAG_TPM2)
-               return tpm2_shutdown(chip, TPM2_SU_CLEAR);
+       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+               tpm2_shutdown(chip, TPM2_SU_STATE);
+               return 0;
+       }
 
        /* for buggy tpm, flush pcrs with extend to selected dummy */
        if (tpm_suspend_pcr) {
index 7b0727c5e803ee9de9ded68da4563a099836e743..f8319a0860fd702f51e7658fe22f49607efb1b4e 100644 (file)
@@ -432,7 +432,8 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
                        u32 *value, const char *desc);
 
 extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
-extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
+extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
 extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
 extern int tpm2_do_selftest(struct tpm_chip *chip);
-extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet);
+extern int tpm2_gen_interrupt(struct tpm_chip *chip);
+extern int tpm2_probe(struct tpm_chip *chip);
index 1abe6502219f258f15e69de50aa3a2434247f116..011909a9be9627632bd1d1ec19230d5945d86719 100644 (file)
@@ -456,20 +456,23 @@ static const struct tpm_input_header tpm2_shutdown_header = {
  * @chip:              TPM chip to use.
  * @shutdown_type      shutdown type. The value is either
  *                     TPM_SU_CLEAR or TPM_SU_STATE.
- *
- * 0 is returned when the operation is successful. If a negative number is
- * returned it remarks a POSIX error code. If a positive number is returned
- * it remarks a TPM error.
  */
-int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
+void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
 {
        struct tpm2_cmd cmd;
+       int rc;
 
        cmd.header.in = tpm2_shutdown_header;
-
        cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
-       return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
-                               "stopping the TPM");
+
+       rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM");
+
+       /* In places where shutdown command is sent there's no much we can do
+        * except print the error code on a system failure.
+        */
+       if (rc < 0)
+               dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
+                        rc);
 }
 EXPORT_SYMBOL_GPL(tpm2_shutdown);
 
@@ -598,20 +601,46 @@ EXPORT_SYMBOL_GPL(tpm2_do_selftest);
 /**
  * tpm2_gen_interrupt() - generate an interrupt
  * @chip: TPM chip to use
- * @quiet: surpress the error message
  *
  * 0 is returned when the operation is successful. If a negative number is
  * returned it remarks a POSIX error code. If a positive number is returned
  * it remarks a TPM error.
  */
-int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet)
+int tpm2_gen_interrupt(struct tpm_chip *chip)
 {
-       const char *desc = NULL;
        u32 dummy;
 
-       if (!quiet)
-               desc = "attempting to generate an interrupt";
-
-       return tpm2_get_tpm_pt(chip, TPM2_CAP_TPM_PROPERTIES, &dummy, desc);
+       return tpm2_get_tpm_pt(chip, 0x100, &dummy,
+                              "attempting to generate an interrupt");
 }
 EXPORT_SYMBOL_GPL(tpm2_gen_interrupt);
+
+/**
+ * tpm2_probe() - probe TPM 2.0
+ * @chip: TPM chip to use
+ *
+ * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on
+ * the reply tag.
+ */
+int tpm2_probe(struct tpm_chip *chip)
+{
+       struct tpm2_cmd cmd;
+       int rc;
+
+       cmd.header.in = tpm2_get_tpm_pt_header;
+       cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES);
+       cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
+       cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
+
+       rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd));
+       if (rc <  0)
+               return rc;
+       else if (rc < TPM_HEADER_SIZE)
+               return -EFAULT;
+
+       if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS)
+               chip->flags |= TPM_CHIP_FLAG_TPM2;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tpm2_probe);
index 3dd23cfae4feefe46279f01bdac5b49c190ba9fd..b26ceee3585e1fbd91bff48cc6f75984a739f488 100644 (file)
@@ -95,21 +95,7 @@ struct crb_priv {
        u8 __iomem *rsp;
 };
 
-#ifdef CONFIG_PM_SLEEP
-static int crb_resume(struct device *dev)
-{
-       int rc;
-       struct tpm_chip *chip = dev_get_drvdata(dev);
-
-       rc = tpm2_shutdown(chip, TPM2_SU_STATE);
-       if (!rc)
-               rc = tpm2_do_selftest(chip);
-
-       return rc;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, crb_resume);
+static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
 
 static u8 crb_status(struct tpm_chip *chip)
 {
@@ -326,6 +312,10 @@ static int crb_acpi_remove(struct acpi_device *device)
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
        tpm_chip_unregister(chip);
+
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               tpm2_shutdown(chip, TPM2_SU_CLEAR);
+
        return 0;
 }
 
index 0840347e251c384af3fa198dfc3bc7e36f7cdbc6..b1e53e3aece5639e622dcced99ba2cd8396b8af7 100644 (file)
@@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
        crq.len = (u16)count;
        crq.data = ibmvtpm->rtce_dma_handle;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]),
+                             cpu_to_be64(word[1]));
        if (rc != H_SUCCESS) {
                dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
                rc = 0;
@@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
        crq.valid = (u8)IBMVTPM_VALID_CMD;
        crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
+                             cpu_to_be64(buf[1]));
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
@@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
        crq.valid = (u8)IBMVTPM_VALID_CMD;
        crq.msg = (u8)VTPM_GET_VERSION;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
+                             cpu_to_be64(buf[1]));
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_get_version failed rc=%d\n", rc);
@@ -336,7 +339,8 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
        crq.valid = (u8)IBMVTPM_VALID_CMD;
        crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
+                             cpu_to_be64(buf[1]));
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "tpm_ibmvtpm_suspend failed rc=%d\n", rc);
@@ -481,11 +485,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
        case IBMVTPM_VALID_CMD:
                switch (crq->msg) {
                case VTPM_GET_RTCE_BUFFER_SIZE_RES:
-                       if (crq->len <= 0) {
+                       if (be16_to_cpu(crq->len) <= 0) {
                                dev_err(ibmvtpm->dev, "Invalid rtce size\n");
                                return;
                        }
-                       ibmvtpm->rtce_size = crq->len;
+                       ibmvtpm->rtce_size = be16_to_cpu(crq->len);
                        ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
                                                    GFP_KERNEL);
                        if (!ibmvtpm->rtce_buf) {
@@ -506,11 +510,11 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
 
                        return;
                case VTPM_GET_VERSION_RES:
-                       ibmvtpm->vtpm_version = crq->data;
+                       ibmvtpm->vtpm_version = be32_to_cpu(crq->data);
                        return;
                case VTPM_TPM_COMMAND_RES:
                        /* len of the data in rtce buffer */
-                       ibmvtpm->res_len = crq->len;
+                       ibmvtpm->res_len = be16_to_cpu(crq->len);
                        wake_up_interruptible(&ibmvtpm->wq);
                        return;
                default:
index 6725bef7cb969108d638fc90258c0f5256b3f81e..f2dffa770b8e93496e2b5c339992ede80b95142b 100644 (file)
@@ -588,6 +588,9 @@ MODULE_PARM_DESC(interrupts, "Enable interrupts");
 
 static void tpm_tis_remove(struct tpm_chip *chip)
 {
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               tpm2_shutdown(chip, TPM2_SU_CLEAR);
+
        iowrite32(~TPM_GLOBAL_INT_ENABLE &
                  ioread32(chip->vendor.iobase +
                           TPM_INT_ENABLE(chip->vendor.
@@ -639,12 +642,9 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
                goto out_err;
        }
 
-       /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands.
-        * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x.
-        */
-       rc = tpm2_gen_interrupt(chip, true);
-       if (rc == 0 || rc == TPM2_RC_INITIALIZE)
-               chip->flags |= TPM_CHIP_FLAG_TPM2;
+       rc = tpm2_probe(chip);
+       if (rc)
+               goto out_err;
 
        vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
        chip->vendor.manufacturer_id = vendor;
@@ -747,7 +747,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 
                        /* Generate Interrupts */
                        if (chip->flags & TPM_CHIP_FLAG_TPM2)
-                               tpm2_gen_interrupt(chip, false);
+                               tpm2_gen_interrupt(chip);
                        else
                                tpm_gen_interrupt(chip);
 
@@ -865,25 +865,22 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 static int tpm_tis_resume(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
-       int ret = 0;
+       int ret;
 
        if (chip->vendor.irq)
                tpm_tis_reenable_interrupts(chip);
 
-       if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-               /* NOP if firmware properly does this. */
-               tpm2_startup(chip, TPM2_SU_STATE);
+       ret = tpm_pm_resume(dev);
+       if (ret)
+               return ret;
 
-               ret = tpm2_shutdown(chip, TPM2_SU_STATE);
-               if (!ret)
-                       ret = tpm2_do_selftest(chip);
-       } else {
-               ret = tpm_pm_resume(dev);
-               if (!ret)
-                       tpm_do_selftest(chip);
-       }
+       /* 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))
+               tpm_do_selftest(chip);
 
-       return ret;
+       return 0;
 }
 #endif
 
This page took 0.032706 seconds and 5 git commands to generate.