backport i40e fixes
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 6 Feb 2019 10:42:55 +0000 (11:42 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 6 Feb 2019 10:42:55 +0000 (11:42 +0100)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
patches/kernel/0008-i40e-Fix-for-Tx-timeouts-when-interface-is-brought-u.patch [new file with mode: 0644]
patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch [new file with mode: 0644]

diff --git a/patches/kernel/0008-i40e-Fix-for-Tx-timeouts-when-interface-is-brought-u.patch b/patches/kernel/0008-i40e-Fix-for-Tx-timeouts-when-interface-is-brought-u.patch
new file mode 100644 (file)
index 0000000..1b78db3
--- /dev/null
@@ -0,0 +1,64 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Martyna Szapar <martyna.szapar@intel.com>
+Date: Tue, 7 Aug 2018 17:11:23 -0700
+Subject: [PATCH] i40e: Fix for Tx timeouts when interface is brought up if DCB
+ is enabled
+
+If interface is connected to switch port configured for DCB there are
+TX timeouts when bringing up interface. Problem started appearing after
+adding in i40e driver code mqprio hardware offload mode. In function
+i40e_vsi_configure_bw_alloc was added resetting BW rate which should
+be executing when mqprio qdisc is removed but was also when there was
+no mqprio qdisc added and DCB was enabled. In this patch was added
+additional check for DCB flag so now when DCB is enabled the correct
+DCB configs from before mqprio patch are restored.
+
+Signed-off-by: Martyna Szapar <martyna.szapar@intel.com>
+Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 08f7bd9001bc..7895a0af37e6 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -5219,15 +5219,17 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc,
+                                      u8 *bw_share)
+ {
+       struct i40e_aqc_configure_vsi_tc_bw_data bw_data;
++      struct i40e_pf *pf = vsi->back;
+       i40e_status ret;
+       int i;
+-      if (vsi->back->flags & I40E_FLAG_TC_MQPRIO)
++      /* There is no need to reset BW when mqprio mode is on.  */
++      if (pf->flags & I40E_FLAG_TC_MQPRIO)
+               return 0;
+-      if (!vsi->mqprio_qopt.qopt.hw) {
++      if (!vsi->mqprio_qopt.qopt.hw && !(pf->flags & I40E_FLAG_DCB_ENABLED)) {
+               ret = i40e_set_bw_limit(vsi, vsi->seid, 0);
+               if (ret)
+-                      dev_info(&vsi->back->pdev->dev,
++                      dev_info(&pf->pdev->dev,
+                                "Failed to reset tx rate for vsi->seid %u\n",
+                                vsi->seid);
+               return ret;
+@@ -5236,12 +5238,11 @@ static int i40e_vsi_configure_bw_alloc(struct i40e_vsi *vsi, u8 enabled_tc,
+       for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
+               bw_data.tc_bw_credits[i] = bw_share[i];
+-      ret = i40e_aq_config_vsi_tc_bw(&vsi->back->hw, vsi->seid, &bw_data,
+-                                     NULL);
++      ret = i40e_aq_config_vsi_tc_bw(&pf->hw, vsi->seid, &bw_data, NULL);
+       if (ret) {
+-              dev_info(&vsi->back->pdev->dev,
++              dev_info(&pf->pdev->dev,
+                        "AQ command Config VSI BW allocation per TC failed = %d\n",
+-                       vsi->back->hw.aq.asq_last_status);
++                       pf->hw.aq.asq_last_status);
+               return -EINVAL;
+       }
diff --git a/patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch b/patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch
new file mode 100644 (file)
index 0000000..4e5367d
--- /dev/null
@@ -0,0 +1,58 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Alan Brady <alan.brady@intel.com>
+Date: Mon, 29 Oct 2018 11:27:21 -0700
+Subject: [PATCH] i40e: prevent overlapping tx_timeout recover
+
+If a TX hang occurs, we attempt to recover by incrementally resetting.
+If we're starved for CPU time, it's possible the reset doesn't actually
+complete (or even fire) before another tx_timeout fires causing us to
+fly through the different resets without actually doing them.
+
+This adds a bit to set and check if a timeout recovery is already
+pending and, if so, bail out of tx_timeout.  The bit will get cleared at
+the end of i40e_rebuild when reset is complete.
+
+Signed-off-by: Alan Brady <alan.brady@intel.com>
+Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ drivers/net/ethernet/intel/i40e/i40e.h      | 1 +
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
+index e019baa905c5..80114d6a910a 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e.h
++++ b/drivers/net/ethernet/intel/i40e/i40e.h
+@@ -145,6 +145,7 @@ enum i40e_state_t {
+       __I40E_MDD_EVENT_PENDING,
+       __I40E_VFLR_EVENT_PENDING,
+       __I40E_RESET_RECOVERY_PENDING,
++      __I40E_TIMEOUT_RECOVERY_PENDING,
+       __I40E_MISC_IRQ_REQUESTED,
+       __I40E_RESET_INTR_RECEIVED,
+       __I40E_REINIT_REQUESTED,
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 7895a0af37e6..874fd143c351 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -365,6 +365,10 @@ static void i40e_tx_timeout(struct net_device *netdev)
+                     (pf->tx_timeout_last_recovery + netdev->watchdog_timeo)))
+               return;   /* don't do any new action before the next timeout */
++      /* don't kick off another recovery if one is already pending */
++      if (test_and_set_bit(__I40E_TIMEOUT_RECOVERY_PENDING, pf->state))
++              return;
++
+       if (tx_ring) {
+               head = i40e_get_head(tx_ring);
+               /* Read interrupt register */
+@@ -9478,6 +9482,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
+       clear_bit(__I40E_RESET_FAILED, pf->state);
+ clear_recovery:
+       clear_bit(__I40E_RESET_RECOVERY_PENDING, pf->state);
++      clear_bit(__I40E_TIMEOUT_RECOVERY_PENDING, pf->state);
+ }
+ /**