/* bnx2x_cmn.c: QLogic Everest network driver. * * Copyright (c) 2007-2013 Broadcom Corporation * Copyright (c) 2014 QLogic Corporation * All rights reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Maintained by: Ariel Elior <ariel.elior@qlogic.com> * Written by: Eliezer Tamir * Based on code from Michael Chan's bnx2 driver * UDP CSUM errata workaround by Arik Gendelman * Slowpath and fastpath rework by Vladislav Zolotarov * Statistics and Link management by Yitchak Gertner *
*/
/** * bnx2x_move_fp - move content of the fastpath structure. * * @bp: driver handle * @from: source FP index * @to: destination FP index * * Makes sure the contents of the bp->fp[to].napi is kept * intact. This is done by first copying the napi struct from * the target to the source, and then mem copying the entire * source onto the target. Update txdata pointers and related * content.
*/ staticinlinevoid bnx2x_move_fp(struct bnx2x *bp, int from, int to)
{ struct bnx2x_fastpath *from_fp = &bp->fp[from]; struct bnx2x_fastpath *to_fp = &bp->fp[to]; struct bnx2x_sp_objs *from_sp_objs = &bp->sp_objs[from]; struct bnx2x_sp_objs *to_sp_objs = &bp->sp_objs[to]; struct bnx2x_fp_stats *from_fp_stats = &bp->fp_stats[from]; struct bnx2x_fp_stats *to_fp_stats = &bp->fp_stats[to]; int old_max_eth_txqs, new_max_eth_txqs; int old_txdata_index = 0, new_txdata_index = 0; struct bnx2x_agg_info *old_tpa_info = to_fp->tpa_info;
/* Copy the NAPI object as it has been already initialized */
from_fp->napi = to_fp->napi;
/* Retain the tpa_info of the original `to' version as we don't want * 2 FPs to contain the same tpa_info pointer.
*/
to_fp->tpa_info = old_tpa_info;
/* move sp_objs contents as well, as their indices match fp ones */
memcpy(to_sp_objs, from_sp_objs, sizeof(*to_sp_objs));
/* move fp_stats contents as well, as their indices match fp ones */
memcpy(to_fp_stats, from_fp_stats, sizeof(*to_fp_stats));
/* Update txdata pointers in fp and move txdata content accordingly: * Each fp consumes 'max_cos' txdata structures, so the index should be * decremented by max_cos x delta.
*/
/** * bnx2x_fill_fw_str - Fill buffer with FW version string. * * @bp: driver handle * @buf: character buffer to fill with the fw name * @buf_len: length of the above buffer *
*/ void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len)
{ if (IS_PF(bp)) {
u8 phy_fw_ver[PHY_FW_VER_LEN];
/** * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact * * @bp: driver handle * @delta: number of eth queues which were not allocated
*/ staticvoid bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta)
{ int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp);
/* Queue pointer cannot be re-set on an fp-basis, as moving pointer * backward along the array could cause memory to be overridden
*/ for (cos = 1; cos < bp->max_cos; cos++) { for (i = 0; i < old_eth_num - delta; i++) { struct bnx2x_fastpath *fp = &bp->fp[i]; int new_idx = cos * (old_eth_num - delta) + i;
/* Need to make the tx_bd_cons update visible to start_xmit() * before checking for netif_tx_queue_stopped(). Without the * memory barrier, there is a small possibility that * start_xmit() will miss it and cause the queue to be stopped * forever. * On the other hand we need an rmb() here to ensure the proper * ordering of bit testing in the following * netif_tx_queue_stopped(txq) call.
*/
smp_mb();
if (unlikely(netif_tx_queue_stopped(txq))) { /* Taking tx_lock() is needed to prevent re-enabling the queue * while it's empty. This could have happen if rx_action() gets * suspended in bnx2x_tx_int() after the condition before * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()): * * stops the queue->sees fresh tx_bd_cons->releases the queue-> * sends some packets consuming the whole queue again-> * stops the queue
*/
/* 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(cqe->sgl_or_raw_data.sgl[sge_len - 1]));
/* Get Toeplitz hash value in the skb using the value from the * CQE (calculated by HW).
*/ static u32 bnx2x_get_rxhash(conststruct bnx2x *bp, conststruct eth_fast_path_rx_cqe *cqe, enum pkt_hash_types *rxhash_type)
{ /* Get Toeplitz hash from CQE */ if ((bp->dev->features & NETIF_F_RXHASH) &&
(cqe->status_flags & ETH_FAST_PATH_RX_CQE_RSS_HASH_FLG)) { enum eth_rss_hash_type htype;
/* print error if current state != stop */ if (tpa_info->tpa_state != BNX2X_TPA_STOP)
BNX2X_ERR("start of bin not in stop [%d]\n", queue);
/* Try to map an empty data buffer from the aggregation info */
mapping = dma_map_single(&bp->pdev->dev,
first_buf->data + NET_SKB_PAD,
fp->rx_buf_size, DMA_FROM_DEVICE); /* * ...if it fails - move the skb from the consumer to the producer * and set the current aggregation state as ERROR to drop it * when TPA_STOP arrives.
*/
if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) { /* Move the BD from the consumer to the producer */
bnx2x_reuse_rx_data(fp, cons, prod);
tpa_info->tpa_state = BNX2X_TPA_ERROR; return;
}
/* move empty data from pool to prod */
prod_rx_buf->data = first_buf->data;
dma_unmap_addr_set(prod_rx_buf, mapping, mapping); /* point prod_bd to new data */
prod_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
prod_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
/* move partial skb from cons to pool (don't unmap yet) */
*first_buf = *cons_rx_buf;
/* mark bin state as START */
tpa_info->parsing_flags =
le16_to_cpu(cqe->pars_flags.flags);
tpa_info->vlan_tag = le16_to_cpu(cqe->vlan_tag);
tpa_info->tpa_state = BNX2X_TPA_START;
tpa_info->len_on_bd = le16_to_cpu(cqe->len_on_bd);
tpa_info->placement_offset = cqe->placement_offset;
tpa_info->rxhash = bnx2x_get_rxhash(bp, cqe, &tpa_info->rxhash_type); if (fp->mode == TPA_MODE_GRO) {
u16 gro_size = le16_to_cpu(cqe->pkt_len_or_gro_seg_len);
tpa_info->full_page = SGE_PAGES / gro_size * gro_size;
tpa_info->gro_size = gro_size;
}
/* Timestamp option length allowed for TPA aggregation: * * nop nop kind length echo val
*/ #define TPA_TSTAMP_OPT_LEN 12 /** * bnx2x_set_gro_params - compute GRO values * * @skb: packet skb * @parsing_flags: parsing flags from the START CQE * @len_on_bd: total length of the first packet for the * aggregation. * @pkt_len: length of all segments * @num_of_coalesced_segs: count of segments * * Approximate value of the MSS for this aggregation calculated using * the first packet of it. * Compute number of aggregated segments, and gso_type.
*/ staticvoid bnx2x_set_gro_params(struct sk_buff *skb, u16 parsing_flags,
u16 len_on_bd, unsignedint pkt_len,
u16 num_of_coalesced_segs)
{ /* TPA aggregation won't have either IP options or TCP options * other than timestamp or IPv6 extension headers.
*/
u16 hdrs_len = ETH_HLEN + sizeof(struct tcphdr);
/* Check if there was a TCP timestamp, if there is it's will * always be 12 bytes length: nop nop kind length echo val. * * Otherwise FW would close the aggregation.
*/ if (parsing_flags & PARSING_FLAGS_TIME_STAMP_EXIST_FLAG)
hdrs_len += TPA_TSTAMP_OPT_LEN;
skb_shinfo(skb)->gso_size = len_on_bd - hdrs_len;
/* tcp_gro_complete() will copy NAPI_GRO_CB(skb)->count * to skb_shinfo(skb)->gso_segs
*/
NAPI_GRO_CB(skb)->count = num_of_coalesced_segs;
}
/* This is needed in order to enable forwarding support */ if (frag_size)
bnx2x_set_gro_params(skb, tpa_info->parsing_flags, len_on_bd,
le16_to_cpu(cqe->pkt_len),
le16_to_cpu(cqe->num_of_coalesced_segs));
#ifdef BNX2X_STOP_ON_ERROR if (pages > min_t(u32, 8, MAX_SKB_FRAGS) * SGE_PAGES) {
BNX2X_ERR("SGL length is too long: %d. CQE index is %d\n",
pages, cqe_idx);
BNX2X_ERR("cqe->pkt_len = %d\n", cqe->pkt_len);
bnx2x_panic(); return -EINVAL;
} #endif
/* 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(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) */ if (fp->mode == TPA_MODE_GRO)
frag_len = min_t(u32, frag_size, (u32)full_page); else/* LRO */
frag_len = min_t(u32, frag_size, (u32)SGE_PAGES);
/* If we fail to allocate a substitute page, we simply stop
where we are and drop the whole packet */
err = bnx2x_alloc_rx_sge(bp, fp, sge_idx, GFP_ATOMIC); if (unlikely(err)) {
bnx2x_fp_qstats(bp, fp)->rx_skb_alloc_failed++; return err;
}
dma_unmap_page(&bp->pdev->dev,
dma_unmap_addr(&old_rx_pg, mapping),
SGE_PAGE_SIZE, DMA_FROM_DEVICE); /* Add one frag and update the appropriate fields in the skb */ if (fp->mode == TPA_MODE_LRO)
skb_fill_page_desc(skb, j, old_rx_pg.page,
old_rx_pg.offset, frag_len); else { /* GRO */ int rem; int offset = 0; for (rem = frag_len; rem > 0; rem -= gro_size) { int len = rem > gro_size ? gro_size : rem;
skb_fill_page_desc(skb, frag_id++,
old_rx_pg.page,
old_rx_pg.offset + offset,
len); if (offset)
get_page(old_rx_pg.page);
offset += len;
}
}
staticvoid *bnx2x_frag_alloc(conststruct bnx2x_fastpath *fp, gfp_t gfp_mask)
{ if (fp->rx_frag_size) { /* GFP_KERNEL allocations are used only during initialization */ if (unlikely(gfpflags_allow_blocking(gfp_mask))) return (void *)__get_free_page(gfp_mask);
/* If we there was an error during the handling of the TPA_START - * drop this aggregation.
*/ if (old_tpa_state == BNX2X_TPA_ERROR) goto drop;
/* Try to allocate the new data */
new_data = bnx2x_frag_alloc(fp, GFP_ATOMIC); /* Unmap skb in the pool anyway, as we are going to change pool entry status to BNX2X_TPA_STOP even if new skb allocation
fails. */
dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
fp->rx_buf_size, DMA_FROM_DEVICE); if (likely(new_data))
skb = bnx2x_build_skb(fp, data);
if (likely(skb)) { #ifdef BNX2X_STOP_ON_ERROR if (pad + len > fp->rx_buf_size) {
BNX2X_ERR("skb_put is about to fail... pad %d len %d rx_buf_size %d\n",
pad, len, fp->rx_buf_size);
bnx2x_panic();
bnx2x_frag_free(fp, new_data); return;
} #endif
skb_reserve(skb, pad + NET_SKB_PAD);
skb_put(skb, len);
skb_set_hash(skb, tpa_info->rxhash, tpa_info->rxhash_type);
if (!bnx2x_fill_frag_skb(bp, fp, tpa_info, pages,
skb, cqe, cqe_idx)) { if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tpa_info->vlan_tag);
bnx2x_gro_receive(bp, fp, skb);
} else {
DP(NETIF_MSG_RX_STATUS, "Failed to allocate new pages - dropping packet!\n");
dev_kfree_skb_any(skb);
}
/* put new data in bin */
rx_buf->data = new_data;
return;
} if (new_data)
bnx2x_frag_free(fp, new_data);
drop: /* drop the packet and keep the buffer in the bin */
DP(NETIF_MSG_RX_STATUS, "Failed to allocate or map a new skb - dropping packet!\n");
bnx2x_fp_stats(bp, fp)->eth_q_stats.rx_skb_alloc_failed++;
}
static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, struct bnx2x_fastpath *fp, struct bnx2x_eth_q_stats *qstats)
{ /* Do nothing if no L4 csum validation was done. * We do not check whether IP csum was validated. For IPv4 we assume * that if the card got as far as validating the L4 csum, it also * validated the IP csum. IPv6 has no IP csum.
*/ if (cqe->fast_path_cqe.status_flags &
ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) return;
/* If L4 validation was done, check if an error was found. */
/* A rmb() is required to ensure that the CQE is not read * before it is written by the adapter DMA. PCI ordering * rules will make sure the other fields are written before * the marker at the end of struct eth_fast_path_rx_cqe * but without rmb() a weakly ordered processor can process * stale data. Without the barrier TPA state-machine might * enter inconsistent state and kernel stack might be * provided with incorrect packet description - these lead * to various kernel crashed.
*/
rmb();
/* Set Toeplitz hash for a none-LRO skb */
rxhash = bnx2x_get_rxhash(bp, cqe_fp, &rxhash_type);
skb_set_hash(skb, rxhash, rxhash_type);
skb_checksum_none_assert(skb);
if (bp->dev->features & NETIF_F_RXCSUM)
bnx2x_csum_validate(skb, cqe, fp,
bnx2x_fp_qstats(bp, fp));
skb_record_rx_queue(skb, fp->rx_queue);
/* Check if this packet was timestamped */ if (unlikely(cqe->fast_path_cqe.type_error_flags &
(1 << ETH_FAST_PATH_RX_CQE_PTP_PKT_SHIFT)))
bnx2x_set_rx_ts(bp, skb);
if (le16_to_cpu(cqe_fp->pars_flags.flags) &
PARSING_FLAGS_VLAN)
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
le16_to_cpu(cqe_fp->vlan_tag));
/* calculates MF speed according to current linespeed and MF configuration */
u16 bnx2x_get_mf_speed(struct bnx2x *bp)
{
u16 line_speed = bp->link_vars.line_speed; if (IS_MF(bp)) {
u16 maxCfg = bnx2x_extract_max_cfg(bp,
bp->mf_config[BP_VN(bp)]);
/* Calculate the current MAX line speed limit for the MF * devices
*/ if (IS_MF_PERCENT_BW(bp))
line_speed = (line_speed * maxCfg) / 100; else { /* SD mode */
u16 vn_max_rate = maxCfg * 100;
if (vn_max_rate < line_speed)
line_speed = vn_max_rate;
}
}
return line_speed;
}
/** * bnx2x_fill_report_data - fill link report data to report * * @bp: driver handle * @data: link state to update * * It uses a none-atomic bit operations because is called under the mutex.
*/ staticvoid bnx2x_fill_report_data(struct bnx2x *bp, struct bnx2x_link_report_data *data)
{
memset(data, 0, sizeof(*data));
if (IS_PF(bp)) { /* Fill the report data: effective line speed */
data->line_speed = bnx2x_get_mf_speed(bp);
/* Link is down */ if (!bp->link_vars.link_up || (bp->flags & MF_FUNC_DIS))
__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
&data->link_report_flags);
if (!BNX2X_NUM_ETH_QUEUES(bp))
__set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
&data->link_report_flags);
/* Full DUPLEX */ if (bp->link_vars.duplex == DUPLEX_FULL)
__set_bit(BNX2X_LINK_REPORT_FD,
&data->link_report_flags);
/* Rx Flow Control is ON */ if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX)
__set_bit(BNX2X_LINK_REPORT_RX_FC_ON,
&data->link_report_flags);
/* Tx Flow Control is ON */ if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
__set_bit(BNX2X_LINK_REPORT_TX_FC_ON,
&data->link_report_flags);
} else { /* VF */
*data = bp->vf_link_vars;
}
}
/** * bnx2x_link_report - report link status to OS. * * @bp: driver handle * * Calls the __bnx2x_link_report() under the same locking scheme * as a link/PHY state managing code to ensure a consistent link * reporting.
*/
/** * __bnx2x_link_report - report link status to OS. * * @bp: driver handle * * None atomic implementation. * Should be called under the phy_lock.
*/ void __bnx2x_link_report(struct bnx2x *bp)
{ struct bnx2x_link_report_data cur_data;
if (bp->force_link_down) {
bp->link_vars.link_up = 0; return;
}
/* reread mf_cfg */ if (IS_PF(bp) && !CHIP_IS_E1(bp))
bnx2x_read_mf_cfg(bp);
/* Read the current link report info */
bnx2x_fill_report_data(bp, &cur_data);
/* Don't report link down or exactly the same link status twice */ if (!memcmp(&cur_data, &bp->last_reported_link, sizeof(cur_data)) ||
(test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
&bp->last_reported_link.link_report_flags) &&
test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
&cur_data.link_report_flags))) return;
bp->link_cnt++;
/* We are going to report a new link parameters now - * remember the current data for the next time.
*/
memcpy(&bp->last_reported_link, &cur_data, sizeof(cur_data));
/* propagate status to VFs */ if (IS_PF(bp))
bnx2x_iov_link_update(bp);
if (test_bit(BNX2X_LINK_REPORT_LINK_DOWN,
&cur_data.link_report_flags)) {
netif_carrier_off(bp->dev);
netdev_err(bp->dev, "NIC Link is Down\n"); return;
} else { constchar *duplex; constchar *flow;
netif_carrier_on(bp->dev);
if (test_and_clear_bit(BNX2X_LINK_REPORT_FD,
&cur_data.link_report_flags))
duplex = "full"; else
duplex = "half";
/* Handle the FC at the end so that only these flags would be * possibly set. This way we may easily check if there is no FC * enabled.
*/ if (cur_data.link_report_flags) { if (test_bit(BNX2X_LINK_REPORT_RX_FC_ON,
&cur_data.link_report_flags)) { if (test_bit(BNX2X_LINK_REPORT_TX_FC_ON,
&cur_data.link_report_flags))
flow = "ON - receive & transmit"; else
flow = "ON - receive";
} else {
flow = "ON - transmit";
}
} else {
flow = "none";
}
netdev_info(bp->dev, "NIC Link is Up, %d Mbps %s duplex, Flow control: %s\n",
cur_data.line_speed, duplex, flow);
}
}
staticvoid bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
{ int i;
for (i = 1; i <= NUM_RX_SGE_PAGES; i++) { struct eth_rx_sge *sge;
/* Activate BD ring */ /* 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);
u16 ring_prod; int i, j;
if (fp->mode != TPA_MODE_DISABLED) { /* Fill the per-aggregation pool */ for (i = 0; i < MAX_AGG_QS(bp); i++) { struct bnx2x_agg_info *tpa_info =
&fp->tpa_info[i]; struct sw_rx_bd *first_buf =
&tpa_info->first_buf;
first_buf->data =
bnx2x_frag_alloc(fp, GFP_KERNEL); if (!first_buf->data) {
BNX2X_ERR("Failed to allocate TPA skb pool for queue[%d] - disabling TPA on this queue!\n",
j);
bnx2x_free_tpa_pool(bp, fp, i);
fp->mode = TPA_MODE_DISABLED; break;
}
dma_unmap_addr_set(first_buf, mapping, 0);
tpa_info->tpa_state = 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,
GFP_KERNEL) < 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_QS(bp));
fp->mode = TPA_MODE_DISABLED;
ring_prod = 0; break;
}
ring_prod = NEXT_SGE_IDX(ring_prod);
}
/* Activate BD ring */ /* 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);
/** * bnx2x_free_msix_irqs - free previously requested MSI-X IRQ vectors * * @bp: driver handle * @nvecs: number of vectors to be released
*/ staticvoid bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
{ int i, offset = 0;
if (nvecs == offset) return;
/* VFs don't have a default SB */ if (IS_PF(bp)) {
free_irq(bp->msix_table[offset].vector, bp->dev);
DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
bp->msix_table[offset].vector);
offset++;
}
if (CNIC_SUPPORT(bp)) { if (nvecs == offset) return;
offset++;
}
for_each_eth_queue(bp, i) { if (nvecs == offset) return;
DP(NETIF_MSG_IFDOWN, "about to release fp #%d->%d irq\n",
i, bp->msix_table[offset].vector);
int bnx2x_enable_msix(struct bnx2x *bp)
{ int msix_vec = 0, i, rc;
/* VFs don't have a default status block */ if (IS_PF(bp)) {
bp->msix_table[msix_vec].entry = msix_vec;
BNX2X_DEV_INFO("msix_table[0].entry = %d (slowpath)\n",
bp->msix_table[0].entry);
msix_vec++;
}
/* Cnic requires an msix vector for itself */ if (CNIC_SUPPORT(bp)) {
bp->msix_table[msix_vec].entry = msix_vec;
BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
msix_vec, bp->msix_table[msix_vec].entry);
msix_vec++;
}
/* We need separate vectors for ETH queues only (not FCoE) */
for_each_eth_queue(bp, i) {
bp->msix_table[msix_vec].entry = msix_vec;
BNX2X_DEV_INFO("msix_table[%d].entry = %d (fastpath #%u)\n",
msix_vec, msix_vec, i);
msix_vec++;
}
DP(BNX2X_MSG_SP, "about to request enable msix with %d vectors\n",
msix_vec);
rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0],
BNX2X_MIN_MSIX_VEC_CNT(bp), msix_vec); /* * reconfigure number of tx/rx queues according to available * MSI-X vectors
*/ if (rc == -ENOSPC) { /* Get by with single vector */
rc = pci_enable_msix_range(bp->pdev, &bp->msix_table[0], 1, 1); if (rc < 0) {
BNX2X_DEV_INFO("Single MSI-X is not attainable rc %d\n",
rc); goto no_msix;
}
BNX2X_DEV_INFO("Using single MSI-X vector\n");
bp->flags |= USING_SINGLE_MSIX_FLAG;
BNX2X_DEV_INFO("set number of queues to 1\n");
bp->num_ethernet_queues = 1;
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
} elseif (rc < 0) {
BNX2X_DEV_INFO("MSI-X is not attainable rc %d\n", rc); goto no_msix;
} elseif (rc < msix_vec) { /* how less vectors we will have? */ int diff = msix_vec - rc;
BNX2X_DEV_INFO("Trying to use less MSI-X vectors: %d\n", rc);
/* * decrease number of queues by number of unallocated entries
*/
bp->num_ethernet_queues -= diff;
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
/* override in STORAGE SD modes */ if (IS_MF_STORAGE_ONLY(bp))
bp->num_ethernet_queues = 1;
/* Add special queues */
bp->num_cnic_queues = CNIC_SUPPORT(bp); /* For FCOE */
bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
}
/** * bnx2x_set_real_num_queues - configure netdev->real_num_[tx,rx]_queues * * @bp: Driver handle * @include_cnic: handle cnic case * * We currently support for at most 16 Tx queues for each CoS thus we will * allocate a multiple of 16 for ETH L2 rings according to the value of the * bp->max_cos. * * If there is an FCoE L2 queue the appropriate Tx queue will have the next * index after all ETH L2 indices. * * If the actual number of Tx queues (for each CoS) is less than 16 then there * will be the holes at the end of each group of 16 ETh L2 indices (0..15, * 16..31,...) with indices that are not coupled with any real Tx queue. * * The proper configuration of skb->queue_mapping is handled by * bnx2x_select_queue() and __skb_tx_hash(). * * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash() * will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
*/ staticint bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic)
{ int rc, tx, rx;
/* account for fcoe queue */ if (include_cnic && !NO_FCOE(bp)) {
rx++;
tx++;
}
rc = netif_set_real_num_tx_queues(bp->dev, tx); if (rc) {
BNX2X_ERR("Failed to set real number of Tx queues: %d\n", rc); return rc;
}
rc = netif_set_real_num_rx_queues(bp->dev, rx); if (rc) {
BNX2X_ERR("Failed to set real number of Rx queues: %d\n", rc); return rc;
}
DP(NETIF_MSG_IFUP, "Setting real num queues to (tx, rx) (%d, %d)\n",
tx, rx);
return rc;
}
staticvoid bnx2x_set_rx_buf_size(struct bnx2x *bp)
{ int i;
/* Always use a mini-jumbo MTU for the FCoE L2 ring */ if (IS_FCOE_IDX(i)) /* * Although there are no IP frames expected to arrive to * this ring we still want to add an * IP_HEADER_ALIGNMENT_PADDING to prevent a buffer * overrun attack.
*/
mtu = BNX2X_FCOE_MINI_JUMBO_MTU; else
mtu = bp->dev->mtu;
fp->rx_buf_size = BNX2X_FW_RX_ALIGN_START +
IP_HEADER_ALIGNMENT_PADDING +
ETH_OVERHEAD +
mtu +
BNX2X_FW_RX_ALIGN_END;
fp->rx_buf_size = SKB_DATA_ALIGN(fp->rx_buf_size); /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */ if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE)
fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD; else
fp->rx_frag_size = 0;
}
}
/* Prepare the initial contents for the indirection table if RSS is * enabled
*/ for (i = 0; i < sizeof(bp->rss_conf_obj.ind_table); i++)
bp->rss_conf_obj.ind_table[i] =
bp->fp->cl_id +
ethtool_rxfh_indir_default(i, num_eth_queues);
/* * For 57710 and 57711 SEARCHER configuration (rss_keys) is * per-port, so if explicit configuration is needed , do it only * for a PMF. * * For 57712 and newer on the other hand it's a per-function * configuration.
*/ return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp));
}
/* Although RSS is meaningless when there is a single HW queue we * still need it enabled in order to have HW Rx hash generated. * * if (!is_eth_multi(bp)) * bp->multi_mode = ETH_RSS_MODE_DISABLED;
*/
if (enable) {
__set_bit(BNX2X_RSS_MODE_REGULAR, ¶ms.rss_flags);
/* RSS configuration */
__set_bit(BNX2X_RSS_IPV4, ¶ms.rss_flags);
__set_bit(BNX2X_RSS_IPV4_TCP, ¶ms.rss_flags);
__set_bit(BNX2X_RSS_IPV6, ¶ms.rss_flags);
__set_bit(BNX2X_RSS_IPV6_TCP, ¶ms.rss_flags); if (rss_obj->udp_rss_v4)
__set_bit(BNX2X_RSS_IPV4_UDP, ¶ms.rss_flags); if (rss_obj->udp_rss_v6)
__set_bit(BNX2X_RSS_IPV6_UDP, ¶ms.rss_flags);
if (!CHIP_IS_E1x(bp)) { /* valid only for TUNN_MODE_VXLAN tunnel mode */
__set_bit(BNX2X_RSS_IPV4_VXLAN, ¶ms.rss_flags);
__set_bit(BNX2X_RSS_IPV6_VXLAN, ¶ms.rss_flags);
/* valid only for TUNN_MODE_GRE tunnel mode */
__set_bit(BNX2X_RSS_TUNN_INNER_HDRS, ¶ms.rss_flags);
}
} else {
__set_bit(BNX2X_RSS_MODE_DISABLED, ¶ms.rss_flags);
}
/* * Cleans the object that have internal lists without sending * ramrods. Should be run when interrupts are disabled.
*/ void bnx2x_squeeze_objects(struct bnx2x *bp)
{ int rc; unsignedlong ramrod_flags = 0, vlan_mac_flags = 0; struct bnx2x_mcast_ramrod_params rparam = {NULL}; struct bnx2x_vlan_mac_obj *mac_obj = &bp->sp_objs->mac_obj;
/***************** Cleanup MACs' object first *************************/
/* Wait for completion of requested */
__set_bit(RAMROD_COMP_WAIT, &ramrod_flags); /* Perform a dry cleanup */
__set_bit(RAMROD_DRV_CLR_ONLY, &ramrod_flags);
/* Clean ETH primary MAC */
__set_bit(BNX2X_ETH_MAC, &vlan_mac_flags);
rc = mac_obj->delete_all(bp, &bp->sp_objs->mac_obj, &vlan_mac_flags,
&ramrod_flags); if (rc != 0)
BNX2X_ERR("Failed to clean ETH MACs: %d\n", rc);
/* Cleanup UC list */
vlan_mac_flags = 0;
__set_bit(BNX2X_UC_LIST_MAC, &vlan_mac_flags);
rc = mac_obj->delete_all(bp, mac_obj, &vlan_mac_flags,
&ramrod_flags); if (rc != 0)
BNX2X_ERR("Failed to clean UC list MACs: %d\n", rc);
/* Add a DEL command... - Since we're doing a driver cleanup only, * we take a lock surrounding both the initial send and the CONTs, * as we don't want a true completion to disrupt us in the middle.
*/
netif_addr_lock_bh(bp->dev);
rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL); if (rc < 0)
BNX2X_ERR("Failed to add a new DEL command to a multi-cast object: %d\n",
rc);
/* ...and wait until all pending commands are cleared */
rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_CONT); while (rc != 0) { if (rc < 0) {
BNX2X_ERR("Failed to clean multi-cast object: %d\n",
rc);
netif_addr_unlock_bh(bp->dev); return;
}
staticint bnx2x_alloc_fw_stats_mem(struct bnx2x *bp)
{ int num_groups, vf_headroom = 0; int is_fcoe_stats = NO_FCOE(bp) ? 0 : 1;
/* number of queues for statistics is number of eth queues + FCoE */
u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp) + is_fcoe_stats;
/* Total number of FW statistics requests = * 1 for port stats + 1 for PF stats + potential 2 for FCoE (fcoe proper * and fcoe l2 queue) stats + num of queues (which includes another 1 * for fcoe l2 queue if applicable)
*/
bp->fw_stats_num = 2 + is_fcoe_stats + num_queue_stats;
/* vf stats appear in the request list, but their data is allocated by * the VFs themselves. We don't include them in the bp->fw_stats_num as * it is used to determine where to place the vf stats queries in the * request struct
*/ if (IS_SRIOV(bp))
vf_headroom = bnx2x_vf_headroom(bp);
/* Request is built from stats_query_header and an array of * stats_query_cmd_group each of which contains * STATS_QUERY_CMD_COUNT rules. The real number or requests is * configured in the stats_query_header.
*/
num_groups =
(((bp->fw_stats_num + vf_headroom) / STATS_QUERY_CMD_COUNT) +
(((bp->fw_stats_num + vf_headroom) % STATS_QUERY_CMD_COUNT) ?
1 : 0));
/* Data for statistics requests + stats_counter * stats_counter holds per-STORM counters that are incremented * when STORM has finished with the current request. * memory for FCoE offloaded statistics are counted anyway, * even if they will not be sent. * VF stats are not accounted for here as the data of VF stats is stored * in memory allocated by the VF, not here.
*/
bp->fw_stats_data_sz = sizeof(struct per_port_stats) + sizeof(struct per_pf_stats) + sizeof(struct fcoe_statistics_params) + sizeof(struct per_queue_stats) * num_queue_stats + sizeof(struct stats_counter);
bp->fw_stats = BNX2X_PCI_ALLOC(&bp->fw_stats_mapping,
bp->fw_stats_data_sz + bp->fw_stats_req_sz); if (!bp->fw_stats) goto alloc_mem_err;
DP(BNX2X_MSG_SP, "statistics request base address set to %x %x\n",
U64_HI(bp->fw_stats_req_mapping),
U64_LO(bp->fw_stats_req_mapping));
DP(BNX2X_MSG_SP, "statistics data base address set to %x %x\n",
U64_HI(bp->fw_stats_data_mapping),
U64_LO(bp->fw_stats_data_mapping)); return 0;
/* if mcp fails to respond we must abort */ if (!(*load_code)) {
BNX2X_ERR("MCP response failure, aborting\n"); return -EBUSY;
}
/* If mcp refused (e.g. other port is in diagnostic mode) we * must abort
*/ if ((*load_code) == FW_MSG_CODE_DRV_LOAD_REFUSED) {
BNX2X_ERR("MCP refused load request, aborting\n"); return -EBUSY;
} return 0;
}
/* check whether another PF has already loaded FW to chip. In * virtualized environments a pf from another VM may have already * initialized the device including loading FW
*/ int bnx2x_compare_fw_ver(struct bnx2x *bp, u32 load_code, bool print_err)
{ /* is another pf loaded on this engine? */ if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
load_code != FW_MSG_CODE_DRV_LOAD_COMMON) {
u8 loaded_fw_major, loaded_fw_minor, loaded_fw_rev, loaded_fw_eng;
u32 loaded_fw;
DP(BNX2X_MSG_SP, "loaded fw 0x%x major 0x%x minor 0x%x rev 0x%x eng 0x%x\n",
loaded_fw, loaded_fw_major, loaded_fw_minor, loaded_fw_rev, loaded_fw_eng);
/* abort nic load if version mismatch */ if (loaded_fw_major != BCM_5710_FW_MAJOR_VERSION ||
loaded_fw_minor != BCM_5710_FW_MINOR_VERSION ||
loaded_fw_eng != BCM_5710_FW_ENGINEERING_VERSION ||
loaded_fw_rev < BCM_5710_FW_REVISION_VERSION_V15) { if (print_err)
BNX2X_ERR("loaded FW incompatible. Aborting\n"); else
BNX2X_DEV_INFO("loaded FW incompatible, possibly due to MF UNDI\n");
return -EBUSY;
}
} return 0;
}
/* returns the "mcp load_code" according to global load_count array */ staticint bnx2x_nic_load_no_mcp(struct bnx2x *bp, int port)
{ int path = BP_PATH(bp);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.