]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Apr 2018 17:52:57 +0000 (19:52 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Apr 2018 17:52:57 +0000 (19:52 +0200)
added patches:
drm-bridge-dw-hdmi-fix-overflow-workaround-for-amlogic-meson-gx-socs.patch
i40e-fix-attach-vf-to-vm-issue.patch
tpm-add-retry-logic.patch
tpm-cmd_ready-command-can-be-issued-only-after-granting-locality.patch
tpm-tpm-interface-fix-tpm_transmit-_cmd-kdoc.patch

queue-4.14/drm-bridge-dw-hdmi-fix-overflow-workaround-for-amlogic-meson-gx-socs.patch [new file with mode: 0644]
queue-4.14/i40e-fix-attach-vf-to-vm-issue.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/tpm-add-retry-logic.patch [new file with mode: 0644]
queue-4.14/tpm-cmd_ready-command-can-be-issued-only-after-granting-locality.patch [new file with mode: 0644]
queue-4.14/tpm-tpm-interface-fix-tpm_transmit-_cmd-kdoc.patch [new file with mode: 0644]

diff --git a/queue-4.14/drm-bridge-dw-hdmi-fix-overflow-workaround-for-amlogic-meson-gx-socs.patch b/queue-4.14/drm-bridge-dw-hdmi-fix-overflow-workaround-for-amlogic-meson-gx-socs.patch
new file mode 100644 (file)
index 0000000..15911ea
--- /dev/null
@@ -0,0 +1,45 @@
+From 9c305eb442f3b371fc722ade827bbf673514123e Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <narmstrong@baylibre.com>
+Date: Fri, 23 Feb 2018 12:44:37 +0100
+Subject: drm: bridge: dw-hdmi: Fix overflow workaround for Amlogic Meson GX SoCs
+
+From: Neil Armstrong <narmstrong@baylibre.com>
+
+commit 9c305eb442f3b371fc722ade827bbf673514123e upstream.
+
+The Amlogic Meson GX SoCs, embedded the v2.01a controller, has been also
+identified needing this workaround.
+This patch adds the corresponding version to enable a single iteration for
+this specific version.
+
+Fixes: be41fc55f1aa ("drm: bridge: dw-hdmi: Handle overflow workaround based on device version")
+Acked-by: Archit Taneja <architt@codeaurora.org>
+[narmstrong: s/identifies/identified and rebased against Jernej's change]
+Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/1519386277-25902-1-git-send-email-narmstrong@baylibre.com
+[narmstrong: v4.14 to v4.16 backport]
+Cc: <stable@vger.kernel.org> # 4.14.x
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+@@ -1634,6 +1634,8 @@ static void dw_hdmi_clear_overflow(struc
+        * (and possibly on the platform). So far only i.MX6Q (v1.30a) and
+        * i.MX6DL (v1.31a) have been identified as needing the workaround, with
+        * 4 and 1 iterations respectively.
++       * The Amlogic Meson GX SoCs (v2.01a) have been identified as needing
++       * the workaround with a single iteration.
+        */
+       switch (hdmi->version) {
+@@ -1641,6 +1643,7 @@ static void dw_hdmi_clear_overflow(struc
+               count = 4;
+               break;
+       case 0x131a:
++      case 0x201a:
+               count = 1;
+               break;
+       default:
diff --git a/queue-4.14/i40e-fix-attach-vf-to-vm-issue.patch b/queue-4.14/i40e-fix-attach-vf-to-vm-issue.patch
new file mode 100644 (file)
index 0000000..cc2f33b
--- /dev/null
@@ -0,0 +1,56 @@
+From 028daf80117376b22909becd9720daaefdfceff4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pawe=C5=82=20Jab=C5=82o=C5=84ski?= <pawel.jablonski@intel.com>
+Date: Thu, 8 Mar 2018 14:52:05 -0800
+Subject: i40e: Fix attach VF to VM issue
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paweł Jabłoński <pawel.jablonski@intel.com>
+
+commit 028daf80117376b22909becd9720daaefdfceff4 upstream.
+
+Fix for "Resource temporarily unavailable" problem when virsh is
+trying to attach a device to VM. When the VF driver is loaded on
+host and virsh is trying to attach it to the VM and set a MAC
+address, it ends with a race condition between i40e_reset_vf and
+i40e_ndo_set_vf_mac functions. The bug is fixed by adding polling
+in i40e_ndo_set_vf_mac function For when the VF is in Reset mode.
+
+Signed-off-by: Paweł Jabłoński <pawel.jablonski@intel.com>
+Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Cc: Sinan Kaya <okaya@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |   11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -2781,6 +2781,7 @@ int i40e_ndo_set_vf_mac(struct net_devic
+       int ret = 0;
+       struct hlist_node *h;
+       int bkt;
++      u8 i;
+       /* validate the request */
+       if (vf_id >= pf->num_alloc_vfs) {
+@@ -2792,6 +2793,16 @@ int i40e_ndo_set_vf_mac(struct net_devic
+       vf = &(pf->vf[vf_id]);
+       vsi = pf->vsi[vf->lan_vsi_idx];
++
++      /* When the VF is resetting wait until it is done.
++       * It can take up to 200 milliseconds,
++       * but wait for up to 300 milliseconds to be safe.
++       */
++      for (i = 0; i < 15; i++) {
++              if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states))
++                      break;
++              msleep(20);
++      }
+       if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
+               dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
+                       vf_id);
index 74f0ca5f7b75d253b0713c83017f1958bb366ac4..e398aedcf33d08269ec54edc74b2da5f18975baa 100644 (file)
@@ -1 +1,6 @@
 revert-pinctrl-intel-initialize-gpio-properly-when-used-through-irqchip.patch
+drm-bridge-dw-hdmi-fix-overflow-workaround-for-amlogic-meson-gx-socs.patch
+i40e-fix-attach-vf-to-vm-issue.patch
+tpm-cmd_ready-command-can-be-issued-only-after-granting-locality.patch
+tpm-tpm-interface-fix-tpm_transmit-_cmd-kdoc.patch
+tpm-add-retry-logic.patch
diff --git a/queue-4.14/tpm-add-retry-logic.patch b/queue-4.14/tpm-add-retry-logic.patch
new file mode 100644 (file)
index 0000000..dfbb8f0
--- /dev/null
@@ -0,0 +1,144 @@
+From e2fb992d82c626c43ed0566e07c410e56a087af3 Mon Sep 17 00:00:00 2001
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+Date: Wed, 21 Mar 2018 11:43:48 -0700
+Subject: tpm: add retry logic
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+
+commit e2fb992d82c626c43ed0566e07c410e56a087af3 upstream.
+
+TPM2 can return TPM2_RC_RETRY to any command and when it does we get
+unexpected failures inside the kernel that surprise users (this is
+mostly observed in the trusted key handling code).  The UEFI 2.6 spec
+has advice on how to handle this:
+
+    The firmware SHALL not return TPM2_RC_RETRY prior to the completion
+    of the call to ExitBootServices().
+
+    Implementer’s Note: the implementation of this function should check
+    the return value in the TPM response and, if it is TPM2_RC_RETRY,
+    resend the command. The implementation may abort if a sufficient
+    number of retries has been done.
+
+So we follow that advice in our tpm_transmit() code using
+TPM2_DURATION_SHORT as the initial wait duration and
+TPM2_DURATION_LONG as the maximum wait time.  This should fix all the
+in-kernel use cases and also means that user space TSS implementations
+don't have to have their own retry handling.
+
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: stable@vger.kernel.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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-interface.c |   75 +++++++++++++++++++++++++++++++--------
+ drivers/char/tpm/tpm.h           |    1 
+ 2 files changed, 61 insertions(+), 15 deletions(-)
+
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -399,21 +399,10 @@ static void tpm_relinquish_locality(stru
+       chip->locality = -1;
+ }
+-/**
+- * tpm_transmit - Internal kernel interface to transmit TPM commands.
+- *
+- * @chip: TPM chip to use
+- * @space: tpm space
+- * @buf: TPM command buffer
+- * @bufsiz: length of the TPM command buffer
+- * @flags: tpm transmit flags - bitmap
+- *
+- * Return:
+- *     0 when the operation is successful.
+- *     A negative number for system errors (errno).
+- */
+-ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+-                   u8 *buf, size_t bufsiz, unsigned int flags)
++static ssize_t tpm_try_transmit(struct tpm_chip *chip,
++                              struct tpm_space *space,
++                              u8 *buf, size_t bufsiz,
++                              unsigned int flags)
+ {
+       struct tpm_output_header *header = (void *)buf;
+       int rc;
+@@ -545,6 +534,62 @@ out_no_locality:
+ }
+ /**
++ * tpm_transmit - Internal kernel interface to transmit TPM commands.
++ *
++ * @chip: TPM chip to use
++ * @space: tpm space
++ * @buf: TPM command buffer
++ * @bufsiz: length of the TPM command buffer
++ * @flags: tpm transmit flags - bitmap
++ *
++ * A wrapper around tpm_try_transmit that handles TPM2_RC_RETRY
++ * returns from the TPM and retransmits the command after a delay up
++ * to a maximum wait of TPM2_DURATION_LONG.
++ *
++ * Note: TPM1 never returns TPM2_RC_RETRY so the retry logic is TPM2
++ * only
++ *
++ * Return:
++ *     the length of the return when the operation is successful.
++ *     A negative number for system errors (errno).
++ */
++ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
++                   u8 *buf, size_t bufsiz, unsigned int flags)
++{
++      struct tpm_output_header *header = (struct tpm_output_header *)buf;
++      /* space for header and handles */
++      u8 save[TPM_HEADER_SIZE + 3*sizeof(u32)];
++      unsigned int delay_msec = TPM2_DURATION_SHORT;
++      u32 rc = 0;
++      ssize_t ret;
++      const size_t save_size = min(space ? sizeof(save) : TPM_HEADER_SIZE,
++                                   bufsiz);
++
++      /*
++       * Subtlety here: if we have a space, the handles will be
++       * transformed, so when we restore the header we also have to
++       * restore the handles.
++       */
++      memcpy(save, buf, save_size);
++
++      for (;;) {
++              ret = tpm_try_transmit(chip, space, buf, bufsiz, flags);
++              if (ret < 0)
++                      break;
++              rc = be32_to_cpu(header->return_code);
++              if (rc != TPM2_RC_RETRY)
++                      break;
++              delay_msec *= 2;
++              if (delay_msec > TPM2_DURATION_LONG) {
++                      dev_err(&chip->dev, "TPM is in retry loop\n");
++                      break;
++              }
++              tpm_msleep(delay_msec);
++              memcpy(buf, save, save_size);
++      }
++      return ret;
++}
++/**
+  * tpm_transmit_cmd - send a tpm command to the device
+  *    The function extracts tpm out header return code
+  *
+--- a/drivers/char/tpm/tpm.h
++++ b/drivers/char/tpm/tpm.h
+@@ -106,6 +106,7 @@ enum tpm2_return_codes {
+       TPM2_RC_COMMAND_CODE    = 0x0143,
+       TPM2_RC_TESTING         = 0x090A, /* RC_WARN */
+       TPM2_RC_REFERENCE_H0    = 0x0910,
++      TPM2_RC_RETRY           = 0x0922,
+ };
+ enum tpm2_algorithms {
diff --git a/queue-4.14/tpm-cmd_ready-command-can-be-issued-only-after-granting-locality.patch b/queue-4.14/tpm-cmd_ready-command-can-be-issued-only-after-granting-locality.patch
new file mode 100644 (file)
index 0000000..4a18280
--- /dev/null
@@ -0,0 +1,360 @@
+From 888d867df4417deffc33927e6fc2c6925736fe92 Mon Sep 17 00:00:00 2001
+From: Tomas Winkler <tomas.winkler@intel.com>
+Date: Mon, 5 Mar 2018 13:34:49 +0200
+Subject: tpm: cmd_ready command can be issued only after granting locality
+
+From: Tomas Winkler <tomas.winkler@intel.com>
+
+commit 888d867df4417deffc33927e6fc2c6925736fe92 upstream.
+
+The correct sequence is to first request locality and only after
+that perform cmd_ready handshake, otherwise the hardware will drop
+the subsequent message as from the device point of view the cmd_ready
+handshake wasn't performed. Symmetrically locality has to be relinquished
+only after going idle handshake has completed, this requires that
+go_idle has to poll for the completion and as well locality
+relinquish has to poll for completion so it is not overridden
+in back to back commands flow.
+
+Two wrapper functions are added (request_locality relinquish_locality)
+to simplify the error handling.
+
+The issue is only visible on devices that support multiple localities.
+
+Fixes: 877c57d0d0ca ("tpm_crb: request and relinquish locality 0")
+Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com>
+Tested-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkine@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-interface.c |   54 ++++++++++++++-----
+ drivers/char/tpm/tpm_crb.c       |  108 +++++++++++++++++++++++++++------------
+ drivers/char/tpm/tpm_tis_core.c  |    4 +
+ include/linux/tpm.h              |    2 
+ 4 files changed, 120 insertions(+), 48 deletions(-)
+
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -369,6 +369,36 @@ err_len:
+       return -EINVAL;
+ }
++static int tpm_request_locality(struct tpm_chip *chip)
++{
++      int rc;
++
++      if (!chip->ops->request_locality)
++              return 0;
++
++      rc = chip->ops->request_locality(chip, 0);
++      if (rc < 0)
++              return rc;
++
++      chip->locality = rc;
++
++      return 0;
++}
++
++static void tpm_relinquish_locality(struct tpm_chip *chip)
++{
++      int rc;
++
++      if (!chip->ops->relinquish_locality)
++              return;
++
++      rc = chip->ops->relinquish_locality(chip, chip->locality);
++      if (rc)
++              dev_err(&chip->dev, "%s: : error %d\n", __func__, rc);
++
++      chip->locality = -1;
++}
++
+ /**
+  * tmp_transmit - Internal kernel interface to transmit TPM commands.
+  *
+@@ -422,8 +452,6 @@ ssize_t tpm_transmit(struct tpm_chip *ch
+       if (!(flags & TPM_TRANSMIT_UNLOCKED))
+               mutex_lock(&chip->tpm_mutex);
+-      if (chip->dev.parent)
+-              pm_runtime_get_sync(chip->dev.parent);
+       if (chip->ops->clk_enable != NULL)
+               chip->ops->clk_enable(chip, true);
+@@ -431,14 +459,15 @@ ssize_t tpm_transmit(struct tpm_chip *ch
+       /* Store the decision as chip->locality will be changed. */
+       need_locality = chip->locality == -1;
+-      if (!(flags & TPM_TRANSMIT_RAW) &&
+-          need_locality && chip->ops->request_locality)  {
+-              rc = chip->ops->request_locality(chip, 0);
++      if (!(flags & TPM_TRANSMIT_RAW) && need_locality) {
++              rc = tpm_request_locality(chip);
+               if (rc < 0)
+                       goto out_no_locality;
+-              chip->locality = rc;
+       }
++      if (chip->dev.parent)
++              pm_runtime_get_sync(chip->dev.parent);
++
+       rc = tpm2_prepare_space(chip, space, ordinal, buf);
+       if (rc)
+               goto out;
+@@ -499,17 +528,16 @@ out_recv:
+       rc = tpm2_commit_space(chip, space, ordinal, buf, &len);
+ out:
+-      if (need_locality && chip->ops->relinquish_locality) {
+-              chip->ops->relinquish_locality(chip, chip->locality);
+-              chip->locality = -1;
+-      }
++      if (chip->dev.parent)
++              pm_runtime_put_sync(chip->dev.parent);
++
++      if (need_locality)
++              tpm_relinquish_locality(chip);
++
+ out_no_locality:
+       if (chip->ops->clk_enable != NULL)
+               chip->ops->clk_enable(chip, false);
+-      if (chip->dev.parent)
+-              pm_runtime_put_sync(chip->dev.parent);
+-
+       if (!(flags & TPM_TRANSMIT_UNLOCKED))
+               mutex_unlock(&chip->tpm_mutex);
+       return rc ? rc : len;
+--- a/drivers/char/tpm/tpm_crb.c
++++ b/drivers/char/tpm/tpm_crb.c
+@@ -117,6 +117,25 @@ struct tpm2_crb_smc {
+       u32 smc_func_id;
+ };
++static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
++                              unsigned long timeout)
++{
++      ktime_t start;
++      ktime_t stop;
++
++      start = ktime_get();
++      stop = ktime_add(start, ms_to_ktime(timeout));
++
++      do {
++              if ((ioread32(reg) & mask) == value)
++                      return true;
++
++              usleep_range(50, 100);
++      } while (ktime_before(ktime_get(), stop));
++
++      return ((ioread32(reg) & mask) == value);
++}
++
+ /**
+  * crb_go_idle - request tpm crb device to go the idle state
+  *
+@@ -132,37 +151,24 @@ struct tpm2_crb_smc {
+  *
+  * Return: 0 always
+  */
+-static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
++static int crb_go_idle(struct device *dev, struct crb_priv *priv)
+ {
+       if ((priv->flags & CRB_FL_ACPI_START) ||
+           (priv->flags & CRB_FL_CRB_SMC_START))
+               return 0;
+       iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->regs_t->ctrl_req);
+-      /* we don't really care when this settles */
++      if (!crb_wait_for_reg_32(&priv->regs_t->ctrl_req,
++                               CRB_CTRL_REQ_GO_IDLE/* mask */,
++                               0, /* value */
++                               TPM2_TIMEOUT_C)) {
++              dev_warn(dev, "goIdle timed out\n");
++              return -ETIME;
++      }
+       return 0;
+ }
+-static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value,
+-                              unsigned long timeout)
+-{
+-      ktime_t start;
+-      ktime_t stop;
+-
+-      start = ktime_get();
+-      stop = ktime_add(start, ms_to_ktime(timeout));
+-
+-      do {
+-              if ((ioread32(reg) & mask) == value)
+-                      return true;
+-
+-              usleep_range(50, 100);
+-      } while (ktime_before(ktime_get(), stop));
+-
+-      return false;
+-}
+-
+ /**
+  * crb_cmd_ready - request tpm crb device to enter ready state
+  *
+@@ -177,8 +183,7 @@ static bool crb_wait_for_reg_32(u32 __io
+  *
+  * Return: 0 on success -ETIME on timeout;
+  */
+-static int __maybe_unused crb_cmd_ready(struct device *dev,
+-                                      struct crb_priv *priv)
++static int crb_cmd_ready(struct device *dev, struct crb_priv *priv)
+ {
+       if ((priv->flags & CRB_FL_ACPI_START) ||
+           (priv->flags & CRB_FL_CRB_SMC_START))
+@@ -196,11 +201,11 @@ static int __maybe_unused crb_cmd_ready(
+       return 0;
+ }
+-static int crb_request_locality(struct tpm_chip *chip, int loc)
++static int __crb_request_locality(struct device *dev,
++                                struct crb_priv *priv, int loc)
+ {
+-      struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+       u32 value = CRB_LOC_STATE_LOC_ASSIGNED |
+-              CRB_LOC_STATE_TPM_REG_VALID_STS;
++                  CRB_LOC_STATE_TPM_REG_VALID_STS;
+       if (!priv->regs_h)
+               return 0;
+@@ -208,21 +213,45 @@ static int crb_request_locality(struct t
+       iowrite32(CRB_LOC_CTRL_REQUEST_ACCESS, &priv->regs_h->loc_ctrl);
+       if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, value, value,
+                                TPM2_TIMEOUT_C)) {
+-              dev_warn(&chip->dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
++              dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
+               return -ETIME;
+       }
+       return 0;
+ }
+-static void crb_relinquish_locality(struct tpm_chip *chip, int loc)
++static int crb_request_locality(struct tpm_chip *chip, int loc)
+ {
+       struct crb_priv *priv = dev_get_drvdata(&chip->dev);
++      return __crb_request_locality(&chip->dev, priv, loc);
++}
++
++static int __crb_relinquish_locality(struct device *dev,
++                                   struct crb_priv *priv, int loc)
++{
++      u32 mask = CRB_LOC_STATE_LOC_ASSIGNED |
++                 CRB_LOC_STATE_TPM_REG_VALID_STS;
++      u32 value = CRB_LOC_STATE_TPM_REG_VALID_STS;
++
+       if (!priv->regs_h)
+-              return;
++              return 0;
+       iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
++      if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value,
++                               TPM2_TIMEOUT_C)) {
++              dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
++              return -ETIME;
++      }
++
++      return 0;
++}
++
++static int crb_relinquish_locality(struct tpm_chip *chip, int loc)
++{
++      struct crb_priv *priv = dev_get_drvdata(&chip->dev);
++
++      return __crb_relinquish_locality(&chip->dev, priv, loc);
+ }
+ static u8 crb_status(struct tpm_chip *chip)
+@@ -466,6 +495,10 @@ static int crb_map_io(struct acpi_device
+                       dev_warn(dev, FW_BUG "Bad ACPI memory layout");
+       }
++      ret = __crb_request_locality(dev, priv, 0);
++      if (ret)
++              return ret;
++
+       priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
+                                  sizeof(struct crb_regs_tail));
+       if (IS_ERR(priv->regs_t))
+@@ -522,6 +555,8 @@ out:
+       crb_go_idle(dev, priv);
++      __crb_relinquish_locality(dev, priv, 0);
++
+       return ret;
+ }
+@@ -589,10 +624,14 @@ static int crb_acpi_add(struct acpi_devi
+       chip->acpi_dev_handle = device->handle;
+       chip->flags = TPM_CHIP_FLAG_TPM2;
+-      rc  = crb_cmd_ready(dev, priv);
++      rc = __crb_request_locality(dev, priv, 0);
+       if (rc)
+               return rc;
++      rc  = crb_cmd_ready(dev, priv);
++      if (rc)
++              goto out;
++
+       pm_runtime_get_noresume(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+@@ -602,12 +641,15 @@ static int crb_acpi_add(struct acpi_devi
+               crb_go_idle(dev, priv);
+               pm_runtime_put_noidle(dev);
+               pm_runtime_disable(dev);
+-              return rc;
++              goto out;
+       }
+-      pm_runtime_put(dev);
++      pm_runtime_put_sync(dev);
+-      return 0;
++out:
++      __crb_relinquish_locality(dev, priv, 0);
++
++      return rc;
+ }
+ static int crb_acpi_remove(struct acpi_device *device)
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -77,11 +77,13 @@ static bool check_locality(struct tpm_ch
+       return false;
+ }
+-static void release_locality(struct tpm_chip *chip, int l)
++static int release_locality(struct tpm_chip *chip, int l)
+ {
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
++
++      return 0;
+ }
+ static int request_locality(struct tpm_chip *chip, int l)
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -49,7 +49,7 @@ struct tpm_class_ops {
+       bool (*update_timeouts)(struct tpm_chip *chip,
+                               unsigned long *timeout_cap);
+       int (*request_locality)(struct tpm_chip *chip, int loc);
+-      void (*relinquish_locality)(struct tpm_chip *chip, int loc);
++      int (*relinquish_locality)(struct tpm_chip *chip, int loc);
+       void (*clk_enable)(struct tpm_chip *chip, bool value);
+ };
diff --git a/queue-4.14/tpm-tpm-interface-fix-tpm_transmit-_cmd-kdoc.patch b/queue-4.14/tpm-tpm-interface-fix-tpm_transmit-_cmd-kdoc.patch
new file mode 100644 (file)
index 0000000..72ff03c
--- /dev/null
@@ -0,0 +1,48 @@
+From 65520d46a4adbf7f23bbb6d9b1773513f7bc7821 Mon Sep 17 00:00:00 2001
+From: "Winkler, Tomas" <tomas.winkler@intel.com>
+Date: Mon, 5 Mar 2018 14:48:25 +0200
+Subject: tpm: tpm-interface: fix tpm_transmit/_cmd kdoc
+
+From: Winkler, Tomas <tomas.winkler@intel.com>
+
+commit 65520d46a4adbf7f23bbb6d9b1773513f7bc7821 upstream.
+
+Fix tmp_ -> tpm_ typo and add reference to 'space' parameter
+in kdoc for tpm_transmit and tpm_transmit_cmd functions.
+
+Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
+Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/tpm/tpm-interface.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -400,9 +400,10 @@ static void tpm_relinquish_locality(stru
+ }
+ /**
+- * tmp_transmit - Internal kernel interface to transmit TPM commands.
++ * tpm_transmit - Internal kernel interface to transmit TPM commands.
+  *
+  * @chip: TPM chip to use
++ * @space: tpm space
+  * @buf: TPM command buffer
+  * @bufsiz: length of the TPM command buffer
+  * @flags: tpm transmit flags - bitmap
+@@ -544,10 +545,11 @@ out_no_locality:
+ }
+ /**
+- * tmp_transmit_cmd - send a tpm command to the device
++ * tpm_transmit_cmd - send a tpm command to the device
+  *    The function extracts tpm out header return code
+  *
+  * @chip: TPM chip to use
++ * @space: tpm space
+  * @buf: TPM command buffer
+  * @bufsiz: length of the buffer
+  * @min_rsp_body_length: minimum expected length of response body