bnxt_en: Misc bug fixes
authorSelvin Xavier <selvin.xavier@broadcom.com>
Sun, 24 Sep 2017 16:00:44 +0000 (09:00 -0700)
committerSelvin Xavier <selvin.xavier@broadcom.com>
Sun, 24 Sep 2017 16:00:44 +0000 (09:00 -0700)
Add new device ids.
Fixes the rtnl_lock issue while loading bnxt_re driver on some of the
systems.

Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
linux-next-cherry-picks/0059-bnxt_en-Fix-bnxt_reset-in-the-slow-path-task.patch [new file with mode: 0644]
linux-next-cherry-picks/0060-bnxt_en-Fix-RTNL-lock-usage-on-bnxt_update_link.patch [new file with mode: 0644]
linux-next-cherry-picks/0061-bnxt_en-Fix-RTNL-lock-usage-on-bnxt_get_port_module_.patch [new file with mode: 0644]
linux-next-cherry-picks/0062-bnxt_en-Added-PCI-IDs-for-BCM57452-and-BCM57454-ASIC.patch [new file with mode: 0644]

diff --git a/linux-next-cherry-picks/0059-bnxt_en-Fix-bnxt_reset-in-the-slow-path-task.patch b/linux-next-cherry-picks/0059-bnxt_en-Fix-bnxt_reset-in-the-slow-path-task.patch
new file mode 100644 (file)
index 0000000..31d2496
--- /dev/null
@@ -0,0 +1,96 @@
+From a551ee94ea723b4af9b827c7460f108bc13425ee Mon Sep 17 00:00:00 2001
+From: Michael Chan <michael.chan@broadcom.com>
+Date: Wed, 25 Jan 2017 02:55:07 -0500
+Subject: [PATCH 1/2] bnxt_en: Fix bnxt_reset() in the slow path task.
+
+In bnxt_sp_task(), we set a bit BNXT_STATE_IN_SP_TASK so that bnxt_close()
+will synchronize and wait for bnxt_sp_task() to finish.  Some functions
+in bnxt_sp_task() require us to clear BNXT_STATE_IN_SP_TASK and then
+acquire rtnl_lock() to prevent race conditions.
+
+There are some bugs related to this logic. This patch refactors the code
+to have common bnxt_rtnl_lock_sp() and bnxt_rtnl_unlock_sp() to handle
+the RTNL and the clearing/setting of the bit.  Multiple functions will
+need the same logic.  We also need to move bnxt_reset() to the end of
+bnxt_sp_task().  Functions that clear BNXT_STATE_IN_SP_TASK must be the
+last functions to be called in bnxt_sp_task().  The common scheme will
+handle the condition properly.
+
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 53e686f..30d7d64 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6200,23 +6200,32 @@ static void bnxt_timer(unsigned long data)
+       mod_timer(&bp->timer, jiffies + bp->current_interval);
+ }
+-/* Only called from bnxt_sp_task() */
+-static void bnxt_reset(struct bnxt *bp, bool silent)
++static void bnxt_rtnl_lock_sp(struct bnxt *bp)
+ {
+-      /* bnxt_reset_task() calls bnxt_close_nic() which waits
+-       * for BNXT_STATE_IN_SP_TASK to clear.
+-       * If there is a parallel dev_close(), bnxt_close() may be holding
++      /* We are called from bnxt_sp_task which has BNXT_STATE_IN_SP_TASK
++       * set.  If the device is being closed, bnxt_close() may be holding
+        * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear.  So we
+        * must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
+        */
+       clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       rtnl_lock();
+-      if (test_bit(BNXT_STATE_OPEN, &bp->state))
+-              bnxt_reset_task(bp, silent);
++}
++
++static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
++{
+       set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       rtnl_unlock();
+ }
++/* Only called from bnxt_sp_task() */
++static void bnxt_reset(struct bnxt *bp, bool silent)
++{
++      bnxt_rtnl_lock_sp(bp);
++      if (test_bit(BNXT_STATE_OPEN, &bp->state))
++              bnxt_reset_task(bp, silent);
++      bnxt_rtnl_unlock_sp(bp);
++}
++
+ static void bnxt_cfg_ntp_filters(struct bnxt *);
+ static void bnxt_sp_task(struct work_struct *work)
+@@ -6266,18 +6275,21 @@ static void bnxt_sp_task(struct work_struct *work)
+               bnxt_hwrm_tunnel_dst_port_free(
+                       bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
+       }
+-      if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+-              bnxt_reset(bp, false);
+-
+-      if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
+-              bnxt_reset(bp, true);
+-
+       if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
+               bnxt_get_port_module_status(bp);
+       if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
+               bnxt_hwrm_port_qstats(bp);
++      /* These functions below will clear BNXT_STATE_IN_SP_TASK.  They
++       * must be the last functions to be called before exiting.
++       */
++      if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
++              bnxt_reset(bp, false);
++
++      if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
++              bnxt_reset(bp, true);
++
+       smp_mb__before_atomic();
+       clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+ }
+-- 
+2.5.5
+
diff --git a/linux-next-cherry-picks/0060-bnxt_en-Fix-RTNL-lock-usage-on-bnxt_update_link.patch b/linux-next-cherry-picks/0060-bnxt_en-Fix-RTNL-lock-usage-on-bnxt_update_link.patch
new file mode 100644 (file)
index 0000000..0d18377
--- /dev/null
@@ -0,0 +1,94 @@
+From 0eaa24b971ae251ae9d3be23f77662a655532063 Mon Sep 17 00:00:00 2001
+From: Michael Chan <michael.chan@broadcom.com>
+Date: Wed, 25 Jan 2017 02:55:08 -0500
+Subject: [PATCH 2/2] bnxt_en: Fix RTNL lock usage on bnxt_update_link().
+
+bnxt_update_link() is called from multiple code paths.  Most callers,
+such as open, ethtool, already hold RTNL.  Only the caller bnxt_sp_task()
+does not.  So it is a bug to take RTNL inside bnxt_update_link().
+
+Fix it by removing the RTNL inside bnxt_update_link().  The function
+now expects the caller to always hold RTNL.
+
+In bnxt_sp_task(), call bnxt_rtnl_lock_sp() before calling
+bnxt_update_link().  We also need to move the call to the end of
+bnxt_sp_task() since it will be clearing the BNXT_STATE_IN_SP_TASK bit.
+
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 30d7d64..69b0fce 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -5314,17 +5314,12 @@ static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
+       if ((link_info->support_auto_speeds | diff) !=
+           link_info->support_auto_speeds) {
+               /* An advertised speed is no longer supported, so we need to
+-               * update the advertisement settings.  See bnxt_reset() for
+-               * comments about the rtnl_lock() sequence below.
++               * update the advertisement settings.  Caller holds RTNL
++               * so we can modify link settings.
+                */
+-              clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+-              rtnl_lock();
+               link_info->advertising = link_info->support_auto_speeds;
+-              if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
+-                  (link_info->autoneg & BNXT_AUTONEG_SPEED))
++              if (link_info->autoneg & BNXT_AUTONEG_SPEED)
+                       bnxt_hwrm_set_link_setting(bp, true, false);
+-              set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+-              rtnl_unlock();
+       }
+       return 0;
+ }
+@@ -6231,7 +6226,6 @@ static void bnxt_cfg_ntp_filters(struct bnxt *);
+ static void bnxt_sp_task(struct work_struct *work)
+ {
+       struct bnxt *bp = container_of(work, struct bnxt, sp_task);
+-      int rc;
+       set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       smp_mb__after_atomic();
+@@ -6245,16 +6239,6 @@ static void bnxt_sp_task(struct work_struct *work)
+       if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
+               bnxt_cfg_ntp_filters(bp);
+-      if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
+-              if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
+-                                     &bp->sp_event))
+-                      bnxt_hwrm_phy_qcaps(bp);
+-
+-              rc = bnxt_update_link(bp, true);
+-              if (rc)
+-                      netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
+-                                 rc);
+-      }
+       if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
+               bnxt_hwrm_exec_fwd_req(bp);
+       if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
+@@ -6284,6 +6268,21 @@ static void bnxt_sp_task(struct work_struct *work)
+       /* These functions below will clear BNXT_STATE_IN_SP_TASK.  They
+        * must be the last functions to be called before exiting.
+        */
++      if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
++              int rc = 0;
++
++              if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
++                                     &bp->sp_event))
++                      bnxt_hwrm_phy_qcaps(bp);
++
++              bnxt_rtnl_lock_sp(bp);
++              if (test_bit(BNXT_STATE_OPEN, &bp->state))
++                      rc = bnxt_update_link(bp, true);
++              bnxt_rtnl_unlock_sp(bp);
++              if (rc)
++                      netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
++                                 rc);
++      }
+       if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+               bnxt_reset(bp, false);
+-- 
+2.5.5
+
diff --git a/linux-next-cherry-picks/0061-bnxt_en-Fix-RTNL-lock-usage-on-bnxt_get_port_module_.patch b/linux-next-cherry-picks/0061-bnxt_en-Fix-RTNL-lock-usage-on-bnxt_get_port_module_.patch
new file mode 100644 (file)
index 0000000..f48e8b5
--- /dev/null
@@ -0,0 +1,45 @@
+From 90c694bb71819fb5bd3501ac397307d7e41ddeca Mon Sep 17 00:00:00 2001
+From: Michael Chan <michael.chan@broadcom.com>
+Date: Wed, 25 Jan 2017 02:55:09 -0500
+Subject: [PATCH 3/3] bnxt_en: Fix RTNL lock usage on
+ bnxt_get_port_module_status().
+
+bnxt_get_port_module_status() calls bnxt_update_link() which expects
+RTNL to be held.  In bnxt_sp_task() that does not hold RTNL, we need to
+call it with a prior call to bnxt_rtnl_lock_sp() and the call needs to
+be moved to the end of bnxt_sp_task().
+
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 69b0fce..4fcc6a8 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -6259,9 +6259,6 @@ static void bnxt_sp_task(struct work_struct *work)
+               bnxt_hwrm_tunnel_dst_port_free(
+                       bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
+       }
+-      if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
+-              bnxt_get_port_module_status(bp);
+-
+       if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
+               bnxt_hwrm_port_qstats(bp);
+@@ -6283,6 +6280,12 @@ static void bnxt_sp_task(struct work_struct *work)
+                       netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
+                                  rc);
+       }
++      if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) {
++              bnxt_rtnl_lock_sp(bp);
++              if (test_bit(BNXT_STATE_OPEN, &bp->state))
++                      bnxt_get_port_module_status(bp);
++              bnxt_rtnl_unlock_sp(bp);
++      }
+       if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+               bnxt_reset(bp, false);
+-- 
+2.5.5
+
diff --git a/linux-next-cherry-picks/0062-bnxt_en-Added-PCI-IDs-for-BCM57452-and-BCM57454-ASIC.patch b/linux-next-cherry-picks/0062-bnxt_en-Added-PCI-IDs-for-BCM57452-and-BCM57454-ASIC.patch
new file mode 100644 (file)
index 0000000..5bad3f5
--- /dev/null
@@ -0,0 +1,46 @@
+From 32b40798c1b40343641f04cdfd09652af70ea0e9 Mon Sep 17 00:00:00 2001
+From: Deepak Khungar <deepak.khungar@broadcom.com>
+Date: Sun, 12 Feb 2017 19:18:18 -0500
+Subject: [PATCH] bnxt_en: Added PCI IDs for BCM57452 and BCM57454 ASICs
+
+Signed-off-by: Deepak Khungar <deepak.khungar@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index c899d61..71f9a18 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -99,6 +99,8 @@ enum board_idx {
+       BCM57407_NPAR,
+       BCM57414_NPAR,
+       BCM57416_NPAR,
++      BCM57452,
++      BCM57454,
+       NETXTREME_E_VF,
+       NETXTREME_C_VF,
+ };
+@@ -133,6 +135,8 @@ static const struct {
+       { "Broadcom BCM57407 NetXtreme-E Ethernet Partition" },
+       { "Broadcom BCM57414 NetXtreme-E Ethernet Partition" },
+       { "Broadcom BCM57416 NetXtreme-E Ethernet Partition" },
++      { "Broadcom BCM57452 NetXtreme-E 10Gb/25Gb/40Gb/50Gb Ethernet" },
++      { "Broadcom BCM57454 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb Ethernet" },
+       { "Broadcom NetXtreme-E Ethernet Virtual Function" },
+       { "Broadcom NetXtreme-C Ethernet Virtual Function" },
+ };
+@@ -168,6 +172,8 @@ static const struct pci_device_id bnxt_pci_tbl[] = {
+       { PCI_VDEVICE(BROADCOM, 0x16ed), .driver_data = BCM57414_NPAR },
+       { PCI_VDEVICE(BROADCOM, 0x16ee), .driver_data = BCM57416_NPAR },
+       { PCI_VDEVICE(BROADCOM, 0x16ef), .driver_data = BCM57416_NPAR },
++      { PCI_VDEVICE(BROADCOM, 0x16f1), .driver_data = BCM57452 },
++      { PCI_VDEVICE(BROADCOM, 0x1614), .driver_data = BCM57454 },
+ #ifdef CONFIG_BNXT_SRIOV
+       { PCI_VDEVICE(BROADCOM, 0x16c1), .driver_data = NETXTREME_E_VF },
+       { PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = NETXTREME_C_VF },
+-- 
+2.5.5
+