Merge branch 'rmobile-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / net / bnx2x / bnx2x_main.c
index 8cdcf5b..a97a4a1 100644 (file)
@@ -145,13 +145,6 @@ static struct {
        { "Broadcom NetXtreme II BCM57712E XGb" }
 };
 
-#ifndef PCI_DEVICE_ID_NX2_57712
-#define PCI_DEVICE_ID_NX2_57712                0x1662
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57712E
-#define PCI_DEVICE_ID_NX2_57712E       0x1663
-#endif
-
 static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
        { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
        { PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
@@ -586,7 +579,7 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
           bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
        /* lock the dmae channel */
-       mutex_lock(&bp->dmae_mutex);
+       spin_lock_bh(&bp->dmae_lock);
 
        /* reset completion */
        *wb_comp = 0;
@@ -617,7 +610,7 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
           bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
 unlock:
-       mutex_unlock(&bp->dmae_mutex);
+       spin_unlock_bh(&bp->dmae_lock);
        return rc;
 }
 
@@ -1397,7 +1390,7 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp,
        }
 
        smp_mb__before_atomic_inc();
-       atomic_inc(&bp->spq_left);
+       atomic_inc(&bp->cq_spq_left);
        /* push the change in fp->state and towards the memory */
        smp_wmb();
 
@@ -1974,13 +1967,22 @@ static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
                vn_max_rate = 0;
 
        } else {
+               u32 maxCfg = bnx2x_extract_max_cfg(bp, vn_cfg);
+
                vn_min_rate = ((vn_cfg & FUNC_MF_CFG_MIN_BW_MASK) >>
                                FUNC_MF_CFG_MIN_BW_SHIFT) * 100;
-               /* If min rate is zero - set it to 1 */
+               /* If fairness is enabled (not all min rates are zeroes) and
+                  if current min rate is zero - set it to 1.
+                  This is a requirement of the algorithm. */
                if (bp->vn_weight_sum && (vn_min_rate == 0))
                        vn_min_rate = DEF_MIN_RATE;
-               vn_max_rate = ((vn_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
-                               FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+
+               if (IS_MF_SI(bp))
+                       /* maxCfg in percents of linkspeed */
+                       vn_max_rate = (bp->link_vars.line_speed * maxCfg) / 100;
+               else
+                       /* maxCfg is absolute in 100Mb units */
+                       vn_max_rate = maxCfg * 100;
        }
 
        DP(NETIF_MSG_IFUP,
@@ -2006,7 +2008,8 @@ static void bnx2x_init_vn_minmax(struct bnx2x *bp, int vn)
                m_fair_vn.vn_credit_delta =
                        max_t(u32, (vn_min_rate * (T_FAIR_COEF /
                                                   (8 * bp->vn_weight_sum))),
-                             (bp->cmng.fair_vars.fair_threshold * 2));
+                             (bp->cmng.fair_vars.fair_threshold +
+                                                       MIN_ABOVE_THRESH));
                DP(NETIF_MSG_IFUP, "m_fair_vn.vn_credit_delta %d\n",
                   m_fair_vn.vn_credit_delta);
        }
@@ -2082,8 +2085,9 @@ static void bnx2x_cmng_fns_init(struct bnx2x *bp, u8 read_cfg, u8 cmng_type)
                bnx2x_calc_vn_weight_sum(bp);
 
                /* calculate and set min-max rate for each vn */
-               for (vn = VN_0; vn < E1HVN_MAX; vn++)
-                       bnx2x_init_vn_minmax(bp, vn);
+               if (bp->port.pmf)
+                       for (vn = VN_0; vn < E1HVN_MAX; vn++)
+                               bnx2x_init_vn_minmax(bp, vn);
 
                /* always enable rate shaping and fairness */
                bp->cmng.flags.cmng_enables |=
@@ -2152,13 +2156,6 @@ static void bnx2x_link_attn(struct bnx2x *bp)
                        bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
        }
 
-       /* indicate link status only if link status actually changed */
-       if (prev_link_status != bp->link_vars.link_status)
-               bnx2x_link_report(bp);
-
-       if (IS_MF(bp))
-               bnx2x_link_sync_notify(bp);
-
        if (bp->link_vars.link_up && bp->link_vars.line_speed) {
                int cmng_fns = bnx2x_get_cmng_fns_mode(bp);
 
@@ -2170,6 +2167,13 @@ static void bnx2x_link_attn(struct bnx2x *bp)
                        DP(NETIF_MSG_IFUP,
                           "single function mode without fairness\n");
        }
+
+       if (IS_MF(bp))
+               bnx2x_link_sync_notify(bp);
+
+       /* indicate link status only if link status actually changed */
+       if (prev_link_status != bp->link_vars.link_status)
+               bnx2x_link_report(bp);
 }
 
 void bnx2x__link_status_update(struct bnx2x *bp)
@@ -2301,15 +2305,10 @@ static void bnx2x_rxq_set_mac_filters(struct bnx2x *bp, u16 cl_id, u32 filters)
                /* accept matched ucast */
                drop_all_ucast = 0;
        }
