diff options
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_cmn.c')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_cmn.c | 1017 |
1 files changed, 563 insertions, 454 deletions
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 02bf710629a3..bc5837514074 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -15,18 +15,16 @@ * */ - #include <linux/etherdevice.h> +#include <linux/if_vlan.h> #include <linux/ip.h> -#include <linux/ipv6.h> +#include <net/ipv6.h> #include <net/ip6_checksum.h> +#include <linux/firmware.h> #include "bnx2x_cmn.h" -#ifdef BCM_VLAN -#include <linux/if_vlan.h> -#endif +#include "bnx2x_init.h" -static int bnx2x_poll(struct napi_struct *napi, int budget); /* free skb in the packet ring at pos idx * return idx of last bd freed @@ -51,7 +49,7 @@ static u16 bnx2x_free_tx_pkt(struct bnx2x *bp, struct bnx2x_fastpath *fp, DP(BNX2X_MSG_OFF, "free bd_idx %d\n", bd_idx); tx_start_bd = &fp->tx_desc_ring[bd_idx].start_bd; dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd), - BD_UNMAP_LEN(tx_start_bd), PCI_DMA_TODEVICE); + BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE); nbd = le16_to_cpu(tx_start_bd->nbd) - 1; #ifdef BNX2X_STOP_ON_ERROR @@ -115,16 +113,10 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp) pkt_cons = TX_BD(sw_cons); - /* prefetch(bp->tx_buf_ring[pkt_cons].skb); */ - - DP(NETIF_MSG_TX_DONE, "hw_cons %u sw_cons %u pkt_cons %u\n", - hw_cons, sw_cons, pkt_cons); + DP(NETIF_MSG_TX_DONE, "queue[%d]: hw_cons %u sw_cons %u " + " pkt_cons %u\n", + fp->index, hw_cons, sw_cons, pkt_cons); -/* if (NEXT_TX_IDX(sw_cons) != hw_cons) { - rmb(); - prefetch(fp->tx_buf_ring[NEXT_TX_IDX(sw_cons)].skb); - } -*/ bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons); sw_cons++; } @@ -140,7 +132,6 @@ int bnx2x_tx_int(struct bnx2x_fastpath *fp) */ smp_mb(); - /* TBD need a thresh? */ if (unlikely(netif_tx_queue_stopped(txq))) { /* Taking tx_lock() is needed to prevent reenabling the queue * while it's empty. This could have happen if rx_action() gets @@ -189,14 +180,16 @@ static void bnx2x_update_sge_prod(struct bnx2x_fastpath *fp, /* First mark all used pages */ for (i = 0; i < sge_len; i++) - SGE_MASK_CLEAR_BIT(fp, RX_SGE(le16_to_cpu(fp_cqe->sgl[i]))); + SGE_MASK_CLEAR_BIT(fp, + RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[i]))); DP(NETIF_MSG_RX_STATUS, "fp_cqe->sgl[%d] = %d\n", - sge_len - 1, le16_to_cpu(fp_cqe->sgl[sge_len - 1])); + sge_len - 1, le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1])); /* Here we assume that the last SGE index is the biggest */ prefetch((void *)(fp->sge_mask)); - bnx2x_update_last_max_sge(fp, le16_to_cpu(fp_cqe->sgl[sge_len - 1])); + bnx2x_update_last_max_sge(fp, + le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[sge_len - 1])); last_max = RX_SGE(fp->last_max_sge); last_elem = last_max >> RX_SGE_MASK_ELEM_SHIFT; @@ -297,7 +290,8 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, /* Run through the SGL and compose the fragmented skb */ for (i = 0, j = 0; i < pages; i += PAGES_PER_SGE, j++) { - u16 sge_idx = RX_SGE(le16_to_cpu(fp_cqe->sgl[j])); + u16 sge_idx = + RX_SGE(le16_to_cpu(fp_cqe->sgl_or_raw_data.sgl[j])); /* FW gives the indices of the SGE as if the ring is an array (meaning that "next" element will consume 2 indices) */ @@ -349,16 +343,9 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, if (likely(new_skb)) { /* fix ip xsum and give it to the stack */ /* (no need to map the new skb) */ -#ifdef BCM_VLAN - int is_vlan_cqe = - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & - PARSING_FLAGS_VLAN); - int is_not_hwaccel_vlan_cqe = - (is_vlan_cqe && (!(bp->flags & HW_VLAN_RX_FLAG))); -#endif prefetch(skb); - prefetch(((char *)(skb)) + 128); + prefetch(((char *)(skb)) + L1_CACHE_BYTES); #ifdef BNX2X_STOP_ON_ERROR if (pad + len > bp->rx_buf_size) { @@ -380,27 +367,18 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, struct iphdr *iph; iph = (struct iphdr *)skb->data; -#ifdef BCM_VLAN - /* If there is no Rx VLAN offloading - - take VLAN tag into an account */ - if (unlikely(is_not_hwaccel_vlan_cqe)) - iph = (struct iphdr *)((u8 *)iph + VLAN_HLEN); -#endif iph->check = 0; iph->check = ip_fast_csum((u8 *)iph, iph->ihl); } if (!bnx2x_fill_frag_skb(bp, fp, skb, &cqe->fast_path_cqe, cqe_idx)) { -#ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && is_vlan_cqe && - (!is_not_hwaccel_vlan_cqe)) - vlan_gro_receive(&fp->napi, bp->vlgrp, + if ((le16_to_cpu(cqe->fast_path_cqe. + pars_flags.flags) & PARSING_FLAGS_VLAN)) + __vlan_hwaccel_put_tag(skb, le16_to_cpu(cqe->fast_path_cqe. - vlan_tag), skb); - else -#endif - napi_gro_receive(&fp->napi, skb); + vlan_tag)); + napi_gro_receive(&fp->napi, skb); } else { DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages" " - dropping packet!\n"); @@ -509,8 +487,11 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) len = le16_to_cpu(cqe->fast_path_cqe.pkt_len); pad = cqe->fast_path_cqe.placement_offset; - /* If CQE is marked both TPA_START and TPA_END - it is a non-TPA CQE */ + /* - If CQE is marked both TPA_START and TPA_END it is + * a non-TPA CQE. + * - FP CQE will always have either TPA_START or/and + * TPA_STOP flags set. + */ if ((!fp->disable_tpa) && (TPA_TYPE(cqe_fp_flags) != (TPA_TYPE_START | TPA_TYPE_END))) { @@ -528,9 +509,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) bnx2x_set_skb_rxhash(bp, cqe, skb); goto next_rx; - } - - if (TPA_TYPE(cqe_fp_flags) == TPA_TYPE_END) { + } else { /* TPA_STOP */ DP(NETIF_MSG_RX_STATUS, "calling tpa_stop on queue %d\n", queue); @@ -560,7 +539,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) dma_unmap_addr(rx_buf, mapping), pad + RX_COPY_THRESH, DMA_FROM_DEVICE); - prefetch(((char *)(skb)) + 128); + prefetch(((char *)(skb)) + L1_CACHE_BYTES); /* is this an error packet? */ if (unlikely(cqe_fp_flags & ETH_RX_ERROR_FALGS)) { @@ -594,7 +573,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) skb_reserve(new_skb, pad); skb_put(new_skb, len); - bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod); + bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod); skb = new_skb; @@ -613,7 +592,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) "of alloc failure\n"); fp->eth_q_stats.rx_skb_alloc_failed++; reuse_rx: - bnx2x_reuse_rx_skb(fp, skb, bd_cons, bd_prod); + bnx2x_reuse_rx_skb(fp, bd_cons, bd_prod); goto next_rx; } @@ -622,7 +601,8 @@ reuse_rx: /* Set Toeplitz hash for a none-LRO skb */ bnx2x_set_skb_rxhash(bp, cqe, skb); - skb->ip_summed = CHECKSUM_NONE; + skb_checksum_none_assert(skb); + if (bp->rx_csum) { if (likely(BNX2X_RX_CSUM_OK(cqe))) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -633,15 +613,11 @@ reuse_rx: skb_record_rx_queue(skb, fp->index); -#ifdef BCM_VLAN - if ((bp->vlgrp != NULL) && (bp->flags & HW_VLAN_RX_FLAG) && - (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & - PARSING_FLAGS_VLAN)) - vlan_gro_receive(&fp->napi, bp->vlgrp, - le16_to_cpu(cqe->fast_path_cqe.vlan_tag), skb); - else -#endif - napi_gro_receive(&fp->napi, skb); + if (le16_to_cpu(cqe->fast_path_cqe.pars_flags.flags) & + PARSING_FLAGS_VLAN) + __vlan_hwaccel_put_tag(skb, + le16_to_cpu(cqe->fast_path_cqe.vlan_tag)); + napi_gro_receive(&fp->napi, skb); next_rx: @@ -685,9 +661,10 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) return IRQ_HANDLED; } - DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB [%d:%d]\n", - fp->index, fp->sb_id); - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0); + DP(BNX2X_MSG_FP, "got an MSI-X interrupt on IDX:SB " + "[fp %d fw_sd %d igusb %d]\n", + fp->index, fp->fw_sb_id, fp->igu_sb_id); + bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, 0, IGU_INT_DISABLE, 0); #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -697,14 +674,12 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie) /* Handle Rx and Tx according to MSI-X vector */ prefetch(fp->rx_cons_sb); prefetch(fp->tx_cons_sb); - prefetch(&fp->status_blk->u_status_block.status_block_index); - prefetch(&fp->status_blk->c_status_block.status_block_index); + prefetch(&fp->sb_running_index[SM_RX_ID]); napi_schedule(&bnx2x_fp(bp, fp->index, napi)); return IRQ_HANDLED; } - /* HW Lock for shared dual port PHYs */ void bnx2x_acquire_phy_lock(struct bnx2x *bp) { @@ -738,12 +713,13 @@ void bnx2x_link_report(struct bnx2x *bp) netdev_info(bp->dev, "NIC Link is Up, "); line_speed = bp->link_vars.line_speed; - if (IS_E1HMF(bp)) { + if (IS_MF(bp)) { u16 vn_max_rate; vn_max_rate = - ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >> - FUNC_MF_CFG_MAX_BW_SHIFT) * 100; + ((bp->mf_config[BP_VN(bp)] & + FUNC_MF_CFG_MAX_BW_MASK) >> + FUNC_MF_CFG_MAX_BW_SHIFT) * 100; if (vn_max_rate < line_speed) line_speed = vn_max_rate; } @@ -773,23 +749,73 @@ void bnx2x_link_report(struct bnx2x *bp) } } +/* Returns the number of actually allocated BDs */ +static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp, + int rx_ring_size) +{ + struct bnx2x *bp = fp->bp; + u16 ring_prod, cqe_ring_prod; + int i; + + fp->rx_comp_cons = 0; + cqe_ring_prod = ring_prod = 0; + for (i = 0; i < rx_ring_size; i++) { + if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) { + BNX2X_ERR("was only able to allocate " + "%d rx skbs on queue[%d]\n", i, fp->index); + fp->eth_q_stats.rx_skb_alloc_failed++; + break; + } + ring_prod = NEXT_RX_IDX(ring_prod); + cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod); + WARN_ON(ring_prod <= i); + } + + fp->rx_bd_prod = ring_prod; + /* Limit the CQE producer by the CQE ring size */ + fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT, + cqe_ring_prod); + fp->rx_pkt = fp->rx_calls = 0; + + return i; +} + +static inline void bnx2x_alloc_rx_bd_ring(struct bnx2x_fastpath *fp) +{ + struct bnx2x *bp = fp->bp; + int rx_ring_size = bp->rx_ring_size ? bp->rx_ring_size : + MAX_RX_AVAIL/bp->num_queues; + + rx_ring_size = max_t(int, MIN_RX_AVAIL, rx_ring_size); + + bnx2x_alloc_rx_bds(fp, rx_ring_size); + + /* Warning! + * this will generate an interrupt (to the TSTORM) + * must only be done after chip is initialized + */ + bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod, + fp->rx_sge_prod); +} + void bnx2x_init_rx_rings(struct bnx2x *bp) { int func = BP_FUNC(bp); int max_agg_queues = CHIP_IS_E1(bp) ? ETH_MAX_AGGREGATION_QUEUES_E1 : ETH_MAX_AGGREGATION_QUEUES_E1H; - u16 ring_prod, cqe_ring_prod; + u16 ring_prod; int i, j; - bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN; + bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN + + IP_HEADER_ALIGNMENT_PADDING; + DP(NETIF_MSG_IFUP, "mtu %d rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size); - if (bp->flags & TPA_ENABLE_FLAG) { - - for_each_queue(bp, j) { - struct bnx2x_fastpath *fp = &bp->fp[j]; + for_each_queue(bp, j) { + struct bnx2x_fastpath *fp = &bp->fp[j]; + if (!fp->disable_tpa) { for (i = 0; i < max_agg_queues; i++) { fp->tpa_pool[i].skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); @@ -807,6 +833,35 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) mapping, 0); fp->tpa_state[i] = BNX2X_TPA_STOP; } + + /* "next page" elements initialization */ + bnx2x_set_next_page_sgl(fp); + + /* set SGEs bit mask */ + bnx2x_init_sge_ring_bit_mask(fp); + + /* Allocate SGEs and initialize the ring elements */ + for (i = 0, ring_prod = 0; + i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) { + + if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) { + BNX2X_ERR("was only able to allocate " + "%d rx sges\n", i); + BNX2X_ERR("disabling TPA for" + " queue[%d]\n", j); + /* Cleanup already allocated elements */ + bnx2x_free_rx_sge_range(bp, + fp, ring_prod); + bnx2x_free_tpa_pool(bp, + fp, max_agg_queues); + fp->disable_tpa = 1; + ring_prod = 0; + break; + } + ring_prod = NEXT_SGE_IDX(ring_prod); + } + + fp->rx_sge_prod = ring_prod; } } @@ -814,109 +869,29 @@ void bnx2x_init_rx_rings(struct bnx2x *bp) struct bnx2x_fastpath *fp = &bp->fp[j]; fp->rx_bd_cons = 0; - fp->rx_cons_sb = BNX2X_RX_SB_INDEX; - fp->rx_bd_cons_sb = BNX2X_RX_SB_BD_INDEX; - - /* "next page" elements initialization */ - /* SGE ring */ - for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { - struct eth_rx_sge *sge; - - sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2]; - sge->addr_hi = - cpu_to_le32(U64_HI(fp->rx_sge_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES))); - sge->addr_lo = - cpu_to_le32(U64_LO(fp->rx_sge_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES))); - } - - bnx2x_init_sge_ring_bit_mask(fp); - /* RX BD ring */ - for (i = 1; i <= NUM_RX_RINGS; i++) { - struct eth_rx_bd *rx_bd; - - rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2]; - rx_bd->addr_hi = - cpu_to_le32(U64_HI(fp->rx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_RINGS))); - rx_bd->addr_lo = - cpu_to_le32(U64_LO(fp->rx_desc_mapping + - BCM_PAGE_SIZE*(i % NUM_RX_RINGS))); - } + bnx2x_set_next_page_rx_bd(fp); /* CQ ring */ - for (i = 1; i <= NUM_RCQ_RINGS; i++) { - struct eth_rx_cqe_next_page *nextpg; - - nextpg = (struct eth_rx_cqe_next_page *) - &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1]; - nextpg->addr_hi = - cpu_to_le32(U64_HI(fp->rx_comp_mapping + - BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS))); - nextpg->addr_lo = - cpu_to_le32(U64_LO(fp->rx_comp_mapping + - BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS))); - } - - /* Allocate SGEs and initialize the ring elements */ - for (i = 0, ring_prod = 0; - i < MAX_RX_SGE_CNT*NUM_RX_SGE_PAGES; i++) { - - if (bnx2x_alloc_rx_sge(bp, fp, ring_prod) < 0) { - BNX2X_ERR("was only able to allocate " - "%d rx sges\n", i); - BNX2X_ERR("disabling TPA for queue[%d]\n", j); - /* Cleanup already allocated elements */ - bnx2x_free_rx_sge_range(bp, fp, ring_prod); - bnx2x_free_tpa_pool(bp, fp, max_agg_queues); - fp->disable_tpa = 1; - ring_prod = 0; - break; - } - ring_prod = NEXT_SGE_IDX(ring_prod); - } - fp->rx_sge_prod = ring_prod; + bnx2x_set_next_page_rx_cq(fp); /* Allocate BDs and initialize BD ring */ - fp->rx_comp_cons = 0; - cqe_ring_prod = ring_prod = 0; - for (i = 0; i < bp->rx_ring_size; i++) { - if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) { - BNX2X_ERR("was only able to allocate " - "%d rx skbs on queue[%d]\n", i, j); - fp->eth_q_stats.rx_skb_alloc_failed++; - break; - } - ring_prod = NEXT_RX_IDX(ring_prod); - cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod); - WARN_ON(ring_prod <= i); - } + bnx2x_alloc_rx_bd_ring(fp); - fp->rx_bd_prod = ring_prod; - /* must not have more available CQEs than BDs */ - fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT, - cqe_ring_prod); - fp->rx_pkt = fp->rx_calls = 0; - - /* Warning! - * this will generate an interrupt (to the TSTORM) - * must only be done after chip is initialized - */ - bnx2x_update_rx_prod(bp, fp, ring_prod, fp->rx_comp_prod, - fp->rx_sge_prod); if (j != 0) continue; - REG_WR(bp, BAR_USTRORM_INTMEM + - USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func), - U64_LO(fp->rx_comp_mapping)); - REG_WR(bp, BAR_USTRORM_INTMEM + - USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4, - U64_HI(fp->rx_comp_mapping)); + if (!CHIP_IS_E2(bp)) { + REG_WR(bp, BAR_USTRORM_INTMEM + + USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func), + U64_LO(fp->rx_comp_mapping)); + REG_WR(bp, BAR_USTRORM_INTMEM + + USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(func) + 4, + U64_HI(fp->rx_comp_mapping)); + } } } + static void bnx2x_free_tx_skbs(struct bnx2x *bp) { int i; @@ -989,55 +964,49 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp) } } -void bnx2x_free_irq(struct bnx2x *bp, bool disable_only) +void bnx2x_free_irq(struct bnx2x *bp) { - if (bp->flags & USING_MSIX_FLAG) { - if (!disable_only) - bnx2x_free_msix_irqs(bp); - pci_disable_msix(bp->pdev); - bp->flags &= ~USING_MSIX_FLAG; - - } else if (bp->flags & USING_MSI_FLAG) { - if (!disable_only) - free_irq(bp->pdev->irq, bp->dev); - pci_disable_msi(bp->pdev); - bp->flags &= ~USING_MSI_FLAG; - - } else if (!disable_only) + if (bp->flags & USING_MSIX_FLAG) + bnx2x_free_msix_irqs(bp); + else if (bp->flags & USING_MSI_FLAG) + free_irq(bp->pdev->irq, bp->dev); + else free_irq(bp->pdev->irq, bp->dev); } -static int bnx2x_enable_msix(struct bnx2x *bp) +int bnx2x_enable_msix(struct bnx2x *bp) { - int i, rc, offset = 1; - int igu_vec = 0; + int msix_vec = 0, i, rc, req_cnt; - bp->msix_table[0].entry = igu_vec; - DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", igu_vec); + bp->msix_table[msix_vec].entry = msix_vec; + DP(NETIF_MSG_IFUP, "msix_table[0].entry = %d (slowpath)\n", + bp->msix_table[0].entry); + msix_vec++; #ifdef BCM_CNIC - igu_vec = BP_L_ID(bp) + offset; - bp->msix_table[1].entry = igu_vec; - DP(NETIF_MSG_IFUP, "msix_table[1].entry = %d (CNIC)\n", igu_vec); - offset++; + bp->msix_table[msix_vec].entry = msix_vec; + DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d (CNIC)\n", + bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry); + msix_vec++; #endif for_each_queue(bp, i) { - igu_vec = BP_L_ID(bp) + offset + i; - bp->msix_table[i + offset].entry = igu_vec; + bp->msix_table[msix_vec].entry = msix_vec; DP(NETIF_MSG_IFUP, "msix_table[%d].entry = %d " - "(fastpath #%u)\n", i + offset, igu_vec, i); + "(fastpath #%u)\n", msix_vec, msix_vec, i); + msix_vec++; } - rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], - BNX2X_NUM_QUEUES(bp) + offset); + req_cnt = BNX2X_NUM_QUEUES(bp) + CNIC_CONTEXT_USE + 1; + + rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt); /* * reconfigure number of tx/rx queues according to available * MSI-X vectors */ if (rc >= BNX2X_MIN_MSIX_VEC_CNT) { - /* vectors available for FP */ - int fp_vec = rc - BNX2X_MSIX_VEC_FP_START; + /* how less vectors we will have? */ + int diff = req_cnt - rc; DP(NETIF_MSG_IFUP, "Trying to use less MSI-X vectors: %d\n", rc); @@ -1049,12 +1018,17 @@ static int bnx2x_enable_msix(struct bnx2x *bp) "MSI-X is not attainable rc %d\n", rc); return rc; } - - bp->num_queues = min(bp->num_queues, fp_vec); + /* + * decrease number of queues by number of unallocated entries + */ + bp->num_queues -= diff; DP(NETIF_MSG_IFUP, "New queue configuration set: %d\n", bp->num_queues); } else if (rc) { + /* fall to INTx if not enough memory */ + if (rc == -ENOMEM) + bp->flags |= DISABLE_MSI_FLAG; DP(NETIF_MSG_IFUP, "MSI-X is not attainable rc %d\n", rc); return rc; } @@ -1083,7 +1057,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", bp->dev->name, i); - rc = request_irq(bp->msix_table[i + offset].vector, + rc = request_irq(bp->msix_table[offset].vector, bnx2x_msix_fp_int, 0, fp->name, fp); if (rc) { BNX2X_ERR("request fp #%d irq failed rc %d\n", i, rc); @@ -1091,10 +1065,12 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) return -EBUSY; } + offset++; fp->state = BNX2X_FP_STATE_IRQ; } i = BNX2X_NUM_QUEUES(bp); + offset = 1 + CNIC_CONTEXT_USE; netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d" " ... fp[%d] %d\n", bp->msix_table[0].vector, @@ -1104,7 +1080,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) return 0; } -static int bnx2x_enable_msi(struct bnx2x *bp) +int bnx2x_enable_msi(struct bnx2x *bp) { int rc; @@ -1175,35 +1151,29 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw) bnx2x_napi_disable(bp); netif_tx_disable(bp->dev); } -static int bnx2x_set_num_queues(struct bnx2x *bp) -{ - int rc = 0; - switch (bp->int_mode) { - case INT_MODE_INTx: - case INT_MODE_MSI: +void bnx2x_set_num_queues(struct bnx2x *bp) +{ + switch (bp->multi_mode) { + case ETH_RSS_MODE_DISABLED: bp->num_queues = 1; - DP(NETIF_MSG_IFUP, "set number of queues to 1\n"); break; - default: - /* Set number of queues according to bp->multi_mode value */ - bnx2x_set_num_queues_msix(bp); - - DP(NETIF_MSG_IFUP, "set number of queues to %d\n", - bp->num_queues); + case ETH_RSS_MODE_REGULAR: + bp->num_queues = bnx2x_calc_num_queues(bp); + break; - /* if we can't use MSI-X we only need one fp, - * so try to enable MSI-X with the requested number of fp's - * and fallback to MSI or legacy INTx with one fp - */ - rc = bnx2x_enable_msix(bp); - if (rc) - /* failed to enable MSI-X */ - bp->num_queues = 1; + default: + bp->num_queues = 1; break; } - bp->dev->real_num_tx_queues = bp->num_queues; - return rc; +} + +static void bnx2x_release_firmware(struct bnx2x *bp) +{ + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); + kfree(bp->init_data); + release_firmware(bp->firmware); } /* must be called with rtnl_lock */ @@ -1212,6 +1182,13 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) u32 load_code; int i, rc; + /* Set init arrays */ + rc = bnx2x_init_firmware(bp); + if (rc) { + BNX2X_ERR("Error loading firmware\n"); + return rc; + } + #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return -EPERM; @@ -1219,83 +1196,64 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; - rc = bnx2x_set_num_queues(bp); + /* must be called before memory allocation and HW init */ + bnx2x_ilt_set_info(bp); - if (bnx2x_alloc_mem(bp)) { - bnx2x_free_irq(bp, true); + if (bnx2x_alloc_mem(bp)) return -ENOMEM; + + netif_set_real_num_tx_queues(bp->dev, bp->num_queues); + rc = netif_set_real_num_rx_queues(bp->dev, bp->num_queues); + if (rc) { + BNX2X_ERR("Unable to update real_num_rx_queues\n"); + goto load_error0; } for_each_queue(bp, i) bnx2x_fp(bp, i, disable_tpa) = ((bp->flags & TPA_ENABLE_FLAG) == 0); - for_each_queue(bp, i) - netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi), - bnx2x_poll, 128); - bnx2x_napi_enable(bp); - if (bp->flags & USING_MSIX_FLAG) { - rc = bnx2x_req_msix_irqs(bp); - if (rc) { - bnx2x_free_irq(bp, true); - goto load_error1; - } - } else { - /* Fall to INTx if failed to enable MSI-X due to lack of - memory (in bnx2x_set_num_queues()) */ - if ((rc != -ENOMEM) && (bp->int_mode != INT_MODE_INTx)) - bnx2x_enable_msi(bp); - bnx2x_ack_int(bp); - rc = bnx2x_req_irq(bp); - if (rc) { - BNX2X_ERR("IRQ request failed rc %d, aborting\n", rc); - bnx2x_free_irq(bp, true); - goto load_error1; - } - if (bp->flags & USING_MSI_FLAG) { - bp->dev->irq = bp->pdev->irq; - netdev_info(bp->dev, "using MSI IRQ %d\n", - bp->pdev->irq); - } - } - /* Send LOAD_REQUEST command to MCP Returns the type of LOAD command: if it is the first port to be initialized common blocks should be initialized, otherwise - not */ if (!BP_NOMCP(bp)) { - load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0); if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; - goto load_error2; + goto load_error1; } if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { rc = -EBUSY; /* other port in diagnostic mode */ - goto load_error2; + goto load_error1; } } else { + int path = BP_PATH(bp); int port = BP_PORT(bp); - DP(NETIF_MSG_IFUP, "NO MCP - load counts %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - load_count[0]++; - load_count[1 + port]++; - DP(NETIF_MSG_IFUP, "NO MCP - new load counts %d, %d, %d\n", - load_count[0], load_count[1], load_count[2]); - if (load_count[0] == 1) + DP(NETIF_MSG_IFUP, "NO MCP - load counts[%d] %d, %d, %d\n", + path, load_count[path][0], load_count[path][1], + load_count[path][2]); + load_count[path][0]++; + load_count[path][1 + port]++; + DP(NETIF_MSG_IFUP, "NO MCP - new load counts[%d] %d, %d, %d\n", + path, load_count[path][0], load_count[path][1], + load_count[path][2]); + if (load_count[path][0] == 1) load_code = FW_MSG_CODE_DRV_LOAD_COMMON; - else if (load_count[1 + port] == 1) + else if (load_count[path][1 + port] == 1) load_code = FW_MSG_CODE_DRV_LOAD_PORT; else load_code = FW_MSG_CODE_DRV_LOAD_FUNCTION; } if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || + (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP) || (load_code == FW_MSG_CODE_DRV_LOAD_PORT)) bp->port.pmf = 1; else @@ -1306,16 +1264,22 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_init_hw(bp, load_code); if (rc) { BNX2X_ERR("HW init failed, aborting\n"); - bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); + goto load_error2; + } + + /* Connect to IRQs */ + rc = bnx2x_setup_irqs(bp); + if (rc) { + bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); goto load_error2; } /* Setup NIC internals and enable interrupts */ bnx2x_nic_init(bp, load_code); - if ((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) && + if (((load_code == FW_MSG_CODE_DRV_LOAD_COMMON) || + (load_code == FW_MSG_CODE_DRV_LOAD_COMMON_CHIP)) && (bp->common.shmem2_base)) SHMEM2_WR(bp, dcc_support, (SHMEM_DCC_SUPPORT_DISABLE_ENABLE_PF_TLV | @@ -1323,7 +1287,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* Send LOAD_DONE command to MCP */ if (!BP_NOMCP(bp)) { - load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); + load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE, 0); if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; @@ -1333,7 +1297,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->state = BNX2X_STATE_OPENING_WAIT4_PORT; - rc = bnx2x_setup_leading(bp); + rc = bnx2x_func_start(bp); + if (rc) { + BNX2X_ERR("Function start failed!\n"); +#ifndef BNX2X_STOP_ON_ERROR + goto load_error3; +#else + bp->panic = 1; + return -EBUSY; +#endif + } + + rc = bnx2x_setup_client(bp, &bp->fp[0], 1 /* Leading */); if (rc) { BNX2X_ERR("Setup leading failed!\n"); #ifndef BNX2X_STOP_ON_ERROR @@ -1344,62 +1319,47 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) #endif } - if (CHIP_IS_E1H(bp)) - if (bp->mf_config & FUNC_MF_CFG_FUNC_DISABLED) { - DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n"); - bp->flags |= MF_FUNC_DIS; - } + if (!CHIP_IS_E1(bp) && + (bp->mf_config[BP_VN(bp)] & FUNC_MF_CFG_FUNC_DISABLED)) { + DP(NETIF_MSG_IFUP, "mf_cfg function disabled\n"); + bp->flags |= MF_FUNC_DIS; + } - if (bp->state == BNX2X_STATE_OPEN) { -#ifdef BCM_CNIC - /* Enable Timer scan */ - REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1); -#endif - for_each_nondefault_queue(bp, i) { - rc = bnx2x_setup_multi(bp, i); - if (rc) #ifdef BCM_CNIC - goto load_error4; -#else - goto load_error3; + /* Enable Timer scan */ + REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + BP_PORT(bp)*4, 1); #endif - } - if (CHIP_IS_E1(bp)) - bnx2x_set_eth_mac_addr_e1(bp, 1); - else - bnx2x_set_eth_mac_addr_e1h(bp, 1); + for_each_nondefault_queue(bp, i) { + rc = bnx2x_setup_client(bp, &bp->fp[i], 0); + if (rc) #ifdef BCM_CNIC - /* Set iSCSI L2 MAC */ - mutex_lock(&bp->cnic_mutex); - if (bp->cnic_eth_dev.drv_state & CNIC_DRV_STATE_REGD) { - bnx2x_set_iscsi_eth_mac_addr(bp, 1); - bp->cnic_flags |= BNX2X_CNIC_FLAG_MAC_SET; - bnx2x_init_sb(bp, bp->cnic_sb, bp->cnic_sb_mapping, - CNIC_SB_ID(bp)); - } - mutex_unlock(&bp->cnic_mutex); + goto load_error4; +#else + goto load_error3; #endif } + /* Now when Clients are configured we are ready to work */ + bp->state = BNX2X_STATE_OPEN; + + bnx2x_set_eth_mac(bp, 1); + if (bp->port.pmf) bnx2x_initial_phy_init(bp, load_mode); /* Start fast path */ switch (load_mode) { case LOAD_NORMAL: - if (bp->state == BNX2X_STATE_OPEN) { - /* Tx queue should be only reenabled */ - netif_tx_wake_all_queues(bp->dev); - } + /* Tx queue should be only reenabled */ + netif_tx_wake_all_queues(bp->dev); /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); break; case LOAD_OPEN: netif_tx_start_all_queues(bp->dev); - if (bp->state != BNX2X_STATE_OPEN) - netif_tx_disable(bp->dev); + smp_mb__after_clear_bit(); /* Initialize the receive filter. */ bnx2x_set_rx_mode(bp->dev); break; @@ -1427,6 +1387,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) #endif bnx2x_inc_load_cnt(bp); + bnx2x_release_firmware(bp); + return 0; #ifdef BCM_CNIC @@ -1436,24 +1398,28 @@ load_error4: #endif load_error3: bnx2x_int_disable_sync(bp, 1); - if (!BP_NOMCP(bp)) { - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP); - bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); - } - bp->port.pmf = 0; + /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); -load_error2: + /* Release IRQs */ - bnx2x_free_irq(bp, false); + bnx2x_free_irq(bp); +load_error2: + if (!BP_NOMCP(bp)) { + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP, 0); + bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0); + } + + bp->port.pmf = 0; load_error1: bnx2x_napi_disable(bp); - for_each_queue(bp, i) - netif_napi_del(&bnx2x_fp(bp, i, napi)); +load_error0: bnx2x_free_mem(bp); + bnx2x_release_firmware(bp); + return rc; } @@ -1481,21 +1447,26 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bp->rx_mode = BNX2X_RX_MODE_NONE; bnx2x_set_storm_rx_mode(bp); - /* Disable HW interrupts, NAPI and Tx */ - bnx2x_netif_stop(bp, 1); - netif_carrier_off(bp->dev); + /* Stop Tx */ + bnx2x_tx_disable(bp); del_timer_sync(&bp->timer); - SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, + + SHMEM_WR(bp, func_mb[BP_FW_MB_IDX(bp)].drv_pulse_mb, (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); - bnx2x_stats_handle(bp, STATS_EVENT_STOP); - /* Release IRQs */ - bnx2x_free_irq(bp, false); + bnx2x_stats_handle(bp, STATS_EVENT_STOP); /* Cleanup the chip if needed */ if (unload_mode != UNLOAD_RECOVERY) bnx2x_chip_cleanup(bp, unload_mode); + else { + /* Disable HW interrupts, NAPI and Tx */ + bnx2x_netif_stop(bp, 1); + + /* Release IRQs */ + bnx2x_free_irq(bp); + } bp->port.pmf = 0; @@ -1503,8 +1474,7 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); - for_each_queue(bp, i) - netif_napi_del(&bnx2x_fp(bp, i, napi)); + bnx2x_free_mem(bp); bp->state = BNX2X_STATE_CLOSED; @@ -1522,10 +1492,17 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) return 0; } + int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) { u16 pmcsr; + /* If there is no power capability, silently succeed */ + if (!bp->pm_cap) { + DP(NETIF_MSG_HW, "No power capability. Breaking.\n"); + return 0; + } + pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr); switch (state) { @@ -1568,13 +1545,10 @@ int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state) return 0; } - - /* * net_device service functions */ - -static int bnx2x_poll(struct napi_struct *napi, int budget) +int bnx2x_poll(struct napi_struct *napi, int budget) { int work_done = 0; struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath, @@ -1603,27 +1577,28 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) /* Fall out from the NAPI loop if needed */ if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { bnx2x_update_fpsb_idx(fp); - /* bnx2x_has_rx_work() reads the status block, thus we need - * to ensure that status block indices have been actually read - * (bnx2x_update_fpsb_idx) prior to this check - * (bnx2x_has_rx_work) so that we won't write the "newer" - * value of the status block to IGU (if there was a DMA right - * after bnx2x_has_rx_work and if there is no rmb, the memory - * reading (bnx2x_update_fpsb_idx) may be postponed to right - * before bnx2x_ack_sb). In this case there will never be - * another interrupt until there is another update of the - * status block, while there is still unhandled work. - */ + /* bnx2x_has_rx_work() reads the status block, + * thus we need to ensure that status block indices + * have been actually read (bnx2x_update_fpsb_idx) + * prior to this check (bnx2x_has_rx_work) so that + * we won't write the "newer" value of the status block + * to IGU (if there was a DMA right after + * bnx2x_has_rx_work and if there is no rmb, the memory + * reading (bnx2x_update_fpsb_idx) may be postponed + * to right before bnx2x_ack_sb). In this case there + * will never be another interrupt until there is + * another update of the status block, while there + * is still unhandled work. + */ rmb(); if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) { napi_complete(napi); /* Re-enable interrupts */ - bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID, - le16_to_cpu(fp->fp_c_idx), - IGU_INT_NOP, 1); - bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID, - le16_to_cpu(fp->fp_u_idx), + DP(NETIF_MSG_HW, + "Update index to %d\n", fp->fp_hc_idx); + bnx2x_ack_sb(bp, fp->igu_sb_id, USTORM_ID, + le16_to_cpu(fp->fp_hc_idx), |