Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[linux-2.6-block.git] / drivers / net / ethernet / broadcom / bnx2x / bnx2x_main.c
index 815f2dea6337738e19b8f1bd313570d645996656..634a793c1c462ab429261a7388867db81bfaaeb8 100644 (file)
@@ -6893,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);
@@ -8063,7 +8063,10 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
 
 int bnx2x_setup_leading(struct bnx2x *bp)
 {
-       return bnx2x_setup_queue(bp, &bp->fp[0], 1);
+       if (IS_PF(bp))
+               return bnx2x_setup_queue(bp, &bp->fp[0], true);
+       else /* VF */
+               return bnx2x_vfpf_setup_q(bp, &bp->fp[0], true);
 }
 
 /**
@@ -8077,8 +8080,10 @@ int bnx2x_set_int_mode(struct bnx2x *bp)
 {
        int rc = 0;
 
-       if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX)
+       if (IS_VF(bp) && int_mode != BNX2X_INT_MODE_MSIX) {
+               BNX2X_ERR("VF not loaded since interrupt mode not msix\n");
                return -EINVAL;
+       }
 
        switch (int_mode) {
        case BNX2X_INT_MODE_MSIX:
@@ -9647,11 +9652,9 @@ 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,
@@ -11649,9 +11652,11 @@ static int bnx2x_init_bp(struct bnx2x *bp)
         * second status block for the L2 queue, and a third status block for
         * CNIC if supported.
         */
-       if (CNIC_SUPPORT(bp))
+       if (IS_VF(bp))
+               bp->min_msix_vec_cnt = 1;
+       else if (CNIC_SUPPORT(bp))
                bp->min_msix_vec_cnt = 3;
-       else
+       else /* PF w/o cnic */
                bp->min_msix_vec_cnt = 2;
        BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt);
 
@@ -11868,34 +11873,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,
@@ -11913,22 +11932,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);
        }
 }
 
@@ -12550,19 +12567,16 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
  * @dev:       pci device
  *
  */
-static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
-                                    int cnic_cnt, bool is_vf)
+static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev, int cnic_cnt)
 {
-       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;
        }
@@ -12575,11 +12589,11 @@ 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;
 
-       return is_vf ? index + 1 : index;
+       return index;
 }
 
 static int set_max_cos_est(int chip_id)
@@ -12659,10 +12673,13 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        is_vf = set_is_vf(ent->driver_data);
        cnic_cnt = is_vf ? 0 : 1;
 
-       max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt, is_vf);
+       max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
+
+       /* add another SB for VF as it has no default SB */
+       max_non_def_sbs += is_vf ? 1 : 0;
 
        /* Maximum number of RSS queues: one IGU SB goes to CNIC */
-       rss_count = is_vf ? 1 : max_non_def_sbs - cnic_cnt;
+       rss_count = max_non_def_sbs - cnic_cnt;
 
        if (rss_count < 1)
                return -EINVAL;