-       if (filters & BNX2X_ACCEPT_MULTICAST) {
+       if (filters & BNX2X_ACCEPT_MULTICAST)
                /* accept matched mcast */
                drop_all_mcast = 0;
-               if (IS_MF_SI(bp))
-                       /* since mcast addresses won't arrive with ovlan,
-                        * fw needs to accept all of them in
-                        * switch-independent mode */
-                       accp_all_mcast = 1;
-       }
+
        if (filters & BNX2X_ACCEPT_ALL_UNICAST) {
                /* accept all mcast */
                drop_all_ucast = 0;
@@ -2478,8 +2477,14 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
        rxq_init->sge_map = fp->rx_sge_mapping;
        rxq_init->rcq_map = fp->rx_comp_mapping;
        rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
-       rxq_init->mtu = bp->dev->mtu;
-       rxq_init->buf_sz = bp->rx_buf_size;
+
+       /* Always use mini-jumbo MTU for FCoE L2 ring */
+       if (IS_FCOE_FP(fp))
+               rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+       else
+               rxq_init->mtu = bp->dev->mtu;
+
+       rxq_init->buf_sz = fp->rx_buf_size;
        rxq_init->cl_qzone_id = fp->cl_qzone_id;
        rxq_init->cl_id = fp->cl_id;
        rxq_init->spcl_id = fp->cl_id;
@@ -2731,11 +2736,18 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 
        spin_lock_bh(&bp->spq_lock);
 
-       if (!atomic_read(&bp->spq_left)) {
-               BNX2X_ERR("BUG! SPQ ring full!\n");
-               spin_unlock_bh(&bp->spq_lock);
-               bnx2x_panic();
-               return -EBUSY;
+       if (common) {
+               if (!atomic_read(&bp->eq_spq_left)) {
+                       BNX2X_ERR("BUG! EQ ring full!\n");
+                       spin_unlock_bh(&bp->spq_lock);
+                       bnx2x_panic();
+                       return -EBUSY;
+               }
+       } else if (!atomic_read(&bp->cq_spq_left)) {
+                       BNX2X_ERR("BUG! SPQ ring full!\n");
+                       spin_unlock_bh(&bp->spq_lock);
+                       bnx2x_panic();
+                       return -EBUSY;
        }
 
        spe = bnx2x_sp_get_next(bp);
@@ -2766,20 +2778,26 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
        spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
 
        /* stats ramrod has it's own slot on the spq */
-       if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY)
+       if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
                /* It's ok if the actual decrement is issued towards the memory
                 * somewhere between the spin_lock and spin_unlock. Thus no
                 * more explict memory barrier is needed.
                 */
-               atomic_dec(&bp->spq_left);
+               if (common)
+                       atomic_dec(&bp->eq_spq_left);
+               else
+                       atomic_dec(&bp->cq_spq_left);
+       }
+
 
        DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
           "SPQE[%x] (%x:%x)  command %d  hw_cid %x  data (%x:%x) "
-          "type(0x%x) left %x\n",
+          "type(0x%x) left (ETH, COMMON) (%x,%x)\n",
           bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
           (u32)(U64_LO(bp->spq_mapping) +
           (void *)bp->spq_prod_bd - (void *)bp->spq), command,
-          HW_CID(bp, cid), data_hi, data_lo, type, atomic_read(&bp->spq_left));
+          HW_CID(bp, cid), data_hi, data_lo, type,
+          atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left));
 
        bnx2x_sp_prod_update(bp);
        spin_unlock_bh(&bp->spq_lock);
@@ -3684,15 +3702,15 @@ static void bnx2x_eq_int(struct bnx2x *bp)
        if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE)
                hw_cons++;
 
-       /* This function may never run in parralel with itself for a
+       /* This function may never run in parallel with itself for a
         * specific bp, thus there is no need in "paired" read memory
         * barrier here.
         */
        sw_cons = bp->eq_cons;
        sw_prod = bp->eq_prod;
 
-       DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->spq_left %u\n",
-                       hw_cons, sw_cons, atomic_read(&bp->spq_left));
+       DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->cq_spq_left %u\n",
+                       hw_cons, sw_cons, atomic_read(&bp->eq_spq_left));
 
        for (; sw_cons != hw_cons;
              sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) {
@@ -3757,13 +3775,15 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
                case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
                        DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
-                       bp->set_mac_pending = 0;
+                       if (elem->message.data.set_mac_event.echo)
+                               bp->set_mac_pending = 0;
                        break;
 
                case (EVENT_RING_OPCODE_SET_MAC |
                      BNX2X_STATE_CLOSING_WAIT4_HALT):
                        DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
-                       bp->set_mac_pending = 0;
+                       if (elem->message.data.set_mac_event.echo)
+                               bp->set_mac_pending = 0;
                        break;
                default:
                        /* unknown event log error and continue */
@@ -3775,7 +3795,7 @@ next_spqe:
        } /* for */
 
        smp_mb__before_atomic_inc();
-       atomic_add(spqe_cnt, &bp->spq_left);
+       atomic_add(spqe_cnt, &bp->eq_spq_left);
 
        bp->eq_cons = sw_cons;
        bp->eq_prod = sw_prod;
@@ -4202,13 +4222,13 @@ void bnx2x_update_coalesce(struct bnx2x *bp)
 
        for_each_eth_queue(bp, i)
                bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
