/* bnx2x_main.c: Broadcom Everest network driver.
*
- * Copyright (c) 2007-2009 Broadcom Corporation
+ * Copyright (c) 2007-2010 Broadcom Corporation
*
* 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
#include <linux/prefetch.h>
#include <linux/zlib.h>
#include <linux/io.h>
+#include <linux/stringify.h>
#include "bnx2x.h"
#include "bnx2x_init_ops.h"
#include "bnx2x_dump.h"
-#define DRV_MODULE_VERSION "1.52.1"
-#define DRV_MODULE_RELDATE "2009/08/12"
+#define DRV_MODULE_VERSION "1.52.1-7"
+#define DRV_MODULE_RELDATE "2010/02/28"
#define BNX2X_BC_VER 0x040200
#include <linux/firmware.h>
#include "bnx2x_fw_file_hdr.h"
/* FW files */
-#define FW_FILE_PREFIX_E1 "bnx2x-e1-"
-#define FW_FILE_PREFIX_E1H "bnx2x-e1h-"
+#define FW_FILE_VERSION \
+ __stringify(BCM_5710_FW_MAJOR_VERSION) "." \
+ __stringify(BCM_5710_FW_MINOR_VERSION) "." \
+ __stringify(BCM_5710_FW_REVISION_VERSION) "." \
+ __stringify(BCM_5710_FW_ENGINEERING_VERSION)
+#define FW_FILE_NAME_E1 "bnx2x-e1-" FW_FILE_VERSION ".fw"
+#define FW_FILE_NAME_E1H "bnx2x-e1h-" FW_FILE_VERSION ".fw"
/* Time in jiffies before concluding the transmitter is hung */
#define TX_TIMEOUT (5*HZ)
MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710/57711/57711E Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_FIRMWARE(FW_FILE_NAME_E1);
+MODULE_FIRMWARE(FW_FILE_NAME_E1H);
static int multi_mode = 1;
module_param(multi_mode, int, 0);
MODULE_PARM_DESC(multi_mode, " Multi queue mode "
"(0 Disable; 1 Enable (default))");
-static int num_rx_queues;
-module_param(num_rx_queues, int, 0);
-MODULE_PARM_DESC(num_rx_queues, " Number of Rx queues for multi_mode=1"
- " (default is half number of CPUs)");
-
-static int num_tx_queues;
-module_param(num_tx_queues, int, 0);
-MODULE_PARM_DESC(num_tx_queues, " Number of Tx queues for multi_mode=1"
- " (default is half number of CPUs)");
+static int num_queues;
+module_param(num_queues, int, 0);
+MODULE_PARM_DESC(num_queues, " Number of queues for multi_mode=1"
+ " (default is as a number of CPUs)");
static int disable_tpa;
module_param(disable_tpa, int, 0);
};
-static const struct pci_device_id bnx2x_pci_tbl[] = {
+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 },
{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711E), BCM57711E },
mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104);
mark = ((mark + 0x3) & ~0x3);
- printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark);
+ pr_err("begin fw dump (mark 0x%x)\n", mark);
- printk(KERN_ERR PFX);
+ pr_err("");
for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) {
for (word = 0; word < 8; word++)
data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
offset + 4*word));
data[8] = 0x0;
- printk(KERN_CONT "%s", (char *)data);
+ pr_cont("%s", (char *)data);
}
for (offset = 0xF108; offset <= mark - 0x08000000; offset += 0x8*4) {
for (word = 0; word < 8; word++)
data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
offset + 4*word));
data[8] = 0x0;
- printk(KERN_CONT "%s", (char *)data);
+ pr_cont("%s", (char *)data);
}
- printk(KERN_ERR PFX "end of fw dump\n");
+ pr_err("end of fw dump\n");
}
static void bnx2x_panic_dump(struct bnx2x *bp)
bp->def_att_idx, bp->attn_state, bp->spq_prod_idx);
/* Rx */
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
BNX2X_ERR("fp%d: rx_bd_prod(%x) rx_bd_cons(%x)"
}
/* Tx */
- for_each_tx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
BNX2X_ERR("fp%d: tx_pkt_prod(%x) tx_pkt_cons(%x)"
/* Rings */
/* Rx */
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10);
}
/* Tx */
- for_each_tx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
start = TX_BD(le16_to_cpu(*fp->tx_cons_sb) - 10);
barrier();
}
-static inline u16 bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
+static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
{
struct host_status_block *fpsb = fp->status_blk;
- u16 rc = 0;
barrier(); /* status block is written to by the chip */
- if (fp->fp_c_idx != fpsb->c_status_block.status_block_index) {
- fp->fp_c_idx = fpsb->c_status_block.status_block_index;
- rc |= 1;
- }
- if (fp->fp_u_idx != fpsb->u_status_block.status_block_index) {
- fp->fp_u_idx = fpsb->u_status_block.status_block_index;
- rc |= 2;
- }
- return rc;
+ fp->fp_c_idx = fpsb->c_status_block.status_block_index;
+ fp->fp_u_idx = fpsb->u_status_block.status_block_index;
}
static u16 bnx2x_ack_int(struct bnx2x *bp)
u16 bd_idx = TX_BD(tx_buf->first_bd), new_cons;
int nbd;
+ /* prefetch skb end pointer to speedup dev_kfree_skb() */
+ prefetch(&skb->end);
+
DP(BNX2X_MSG_OFF, "pkt_idx %d buff @(%p)->skb %p\n",
idx, tx_buf, skb);
/* release skb */
WARN_ON(!skb);
- dev_kfree_skb_any(skb);
+ dev_kfree_skb(skb);
tx_buf->first_bd = 0;
tx_buf->skb = NULL;
u16 prod;
u16 cons;
- barrier(); /* Tell compiler that prod and cons can change */
prod = fp->tx_bd_prod;
cons = fp->tx_bd_cons;
return (s16)(fp->bp->tx_ring_size) - used;
}
-static void bnx2x_tx_int(struct bnx2x_fastpath *fp)
+static inline int bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
+{
+ u16 hw_cons;
+
+ /* Tell compiler that status block fields can change */
+ barrier();
+ hw_cons = le16_to_cpu(*fp->tx_cons_sb);
+ return hw_cons != fp->tx_pkt_cons;
+}
+
+static int bnx2x_tx_int(struct bnx2x_fastpath *fp)
{
struct bnx2x *bp = fp->bp;
struct netdev_queue *txq;
u16 hw_cons, sw_cons, bd_cons = fp->tx_bd_cons;
- int done = 0;
#ifdef BNX2X_STOP_ON_ERROR
if (unlikely(bp->panic))
- return;
+ return -1;
#endif
- txq = netdev_get_tx_queue(bp->dev, fp->index - bp->num_rx_queues);
+ txq = netdev_get_tx_queue(bp->dev, fp->index);
hw_cons = le16_to_cpu(*fp->tx_cons_sb);
sw_cons = fp->tx_pkt_cons;
*/
bd_cons = bnx2x_free_tx_pkt(bp, fp, pkt_cons);
sw_cons++;
- done++;
}
fp->tx_pkt_cons = sw_cons;
fp->tx_bd_cons = bd_cons;
+ /* 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.
+ */
+ smp_mb();
+
/* TBD need a thresh? */
if (unlikely(netif_tx_queue_stopped(txq))) {
-
- /* 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.
+ /* Taking tx_lock() is needed to prevent reenabling 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
*/
- smp_mb();
+
+ __netif_tx_lock(txq, smp_processor_id());
if ((netif_tx_queue_stopped(txq)) &&
(bp->state == BNX2X_STATE_OPEN) &&
(bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3))
netif_tx_wake_queue(txq);
+
+ __netif_tx_unlock(txq);
}
+ return 0;
}
#ifdef BCM_CNIC
} else {
rx_buf = &fp->rx_buf_ring[bd_cons];
skb = rx_buf->skb;
+ prefetch(skb);
+ prefetch((u8 *)skb + 256);
len = le16_to_cpu(cqe->fast_path_cqe.pkt_len);
pad = cqe->fast_path_cqe.placement_offset;
if (unlikely(bp->panic))
return IRQ_HANDLED;
#endif
- /* Handle Rx or Tx according to MSI-X vector */
- if (fp->is_rx_queue) {
- prefetch(fp->rx_cons_sb);
- prefetch(&fp->status_blk->u_status_block.status_block_index);
- napi_schedule(&bnx2x_fp(bp, fp->index, napi));
-
- } else {
- prefetch(fp->tx_cons_sb);
- prefetch(&fp->status_blk->c_status_block.status_block_index);
-
- bnx2x_update_fpsb_idx(fp);
- rmb();
- bnx2x_tx_int(fp);
-
- /* Re-enable interrupts */
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
- }
+ /* 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);
+ napi_schedule(&bnx2x_fp(bp, fp->index, napi));
return IRQ_HANDLED;
}
mask = 0x2 << fp->sb_id;
if (status & mask) {
- /* Handle Rx or Tx according to SB id */
- if (fp->is_rx_queue) {
- prefetch(fp->rx_cons_sb);
- prefetch(&fp->status_blk->u_status_block.
- status_block_index);
-
- napi_schedule(&bnx2x_fp(bp, fp->index, napi));
-
- } else {
- prefetch(fp->tx_cons_sb);
- prefetch(&fp->status_blk->c_status_block.
- status_block_index);
-
- bnx2x_update_fpsb_idx(fp);
- rmb();
- bnx2x_tx_int(fp);
-
- /* Re-enable interrupts */
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx),
- IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx),
- IGU_INT_ENABLE, 1);
- }
+ /* Handle Rx and Tx according to SB id */
+ prefetch(fp->rx_cons_sb);
+ prefetch(&fp->status_blk->u_status_block.
+ status_block_index);
+ prefetch(fp->tx_cons_sb);
+ prefetch(&fp->status_blk->c_status_block.
+ status_block_index);
+ napi_schedule(&bnx2x_fp(bp, fp->index, napi));
status &= ~mask;
}
}
{
if (bp->flags & MF_FUNC_DIS) {
netif_carrier_off(bp->dev);
- printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+ netdev_err(bp->dev, "NIC Link is Down\n");
return;
}
if (bp->link_vars.link_up) {
+ u16 line_speed;
+
if (bp->state == BNX2X_STATE_OPEN)
netif_carrier_on(bp->dev);
- printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name);
+ netdev_info(bp->dev, "NIC Link is Up, ");
- printk("%d Mbps ", bp->link_vars.line_speed);
+ line_speed = bp->link_vars.line_speed;
+ if (IS_E1HMF(bp)) {
+ u16 vn_max_rate;
+
+ vn_max_rate =
+ ((bp->mf_config & FUNC_MF_CFG_MAX_BW_MASK) >>
+ FUNC_MF_CFG_MAX_BW_SHIFT) * 100;
+ if (vn_max_rate < line_speed)
+ line_speed = vn_max_rate;
+ }
+ pr_cont("%d Mbps ", line_speed);
if (bp->link_vars.duplex == DUPLEX_FULL)
- printk("full duplex");
+ pr_cont("full duplex");
else
- printk("half duplex");
+ pr_cont("half duplex");
if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) {
if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) {
- printk(", receive ");
+ pr_cont(", receive ");
if (bp->link_vars.flow_ctrl &
BNX2X_FLOW_CTRL_TX)
- printk("& transmit ");
+ pr_cont("& transmit ");
} else {
- printk(", transmit ");
+ pr_cont(", transmit ");
}
- printk("flow control ON");
+ pr_cont("flow control ON");
}
- printk("\n");
+ pr_cont("\n");
} else { /* link_down */
netif_carrier_off(bp->dev);
- printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+ netdev_err(bp->dev, "NIC Link is Down\n");
}
}
static void bnx2x_e1h_disable(struct bnx2x *bp)
{
int port = BP_PORT(bp);
- int i;
-
- bp->rx_mode = BNX2X_RX_MODE_NONE;
- bnx2x_set_storm_rx_mode(bp);
netif_tx_disable(bp->dev);
- bp->dev->trans_start = jiffies; /* prevent tx timeout */
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
- bnx2x_set_eth_mac_addr_e1h(bp, 0);
-
- for (i = 0; i < MC_HASH_SIZE; i++)
- REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
-
netif_carrier_off(bp->dev);
}
REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 1);
- bnx2x_set_eth_mac_addr_e1h(bp, 1);
-
/* Tx queue should be only reenabled */
netif_tx_wake_all_queues(bp->dev);
- /* Initialize the receive filter. */
- bnx2x_set_rx_mode(bp->dev);
+ /*
+ * Should not call netif_carrier_on since it will be called if the link
+ * is up when checking for link state
+ */
}
static void bnx2x_update_min_max(struct bnx2x *bp)
bp->link_params.ext_phy_config);
/* log the failure */
- printk(KERN_ERR PFX "Fan Failure on Network Controller %s has caused"
- " the driver to shutdown the card to prevent permanent"
- " damage. Please contact Dell Support for assistance\n",
- bp->dev->name);
+ netdev_err(bp->dev, "Fan Failure on Network Controller has caused the driver to shutdown the card to prevent permanent damage.\n"
+ "Please contact Dell Support for assistance.\n");
}
static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn)
estats->no_buff_discard_hi = 0;
estats->no_buff_discard_lo = 0;
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
int cl_id = fp->cl_id;
struct tstorm_per_client_stats *tclient =
nstats->tx_bytes = bnx2x_hilo(&estats->total_bytes_transmitted_hi);
nstats->rx_dropped = estats->mac_discard;
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
nstats->rx_dropped +=
le32_to_cpu(bp->fp[i].old_tclient.checksum_discard);
estats->rx_err_discard_pkt = 0;
estats->rx_skb_alloc_failed = 0;
estats->hw_csum_err = 0;
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_eth_q_stats *qstats = &bp->fp[i].eth_q_stats;
estats->driver_xoff += qstats->driver_xoff;
bnx2x_net_stats_update(bp);
bnx2x_drv_stats_update(bp);
- if (bp->msglevel & NETIF_MSG_TIMER) {
+ if (netif_msg_timer(bp)) {
struct bnx2x_fastpath *fp0_rx = bp->fp;
- struct bnx2x_fastpath *fp0_tx = &(bp->fp[bp->num_rx_queues]);
+ struct bnx2x_fastpath *fp0_tx = bp->fp;
struct tstorm_per_client_stats *old_tclient =
&bp->fp->old_tclient;
struct bnx2x_eth_q_stats *qstats = &bp->fp->eth_q_stats;
struct net_device_stats *nstats = &bp->dev->stats;
int i;
- printk(KERN_DEBUG "%s:\n", bp->dev->name);
+ netdev_printk(KERN_DEBUG, bp->dev, "\n");
printk(KERN_DEBUG " tx avail (%4x) tx hc idx (%x)"
" tx pkt (%lx)\n",
bnx2x_tx_avail(fp0_tx),
/* Make sure the state has been "changed" */
smp_wmb();
- if ((event != STATS_EVENT_UPDATE) || (bp->msglevel & NETIF_MSG_TIMER))
+ if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
state, event, bp->stats_state);
}
REG_WR8(bp, BAR_CSTRORM_INTMEM +
CSTORM_SB_HC_TIMEOUT_U_OFFSET(port, sb_id,
U_SB_ETH_RX_CQ_INDEX),
- bp->rx_ticks/12);
+ bp->rx_ticks/(4 * BNX2X_BTR));
REG_WR16(bp, BAR_CSTRORM_INTMEM +
CSTORM_SB_HC_DISABLE_U_OFFSET(port, sb_id,
U_SB_ETH_RX_CQ_INDEX),
- (bp->rx_ticks/12) ? 0 : 1);
+ (bp->rx_ticks/(4 * BNX2X_BTR)) ? 0 : 1);
/* HC_INDEX_C_ETH_TX_CQ_CONS */
REG_WR8(bp, BAR_CSTRORM_INTMEM +
CSTORM_SB_HC_TIMEOUT_C_OFFSET(port, sb_id,
C_SB_ETH_TX_CQ_INDEX),
- bp->tx_ticks/12);
+ bp->tx_ticks/(4 * BNX2X_BTR));
REG_WR16(bp, BAR_CSTRORM_INTMEM +
CSTORM_SB_HC_DISABLE_C_OFFSET(port, sb_id,
C_SB_ETH_TX_CQ_INDEX),
- (bp->tx_ticks/12) ? 0 : 1);
+ (bp->tx_ticks/(4 * BNX2X_BTR)) ? 0 : 1);
}
}
if (bp->flags & TPA_ENABLE_FLAG) {
- for_each_rx_queue(bp, j) {
+ for_each_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
for (i = 0; i < max_agg_queues; i++) {
}
}
- for_each_rx_queue(bp, j) {
+ for_each_queue(bp, j) {
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;
- /* Mark queue as Rx */
- fp->is_rx_queue = 1;
-
/* "next page" elements initialization */
/* SGE ring */
for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
{
int i, j;
- for_each_tx_queue(bp, j) {
+ for_each_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
for (i = 1; i <= NUM_TX_RINGS; i++) {
fp->tx_cons_sb = BNX2X_TX_SB_INDEX;
fp->tx_pkt = 0;
}
-
- /* clean tx statistics */
- for_each_rx_queue(bp, i)
- bnx2x_fp(bp, i, tx_pkt) = 0;
}
static void bnx2x_init_sp_ring(struct bnx2x *bp)
{
int i;
- for_each_rx_queue(bp, i) {
+ /* Rx */
+ for_each_queue(bp, i) {
struct eth_context *context = bnx2x_sp(bp, context[i].eth);
struct bnx2x_fastpath *fp = &bp->fp[i];
u8 cl_id = fp->cl_id;
ETH_CONNECTION_TYPE);
}
- for_each_tx_queue(bp, i) {
+ /* Tx */
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
struct eth_context *context =
- bnx2x_sp(bp, context[i - bp->num_rx_queues].eth);
+ bnx2x_sp(bp, context[i].eth);
context->cstorm_st_context.sb_index_number =
C_SB_ETH_TX_CQ_INDEX;
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_rx_queues));
+ bp->fp->cl_id + (i % bp->num_queues));
}
static void bnx2x_set_client_config(struct bnx2x *bp)
min((u32)(min((u32)8, (u32)MAX_SKB_FRAGS) *
SGE_PAGE_SIZE * PAGES_PER_SGE),
(u32)0xffff);
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
REG_WR(bp, BAR_USTRORM_INTMEM +
rx_pause.cqe_thr_high = 350;
rx_pause.sge_thr_high = 0;
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
if (!fp->disable_tpa) {
#else
fp->sb_id = fp->cl_id;
#endif
- /* Suitable Rx and Tx SBs are served by the same client */
- if (i >= bp->num_rx_queues)
- fp->cl_id -= bp->num_rx_queues;
DP(NETIF_MSG_IFUP,
"queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d sb %d\n",
i, bp, fp->status_blk, fp->cl_id, fp->sb_id);
bp->gunzip_buf = NULL;
gunzip_nomem1:
- printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for"
- " un-compression\n", bp->dev->name);
+ netdev_err(bp->dev, "Cannot allocate firmware buffer for un-compression\n");
return -ENOMEM;
}
rc = zlib_inflate(bp->strm, Z_FINISH);
if ((rc != Z_OK) && (rc != Z_STREAM_END))
- printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
- bp->dev->name, bp->strm->msg);
+ netdev_err(bp->dev, "Firmware decompression error: %s\n",
+ bp->strm->msg);
bp->gunzip_outlen = (FW_BUF_SIZE - bp->strm->avail_out);
if (bp->gunzip_outlen & 0x3)
- printk(KERN_ERR PFX "%s: Firmware decompression error:"
- " gunzip_outlen (%d) not aligned\n",
- bp->dev->name, bp->gunzip_outlen);
+ netdev_err(bp->dev, "Firmware decompression error: gunzip_outlen (%d) not aligned\n",
+ bp->gunzip_outlen);
bp->gunzip_outlen >>= 2;
zlib_inflateEnd(bp->strm);
if (sizeof(union cdu_context) != 1024)
/* we currently assume that a context is 1024 bytes */
- printk(KERN_ALERT PFX "please adjust the size of"
- " cdu_context(%ld)\n", (long)sizeof(union cdu_context));
+ pr_alert("please adjust the size of cdu_context(%ld)\n",
+ (long)sizeof(union cdu_context));
bnx2x_init_block(bp, CDU_BLOCK, COMMON_STAGE);
val = (4 << 24) + (0 << 12) + 1024;
sizeof(struct host_status_block));
}
/* Rx */
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
/* fastpath rx rings: rx_buf rx_desc rx_comp */
BNX2X_FREE(bnx2x_fp(bp, i, rx_buf_ring));
BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
}
/* Tx */
- for_each_tx_queue(bp, i) {
+ for_each_queue(bp, i) {
/* fastpath tx rings: tx_buf tx_desc */
BNX2X_FREE(bnx2x_fp(bp, i, tx_buf_ring));
sizeof(struct host_status_block));
}
/* Rx */
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
/* fastpath rx rings: rx_buf rx_desc rx_comp */
BNX2X_ALLOC(bnx2x_fp(bp, i, rx_buf_ring),
BCM_PAGE_SIZE * NUM_RX_SGE_PAGES);
}
/* Tx */
- for_each_tx_queue(bp, i) {
+ for_each_queue(bp, i) {
/* fastpath tx rings: tx_buf tx_desc */
BNX2X_ALLOC(bnx2x_fp(bp, i, tx_buf_ring),
{
int i;
- for_each_tx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
u16 bd_cons = fp->tx_bd_cons;
{
int i, j;
- for_each_rx_queue(bp, j) {
+ for_each_queue(bp, j) {
struct bnx2x_fastpath *fp = &bp->fp[j];
for (i = 0; i < NUM_RX_BD; i++) {
}
}
-static void bnx2x_free_irq(struct bnx2x *bp)
+static void bnx2x_free_irq(struct bnx2x *bp, bool disable_only)
{
if (bp->flags & USING_MSIX_FLAG) {
- bnx2x_free_msix_irqs(bp);
+ 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) {
- free_irq(bp->pdev->irq, bp->dev);
+ if (!disable_only)
+ free_irq(bp->pdev->irq, bp->dev);
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
- } else
+ } else if (!disable_only)
free_irq(bp->pdev->irq, bp->dev);
}
#endif
for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
-
- if (i < bp->num_rx_queues)
- sprintf(fp->name, "%s-rx-%d", bp->dev->name, i);
- else
- sprintf(fp->name, "%s-tx-%d",
- bp->dev->name, i - bp->num_rx_queues);
+ snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
+ bp->dev->name, i);
rc = request_irq(bp->msix_table[i + offset].vector,
bnx2x_msix_fp_int, 0, fp->name, fp);
}
i = BNX2X_NUM_QUEUES(bp);
- printk(KERN_INFO PFX "%s: using MSI-X IRQs: sp %d fp[%d] %d"
- " ... fp[%d] %d\n",
- bp->dev->name, bp->msix_table[0].vector,
- 0, bp->msix_table[offset].vector,
- i - 1, bp->msix_table[offset + i - 1].vector);
+ netdev_info(bp->dev, "using MSI-X IRQs: sp %d fp[%d] %d ... fp[%d] %d\n",
+ bp->msix_table[0].vector,
+ 0, bp->msix_table[offset].vector,
+ i - 1, bp->msix_table[offset + i - 1].vector);
return 0;
}
{
int i;
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
napi_enable(&bnx2x_fp(bp, i, napi));
}
{
int i;
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
napi_disable(&bnx2x_fp(bp, i, napi));
}
bnx2x_int_disable_sync(bp, disable_hw);
bnx2x_napi_disable(bp);
netif_tx_disable(bp->dev);
- bp->dev->trans_start = jiffies; /* prevent tx timeout */
}
/*
static int bnx2x_poll(struct napi_struct *napi, int budget);
-static void bnx2x_set_int_mode_msix(struct bnx2x *bp, int *num_rx_queues_out,
- int *num_tx_queues_out)
+static void bnx2x_set_num_queues_msix(struct bnx2x *bp)
{
- int _num_rx_queues = 0, _num_tx_queues = 0;
switch (bp->multi_mode) {
case ETH_RSS_MODE_DISABLED:
- _num_rx_queues = 1;
- _num_tx_queues = 1;
+ bp->num_queues = 1;
break;
case ETH_RSS_MODE_REGULAR:
- if (num_rx_queues)
- _num_rx_queues = min_t(u32, num_rx_queues,
- BNX2X_MAX_QUEUES(bp));
- else
- _num_rx_queues = min_t(u32, num_online_cpus(),
- BNX2X_MAX_QUEUES(bp));
-
- if (num_tx_queues)
- _num_tx_queues = min_t(u32, num_tx_queues,
- BNX2X_MAX_QUEUES(bp));
+ if (num_queues)
+ bp->num_queues = min_t(u32, num_queues,
+ BNX2X_MAX_QUEUES(bp));
else
- _num_tx_queues = min_t(u32, num_online_cpus(),
- BNX2X_MAX_QUEUES(bp));
-
- /* There must be not more Tx queues than Rx queues */
- if (_num_tx_queues > _num_rx_queues) {
- BNX2X_ERR("number of tx queues (%d) > "
- "number of rx queues (%d)"
- " defaulting to %d\n",
- _num_tx_queues, _num_rx_queues,
- _num_rx_queues);
- _num_tx_queues = _num_rx_queues;
- }
+ bp->num_queues = min_t(u32, num_online_cpus(),
+ BNX2X_MAX_QUEUES(bp));
break;
default:
- _num_rx_queues = 1;
- _num_tx_queues = 1;
+ bp->num_queues = 1;
break;
}
-
- *num_rx_queues_out = _num_rx_queues;
- *num_tx_queues_out = _num_tx_queues;
}
-static int bnx2x_set_int_mode(struct bnx2x *bp)
+static int bnx2x_set_num_queues(struct bnx2x *bp)
{
int rc = 0;
switch (int_mode) {
case INT_MODE_INTx:
case INT_MODE_MSI:
- bp->num_rx_queues = 1;
- bp->num_tx_queues = 1;
+ bp->num_queues = 1;
DP(NETIF_MSG_IFUP, "set number of queues to 1\n");
break;
case INT_MODE_MSIX:
default:
- /* Set interrupt mode according to bp->multi_mode value */
- bnx2x_set_int_mode_msix(bp, &bp->num_rx_queues,
- &bp->num_tx_queues);
+ /* 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: rx %d tx %d\n",
- bp->num_rx_queues, bp->num_tx_queues);
+ DP(NETIF_MSG_IFUP, "set number of queues to %d\n",
+ bp->num_queues);
/* 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) {
+ if (rc)
/* failed to enable MSI-X */
- if (bp->multi_mode)
- BNX2X_ERR("Multi requested but failed to "
- "enable MSI-X (rx %d tx %d), "
- "set number of queues to 1\n",
- bp->num_rx_queues, bp->num_tx_queues);
- bp->num_rx_queues = 1;
- bp->num_tx_queues = 1;
- }
+ bp->num_queues = 1;
break;
}
- bp->dev->real_num_tx_queues = bp->num_tx_queues;
+ bp->dev->real_num_tx_queues = bp->num_queues;
return rc;
}
bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
- rc = bnx2x_set_int_mode(bp);
+ rc = bnx2x_set_num_queues(bp);
- if (bnx2x_alloc_mem(bp))
+ if (bnx2x_alloc_mem(bp)) {
+ bnx2x_free_irq(bp, true);
return -ENOMEM;
+ }
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
bnx2x_fp(bp, i, disable_tpa) =
((bp->flags & TPA_ENABLE_FLAG) == 0);
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
bnx2x_poll, 128);
if (bp->flags & USING_MSIX_FLAG) {
rc = bnx2x_req_msix_irqs(bp);
if (rc) {
- pci_disable_msix(bp->pdev);
+ 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_int_mode()) */
+ memory (in bnx2x_set_num_queues()) */
if ((rc != -ENOMEM) && (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);
- if (bp->flags & USING_MSI_FLAG)
- pci_disable_msi(bp->pdev);
+ bnx2x_free_irq(bp, true);
goto load_error1;
}
if (bp->flags & USING_MSI_FLAG) {
bp->dev->irq = bp->pdev->irq;
- printk(KERN_INFO PFX "%s: using MSI IRQ %d\n",
- bp->dev->name, bp->pdev->irq);
+ netdev_info(bp->dev, "using MSI IRQ %d\n",
+ bp->pdev->irq);
}
}
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);
goto load_error2;
}
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);
#endif
bp->port.pmf = 0;
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
- for_each_rx_queue(bp, i)
+ 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);
+ bnx2x_free_irq(bp, false);
load_error1:
bnx2x_napi_disable(bp);
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
bnx2x_free_mem(bp);
bnx2x_stats_handle(bp, STATS_EVENT_STOP);
/* Release IRQs */
- bnx2x_free_irq(bp);
+ bnx2x_free_irq(bp, false);
/* Wait until tx fastpath tasks complete */
- for_each_tx_queue(bp, i) {
+ for_each_queue(bp, i) {
struct bnx2x_fastpath *fp = &bp->fp[i];
cnt = 1000;
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
bnx2x_free_mem(bp);
val3 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[8]);
val4 = SHMEM_RD(bp, dev_info.shared_hw_config.part_num[12]);
- printk(KERN_INFO PFX "part number %X-%X-%X-%X\n",
- val, val2, val3, val4);
+ pr_info("part number %X-%X-%X-%X\n", val, val2, val3, val4);
}
static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
bnx2x_undi_unload(bp);
if (CHIP_REV_IS_FPGA(bp))
- printk(KERN_ERR PFX "FPGA detected\n");
+ pr_err("FPGA detected\n");
if (BP_NOMCP(bp) && (func == 0))
- printk(KERN_ERR PFX
- "MCP disabled, must load devices in order!\n");
+ pr_err("MCP disabled, must load devices in order!\n");
/* Set multi queue mode */
if ((multi_mode != ETH_RSS_MODE_DISABLED) &&
((int_mode == INT_MODE_INTx) || (int_mode == INT_MODE_MSI))) {
- printk(KERN_ERR PFX
- "Multi disabled since int_mode requested is not MSI-X\n");
+ pr_err("Multi disabled since int_mode requested is not MSI-X\n");
multi_mode = ETH_RSS_MODE_DISABLED;
}
bp->multi_mode = multi_mode;
bp->rx_csum = 1;
- bp->tx_ticks = 50;
- bp->rx_ticks = 25;
+ /* make sure that the numbers are in the right granularity */
+ bp->tx_ticks = (50 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR);
+ bp->rx_ticks = (25 / (4 * BNX2X_BTR)) * (4 * BNX2X_BTR);
timer_interval = (CHIP_REV_IS_SLOW(bp) ? 5*HZ : HZ);
bp->current_interval = (poll ? poll : timer_interval);
{
struct bnx2x *bp = netdev_priv(dev);
- return bp->msglevel;
+ return bp->msg_enable;
}
static void bnx2x_set_msglevel(struct net_device *dev, u32 level)
struct bnx2x *bp = netdev_priv(dev);
if (capable(CAP_NET_ADMIN))
- bp->msglevel = level;
+ bp->msg_enable = level;
}
static int bnx2x_nway_reset(struct net_device *dev)
/* TPA requires Rx CSUM offloading */
if ((data & ETH_FLAG_LRO) && bp->rx_csum) {
- if (!(dev->features & NETIF_F_LRO)) {
- dev->features |= NETIF_F_LRO;
- bp->flags |= TPA_ENABLE_FLAG;
- changed = 1;
- }
-
+ if (!disable_tpa) {
+ if (!(dev->features & NETIF_F_LRO)) {
+ dev->features |= NETIF_F_LRO;
+ bp->flags |= TPA_ENABLE_FLAG;
+ changed = 1;
+ }
+ } else
+ rc = -EINVAL;
} else if (dev->features & NETIF_F_LRO) {
dev->features &= ~NETIF_F_LRO;
bp->flags &= ~TPA_ENABLE_FLAG;
struct sk_buff *skb;
unsigned char *packet;
struct bnx2x_fastpath *fp_rx = &bp->fp[0];
- struct bnx2x_fastpath *fp_tx = &bp->fp[bp->num_rx_queues];
+ struct bnx2x_fastpath *fp_tx = &bp->fp[0];
u16 tx_start_idx, tx_idx;
u16 rx_start_idx, rx_idx;
u16 pkt_prod, bd_prod;
fp_tx->tx_db.data.prod += 2;
barrier();
- DOORBELL(bp, fp_tx->index - bp->num_rx_queues, fp_tx->tx_db.raw);
+ DOORBELL(bp, fp_tx->index, fp_tx->tx_db.raw);
mmiowb();
num_pkts++;
fp_tx->tx_bd_prod += 2; /* start + pbd */
- bp->dev->trans_start = jiffies;
udelay(100);
config->hdr.length = 0;
if (CHIP_IS_E1(bp))
- config->hdr.offset = (BP_PORT(bp) ? 32 : 0);
+ /* use last unicast entries */
+ config->hdr.offset = (BP_PORT(bp) ? 63 : 31);
else
config->hdr.offset = BP_FUNC(bp);
config->hdr.client_id = bp->fp->cl_id;
/* disable input for TX port IF */
REG_WR(bp, NIG_REG_EGRESS_UMP0_IN_EN + port*4, 0);
- link_up = bp->link_vars.link_up;
+ link_up = (bnx2x_link_test(bp) == 0);
bnx2x_nic_unload(bp, UNLOAD_NORMAL);
bnx2x_nic_load(bp, LOAD_DIAG);
/* wait until link state is restored */
((bnx2x_stats_arr[i].flags & STATS_FLAGS_BOTH) == STATS_FLAGS_PORT)
#define IS_FUNC_STAT(i) (bnx2x_stats_arr[i].flags & STATS_FLAGS_FUNC)
#define IS_E1HMF_MODE_STAT(bp) \
- (IS_E1HMF(bp) && !(bp->msglevel & BNX2X_MSG_STATS))
+ (IS_E1HMF(bp) && !(bp->msg_enable & BNX2X_MSG_STATS))
static int bnx2x_get_sset_count(struct net_device *dev, int stringset)
{
switch(stringset) {
case ETH_SS_STATS:
if (is_multi(bp)) {
- num_stats = BNX2X_NUM_Q_STATS * bp->num_rx_queues;
+ num_stats = BNX2X_NUM_Q_STATS * bp->num_queues;
if (!IS_E1HMF_MODE_STAT(bp))
num_stats += BNX2X_NUM_STATS;
} else {
case ETH_SS_STATS:
if (is_multi(bp)) {
k = 0;
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
for (j = 0; j < BNX2X_NUM_Q_STATS; j++)
sprintf(buf + (k + j)*ETH_GSTRING_LEN,
bnx2x_q_stats_arr[j].string, i);
if (is_multi(bp)) {
k = 0;
- for_each_rx_queue(bp, i) {
+ for_each_queue(bp, i) {
hw_stats = (u32 *)&bp->fp[i].eth_q_stats;
for (j = 0; j < BNX2X_NUM_Q_STATS; j++) {
if (bnx2x_q_stats_arr[j].size == 0) {
static int bnx2x_phys_id(struct net_device *dev, u32 data)
{
struct bnx2x *bp = netdev_priv(dev);
- int port = BP_PORT(bp);
int i;
if (!netif_running(dev))
for (i = 0; i < (data * 2); i++) {
if ((i % 2) == 0)
- bnx2x_set_led(bp, port, LED_MODE_OPER, SPEED_1000,
- bp->link_params.hw_led_mode,
- bp->link_params.chip_id);
+ bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
+ SPEED_1000);
else
- bnx2x_set_led(bp, port, LED_MODE_OFF, 0,
- bp->link_params.hw_led_mode,
- bp->link_params.chip_id);
+ bnx2x_set_led(&bp->link_params, LED_MODE_OFF, 0);
msleep_interruptible(500);
if (signal_pending(current))
}
if (bp->link_vars.link_up)
- bnx2x_set_led(bp, port, LED_MODE_OPER,
- bp->link_vars.line_speed,
- bp->link_params.hw_led_mode,
- bp->link_params.chip_id);
+ bnx2x_set_led(&bp->link_params, LED_MODE_OPER,
+ bp->link_vars.line_speed);
return 0;
}
static int bnx2x_poll(struct napi_struct *napi, int budget)
{
+ int work_done = 0;
struct bnx2x_fastpath *fp = container_of(napi, struct bnx2x_fastpath,
napi);
struct bnx2x *bp = fp->bp;
- int work_done = 0;
+ while (1) {
#ifdef BNX2X_STOP_ON_ERROR
- if (unlikely(bp->panic))
- goto poll_panic;
+ if (unlikely(bp->panic)) {
+ napi_complete(napi);
+ return 0;
+ }
#endif
- prefetch(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb);
- prefetch((char *)(fp->rx_buf_ring[RX_BD(fp->rx_bd_cons)].skb) + 256);
-
- bnx2x_update_fpsb_idx(fp);
-
- if (bnx2x_has_rx_work(fp)) {
- work_done = bnx2x_rx_int(fp, budget);
+ if (bnx2x_has_tx_work(fp))
+ bnx2x_tx_int(fp);
- /* must not complete if we consumed full budget */
- if (work_done >= budget)
- goto poll_again;
- }
+ if (bnx2x_has_rx_work(fp)) {
+ work_done += bnx2x_rx_int(fp, budget - work_done);
- /* 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();
+ /* must not complete if we consumed full budget */
+ if (work_done >= budget)
+ break;
+ }
- if (!bnx2x_has_rx_work(fp)) {
-#ifdef BNX2X_STOP_ON_ERROR
-poll_panic:
-#endif
- napi_complete(napi);
+ /* 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.
+ */
+ rmb();
- bnx2x_ack_sb(bp, fp->sb_id, USTORM_ID,
- le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
- bnx2x_ack_sb(bp, fp->sb_id, CSTORM_ID,
- le16_to_cpu(fp->fp_c_idx), IGU_INT_ENABLE, 1);
+ 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),
+ IGU_INT_ENABLE, 1);
+ break;
+ }
+ }
}
-poll_again:
return work_done;
}
}
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
- rc |= XMIT_GSO_V4;
+ rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP);
else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
- rc |= XMIT_GSO_V6;
+ rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6);
return rc;
}
static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
- struct bnx2x_fastpath *fp, *fp_stat;
+ struct bnx2x_fastpath *fp;
struct netdev_queue *txq;
struct sw_tx_bd *tx_buf;
struct eth_tx_start_bd *tx_start_bd;
fp_index = skb_get_queue_mapping(skb);
txq = netdev_get_tx_queue(dev, fp_index);
- fp = &bp->fp[fp_index + bp->num_rx_queues];
- fp_stat = &bp->fp[fp_index];
+ fp = &bp->fp[fp_index];
if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) {
- fp_stat->eth_q_stats.driver_xoff++;
+ fp->eth_q_stats.driver_xoff++;
netif_tx_stop_queue(txq);
BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
return NETDEV_TX_BUSY;
fp->tx_db.data.prod += nbd;
barrier();
- DOORBELL(bp, fp->index - bp->num_rx_queues, fp->tx_db.raw);
+ DOORBELL(bp, fp->index, fp->tx_db.raw);
mmiowb();
if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
netif_tx_stop_queue(txq);
- /* We want bnx2x_tx_int to "see" the updated tx_bd_prod
- if we put Tx into XOFF state. */
+
+ /* paired memory barrier is in bnx2x_tx_int(), we have to keep
+ * ordering of set_bit() in netif_tx_stop_queue() and read of
+ * fp->bd_tx_cons */
smp_mb();
- fp_stat->eth_q_stats.driver_xoff++;
+
+ fp->eth_q_stats.driver_xoff++;
if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
netif_tx_wake_queue(txq);
}
- fp_stat->tx_pkt++;
+ fp->tx_pkt++;
return NETDEV_TX_OK;
}
rx_mode = BNX2X_RX_MODE_PROMISC;
else if ((dev->flags & IFF_ALLMULTI) ||
- ((dev->mc_count > BNX2X_MAX_MULTICAST) && CHIP_IS_E1(bp)))
+ ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
+ CHIP_IS_E1(bp)))
rx_mode = BNX2X_RX_MODE_ALLMULTI;
else { /* some multicasts */
struct mac_configuration_cmd *config =
bnx2x_sp(bp, mcast_config);
- for (i = 0, mclist = dev->mc_list;
- mclist && (i < dev->mc_count);
- i++, mclist = mclist->next) {
-
+ i = 0;
+ netdev_for_each_mc_addr(mclist, dev) {
config->config_table[i].
cam_entry.msb_mac_addr =
swab16(*(u16 *)&mclist->dmi_addr[0]);
cam_entry.middle_mac_addr,
config->config_table[i].
cam_entry.lsb_mac_addr);
+ i++;
}
old = config->hdr.length;
if (old > i) {
memset(mc_filter, 0, 4 * MC_HASH_SIZE);
- for (i = 0, mclist = dev->mc_list;
- mclist && (i < dev->mc_count);
- i++, mclist = mclist->next) {
-
+ netdev_for_each_mc_addr(mclist, dev) {
DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
mclist->dmi_addr);
#endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
static void poll_bnx2x(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
#ifdef BCM_VLAN
.ndo_vlan_rx_register = bnx2x_vlan_rx_register,
#endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = poll_bnx2x,
#endif
};
rc = pci_enable_device(pdev);
if (rc) {
- printk(KERN_ERR PFX "Cannot enable PCI device, aborting\n");
+ pr_err("Cannot enable PCI device, aborting\n");
goto err_out;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find PCI device base address,"
- " aborting\n");
+ pr_err("Cannot find PCI device base address, aborting\n");
rc = -ENODEV;
goto err_out_disable;
}
if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find second PCI device"
- " base address, aborting\n");
+ pr_err("Cannot find second PCI device base address, aborting\n");
rc = -ENODEV;
goto err_out_disable;
}
if (atomic_read(&pdev->enable_cnt) == 1) {
rc = pci_request_regions(pdev, DRV_MODULE_NAME);
if (rc) {
- printk(KERN_ERR PFX "Cannot obtain PCI resources,"
- " aborting\n");
+ pr_err("Cannot obtain PCI resources, aborting\n");
goto err_out_disable;
}
bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
if (bp->pm_cap == 0) {
- printk(KERN_ERR PFX "Cannot find power management"
- " capability, aborting\n");
+ pr_err("Cannot find power management capability, aborting\n");
rc = -EIO;
goto err_out_release;
}
bp->pcie_cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
if (bp->pcie_cap == 0) {
- printk(KERN_ERR PFX "Cannot find PCI Express capability,"
- " aborting\n");
+ pr_err("Cannot find PCI Express capability, aborting\n");
rc = -EIO;
goto err_out_release;
}
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
bp->flags |= USING_DAC_FLAG;
if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
- printk(KERN_ERR PFX "pci_set_consistent_dma_mask"
- " failed, aborting\n");
+ pr_err("pci_set_consistent_dma_mask failed, aborting\n");
rc = -EIO;
goto err_out_release;
}
} else if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
- printk(KERN_ERR PFX "System does not support DMA,"
- " aborting\n");
+ pr_err("System does not support DMA, aborting\n");
rc = -EIO;
goto err_out_release;
}
bp->regview = pci_ioremap_bar(pdev, 0);
if (!bp->regview) {
- printk(KERN_ERR PFX "Cannot map register space, aborting\n");
+ pr_err("Cannot map register space, aborting\n");
rc = -ENOMEM;
goto err_out_release;
}
min_t(u64, BNX2X_DB_SIZE,
pci_resource_len(pdev, 2)));
if (!bp->doorbells) {
- printk(KERN_ERR PFX "Cannot map doorbell space, aborting\n");
+ pr_err("Cannot map doorbell space, aborting\n");
rc = -ENOMEM;
goto err_out_unmap;
}
offset = be32_to_cpu(sections[i].offset);
len = be32_to_cpu(sections[i].len);
if (offset + len > firmware->size) {
- printk(KERN_ERR PFX "Section %d length is out of "
- "bounds\n", i);
+ pr_err("Section %d length is out of bounds\n", i);
return -EINVAL;
}
}
for (i = 0; i < be32_to_cpu(fw_hdr->init_ops_offsets.len) / 2; i++) {
if (be16_to_cpu(ops_offsets[i]) > num_ops) {
- printk(KERN_ERR PFX "Section offset %d is out of "
- "bounds\n", i);
+ pr_err("Section offset %d is out of bounds\n", i);
return -EINVAL;
}
}
(fw_ver[1] != BCM_5710_FW_MINOR_VERSION) ||
(fw_ver[2] != BCM_5710_FW_REVISION_VERSION) ||
(fw_ver[3] != BCM_5710_FW_ENGINEERING_VERSION)) {
- printk(KERN_ERR PFX "Bad FW version:%d.%d.%d.%d."
- " Should be %d.%d.%d.%d\n",
+ pr_err("Bad FW version:%d.%d.%d.%d. Should be %d.%d.%d.%d\n",
fw_ver[0], fw_ver[1], fw_ver[2],
fw_ver[3], BCM_5710_FW_MAJOR_VERSION,
BCM_5710_FW_MINOR_VERSION,
target[i] = be16_to_cpu(source[i]);
}
-#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \
- do { \
- u32 len = be32_to_cpu(fw_hdr->arr.len); \
- bp->arr = kmalloc(len, GFP_KERNEL); \
- if (!bp->arr) { \
- printk(KERN_ERR PFX "Failed to allocate %d bytes " \
- "for "#arr"\n", len); \
- goto lbl; \
- } \
- func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \
- (u8 *)bp->arr, len); \
- } while (0)
+#define BNX2X_ALLOC_AND_SET(arr, lbl, func) \
+do { \
+ u32 len = be32_to_cpu(fw_hdr->arr.len); \
+ bp->arr = kmalloc(len, GFP_KERNEL); \
+ if (!bp->arr) { \
+ pr_err("Failed to allocate %d bytes for "#arr"\n", len); \
+ goto lbl; \
+ } \
+ func(bp->firmware->data + be32_to_cpu(fw_hdr->arr.offset), \
+ (u8 *)bp->arr, len); \
+} while (0)
static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev)
{
- char fw_file_name[40] = {0};
+ const char *fw_file_name;
struct bnx2x_fw_file_hdr *fw_hdr;
- int rc, offset;
+ int rc;
- /* Create a FW file name */
if (CHIP_IS_E1(bp))
- offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1);
+ fw_file_name = FW_FILE_NAME_E1;
else
- offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H);
-
- sprintf(fw_file_name + offset, "%d.%d.%d.%d.fw",
- BCM_5710_FW_MAJOR_VERSION,
- BCM_5710_FW_MINOR_VERSION,
- BCM_5710_FW_REVISION_VERSION,
- BCM_5710_FW_ENGINEERING_VERSION);
+ fw_file_name = FW_FILE_NAME_E1H;
- printk(KERN_INFO PFX "Loading %s\n", fw_file_name);
+ pr_info("Loading %s\n", fw_file_name);
rc = request_firmware(&bp->firmware, fw_file_name, dev);
if (rc) {
- printk(KERN_ERR PFX "Can't load firmware file %s\n",
- fw_file_name);
+ pr_err("Can't load firmware file %s\n", fw_file_name);
goto request_firmware_exit;
}
rc = bnx2x_check_firmware(bp);
if (rc) {
- printk(KERN_ERR PFX "Corrupt firmware file %s\n", fw_file_name);
+ pr_err("Corrupt firmware file %s\n", fw_file_name);
goto request_firmware_exit;
}
/* dev zeroed in init_etherdev */
dev = alloc_etherdev_mq(sizeof(*bp), MAX_CONTEXT);
if (!dev) {
- printk(KERN_ERR PFX "Cannot allocate net device\n");
+ pr_err("Cannot allocate net device\n");
return -ENOMEM;
}
bp = netdev_priv(dev);
- bp->msglevel = debug;
+ bp->msg_enable = debug;
pci_set_drvdata(pdev, dev);
/* Set init arrays */
rc = bnx2x_init_firmware(bp, &pdev->dev);
if (rc) {
- printk(KERN_ERR PFX "Error loading firmware\n");
+ pr_err("Error loading firmware\n");
goto init_one_exit;
}
}
bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
- printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx,"
- " IRQ %d, ", dev->name, board_info[ent->driver_data].name,
- (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
- pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz",
- dev->base_addr, bp->pdev->irq);
- printk(KERN_CONT "node addr %pM\n", dev->dev_addr);
+ netdev_info(dev, "%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
+ board_info[ent->driver_data].name,
+ (CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
+ pcie_width, (pcie_speed == 2) ? "5GHz (Gen2)" : "2.5GHz",
+ dev->base_addr, bp->pdev->irq, dev->dev_addr);
return 0;
struct bnx2x *bp;
if (!dev) {
- printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
+ pr_err("BAD net device from bnx2x_init_one\n");
return;
}
bp = netdev_priv(dev);
struct bnx2x *bp;
if (!dev) {
- printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
+ pr_err("BAD net device from bnx2x_init_one\n");
return -ENODEV;
}
bp = netdev_priv(dev);
int rc;
if (!dev) {
- printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n");
+ pr_err("BAD net device from bnx2x_init_one\n");
return -ENODEV;
}
bp = netdev_priv(dev);
DP(BNX2X_MSG_STATS, "stats_state - DISABLED\n");
/* Release IRQs */
- bnx2x_free_irq(bp);
+ bnx2x_free_irq(bp, false);
if (CHIP_IS_E1(bp)) {
struct mac_configuration_cmd *config =
/* Free SKBs, SGEs, TPA pool and driver internals */
bnx2x_free_skbs(bp);
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
- for_each_rx_queue(bp, i)
+ for_each_queue(bp, i)
netif_napi_del(&bnx2x_fp(bp, i, napi));
bnx2x_free_mem(bp);
{
int ret;
- printk(KERN_INFO "%s", version);
+ pr_info("%s", version);
bnx2x_wq = create_singlethread_workqueue("bnx2x");
if (bnx2x_wq == NULL) {
- printk(KERN_ERR PFX "Cannot create workqueue\n");
+ pr_err("Cannot create workqueue\n");
return -ENOMEM;
}
ret = pci_register_driver(&bnx2x_pci_driver);
if (ret) {
- printk(KERN_ERR PFX "Cannot register driver\n");
+ pr_err("Cannot register driver\n");
destroy_workqueue(bnx2x_wq);
}
return ret;