bnx2x: VF RSS support - PF side
[firefly-linux-kernel-4.4.55.git] / drivers / net / ethernet / broadcom / bnx2x / bnx2x_main.c
index 955d6cfd9cb7c48179b587a7bf5239a572b7e9e8..5729aa7be1d03eff72142a35f86b5149d6f40f85 100644 (file)
@@ -2261,6 +2261,23 @@ static void bnx2x_set_requested_fc(struct bnx2x *bp)
                bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
 }
 
+static void bnx2x_init_dropless_fc(struct bnx2x *bp)
+{
+       u32 pause_enabled = 0;
+
+       if (!CHIP_IS_E1(bp) && bp->dropless_fc && bp->link_vars.link_up) {
+               if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
+                       pause_enabled = 1;
+
+               REG_WR(bp, BAR_USTRORM_INTMEM +
+                          USTORM_ETH_PAUSE_ENABLED_OFFSET(BP_PORT(bp)),
+                      pause_enabled);
+       }
+
+       DP(NETIF_MSG_IFUP | NETIF_MSG_LINK, "dropless_fc is %s\n",
+          pause_enabled ? "enabled" : "disabled");
+}
+
 int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 {
        int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp);
@@ -2294,6 +2311,8 @@ int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
 
                if (bp->link_vars.link_up) {
@@ -2315,6 +2334,8 @@ void bnx2x_link_set(struct bnx2x *bp)
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                bnx2x_release_phy_lock(bp);
 
+               bnx2x_init_dropless_fc(bp);
+
                bnx2x_calc_fc_adv(bp);
        } else
                BNX2X_ERR("Bootcode is missing - can not set link\n");
@@ -2556,20 +2577,9 @@ static void bnx2x_link_attn(struct bnx2x *bp)
 
        bnx2x_link_update(&bp->link_params, &bp->link_vars);
 
-       if (bp->link_vars.link_up) {
-
-               /* dropless flow control */
-               if (!CHIP_IS_E1(bp) && bp->dropless_fc) {
-                       int port = BP_PORT(bp);
-                       u32 pause_enabled = 0;
-
-                       if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
-                               pause_enabled = 1;
+       bnx2x_init_dropless_fc(bp);
 
-                       REG_WR(bp, BAR_USTRORM_INTMEM +
-                              USTORM_ETH_PAUSE_ENABLED_OFFSET(port),
-                              pause_enabled);
-               }
+       if (bp->link_vars.link_up) {
 
                if (bp->link_vars.mac_type != MAC_TYPE_EMAC) {
                        struct host_port_stats *pstats;
@@ -6883,7 +6893,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
                bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
 
        bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
-       REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
+
        if (!CHIP_REV_IS_SLOW(bp))
                /* enable hw interrupt from doorbell Q */
                REG_WR(bp, DORQ_REG_DORQ_INT_MASK, 0);
@@ -9634,17 +9644,21 @@ sp_rtnl_not_reset:
                }
        }
 
-       if (test_and_clear_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
-                              &bp->sp_rtnl_state)) {
-               DP(BNX2X_MSG_SP,
-                  "sending set storm rx mode vf pf channel message from rtnl sp-task\n");
-               bnx2x_vfpf_storm_rx_mode(bp);
+       if (test_and_clear_bit(BNX2X_SP_RTNL_RX_MODE, &bp->sp_rtnl_state)) {
+               DP(BNX2X_MSG_SP, "Handling Rx Mode setting\n");
+               bnx2x_set_rx_mode_inner(bp);
        }
 
        if (test_and_clear_bit(BNX2X_SP_RTNL_HYPERVISOR_VLAN,
                               &bp->sp_rtnl_state))
                bnx2x_pf_set_vfs_vlan(bp);
 
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_STOP, &bp->sp_rtnl_state))
+               bnx2x_dcbx_stop_hw_tx(bp);
+
+       if (test_and_clear_bit(BNX2X_SP_RTNL_TX_RESUME, &bp->sp_rtnl_state))
+               bnx2x_dcbx_resume_hw_tx(bp);
+
        /* work which needs rtnl lock not-taken (as it takes the lock itself and
         * can be called from other contexts as well)
         */
@@ -11147,6 +11161,9 @@ static bool bnx2x_get_dropless_info(struct bnx2x *bp)
        int tmp;
        u32 cfg;
 