-                                        bp->rx_ticks, bp->tx_ticks);
+                                        bp->tx_ticks, bp->rx_ticks);
 }
 
 static void bnx2x_init_sp_ring(struct bnx2x *bp)
 {
        spin_lock_init(&bp->spq_lock);
-       atomic_set(&bp->spq_left, MAX_SPQ_PENDING);
+       atomic_set(&bp->cq_spq_left, MAX_SPQ_PENDING);
 
        bp->spq_prod_idx = 0;
        bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
@@ -4233,9 +4253,12 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
        bp->eq_cons = 0;
        bp->eq_prod = NUM_EQ_DESC;
        bp->eq_cons_sb = BNX2X_EQ_INDEX;
+       /* we want a warning message before it gets rought... */
+       atomic_set(&bp->eq_spq_left,
+               min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
 }
 
-static void bnx2x_init_ind_table(struct bnx2x *bp)
+void bnx2x_push_indir_table(struct bnx2x *bp)
 {
        int func = BP_FUNC(bp);
        int i;
@@ -4243,13 +4266,20 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
        if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
                return;
 
-       DP(NETIF_MSG_IFUP,
-          "Initializing indirection table  multi_mode %d\n", bp->multi_mode);
        for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
                REG_WR8(bp, BAR_TSTRORM_INTMEM +
                        TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
-                       bp->fp->cl_id + (i % (bp->num_queues -
-                               NONE_ETH_CONTEXT_USE)));
+                       bp->fp->cl_id + bp->rx_indir_table[i]);
+}
+
+static void bnx2x_init_ind_table(struct bnx2x *bp)
+{
+       int i;
+
+       for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+               bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp);
+
+       bnx2x_push_indir_table(bp);
 }
 
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
@@ -4281,9 +4311,12 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
                def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
                                BNX2X_ACCEPT_MULTICAST;
 #ifdef BCM_CNIC
-               cl_id = bnx2x_fcoe(bp, cl_id);
-               bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_UNICAST |
-                                         BNX2X_ACCEPT_MULTICAST);
+               if (!NO_FCOE(bp)) {
+                       cl_id = bnx2x_fcoe(bp, cl_id);
+                       bnx2x_rxq_set_mac_filters(bp, cl_id,
+                                                 BNX2X_ACCEPT_UNICAST |
+                                                 BNX2X_ACCEPT_MULTICAST);
+               }
 #endif
                break;
 
@@ -4291,18 +4324,29 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
                def_q_filters |= BNX2X_ACCEPT_UNICAST | BNX2X_ACCEPT_BROADCAST |
                                BNX2X_ACCEPT_ALL_MULTICAST;
 #ifdef BCM_CNIC
-               cl_id = bnx2x_fcoe(bp, cl_id);
-               bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_UNICAST |
-                                         BNX2X_ACCEPT_MULTICAST);
+               /*
+                *  Prevent duplication of multicast packets by configuring FCoE
+                *  L2 Client to receive only matched unicast frames.
+                */
+               if (!NO_FCOE(bp)) {
+                       cl_id = bnx2x_fcoe(bp, cl_id);
+                       bnx2x_rxq_set_mac_filters(bp, cl_id,
+                                                 BNX2X_ACCEPT_UNICAST);
+               }
 #endif
                break;
 
        case BNX2X_RX_MODE_PROMISC:
                def_q_filters |= BNX2X_PROMISCUOUS_MODE;
 #ifdef BCM_CNIC
-               cl_id = bnx2x_fcoe(bp, cl_id);
-               bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_UNICAST |
-                                         BNX2X_ACCEPT_MULTICAST);
+               /*
+                *  Prevent packets duplication by configuring DROP_ALL for FCoE
+                *  L2 Client.
+                */
+               if (!NO_FCOE(bp)) {
+                       cl_id = bnx2x_fcoe(bp, cl_id);
+                       bnx2x_rxq_set_mac_filters(bp, cl_id, BNX2X_ACCEPT_NONE);
+               }
 #endif
                /* pass management unicast packets as well */
                llh_mask |= NIG_LLH0_BRB1_DRV_MASK_REG_LLH0_BRB1_DRV_MASK_UNCST;
@@ -5045,7 +5089,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
                /* Step 1: set zeroes to all ilt page entries with valid bit on
                 * Step 2: set the timers first/last ilt entry to point
                 * to the entire range to prevent ILT range error for 3rd/4th
-                * vnic (this code assumes existance of the vnic)
+                * vnic (this code assumes existence of the vnic)
                 *
                 * both steps performed by call to bnx2x_ilt_client_init_op()
                 * with dummy TM client
@@ -5296,10 +5340,6 @@ static int bnx2x_init_hw_common(struct bnx2x *bp, u32 load_code)
                }
        }
 
-       bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-                                                      bp->common.shmem_base,
-                                                      bp->common.shmem2_base);
-
        bnx2x_setup_fan_failure_detection(bp);
 
        /* clear PXP2 attentions */
@@ -5503,9 +5543,6 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        bnx2x_init_block(bp, MCP_BLOCK, init_stage);
        bnx2x_init_block(bp, DMAE_BLOCK, init_stage);
