i40e: Workaround fix for mss < 256 issue
authorAnjali Singhai Jain <anjali.singhai@intel.com>
Wed, 21 Oct 2015 23:47:07 +0000 (19:47 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 15 Sep 2016 06:27:37 +0000 (08:27 +0200)
[ Upstream commit 4f2f017c6101ab2ba202d6059c238c15577ad38b ]

HW/NVM sets a limit of no less than 256 bytes for MSS. Stack can send as
low as 76 bytes MSS. This patch lowers the HW limit to 64 bytes to avoid
MDDs from firing and causing a reset when the MSS is lower than 256.

Change-ID: I36b500a6bb227d283c3e321a7718e0672b11fab0
Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/intel/i40e/i40e_main.c

index 4a9873ec28c7119d28aabb791bd0628ceccf56ad..59b0bcc76a12d9bef7f30ce2a6afbffe1bb43da5 100644 (file)
@@ -6685,6 +6685,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
        struct i40e_hw *hw = &pf->hw;
        u8 set_fc_aq_fail = 0;
        i40e_status ret;
+       u32 val;
        u32 v;
 
        /* Now we wait for GRST to settle out.
@@ -6823,6 +6824,20 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit)
                }
        }
 
+       /* Reconfigure hardware for allowing smaller MSS in the case
+        * of TSO, so that we avoid the MDD being fired and causing
+        * a reset in the case of small MSS+TSO.
+        */
+#define I40E_REG_MSS          0x000E64DC
+#define I40E_REG_MSS_MIN_MASK 0x3FF0000
+#define I40E_64BYTE_MSS       0x400000
+       val = rd32(hw, I40E_REG_MSS);
+       if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) {
+               val &= ~I40E_REG_MSS_MIN_MASK;
+               val |= I40E_64BYTE_MSS;
+               wr32(hw, I40E_REG_MSS, val);
+       }
+
        if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) ||
            (pf->hw.aq.fw_maj_ver < 4)) {
                msleep(75);
@@ -10183,6 +10198,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        u16 link_status;
        int err;
        u32 len;
+       u32 val;
        u32 i;
        u8 set_fc_aq_fail;
 
@@ -10493,6 +10509,17 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                         i40e_stat_str(&pf->hw, err),
                         i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
 
+       /* Reconfigure hardware for allowing smaller MSS in the case
+        * of TSO, so that we avoid the MDD being fired and causing
+        * a reset in the case of small MSS+TSO.
+        */
+       val = rd32(hw, I40E_REG_MSS);
+       if ((val & I40E_REG_MSS_MIN_MASK) > I40E_64BYTE_MSS) {
+               val &= ~I40E_REG_MSS_MIN_MASK;
+               val |= I40E_64BYTE_MSS;
+               wr32(hw, I40E_REG_MSS, val);
+       }
+
        if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) ||
            (pf->hw.aq.fw_maj_ver < 4)) {
                msleep(75);