+       if (IS_VF(bp))
+               return 0;
+
        if (IS_MF(bp) && !CHIP_IS_E1x(bp)) {
                /* Take function: tmp = func */
                tmp = BP_ABS_FUNC(bp);
@@ -11860,34 +11877,48 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
 void bnx2x_set_rx_mode(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
-       u32 rx_mode = BNX2X_RX_MODE_NORMAL;
 
        if (bp->state != BNX2X_STATE_OPEN) {
                DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
                return;
+       } else {
+               /* Schedule an SP task to handle rest of change */
+               DP(NETIF_MSG_IFUP, "Scheduling an Rx mode change\n");
+               smp_mb__before_clear_bit();
+               set_bit(BNX2X_SP_RTNL_RX_MODE, &bp->sp_rtnl_state);
+               smp_mb__after_clear_bit();
+               schedule_delayed_work(&bp->sp_rtnl_task, 0);
        }
+}
+
+void bnx2x_set_rx_mode_inner(struct bnx2x *bp)
+{
+       u32 rx_mode = BNX2X_RX_MODE_NORMAL;
 
        DP(NETIF_MSG_IFUP, "dev->flags = %x\n", bp->dev->flags);
 
-       if (dev->flags & IFF_PROMISC)
+       netif_addr_lock_bh(bp->dev);
+
+       if (bp->dev->flags & IFF_PROMISC) {
                rx_mode = BNX2X_RX_MODE_PROMISC;
-       else if ((dev->flags & IFF_ALLMULTI) ||
-                ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
-                 CHIP_IS_E1(bp)))
+       } else if ((bp->dev->flags & IFF_ALLMULTI) ||
+                  ((netdev_mc_count(bp->dev) > BNX2X_MAX_MULTICAST) &&
+                   CHIP_IS_E1(bp))) {
                rx_mode = BNX2X_RX_MODE_ALLMULTI;
-       else {
+       else {
                if (IS_PF(bp)) {
                        /* some multicasts */
                        if (bnx2x_set_mc_list(bp) < 0)
                                rx_mode = BNX2X_RX_MODE_ALLMULTI;
 
+                       /* release bh lock, as bnx2x_set_uc_list might sleep */
+                       netif_addr_unlock_bh(bp->dev);
                        if (bnx2x_set_uc_list(bp) < 0)
                                rx_mode = BNX2X_RX_MODE_PROMISC;
+                       netif_addr_lock_bh(bp->dev);
                } else {
                        /* configuring mcast to a vf involves sleeping (when we
-                        * wait for the pf's response). Since this function is
-                        * called from non sleepable context we must schedule
-                        * a work item for this purpose
+                        * wait for the pf's response).
                         */
                        smp_mb__before_clear_bit();
                        set_bit(BNX2X_SP_RTNL_VFPF_MCAST,
@@ -11905,22 +11936,20 @@ void bnx2x_set_rx_mode(struct net_device *dev)
        /* Schedule the rx_mode command */
        if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
                set_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state);
+               netif_addr_unlock_bh(bp->dev);
                return;
        }
 
        if (IS_PF(bp)) {
                bnx2x_set_storm_rx_mode(bp);
+               netif_addr_unlock_bh(bp->dev);
        } else {
-               /* configuring rx mode to storms in a vf involves sleeping (when
-                * we wait for the pf's response). Since this function is
-                * called from non sleepable context we must schedule
-                * a work item for this purpose
+               /* VF will need to request the PF to make this change, and so
+                * the VF needs to release the bottom-half lock prior to the
+                * request (as it will likely require sleep on the VF side)
                 */
-               smp_mb__before_clear_bit();
-               set_bit(BNX2X_SP_RTNL_VFPF_STORM_RX_MODE,
-                       &bp->sp_rtnl_state);
-               smp_mb__after_clear_bit();
-               schedule_delayed_work(&bp->sp_rtnl_task, 0);
+               netif_addr_unlock_bh(bp->dev);
+               bnx2x_vfpf_storm_rx_mode(bp);
        }
 }
 
@@ -12545,16 +12574,14 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
 static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
                                     int cnic_cnt, bool is_vf)
 {
-       int pos, index;
+       int index;
        u16 control = 0;
 
-       pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
-
        /*
         * If MSI-X is not supported - return number of SBs needed to support
         * one fast path queue: one FP queue + SB for CNIC
         */
-       if (!pos) {
+       if (!pdev->msix_cap) {
                dev_info(&pdev->dev, "no msix capability found\n");
                return 1 + cnic_cnt;
        }
@@ -12567,7 +12594,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
         * without the default SB.
         * For VFs there is no default SB, then we return (index+1).
         */
-       pci_read_config_word(pdev, pos  + PCI_MSI_FLAGS, &control);
+       pci_read_config_word(pdev, pdev->msix_cap + PCI_MSI_FLAGS, &control);
 
        index = control & PCI_MSIX_FLAGS_QSIZE;