-       bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-                                                      bp->common.shmem_base,
-                                                      bp->common.shmem2_base);
        if (bnx2x_fan_failure_det_req(bp, bp->common.shmem_base,
                                      bp->common.shmem2_base, port)) {
                u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
@@ -5838,7 +5875,7 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
           BP_ABS_FUNC(bp), load_code);
 
        bp->dmae_ready = 0;
-       mutex_init(&bp->dmae_mutex);
+       spin_lock_init(&bp->dmae_lock);
        rc = bnx2x_gunzip_init(bp);
        if (rc)
                return rc;
@@ -5990,6 +6027,8 @@ void bnx2x_free_mem(struct bnx2x *bp)
        BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
                       BCM_PAGE_SIZE * NUM_EQ_PAGES);
 
+       BNX2X_FREE(bp->rx_indir_table);
+
 #undef BNX2X_PCI_FREE
 #undef BNX2X_KFREE
 }
@@ -6120,6 +6159,9 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
        /* EQ */
        BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
                        BCM_PAGE_SIZE * NUM_EQ_PAGES);
+
+       BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) *
+                   TSTORM_INDIRECTION_TABLE_SIZE);
        return 0;
 
 alloc_mem_err:
@@ -6173,12 +6215,14 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
        int ramrod_flags = WAIT_RAMROD_COMMON;
 
        bp->set_mac_pending = 1;
-       smp_wmb();
 
        config->hdr.length = 1;
        config->hdr.offset = cam_offset;
        config->hdr.client_id = 0xff;
-       config->hdr.reserved1 = 0;
+       /* Mark the single MAC configuration ramrod as opposed to a
+        * UC/MC list configuration).
+        */
+       config->hdr.echo = 1;
 
        /* primary MAC */
        config->config_table[0].msb_mac_addr =
@@ -6210,6 +6254,8 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
           config->config_table[0].middle_mac_addr,
           config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
 
+       mb();
+
        bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
                      U64_HI(bnx2x_sp_mapping(bp, mac_config)),
                      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
@@ -6274,20 +6320,15 @@ static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
        if (CHIP_IS_E1H(bp))
                return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
        else if (CHIP_MODE_IS_4_PORT(bp))
-               return BP_FUNC(bp) * 32  + rel_offset;
+               return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
        else
-               return BP_VN(bp) * 32  + rel_offset;
+               return E2_FUNC_MAX * rel_offset + BP_VN(bp);
 }
 
 /**
  *  LLH CAM line allocations: currently only iSCSI and ETH macs are
  *  relevant. In addition, current implementation is tuned for a
  *  single ETH MAC.
- *
- *  When multiple unicast ETH MACs PF configuration in switch
- *  independent mode is required (NetQ, multiple netdev MACs,
- *  etc.), consider better utilisation of 16 per function MAC
- *  entries in the LLH memory.
  */
 enum {
        LLH_CAM_ISCSI_ETH_LINE = 0,
@@ -6362,14 +6403,37 @@ void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
                bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
        }
 }
-static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
+
+static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
+{
+       return CHIP_REV_IS_SLOW(bp) ?
+               (BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
+               (BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
+}
+
+/* set mc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of a very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
 {
        int i = 0, old;
        struct net_device *dev = bp->dev;
+       u8 offset = bnx2x_e1_cam_mc_offset(bp);
        struct netdev_hw_addr *ha;
        struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
        dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
 
+       if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
+               return -EINVAL;
+
        netdev_for_each_mc_addr(ha, dev) {
                /* copy mac */
                config_cmd->config_table[i].msb_mac_addr =
@@ -6410,32 +6474,47 @@ static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
                }
        }
 
+       wmb();
+
        config_cmd->hdr.length = i;
        config_cmd->hdr.offset = offset;
        config_cmd->hdr.client_id = 0xff;
-       config_cmd->hdr.reserved1 = 0;
+       /* Mark that this ramrod doesn't use bp->set_mac_pending for
+        * synchronization.
+        */
+       config_cmd->hdr.echo = 0;
 
-       bp->set_mac_pending = 1;
-       smp_wmb();
+       mb();
 
-       bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+       return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
                   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
 }
-static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
+
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
 {
        int i;
        struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
        dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
        int ramrod_flags = WAIT_RAMROD_COMMON;
+       u8 offset = bnx2x_e1_cam_mc_offset(bp);
 
-       bp->set_mac_pending = 1;
-       smp_wmb();
-
-       for (i = 0; i < config_cmd->hdr.length; i++)
+       for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
                SET_FLAG(config_cmd->config_table[i].flags,
                        MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
                        T_ETH_MAC_COMMAND_INVALIDATE);
 
+       wmb();
+
+       config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
+       config_cmd->hdr.offset = offset;
+       config_cmd->hdr.client_id = 0xff;
+       /* We'll wait for a completion this time... */
+       config_cmd->hdr.echo = 1;
+
+       bp->set_mac_pending = 1;
+
+       mb();
+
        bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
                      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
 
@@ -6445,6 +6524,44 @@ static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
 
 }
 
