Merge branch 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Sep 2017 18:34:28 +0000 (11:34 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Sep 2017 18:34:28 +0000 (11:34 -0700)
Pull TPM updates from James Morris:
 "Here are the TPM updates from Jarkko for v4.14, which I've placed in
  their own branch (next-tpm). I ended up cherry-picking them as other
  changes had been made in Jarkko's branch after he sent me his original
  pull request.

  I plan on maintaining a separate branch for TPM (and other security
  subsystems) from now on.

  From Jarkko: 'Not much this time except a few fixes'"

* 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  tpm: ibmvtpm: simplify crq initialization and document crq format
  tpm: replace msleep() with  usleep_range() in TPM 1.2/2.0 generic drivers
  Documentation: tpm: add powered-while-suspended binding documentation
  tpm: tpm_crb: constify acpi_device_id.
  tpm: vtpm: constify vio_device_id

Documentation/devicetree/bindings/security/tpm/tpm-i2c.txt
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_infineon.c
drivers/char/tpm/tpm_tis_core.c

index 3eca6de6369d773ef70bba048345aaed1d2737df..a65d7b71e81a2a22bfc23ab79ede461a25d2de37 100644 (file)
@@ -8,6 +8,12 @@ Required properties:
                    the firmware event log
 - linux,sml-size : size of the memory allocated for the firmware event log
 
+Optional properties:
+
+- powered-while-suspended: present when the TPM is left powered on between
+                           suspend and resume (makes the suspend/resume
+                           callbacks do nothing).
+
 Example (for OpenPower Systems with Nuvoton TPM 2.0 on I2C)
 ----------------------------------------------------------
 
index fe597e6c55c40ca34f070f83a2af53e9b42a66de..1d6729be4cd6376727b9b210319bd77f03ccfb02 100644 (file)
@@ -455,7 +455,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
                        goto out;
                }
 
-               msleep(TPM_TIMEOUT);    /* CHECK */
+               tpm_msleep(TPM_TIMEOUT);
                rmb();
        } while (time_before(jiffies, stop));
 
@@ -970,7 +970,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
                        dev_info(
                            &chip->dev, HW_ERR
                            "TPM command timed out during continue self test");
-                       msleep(delay_msec);
+                       tpm_msleep(delay_msec);
                        continue;
                }
 
@@ -985,7 +985,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
                }
                if (rc != TPM_WARN_DOING_SELFTEST)
                        return rc;
-               msleep(delay_msec);
+               tpm_msleep(delay_msec);
        } while (--loops > 0);
 
        return rc;
@@ -1085,7 +1085,7 @@ again:
                }
        } else {
                do {
-                       msleep(TPM_TIMEOUT);
+                       tpm_msleep(TPM_TIMEOUT);
                        status = chip->ops->status(chip);
                        if ((status & mask) == mask)
                                return 0;
@@ -1150,7 +1150,7 @@ int tpm_pm_suspend(struct device *dev)
                 */
                if (rc != TPM_WARN_RETRY)
                        break;
-               msleep(TPM_TIMEOUT_RETRY);
+               tpm_msleep(TPM_TIMEOUT_RETRY);
        }
 
        if (rc)
index 04fbff2edbf38ce19845e5c1fdd1cd619293419d..2d5466a72e40f82b3272b857b74a1f822f82b966 100644 (file)
@@ -50,7 +50,8 @@ enum tpm_const {
 
 enum tpm_timeout {
        TPM_TIMEOUT = 5,        /* msecs */
-       TPM_TIMEOUT_RETRY = 100 /* msecs */
+       TPM_TIMEOUT_RETRY = 100, /* msecs */
+       TPM_TIMEOUT_RANGE_US = 300      /* usecs */
 };
 
 /* TPM addresses */
@@ -527,6 +528,12 @@ int tpm_pm_resume(struct device *dev);
 int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
                      wait_queue_head_t *queue, bool check_cancel);
 
+static inline void tpm_msleep(unsigned int delay_msec)
+{
+       usleep_range(delay_msec * 1000,
+                    (delay_msec * 1000) + TPM_TIMEOUT_RANGE_US);
+};
+
 struct tpm_chip *tpm_chip_find_get(int chip_num);
 __must_check int tpm_try_get_ops(struct tpm_chip *chip);
 void tpm_put_ops(struct tpm_chip *chip);
index f7f34b2aa98190c7474b3dd6c0f02b2abc032ec9..e1a41b788f081c829ad0d0353ac7d3622752c82f 100644 (file)
@@ -899,7 +899,7 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
                if (rc != TPM2_RC_TESTING)
                        break;
 
-               msleep(delay_msec);
+               tpm_msleep(delay_msec);
        }
 
        return rc;
