#include <linux/cache.h>
#include <linux/firmware.h>
#include <linux/log2.h>
+#include <linux/list.h>
+#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
+#define BCM_CNIC 1
+#include "cnic_if.h"
+#endif
#include "bnx2.h"
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "2.0.1"
-#define DRV_MODULE_RELDATE "May 6, 2009"
-#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-4.6.16.fw"
-#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-4.6.16.fw"
-#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-4.6.17.fw"
-#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-4.6.15.fw"
+#define DRV_MODULE_VERSION "2.0.2"
+#define DRV_MODULE_RELDATE "Aug 21, 2009"
+#define FW_MIPS_FILE_06 "bnx2/bnx2-mips-06-5.0.0.j3.fw"
+#define FW_RV2P_FILE_06 "bnx2/bnx2-rv2p-06-5.0.0.j3.fw"
+#define FW_MIPS_FILE_09 "bnx2/bnx2-mips-09-5.0.0.j3.fw"
+#define FW_RV2P_FILE_09_Ax "bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw"
+#define FW_RV2P_FILE_09 "bnx2/bnx2-rv2p-09-5.0.0.j3.fw"
#define RUN_AT(x) (jiffies + (x))
MODULE_FIRMWARE(FW_RV2P_FILE_06);
MODULE_FIRMWARE(FW_MIPS_FILE_09);
MODULE_FIRMWARE(FW_RV2P_FILE_09);
+MODULE_FIRMWARE(FW_RV2P_FILE_09_Ax);
static int disable_msi = 0;
{ 0, }
};
-static struct flash_spec flash_table[] =
+static const struct flash_spec flash_table[] =
{
#define BUFFERED_FLAGS (BNX2_NV_BUFFERED | BNX2_NV_TRANSLATE)
#define NONBUFFERED_FLAGS (BNX2_NV_WREN)
"Buffered flash (256kB)"},
};
-static struct flash_spec flash_5709 = {
+static const struct flash_spec flash_5709 = {
.flags = BNX2_NV_BUFFERED,
.page_bits = BCM5709_FLASH_PAGE_BITS,
.page_size = BCM5709_FLASH_PAGE_SIZE,
spin_unlock_bh(&bp->indirect_lock);
}
+#ifdef BCM_CNIC
+static int
+bnx2_drv_ctl(struct net_device *dev, struct drv_ctl_info *info)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+ struct drv_ctl_io *io = &info->data.io;
+
+ switch (info->cmd) {
+ case DRV_CTL_IO_WR_CMD:
+ bnx2_reg_wr_ind(bp, io->offset, io->data);
+ break;
+ case DRV_CTL_IO_RD_CMD:
+ io->data = bnx2_reg_rd_ind(bp, io->offset);
+ break;
+ case DRV_CTL_CTX_WR_CMD:
+ bnx2_ctx_wr(bp, io->cid_addr, io->offset, io->data);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void bnx2_setup_cnic_irq_info(struct bnx2 *bp)
+{
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+ int sb_id;
+
+ if (bp->flags & BNX2_FLAG_USING_MSIX) {
+ cp->drv_state |= CNIC_DRV_STATE_USING_MSIX;
+ bnapi->cnic_present = 0;
+ sb_id = bp->irq_nvecs;
+ cp->irq_arr[0].irq_flags |= CNIC_IRQ_FL_MSIX;
+ } else {
+ cp->drv_state &= ~CNIC_DRV_STATE_USING_MSIX;
+ bnapi->cnic_tag = bnapi->last_status_idx;
+ bnapi->cnic_present = 1;
+ sb_id = 0;
+ cp->irq_arr[0].irq_flags &= ~CNIC_IRQ_FL_MSIX;
+ }
+
+ cp->irq_arr[0].vector = bp->irq_tbl[sb_id].vector;
+ cp->irq_arr[0].status_blk = (void *)
+ ((unsigned long) bnapi->status_blk.msi +
+ (BNX2_SBLK_MSIX_ALIGN_SIZE * sb_id));
+ cp->irq_arr[0].status_blk_num = sb_id;
+ cp->num_irq = 1;
+}
+
+static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops,
+ void *data)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+ if (ops == NULL)
+ return -EINVAL;
+
+ if (cp->drv_state & CNIC_DRV_STATE_REGD)
+ return -EBUSY;
+
+ bp->cnic_data = data;
+ rcu_assign_pointer(bp->cnic_ops, ops);
+
+ cp->num_irq = 0;
+ cp->drv_state = CNIC_DRV_STATE_REGD;
+
+ bnx2_setup_cnic_irq_info(bp);
+
+ return 0;
+}
+
+static int bnx2_unregister_cnic(struct net_device *dev)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+ mutex_lock(&bp->cnic_lock);
+ cp->drv_state = 0;
+ bnapi->cnic_present = 0;
+ rcu_assign_pointer(bp->cnic_ops, NULL);
+ mutex_unlock(&bp->cnic_lock);
+ synchronize_rcu();
+ return 0;
+}
+
+struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+ struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+
+ cp->drv_owner = THIS_MODULE;
+ cp->chip_id = bp->chip_id;
+ cp->pdev = bp->pdev;
+ cp->io_base = bp->regview;
+ cp->drv_ctl = bnx2_drv_ctl;
+ cp->drv_register_cnic = bnx2_register_cnic;
+ cp->drv_unregister_cnic = bnx2_unregister_cnic;
+
+ return cp;
+}
+EXPORT_SYMBOL(bnx2_cnic_probe);
+
+static void
+bnx2_cnic_stop(struct bnx2 *bp)
+{
+ struct cnic_ops *c_ops;
+ struct cnic_ctl_info info;
+
+ mutex_lock(&bp->cnic_lock);
+ c_ops = bp->cnic_ops;
+ if (c_ops) {
+ info.cmd = CNIC_CTL_STOP_CMD;
+ c_ops->cnic_ctl(bp->cnic_data, &info);
+ }
+ mutex_unlock(&bp->cnic_lock);
+}
+
+static void
+bnx2_cnic_start(struct bnx2 *bp)
+{
+ struct cnic_ops *c_ops;
+ struct cnic_ctl_info info;
+
+ mutex_lock(&bp->cnic_lock);
+ c_ops = bp->cnic_ops;
+ if (c_ops) {
+ if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
+ struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
+
+ bnapi->cnic_tag = bnapi->last_status_idx;
+ }
+ info.cmd = CNIC_CTL_START_CMD;
+ c_ops->cnic_ctl(bp->cnic_data, &info);
+ }
+ mutex_unlock(&bp->cnic_lock);
+}
+
+#else
+
+static void
+bnx2_cnic_stop(struct bnx2 *bp)
+{
+}
+
+static void
+bnx2_cnic_start(struct bnx2 *bp)
+{
+}
+
+#endif
+
static int
bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
{
int i;
atomic_inc(&bp->intr_sem);
+ if (!netif_running(bp->dev))
+ return;
+
bnx2_disable_int(bp);
for (i = 0; i < bp->irq_nvecs; i++)
synchronize_irq(bp->irq_tbl[i].vector);
static void
bnx2_netif_stop(struct bnx2 *bp)
{
+ bnx2_cnic_stop(bp);
bnx2_disable_int_sync(bp);
if (netif_running(bp->dev)) {
bnx2_napi_disable(bp);
netif_tx_wake_all_queues(bp->dev);
bnx2_napi_enable(bp);
bnx2_enable_int(bp);
+ bnx2_cnic_start(bp);
}
}
}
rxr->rx_desc_mapping[j]);
rxr->rx_desc_ring[j] = NULL;
}
- if (rxr->rx_buf_ring)
- vfree(rxr->rx_buf_ring);
+ vfree(rxr->rx_buf_ring);
rxr->rx_buf_ring = NULL;
for (j = 0; j < bp->rx_max_pg_ring; j++) {
rxr->rx_pg_desc_mapping[j]);
rxr->rx_pg_desc_ring[j] = NULL;
}
- if (rxr->rx_pg_ring)
- vfree(rxr->rx_pg_ring);
+ vfree(rxr->rx_pg_ring);
rxr->rx_pg_ring = NULL;
}
}
tx_buf = &txr->tx_buf_ring[sw_ring_cons];
skb = tx_buf->skb;
+ /* prefetch skb_end_pointer() to speedup skb_shinfo(skb) */
+ prefetch(&skb->end);
+
/* partial BD completions possible with TSO packets */
- if (skb_is_gso(skb)) {
+ if (tx_buf->is_gso) {
u16 last_idx, last_ring_idx;
- last_idx = sw_cons +
- skb_shinfo(skb)->nr_frags + 1;
- last_ring_idx = sw_ring_cons +
- skb_shinfo(skb)->nr_frags + 1;
+ last_idx = sw_cons + tx_buf->nr_frags + 1;
+ last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1;
if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
last_idx++;
}
skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
tx_buf->skb = NULL;
- last = skb_shinfo(skb)->nr_frags;
+ last = tx_buf->nr_frags;
for (i = 0; i < last; i++) {
sw_cons = NEXT_TX_BD(sw_cons);
if (tx_pkt == budget)
break;
- hw_cons = bnx2_get_hw_tx_cons(bnapi);
+ if (hw_cons == sw_cons)
+ hw_cons = bnx2_get_hw_tx_cons(bnapi);
}
txr->hw_tx_cons = hw_cons;
if (bnx2_has_fast_work(bnapi))
return 1;
+#ifdef BCM_CNIC
+ if (bnapi->cnic_present && (bnapi->cnic_tag != sblk->status_idx))
+ return 1;
+#endif
+
if ((sblk->status_attn_bits & STATUS_ATTN_EVENTS) !=
(sblk->status_attn_bits_ack & STATUS_ATTN_EVENTS))
return 1;
bp->idle_chk_status_idx = bnapi->last_status_idx;
}
+#ifdef BCM_CNIC
+static void bnx2_poll_cnic(struct bnx2 *bp, struct bnx2_napi *bnapi)
+{
+ struct cnic_ops *c_ops;
+
+ if (!bnapi->cnic_present)
+ return;
+
+ rcu_read_lock();
+ c_ops = rcu_dereference(bp->cnic_ops);
+ if (c_ops)
+ bnapi->cnic_tag = c_ops->cnic_handler(bp->cnic_data,
+ bnapi->status_blk.msi);
+ rcu_read_unlock();
+}
+#endif
+
static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
{
struct status_block *sblk = bnapi->status_blk.msi;
work_done = bnx2_poll_work(bp, bnapi, work_done, budget);
+#ifdef BCM_CNIC
+ bnx2_poll_cnic(bp, bnapi);
+#endif
+
/* bnapi->last_status_idx is used below to tell the hw how
* much work has been processed, so we must read it before
* checking for more work.
{
struct bnx2 *bp = netdev_priv(dev);
u32 rx_mode, sort_mode;
- struct dev_addr_list *uc_ptr;
+ struct netdev_hw_addr *ha;
int i;
if (!netif_running(dev))
sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
}
- uc_ptr = NULL;
- if (dev->uc_count > BNX2_MAX_UNICAST_ADDRESSES) {
+ if (dev->uc.count > BNX2_MAX_UNICAST_ADDRESSES) {
rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN |
BNX2_RPM_SORT_USER0_PROM_VLAN;
} else if (!(dev->flags & IFF_PROMISC)) {
- uc_ptr = dev->uc_list;
-
/* Add all entries into to the match filter list */
- for (i = 0; i < dev->uc_count; i++) {
- bnx2_set_mac_addr(bp, uc_ptr->da_addr,
+ i = 0;
+ list_for_each_entry(ha, &dev->uc.list, list) {
+ bnx2_set_mac_addr(bp, ha->addr,
i + BNX2_START_UNICAST_ADDRESS_INDEX);
sort_mode |= (1 <<
(i + BNX2_START_UNICAST_ADDRESS_INDEX));
- uc_ptr = uc_ptr->next;
+ i++;
}
}
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
mips_fw_file = FW_MIPS_FILE_09;
- rv2p_fw_file = FW_RV2P_FILE_09;
+ if ((CHIP_ID(bp) == CHIP_ID_5709_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5709_A1))
+ rv2p_fw_file = FW_RV2P_FILE_09_Ax;
+ else
+ rv2p_fw_file = FW_RV2P_FILE_09;
} else {
mips_fw_file = FW_MIPS_FILE_06;
rv2p_fw_file = FW_RV2P_FILE_06;
{
u32 val;
int j, entry_count, rc = 0;
- struct flash_spec *flash;
+ const struct flash_spec *flash;
if (CHIP_NUM(bp) == CHIP_NUM_5709) {
bp->flash_info = &flash_5709;
val = REG_RD(bp, BNX2_MQ_CONFIG);
val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
- if (CHIP_ID(bp) == CHIP_ID_5709_A0 || CHIP_ID(bp) == CHIP_ID_5709_A1)
- val |= BNX2_MQ_CONFIG_HALT_DIS;
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ val |= BNX2_MQ_CONFIG_BIN_MQ_MODE;
+ if (CHIP_REV(bp) == CHIP_REV_Ax)
+ val |= BNX2_MQ_CONFIG_HALT_DIS;
+ }
REG_WR(bp, BNX2_MQ_CONFIG, val);
bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu));
bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu));
+ memset(bp->bnx2_napi[0].status_blk.msi, 0, bp->status_stats_size);
for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
bp->bnx2_napi[i].last_status_idx = 0;
REG_WR(bp, BNX2_HC_CMD_TICKS,
(bp->cmd_ticks_int << 16) | bp->cmd_ticks);
- if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ if (bp->flags & BNX2_FLAG_BROKEN_STATS)
REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
else
REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
}
if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
- val |= BNX2_HC_CONFIG_ONE_SHOT;
+ val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM;
REG_WR(bp, BNX2_HC_CONFIG, val);
dev_kfree_skb(skb);
return -EIO;
}
- map = skb_shinfo(skb)->dma_maps[0];
+ map = skb_shinfo(skb)->dma_head;
REG_WR(bp, BNX2_HC_COMMAND,
bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
bnx2_reg_rd_ind(bp, BNX2_FW_RX_DROP_COUNT);
/* workaround occasional corrupted counters */
- if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
+ if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks)
REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
BNX2_HC_COMMAND_STATS_NOW);
{
struct bnx2 *bp = netdev_priv(dev);
- bnx2_netif_stop(bp);
+ if (netif_running(dev))
+ bnx2_netif_stop(bp);
bp->vlgrp = vlgrp;
+
+ if (!netif_running(dev))
+ return;
+
bnx2_set_rx_mode(dev);
if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
* bnx2_tx_int() runs without netif_tx_lock unless it needs to call
* netif_wake_queue().
*/
-static int
+static netdev_tx_t
bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
}
sp = skb_shinfo(skb);
- mapping = sp->dma_maps[0];
+ mapping = sp->dma_head;
tx_buf = &txr->tx_buf_ring[ring_prod];
tx_buf->skb = skb;
txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START;
last_frag = skb_shinfo(skb)->nr_frags;
+ tx_buf->nr_frags = last_frag;
+ tx_buf->is_gso = skb_is_gso(skb);
for (i = 0; i < last_frag; i++) {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
txbd = &txr->tx_desc_ring[ring_prod];
len = frag->size;
- mapping = sp->dma_maps[i + 1];
+ mapping = sp->dma_maps[i];
txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
mmiowb();
txr->tx_prod = prod;
- dev->trans_start = jiffies;
if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) {
netif_tx_stop_queue(txq);
stats_blk->stat_EtherStatsOverrsizePkts);
net_stats->rx_over_errors =
- (unsigned long) stats_blk->stat_IfInMBUFDiscards;
+ (unsigned long) (stats_blk->stat_IfInFTQDiscards +
+ stats_blk->stat_IfInMBUFDiscards);
net_stats->rx_frame_errors =
(unsigned long) stats_blk->stat_Dot3StatsAlignmentErrors;
net_stats->tx_carrier_errors;
net_stats->rx_missed_errors =
- (unsigned long) (stats_blk->stat_IfInMBUFDiscards +
- stats_blk->stat_FwRxDrop);
+ (unsigned long) (stats_blk->stat_IfInFTQDiscards +
+ stats_blk->stat_IfInMBUFDiscards + stats_blk->stat_FwRxDrop);
return net_stats;
}
return 0;
}
+static u32
+bnx2_get_link(struct net_device *dev)
+{
+ struct bnx2 *bp = netdev_priv(dev);
+
+ return bp->link_up;
+}
+
static int
bnx2_get_eeprom_len(struct net_device *dev)
{
0xff;
bp->stats_ticks = coal->stats_block_coalesce_usecs;
- if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ if (bp->flags & BNX2_FLAG_BROKEN_STATS) {
if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
bp->stats_ticks = USEC_PER_SEC;
}
int rc;
rc = bnx2_alloc_mem(bp);
- if (rc)
+ if (!rc)
+ rc = bnx2_init_nic(bp, 0);
+
+ if (rc) {
+ bnx2_napi_enable(bp);
+ dev_close(bp->dev);
return rc;
- bnx2_init_nic(bp, 0);
+ }
bnx2_netif_start(bp);
}
return 0;
return 0;
}
-#define BNX2_NUM_STATS 46
-
static struct {
char string[ETH_GSTRING_LEN];
-} bnx2_stats_str_arr[BNX2_NUM_STATS] = {
+} bnx2_stats_str_arr[] = {
{ "rx_bytes" },
{ "rx_error_bytes" },
{ "tx_bytes" },
{ "tx_xoff_frames" },
{ "rx_mac_ctrl_frames" },
{ "rx_filtered_packets" },
+ { "rx_ftq_discards" },
{ "rx_discards" },
{ "rx_fw_discards" },
};
+#define BNX2_NUM_STATS (sizeof(bnx2_stats_str_arr)/\
+ sizeof(bnx2_stats_str_arr[0]))
+
#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
STATS_OFFSET32(stat_OutXoffSent),
STATS_OFFSET32(stat_MacControlFramesReceived),
STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),
+ STATS_OFFSET32(stat_IfInFTQDiscards),
STATS_OFFSET32(stat_IfInMBUFDiscards),
STATS_OFFSET32(stat_FwRxDrop),
};
4,0,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
- 4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,
};
static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
4,4,4,4,4,4,4,4,4,4,
- 4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,
};
#define BNX2_NUM_TESTS 6
.get_wol = bnx2_get_wol,
.set_wol = bnx2_set_wol,
.nway_reset = bnx2_nway_reset,
- .get_link = ethtool_op_get_link,
+ .get_link = bnx2_get_link,
.get_eeprom_len = bnx2_get_eeprom_len,
.get_eeprom = bnx2_get_eeprom,
.set_eeprom = bnx2_set_eeprom,
}
case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
return -EOPNOTSUPP;
spin_lock_init(&bp->phy_lock);
spin_lock_init(&bp->indirect_lock);
+#ifdef BCM_CNIC
+ mutex_init(&bp->cnic_lock);
+#endif
INIT_WORK(&bp->reset_task, bnx2_reset_task);
dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
- mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS);
+ mem_len = MB_GET_CID_ADDR(TX_TSS_CID + TX_MAX_TSS_RINGS + 1);
dev->mem_end = dev->mem_start + mem_len;
dev->irq = pdev->irq;
rc = -EIO;
goto err_out_unmap;
}
+ bp->flags |= BNX2_FLAG_BROKEN_STATS;
}
if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) {
bp->rx_csum = 1;
- bp->tx_quick_cons_trip_int = 20;
+ bp->tx_quick_cons_trip_int = 2;
bp->tx_quick_cons_trip = 20;
- bp->tx_ticks_int = 80;
+ bp->tx_ticks_int = 18;
bp->tx_ticks = 80;
- bp->rx_quick_cons_trip_int = 6;
- bp->rx_quick_cons_trip = 6;
+ bp->rx_quick_cons_trip_int = 2;
+ bp->rx_quick_cons_trip = 12;
bp->rx_ticks_int = 18;
bp->rx_ticks = 18;
#endif
};
+static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+{
+#ifdef BCM_VLAN
+ dev->vlan_features |= flags;
+#endif
+}
+
static int __devinit
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
memcpy(dev->perm_addr, bp->mac_addr, 6);
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ vlan_features_add(dev, NETIF_F_IP_CSUM | NETIF_F_SG);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
dev->features |= NETIF_F_IPV6_CSUM;
-
+ vlan_features_add(dev, NETIF_F_IPV6_CSUM);
+ }
#ifdef BCM_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
+ vlan_features_add(dev, NETIF_F_TSO | NETIF_F_TSO_ECN);
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
dev->features |= NETIF_F_TSO6;
-
+ vlan_features_add(dev, NETIF_F_TSO6);
+ }
if ((rc = register_netdev(dev))) {
dev_err(&pdev->dev, "Cannot register net device\n");
goto error;
rtnl_lock();
netif_device_detach(dev);
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
if (netif_running(dev)) {
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);