+/* Accept one or more multicasts */
+static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
+{
+       struct net_device *dev = bp->dev;
+       struct netdev_hw_addr *ha;
+       u32 mc_filter[MC_HASH_SIZE];
+       u32 crc, bit, regidx;
+       int i;
+
+       memset(mc_filter, 0, 4 * MC_HASH_SIZE);
+
+       netdev_for_each_mc_addr(ha, dev) {
+               DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
+                  bnx2x_mc_addr(ha));
+
+               crc = crc32c_le(0, bnx2x_mc_addr(ha),
+                               ETH_ALEN);
+               bit = (crc >> 24) & 0xff;
+               regidx = bit >> 5;
+               bit &= 0x1f;
+               mc_filter[regidx] |= (1 << bit);
+       }
+
+       for (i = 0; i < MC_HASH_SIZE; i++)
+               REG_WR(bp, MC_HASH_OFFSET(bp, i),
+                      mc_filter[i]);
+
+       return 0;
+}
+
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
+{
+       int i;
+
+       for (i = 0; i < MC_HASH_SIZE; i++)
+               REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+}
+
 #ifdef BCM_CNIC
 /**
  * Set iSCSI MAC(s) at the next enties in the CAM after the ETH
@@ -6463,12 +6580,13 @@ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
        u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
                BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
        u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
+       u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
 
        /* Send a SET_MAC ramrod */
-       bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec,
+       bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec,
                               cam_offset, 0);
 
-       bnx2x_set_mac_in_nig(bp, set, bp->iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
+       bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
 
        return 0;
 }
@@ -7110,20 +7228,15 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
        /* Give HW time to discard old tx messages */
        msleep(1);
 
-       if (CHIP_IS_E1(bp)) {
-               /* invalidate mc list,
-                * wait and poll (interrupts are off)
-                */
-               bnx2x_invlidate_e1_mc_list(bp);
-               bnx2x_set_eth_mac(bp, 0);
+       bnx2x_set_eth_mac(bp, 0);
 
-       } else {
-               REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+       bnx2x_invalidate_uc_list(bp);
 
-               bnx2x_set_eth_mac(bp, 0);
-
-               for (i = 0; i < MC_HASH_SIZE; i++)
-                       REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+       if (CHIP_IS_E1(bp))
+               bnx2x_invalidate_e1_mc_list(bp);
+       else {
+               bnx2x_invalidate_e1h_mc_list(bp);
+               REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
        }
 
 #ifdef BCM_CNIC
@@ -8379,13 +8492,60 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
                 (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
                bp->mdio.prtad =
                        XGXS_EXT_PHY_ADDR(ext_phy_config);
+
+       /*
+        * Check if hw lock is required to access MDC/MDIO bus to the PHY(s)
+        * In MF mode, it is set to cover self test cases
+        */
+       if (IS_MF(bp))
+               bp->port.need_hw_lock = 1;
+       else
+               bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
+                                                       bp->common.shmem_base,
+                                                       bp->common.shmem2_base);
+}
+
+#ifdef BCM_CNIC
+static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
+{
+       u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
+                               drv_lic_key[BP_PORT(bp)].max_iscsi_conn);
+       u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
+                               drv_lic_key[BP_PORT(bp)].max_fcoe_conn);
+
+       /* Get the number of maximum allowed iSCSI and FCoE connections */
+       bp->cnic_eth_dev.max_iscsi_conn =
+               (max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >>
+               BNX2X_MAX_ISCSI_INIT_CONN_SHIFT;
+
+       bp->cnic_eth_dev.max_fcoe_conn =
+               (max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
+               BNX2X_MAX_FCOE_INIT_CONN_SHIFT;
+
+       BNX2X_DEV_INFO("max_iscsi_conn 0x%x max_fcoe_conn 0x%x\n",
+                      bp->cnic_eth_dev.max_iscsi_conn,
+                      bp->cnic_eth_dev.max_fcoe_conn);
+
+       /* If mamimum allowed number of connections is zero -
+        * disable the feature.
+        */
+       if (!bp->cnic_eth_dev.max_iscsi_conn)
+               bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+
+       if (!bp->cnic_eth_dev.max_fcoe_conn)
+               bp->flags |= NO_FCOE_FLAG;
 }
+#endif
 
 static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 {
        u32 val, val2;
        int func = BP_ABS_FUNC(bp);
        int port = BP_PORT(bp);
+#ifdef BCM_CNIC
+       u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
+       u8 *fip_mac = bp->fip_mac;
+#endif
 
        if (BP_NOMCP(bp)) {
                BNX2X_ERROR("warning: random MAC workaround active\n");
@@ -8398,7 +8558,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
                        bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
 
 #ifdef BCM_CNIC
-               /* iSCSI NPAR MAC */
+               /* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
+                * FCoE MAC then the appropriate feature should be disabled.
+                */
                if (IS_MF_SI(bp)) {
                        u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
                        if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
@@ -8406,8 +8568,39 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
                                                     iscsi_mac_addr_upper);
                                val = MF_CFG_RD(bp, func_ext_config[func].
                                                    iscsi_mac_addr_lower);
-                               bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
-                       }
+                               BNX2X_DEV_INFO("Read iSCSI MAC: "
+                                              "0x%x:0x%04x\n", val2, val);
+                               bnx2x_set_mac_buf(iscsi_mac, val, val2);
+
+                               /* Disable iSCSI OOO if MAC configuration is
+                                * invalid.
+                                */
+                               if (!is_valid_ether_addr(iscsi_mac)) {
+                                       bp->flags |= NO_ISCSI_OOO_FLAG |
+                                                    NO_ISCSI_FLAG;
+                                       memset(iscsi_mac, 0, ETH_ALEN);
+                               }
+                       } else
+                               bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+
+                       if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
+                               val2 = MF_CFG_RD(bp, func_ext_config[func].
+                                                    fcoe_mac_addr_upper);
+                               val = MF_CFG_RD(bp, func_ext_config[func].
+                                                   fcoe_mac_addr_lower);
+                               BNX2X_DEV_INFO("Read FCoE MAC to "
+                                              "0x%x:0x%04x\n", val2, val);
+                               bnx2x_set_mac_buf(fip_mac, val, val2);
+
+                               /* Disable FCoE if MAC configuration is
+                                * invalid.
+                                */
+                               if (!is_valid_ether_addr(fip_mac)) {
+                                       bp->flags |= NO_FCOE_FLAG;
+                                       memset(bp->fip_mac, 0, ETH_ALEN);
+                               }
+                       } else
+                               bp->flags |= NO_FCOE_FLAG;
                }
 #endif
        } else {
@@ -8421,7 +8614,7 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
                                    iscsi_mac_upper);
                val = SHMEM_RD(bp, dev_info.port_hw_config[port].
                                   iscsi_mac_lower);