index a4ac63a21d8a051da3c336f5343b9dc72574b719..8f0a98dea327a5bc90d7fcf3529c3701d17abd6b 100644 (file)
@@ -665,7 +665,7 @@ static const struct dev_pm_ops crb_pm = {
        SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL)
 };
 
-static struct acpi_device_id crb_device_ids[] = {
+static const struct acpi_device_id crb_device_ids[] = {
        {"MSFT0101", 0},
        {"", 0},
 };
index f01d083eced2fc056d6d74e4423a62f28470e302..25f6e2665385d063d47c50ad9f21e25591f828c9 100644 (file)
 
 static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
 
-static struct vio_device_id tpm_ibmvtpm_device_table[] = {
+static const struct vio_device_id tpm_ibmvtpm_device_table[] = {
        { "IBM,vtpm", "IBM,vtpm"},
        { "", "" }
 };
 MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
 
 /**
+ *
+ * ibmvtpm_send_crq_word - Send a CRQ request
+ * @vdev:      vio device struct
+ * @w1:                pre-constructed first word of tpm crq (second word is reserved)
+ *
+ * Return:
+ *     0 - Success
+ *     Non-zero - Failure
+ */
+static int ibmvtpm_send_crq_word(struct vio_dev *vdev, u64 w1)
+{
+       return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, 0);
+}
+
+/**
+ *
  * ibmvtpm_send_crq - Send a CRQ request
  *
  * @vdev:      vio device struct
- * @w1:                first word
- * @w2:                second word
+ * @valid:     Valid field
+ * @msg:       Type field
+ * @len:       Length field
+ * @data:      Data field
+ *
+ * The ibmvtpm crq is defined as follows:
+ *
+ * Byte  |   0   |   1   |   2   |   3   |   4   |   5   |   6   |   7
+ * -----------------------------------------------------------------------
+ * Word0 | Valid | Type  |     Length    |              Data
+ * -----------------------------------------------------------------------
+ * Word1 |                Reserved
+ * -----------------------------------------------------------------------
+ *
+ * Which matches the following structure (on bigendian host):
+ *
+ * struct ibmvtpm_crq {
+ *         u8 valid;
+ *         u8 msg;
+ *         __be16 len;
+ *         __be32 data;
+ *         __be64 reserved;
+ * } __attribute__((packed, aligned(8)));
+ *
+ * However, the value is passed in a register so just compute the numeric value
+ * to load into the register avoiding byteswap altogether. Endian only affects
+ * memory loads and stores - registers are internally represented the same.
  *
  * Return:
- *     0 -Sucess
+ *     0 (H_SUCCESS) - Success
  *     Non-zero - Failure
  */
-static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
+static int ibmvtpm_send_crq(struct vio_dev *vdev,
+               u8 valid, u8 msg, u16 len, u32 data)
 {
-       return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
+       u64 w1 = ((u64)valid << 56) | ((u64)msg << 48) | ((u64)len << 32) |
+               (u64)data;
+       return ibmvtpm_send_crq_word(vdev, w1);
 }
 
 /**
@@ -109,8 +153,6 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
        struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
-       struct ibmvtpm_crq crq;
-       __be64 *word = (__be64 *)&crq;
        int rc, sig;
 
        if (!ibmvtpm->rtce_buf) {
@@ -137,10 +179,6 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
        spin_lock(&ibmvtpm->rtce_lock);
        ibmvtpm->res_len = 0;
        memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_TPM_COMMAND;
-       crq.len = cpu_to_be16(count);
-       crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);
 
        /*
         * set the processing flag before the Hcall, since we may get the
@@ -148,8 +186,9 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
         */
        ibmvtpm->tpm_processing_cmd = true;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
-                             be64_to_cpu(word[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
+                       count, ibmvtpm->rtce_dma_handle);
        if (rc != H_SUCCESS) {
                dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
                rc = 0;
@@ -182,15 +221,10 @@ static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
  */
 static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
 {
-       struct ibmvtpm_crq crq;
-       u64 *buf = (u64 *) &crq;
        int rc;
 
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
-
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
-                             cpu_to_be64(buf[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_GET_RTCE_BUFFER_SIZE, 0, 0);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
@@ -210,15 +244,10 @@ static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
  */
 static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
 {
-       struct ibmvtpm_crq crq;
-       u64 *buf = (u64 *) &crq;
        int rc;
 
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_GET_VERSION;
-
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
-                             cpu_to_be64(buf[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_GET_VERSION, 0, 0);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_get_version failed rc=%d\n", rc);
@@ -238,7 +267,7 @@ static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
 {
        int rc;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
+       rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_COMP_CMD);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
@@ -258,7 +287,7 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
 {
        int rc;
 
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
+       rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "ibmvtpm_crq_send_init failed rc=%d\n", rc);
@@ -340,15 +369,10 @@ static int tpm_ibmvtpm_suspend(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
        struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
-       struct ibmvtpm_crq crq;
-       u64 *buf = (u64 *) &crq;
        int rc = 0;
 
-       crq.valid = (u8)IBMVTPM_VALID_CMD;
-       crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
-
-       rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]),
-                             cpu_to_be64(buf[1]));
+       rc = ibmvtpm_send_crq(ibmvtpm->vdev,
+                       IBMVTPM_VALID_CMD, VTPM_PREPARE_TO_SUSPEND, 0, 0);
        if (rc != H_SUCCESS)
                dev_err(ibmvtpm->dev,
                        "tpm_ibmvtpm_suspend failed rc=%d\n", rc);
index 3b1b9f9322d5547120f35f490b7ec7b802d2b085..d8f10047fbbaf1f2f965a795358e60be859fb759 100644 (file)
@@ -191,7 +191,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
                /* check the status-register if wait_for_bit is set */
                if (status & 1 << wait_for_bit)
                        break;
-               msleep(TPM_MSLEEP_TIME);
+               tpm_msleep(TPM_MSLEEP_TIME);
        }
        if (i == TPM_MAX_TRIES) {       /* timeout occurs */
                if (wait_for_bit == STAT_XFE)
@@ -226,7 +226,7 @@ static void tpm_wtx(struct tpm_chip *chip)
        wait_and_send(chip, TPM_CTRL_WTX);
        wait_and_send(chip, 0x00);
        wait_and_send(chip, 0x00);
-       msleep(TPM_WTX_MSLEEP_TIME);
+       tpm_msleep(TPM_WTX_MSLEEP_TIME);
 }
 
 static void tpm_wtx_abort(struct tpm_chip *chip)
@@ -237,7 +237,7 @@ static void tpm_wtx_abort(struct tpm_chip *chip)
        wait_and_send(chip, 0x00);
        wait_and_send(chip, 0x00);
        number_of_wtx = 0;
-       msleep(TPM_WTX_MSLEEP_TIME);
+       tpm_msleep(TPM_WTX_MSLEEP_TIME);
 }
 
 static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
index b617b2eeb080ad41034b7b7cbd1b21aaed524a3a..63bc6c3b949e51406527a484d356e24959ed9615 100644 (file)
@@ -51,7 +51,7 @@ static int wait_startup(struct tpm_chip *chip, int l)
 
                if (access & TPM_ACCESS_VALID)
                        return 0;
-               msleep(TPM_TIMEOUT);
+               tpm_msleep(TPM_TIMEOUT);
        } while (time_before(jiffies, stop));
        return -1;
 }
@@ -117,7 +117,7 @@ again:
                do {
                        if (check_locality(chip, l))
                                return l;
-                       msleep(TPM_TIMEOUT);
+                       tpm_msleep(TPM_TIMEOUT);
                } while (time_before(jiffies, stop));
        }
        return -1;
@@ -164,7 +164,7 @@ static int get_burstcount(struct tpm_chip *chip)
                burstcnt = (value >> 8) & 0xFFFF;
                if (burstcnt)
                        return burstcnt;
-               msleep(TPM_TIMEOUT);
+               tpm_msleep(TPM_TIMEOUT);
        } while (time_before(jiffies, stop));
        return -EBUSY;
 }
@@ -396,7 +396,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
        priv->irq = irq;
        chip->flags |= TPM_CHIP_FLAG_IRQ;
        if (!priv->irq_tested)
-               msleep(1);
+               tpm_msleep(1);
        if (!priv->irq_tested)
                disable_interrupts(chip);
        priv->irq_tested = true;