-               bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
+               bnx2x_set_mac_buf(iscsi_mac, val, val2);
 #endif
        }
 
@@ -8429,14 +8622,12 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
        memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
 #ifdef BCM_CNIC
-       /* Inform the upper layers about FCoE MAC */
+       /* Set the FCoE MAC in modes other then MF_SI */
        if (!CHIP_IS_E1x(bp)) {
                if (IS_MF_SD(bp))
-                       memcpy(bp->fip_mac, bp->dev->dev_addr,
-                              sizeof(bp->fip_mac));
-               else
-                       memcpy(bp->fip_mac, bp->iscsi_mac,
-                              sizeof(bp->fip_mac));
+                       memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
+               else if (!IS_MF(bp))
+                       memcpy(fip_mac, iscsi_mac, ETH_ALEN);
        }
 #endif
 }
@@ -8494,7 +8685,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
                                E1H_FUNC_MAX * sizeof(struct drv_func_mb);
                /*
                 * get mf configuration:
-                * 1. existance of MF configuration
+                * 1. existence of MF configuration
                 * 2. MAC address must be legal (check only upper bytes)
                 *    for  Switch-Independent mode;
                 *    OVLAN must be legal for Switch-Dependent mode
@@ -8536,7 +8727,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
                        default:
                                /* Unknown configuration: reset mf_config */
                                bp->mf_config[vn] = 0;
-                               DP(NETIF_MSG_PROBE, "Unkown MF mode 0x%x\n",
+                               DP(NETIF_MSG_PROBE, "Unknown MF mode 0x%x\n",
                                   val);
                        }
                }
@@ -8599,6 +8790,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
        /* Get MAC addresses */
        bnx2x_get_mac_hwinfo(bp);
 
+#ifdef BCM_CNIC
+       bnx2x_get_cnic_info(bp);
+#endif
+
        return rc;
 }
 
@@ -8813,12 +9008,197 @@ static int bnx2x_close(struct net_device *dev)
        return 0;
 }
 
+#define E1_MAX_UC_LIST 29
+#define E1H_MAX_UC_LIST        30
+#define E2_MAX_UC_LIST 14
+static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+{
+       if (CHIP_IS_E1(bp))
+               return E1_MAX_UC_LIST;
+       else if (CHIP_IS_E1H(bp))
+               return E1H_MAX_UC_LIST;
+       else
+               return E2_MAX_UC_LIST;
+}
+
+
+static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
+{
+       if (CHIP_IS_E1(bp))
+               /* CAM Entries for Port0:
+                *      0 - prim ETH MAC
+                *      1 - BCAST MAC
+                *      2 - iSCSI L2 ring ETH MAC
+                *      3-31 - UC MACs
+                *
+                * Port1 entries are allocated the same way starting from
+                * entry 32.
+                */
+               return 3 + 32 * BP_PORT(bp);
+       else if (CHIP_IS_E1H(bp)) {
+               /* CAM Entries:
+                *      0-7  - prim ETH MAC for each function
+                *      8-15 - iSCSI L2 ring ETH MAC for each function
+                *      16 till 255 UC MAC lists for each function
+                *
+                * Remark: There is no FCoE support for E1H, thus FCoE related
+                *         MACs are not considered.
+                */
+               return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
+                       bnx2x_max_uc_list(bp) * BP_FUNC(bp);
+       } else {
+               /* CAM Entries (there is a separate CAM per engine):
+                *      0-4  - prim ETH MAC for each function
+                *      4-7 - iSCSI L2 ring ETH MAC for each function
+                *      8-11 - FIP ucast L2 MAC for each function
+                *      12-15 - ALL_ENODE_MACS mcast MAC for each function
+                *      16 till 71 UC MAC lists for each function
+                */
+               u8 func_idx =
+                       (CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
+
+               return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
+                       bnx2x_max_uc_list(bp) * func_idx;
+       }
+}
+
+/* set uc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_uc_list(struct bnx2x *bp)
+{
+       int i = 0, old;
+       struct net_device *dev = bp->dev;
+       u8 offset = bnx2x_uc_list_cam_offset(bp);
+       struct netdev_hw_addr *ha;
+       struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+       dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+
+       if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
+               return -EINVAL;
+
+       netdev_for_each_uc_addr(ha, dev) {
+               /* copy mac */
+               config_cmd->config_table[i].msb_mac_addr =
+                       swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
+               config_cmd->config_table[i].middle_mac_addr =
+                       swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
+               config_cmd->config_table[i].lsb_mac_addr =
+                       swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
+
+               config_cmd->config_table[i].vlan_id = 0;
+               config_cmd->config_table[i].pf_id = BP_FUNC(bp);
+               config_cmd->config_table[i].clients_bit_vector =
+                       cpu_to_le32(1 << BP_L_ID(bp));
+
+               SET_FLAG(config_cmd->config_table[i].flags,
+                       MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+                       T_ETH_MAC_COMMAND_SET);
+
+               DP(NETIF_MSG_IFUP,
+                  "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
+                  config_cmd->config_table[i].msb_mac_addr,
+                  config_cmd->config_table[i].middle_mac_addr,
+                  config_cmd->config_table[i].lsb_mac_addr);
+
+               i++;
+
+               /* Set uc MAC in NIG */
+               bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
+                                    LLH_CAM_ETH_LINE + i);
+       }
+       old = config_cmd->hdr.length;
+       if (old > i) {
+               for (; i < old; i++) {
+                       if (CAM_IS_INVALID(config_cmd->
+                                          config_table[i])) {
+                               /* already invalidated */
+                               break;
+                       }
+                       /* invalidate */
+                       SET_FLAG(config_cmd->config_table[i].flags,
+                               MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+                               T_ETH_MAC_COMMAND_INVALIDATE);
+               }
+       }
+
+       wmb();
+
+       config_cmd->hdr.length = i;
+       config_cmd->hdr.offset = offset;
+       config_cmd->hdr.client_id = 0xff;
+       /* Mark that this ramrod doesn't use bp->set_mac_pending for
+        * synchronization.
+        */
+       config_cmd->hdr.echo = 0;
+
+       mb();
+
+       return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+                  U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+}
+
+void bnx2x_invalidate_uc_list(struct bnx2x *bp)
+{
+       int i;
+       struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+       dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+       int ramrod_flags = WAIT_RAMROD_COMMON;
+       u8 offset = bnx2x_uc_list_cam_offset(bp);
+       u8 max_list_size = bnx2x_max_uc_list(bp);
+
+       for (i = 0; i < max_list_size; i++) {
+               SET_FLAG(config_cmd->config_table[i].flags,
+                       MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+                       T_ETH_MAC_COMMAND_INVALIDATE);
+               bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
+       }
+
+       wmb();
+
+       config_cmd->hdr.length = max_list_size;
+       config_cmd->hdr.offset = offset;
+       config_cmd->hdr.client_id = 0xff;
+       /* We'll wait for a completion this time... */
+       config_cmd->hdr.echo = 1;
+
+       bp->set_mac_pending = 1;
+
+       mb();
+
+       bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+                     U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+       /* Wait for a completion */
+       bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
+                               ramrod_flags);
+
+}
+
+static inline int bnx2x_set_mc_list(struct bnx2x *bp)
+{
+       /* some multicasts */
+       if (CHIP_IS_E1(bp)) {
+               return bnx2x_set_e1_mc_list(bp);
+       } else { /* E1H and newer */
+               return bnx2x_set_e1h_mc_list(bp);
+       }
+}
+
 /* called with netif_tx_lock from dev_mcast.c */
 void bnx2x_set_rx_mode(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
        u32 rx_mode = BNX2X_RX_MODE_NORMAL;
-       int port = BP_PORT(bp);
 
        if (bp->state != BNX2X_STATE_OPEN) {
                DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
@@ -8829,47 +9209,16 @@ void bnx2x_set_rx_mode(struct net_device *dev)
 
        if (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 (dev->flags & IFF_ALLMULTI)
                rx_mode = BNX2X_RX_MODE_ALLMULTI;
-       else { /* some multicasts */
-               if (CHIP_IS_E1(bp)) {
-                       /*
-                        * set mc list, do not wait as wait implies sleep
-                        * and set_rx_mode can be invoked from non-sleepable
-                        * context
-                        */
-                       u8 offset = (CHIP_REV_IS_SLOW(bp) ?
-                                    BNX2X_MAX_EMUL_MULTI*(1 + port) :
-                                    BNX2X_MAX_MULTICAST*(1 + port));
-
-                       bnx2x_set_e1_mc_list(bp, offset);
-               } else { /* E1H */
-                       /* Accept one or more multicasts */
-                       struct netdev_hw_addr *ha;
-                       u32 mc_filter[MC_HASH_SIZE];
-                       u32 crc, bit, regidx;
-                       int i;
-
-                       memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
-                       netdev_for_each_mc_addr(ha, dev) {
-                               DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
-                                  bnx2x_mc_addr(ha));
-
-                               crc = crc32c_le(0, bnx2x_mc_addr(ha),
-                                               ETH_ALEN);
-                               bit = (crc >> 24) & 0xff;
-                               regidx = bit >> 5;
-                               bit &= 0x1f;
-                               mc_filter[regidx] |= (1 << bit);
-                       }
+       else {
+               /* some multicasts */
+               if (bnx2x_set_mc_list(bp))
+                       rx_mode = BNX2X_RX_MODE_ALLMULTI;
 
-                       for (i = 0; i < MC_HASH_SIZE; i++)
-                               REG_WR(bp, MC_HASH_OFFSET(bp, i),
-                                      mc_filter[i]);
-               }
+               /* some unicasts */
+               if (bnx2x_set_uc_list(bp))
+                       rx_mode = BNX2X_RX_MODE_PROMISC;
        }
 
        bp->rx_mode = rx_mode;
@@ -8950,7 +9299,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
        .ndo_stop               = bnx2x_close,
        .ndo_start_xmit         = bnx2x_start_xmit,
        .ndo_select_queue       = bnx2x_select_queue,
-       .ndo_set_multicast_list = bnx2x_set_rx_mode,
+       .ndo_set_rx_mode        = bnx2x_set_rx_mode,
        .ndo_set_mac_address    = bnx2x_change_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_do_ioctl           = bnx2x_ioctl,
@@ -9096,7 +9445,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
        dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
        dev->vlan_features |= NETIF_F_TSO6;
 
-#ifdef BCM_DCB
+#ifdef BCM_DCBNL
        dev->dcbnl_ops = &bnx2x_dcbnl_ops;
 #endif
 
@@ -9428,7 +9777,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
 #endif
 
-       /* Configure interupt mode: try to enable MSI-X/MSI if
+       /* Configure interrupt mode: try to enable MSI-X/MSI if
         * needed, set bp->num_queues appropriately.
         */
        bnx2x_set_int_mode(bp);
@@ -9503,6 +9852,11 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
        }
 #endif
 
+#ifdef BCM_DCBNL
+       /* Delete app tlvs from dcbnl */
+       bnx2x_dcbnl_update_applist(bp, true);
+#endif
+
        unregister_netdev(dev);
 
        /* Delete all NAPI objects */
@@ -9776,15 +10130,21 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
                                        HW_CID(bp, BNX2X_ISCSI_ETH_CID));
                }
 
-               /* There may be not more than 8 L2 and COMMON SPEs and not more
-                * than 8 L5 SPEs in the air.
+               /* There may be not more than 8 L2 and not more than 8 L5 SPEs
+                * We also check that the number of outstanding
+                * COMMON ramrods is not more than the EQ and SPQ can
+                * accommodate.
                 */
-               if ((type == NONE_CONNECTION_TYPE) ||
-                   (type == ETH_CONNECTION_TYPE)) {
-                       if (!atomic_read(&bp->spq_left))
+               if (type == ETH_CONNECTION_TYPE) {
+                       if (!atomic_read(&bp->cq_spq_left))
                                break;
                        else
-                               atomic_dec(&bp->spq_left);
+                               atomic_dec(&bp->cq_spq_left);
+               } else if (type == NONE_CONNECTION_TYPE) {
+                       if (!atomic_read(&bp->eq_spq_left))
+                               break;
+                       else
+                               atomic_dec(&bp->eq_spq_left);
                } else if ((type == ISCSI_CONNECTION_TYPE) ||
                           (type == FCOE_CONNECTION_TYPE)) {
                        if (bp->cnic_spq_pending >=
@@ -9862,7 +10222,8 @@ static int bnx2x_cnic_ctl_send(struct bnx2x *bp, struct cnic_ctl_info *ctl)
        int rc = 0;
 
        mutex_lock(&bp->cnic_mutex);
-       c_ops = bp->cnic_ops;
+       c_ops = rcu_dereference_protected(bp->cnic_ops,
+                                         lockdep_is_held(&bp->cnic_mutex));
        if (c_ops)
                rc = c_ops->cnic_ctl(bp->cnic_data, ctl);
        mutex_unlock(&bp->cnic_mutex);
@@ -9976,7 +10337,7 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
                int count = ctl->data.credit.credit_count;
 
                smp_mb__before_atomic_inc();
-               atomic_add(count, &bp->spq_left);
+               atomic_add(count, &bp->cq_spq_left);
                smp_mb__after_atomic_inc();
                break;
        }
@@ -10072,6 +10433,13 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
        struct bnx2x *bp = netdev_priv(dev);
        struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
+       /* If both iSCSI and FCoE are disabled - return NULL in
+        * order to indicate CNIC that it should not try to work
+        * with this device.
+        */
+       if (NO_ISCSI(bp) && NO_FCOE(bp))
+               return NULL;
+
        cp->drv_owner = THIS_MODULE;
        cp->chip_id = CHIP_ID(bp);
        cp->pdev = bp->pdev;
@@ -10092,6 +10460,15 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
                BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
        cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
 
+       if (NO_ISCSI_OOO(bp))
+               cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
+
+       if (NO_ISCSI(bp))
+               cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
+
+       if (NO_FCOE(bp))
+               cp->drv_state |= CNIC_DRV_STATE_NO_FCOE;
+
        DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
                         "starting cid %d\n",
           cp->ctx_blk_size,