* Written by: Michael Chan (mchan@broadcom.com)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <asm/irq.h>
#include <linux/delay.h>
#include <asm/byteorder.h>
-#include <asm/page.h>
#include <linux/time.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/crc32.h>
#include <linux/prefetch.h>
#include <linux/cache.h>
-#include <linux/zlib.h>
#include "bnx2.h"
#include "bnx2_fw.h"
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.4.44"
-#define DRV_MODULE_RELDATE "August 10, 2006"
+#define DRV_MODULE_VERSION "1.4.40"
+#define DRV_MODULE_RELDATE "May 22, 2006"
#define RUN_AT(x) (jiffies + (x))
static inline u32 bnx2_tx_avail(struct bnx2 *bp)
{
- u32 diff;
+ u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
- smp_mb();
- diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
if (diff > MAX_TX_DESC_CNT)
diff = (diff & MAX_TX_DESC_CNT) - 1;
return (bp->tx_ring_size - diff);
struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
unsigned long align;
- skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+ skb = dev_alloc_skb(bp->rx_buf_size);
if (skb == NULL) {
return -ENOMEM;
}
skb_reserve(skb, 8 - align);
}
+ skb->dev = bp->dev;
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
PCI_DMA_FROMDEVICE);
skb = tx_buf->skb;
#ifdef BCM_TSO
/* partial BD completions possible with TSO packets */
- if (skb_is_gso(skb)) {
+ if (skb_shinfo(skb)->tso_size){
u16 last_idx, last_ring_idx;
last_idx = sw_cons +
tx_free_bd += last + 1;
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
hw_cons = bp->hw_tx_cons =
sblk->status_tx_quick_consumer_index0;
}
bp->tx_cons = sw_cons;
- /* Need to make the tx_cons update visible to bnx2_start_xmit()
- * before checking for netif_queue_stopped(). Without the
- * memory barrier, there is a small possibility that bnx2_start_xmit()
- * will miss it and cause the queue to be stopped forever.
- */
- smp_mb();
- if (unlikely(netif_queue_stopped(bp->dev)) &&
- (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) {
- netif_tx_lock(bp->dev);
+ if (unlikely(netif_queue_stopped(bp->dev))) {
+ spin_lock(&bp->tx_lock);
if ((netif_queue_stopped(bp->dev)) &&
- (bnx2_tx_avail(bp) > bp->tx_wake_thresh))
+ (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
+
netif_wake_queue(bp->dev);
- netif_tx_unlock(bp->dev);
+ }
+ spin_unlock(&bp->tx_lock);
}
}
if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
struct sk_buff *new_skb;
- new_skb = netdev_alloc_skb(bp->dev, len + 2);
+ new_skb = dev_alloc_skb(len + 2);
if (new_skb == NULL)
goto reuse_rx;
skb_reserve(new_skb, 2);
skb_put(new_skb, len);
+ new_skb->dev = bp->dev;
bnx2_reuse_rx_skb(bp, skb,
sw_ring_cons, sw_ring_prod);
skb->protocol = eth_type_trans(skb, bp->dev);
if ((len > (bp->dev->mtu + ETH_HLEN)) &&
- (ntohs(skb->protocol) != 0x8100)) {
+ (htons(skb->protocol) != 0x8100)) {
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
goto next_rx;
}
spin_unlock_bh(&bp->phy_lock);
}
-#define FW_BUF_SIZE 0x8000
-
-static int
-bnx2_gunzip_init(struct bnx2 *bp)
-{
- if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
- goto gunzip_nomem1;
-
- if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
- goto gunzip_nomem2;
-
- bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
- if (bp->strm->workspace == NULL)
- goto gunzip_nomem3;
-
- return 0;
-
-gunzip_nomem3:
- kfree(bp->strm);
- bp->strm = NULL;
-
-gunzip_nomem2:
- vfree(bp->gunzip_buf);
- bp->gunzip_buf = NULL;
-
-gunzip_nomem1:
- printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
- "uncompression.\n", bp->dev->name);
- return -ENOMEM;
-}
-
-static void
-bnx2_gunzip_end(struct bnx2 *bp)
-{
- kfree(bp->strm->workspace);
-
- kfree(bp->strm);
- bp->strm = NULL;
-
- if (bp->gunzip_buf) {
- vfree(bp->gunzip_buf);
- bp->gunzip_buf = NULL;
- }
-}
-
-static int
-bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
-{
- int n, rc;
-
- /* check gzip header */
- if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
- return -EINVAL;
-
- n = 10;
-
-#define FNAME 0x8
- if (zbuf[3] & FNAME)
- while ((zbuf[n++] != 0) && (n < len));
-
- bp->strm->next_in = zbuf + n;
- bp->strm->avail_in = len - n;
- bp->strm->next_out = bp->gunzip_buf;
- bp->strm->avail_out = FW_BUF_SIZE;
-
- rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
- if (rc != Z_OK)
- return rc;
-
- rc = zlib_inflate(bp->strm, Z_FINISH);
-
- *outlen = FW_BUF_SIZE - bp->strm->avail_out;
- *outbuf = bp->gunzip_buf;
-
- if ((rc != Z_OK) && (rc != Z_STREAM_END))
- printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
- bp->dev->name, bp->strm->msg);
-
- zlib_inflateEnd(bp->strm);
-
- if (rc == Z_STREAM_END)
- return 0;
-
- return rc;
-}
-
static void
load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
u32 rv2p_proc)
for (i = 0; i < rv2p_code_len; i += 8) {
- REG_WR(bp, BNX2_RV2P_INSTR_HIGH, cpu_to_le32(*rv2p_code));
+ REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
rv2p_code++;
- REG_WR(bp, BNX2_RV2P_INSTR_LOW, cpu_to_le32(*rv2p_code));
+ REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
rv2p_code++;
if (rv2p_proc == RV2P_PROC1) {
int j;
for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
- REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
+ REG_WR_IND(bp, offset, fw->text[j]);
}
}
REG_WR_IND(bp, cpu_reg->mode, val);
}
-static int
+static void
bnx2_init_cpus(struct bnx2 *bp)
{
struct cpu_reg cpu_reg;
struct fw_info fw;
- int rc = 0;
- void *text;
- u32 text_len;
-
- if ((rc = bnx2_gunzip_init(bp)) != 0)
- return rc;
/* Initialize the RV2P processor. */
- rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
- &text_len);
- if (rc)
- goto init_cpu_err;
-
- load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
-
- rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
- &text_len);
- if (rc)
- goto init_cpu_err;
-
- load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
+ load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
+ load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
/* Initialize the RX Processor. */
cpu_reg.mode = BNX2_RXP_CPU_MODE;
fw.text_addr = bnx2_RXP_b06FwTextAddr;
fw.text_len = bnx2_RXP_b06FwTextLen;
fw.text_index = 0;
-
- rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText),
- &text, &text_len);
- if (rc)
- goto init_cpu_err;
-
- fw.text = text;
+ fw.text = bnx2_RXP_b06FwText;
fw.data_addr = bnx2_RXP_b06FwDataAddr;
fw.data_len = bnx2_RXP_b06FwDataLen;
fw.text_addr = bnx2_TXP_b06FwTextAddr;
fw.text_len = bnx2_TXP_b06FwTextLen;
fw.text_index = 0;
-
- rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText),
- &text, &text_len);
- if (rc)
- goto init_cpu_err;
-
- fw.text = text;
+ fw.text = bnx2_TXP_b06FwText;
fw.data_addr = bnx2_TXP_b06FwDataAddr;
fw.data_len = bnx2_TXP_b06FwDataLen;
fw.text_addr = bnx2_TPAT_b06FwTextAddr;
fw.text_len = bnx2_TPAT_b06FwTextLen;
fw.text_index = 0;
-
- rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText),
- &text, &text_len);
- if (rc)
- goto init_cpu_err;
-
- fw.text = text;
+ fw.text = bnx2_TPAT_b06FwText;
fw.data_addr = bnx2_TPAT_b06FwDataAddr;
fw.data_len = bnx2_TPAT_b06FwDataLen;
fw.text_addr = bnx2_COM_b06FwTextAddr;
fw.text_len = bnx2_COM_b06FwTextLen;
fw.text_index = 0;
-
- rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText),
- &text, &text_len);
- if (rc)
- goto init_cpu_err;
-
- fw.text = text;
+ fw.text = bnx2_COM_b06FwText;
fw.data_addr = bnx2_COM_b06FwDataAddr;
fw.data_len = bnx2_COM_b06FwDataLen;
load_cpu_fw(bp, &cpu_reg, &fw);
-init_cpu_err:
- bnx2_gunzip_end(bp);
- return rc;
}
static int
* context block must have already been enabled. */
bnx2_init_context(bp);
- if ((rc = bnx2_init_cpus(bp)) != 0)
- return rc;
-
+ bnx2_init_cpus(bp);
bnx2_init_nvram(bp);
bnx2_set_mac_addr(bp);
struct tx_bd *txbd;
u32 val;
- bp->tx_wake_thresh = bp->tx_ring_size / 2;
-
txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
skb_shinfo(skb)->frags[j].size,
PCI_DMA_TODEVICE);
}
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
i += j + 1;
}
rx_buf->skb = NULL;
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
}
if (rc)
return rc;
- if ((rc = bnx2_init_chip(bp)) != 0)
- return rc;
-
+ bnx2_init_chip(bp);
bnx2_init_tx_ring(bp);
bnx2_init_rx_ring(bp);
return 0;
return -EINVAL;
pkt_size = 1514;
- skb = netdev_alloc_skb(bp->dev, pkt_size);
+ skb = dev_alloc_skb(pkt_size);
if (!skb)
return -ENOMEM;
packet = skb_put(skb, pkt_size);
udelay(5);
pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_prod) {
goto loopback_test_done;
msg = (u32) ++bp->fw_drv_pulse_wr_seq;
REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
- bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
-
if ((bp->phy_flags & PHY_SERDES_FLAG) &&
(CHIP_NUM(bp) == CHIP_NUM_5706)) {
}
else {
rc = request_irq(bp->pdev->irq, bnx2_interrupt,
- IRQF_SHARED, dev->name, dev);
+ SA_SHIRQ, dev->name, dev);
}
}
else {
- rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED,
+ rc = request_irq(bp->pdev->irq, bnx2_interrupt, SA_SHIRQ,
dev->name, dev);
}
if (rc) {
if (!rc) {
rc = request_irq(bp->pdev->irq, bnx2_interrupt,
- IRQF_SHARED, dev->name, dev);
+ SA_SHIRQ, dev->name, dev);
}
if (rc) {
bnx2_free_skbs(bp);
#endif
/* Called with netif_tx_lock.
- * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
- * netif_wake_queue().
+ * hard_start_xmit is pseudo-lockless - a lock is only required when
+ * the tx queue is full. This way, we get the benefit of lockless
+ * operations most of the time without the complexities to handle
+ * netif_stop_queue/wake_queue race conditions.
*/
static int
bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
}
#ifdef BCM_TSO
- if ((mss = skb_shinfo(skb)->gso_size) &&
+ if ((mss = skb_shinfo(skb)->tso_size) &&
(skb->len > (bp->dev->mtu + ETH_HLEN))) {
u32 tcp_opt_len, ip_tcp_len;
ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
skb->nh.iph->check = 0;
- skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
+ skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
skb->h.th->check =
~csum_tcpudp_magic(skb->nh.iph->saddr,
skb->nh.iph->daddr,
dev->trans_start = jiffies;
if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
+ spin_lock(&bp->tx_lock);
netif_stop_queue(dev);
- if (bnx2_tx_avail(bp) > bp->tx_wake_thresh)
+
+ if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
netif_wake_queue(dev);
+ spin_unlock(&bp->tx_lock);
}
return NETDEV_TX_OK;
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
if (bp->flags & NO_WOL_FLAG)
- reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
+ reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
else if (bp->wol)
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
else
net_stats->tx_aborted_errors +
net_stats->tx_carrier_errors;
- net_stats->rx_missed_errors =
- (unsigned long) (stats_blk->stat_IfInMBUFDiscards +
- stats_blk->stat_FwRxDrop);
-
return net_stats;
}
return 0;
}
-static int
-bnx2_set_tso(struct net_device *dev, u32 data)
-{
- if (data)
- dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
- else
- dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO_ECN);
- return 0;
-}
-
-#define BNX2_NUM_STATS 46
+#define BNX2_NUM_STATS 45
static struct {
char string[ETH_GSTRING_LEN];
{ "rx_mac_ctrl_frames" },
{ "rx_filtered_packets" },
{ "rx_discards" },
- { "rx_fw_discards" },
};
#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
STATS_OFFSET32(stat_MacControlFramesReceived),
STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),
STATS_OFFSET32(stat_IfInMBUFDiscards),
- STATS_OFFSET32(stat_FwRxDrop),
};
/* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
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,
};
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,
};
#define BNX2_NUM_TESTS 6
.set_sg = ethtool_op_set_sg,
#ifdef BCM_TSO
.get_tso = ethtool_op_get_tso,
- .set_tso = bnx2_set_tso,
+ .set_tso = ethtool_op_set_tso,
#endif
.self_test_count = bnx2_self_test_count,
.self_test = bnx2_self_test,
/* enable device (incl. PCI PM wakeup), and bus-mastering */
rc = pci_enable_device(pdev);
if (rc) {
- dev_err(&pdev->dev, "Cannot enable PCI device, aborting.");
+ printk(KERN_ERR PFX "Cannot enable PCI device, aborting.");
goto err_out;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- dev_err(&pdev->dev,
- "Cannot find PCI device base address, aborting.\n");
+ printk(KERN_ERR PFX "Cannot find PCI device base address, "
+ "aborting.\n");
rc = -ENODEV;
goto err_out_disable;
}
rc = pci_request_regions(pdev, DRV_MODULE_NAME);
if (rc) {
- dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n");
+ printk(KERN_ERR PFX "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) {
- dev_err(&pdev->dev,
- "Cannot find power management capability, aborting.\n");
+ printk(KERN_ERR PFX "Cannot find power management capability, "
+ "aborting.\n");
rc = -EIO;
goto err_out_release;
}
bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
if (bp->pcix_cap == 0) {
- dev_err(&pdev->dev, "Cannot find PCIX capability, aborting.\n");
+ printk(KERN_ERR PFX "Cannot find PCIX capability, aborting.\n");
rc = -EIO;
goto err_out_release;
}
if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
bp->flags |= USING_DAC_FLAG;
if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
- dev_err(&pdev->dev,
- "pci_set_consistent_dma_mask failed, aborting.\n");
+ printk(KERN_ERR PFX "pci_set_consistent_dma_mask "
+ "failed, aborting.\n");
rc = -EIO;
goto err_out_release;
}
}
else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
- dev_err(&pdev->dev, "System does not support DMA, aborting.\n");
+ printk(KERN_ERR PFX "System does not support DMA, aborting.\n");
rc = -EIO;
goto err_out_release;
}
bp->pdev = pdev;
spin_lock_init(&bp->phy_lock);
+ spin_lock_init(&bp->tx_lock);
INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
bp->regview = ioremap_nocache(dev->base_addr, mem_len);
if (!bp->regview) {
- dev_err(&pdev->dev, "Cannot map register space, aborting.\n");
+ printk(KERN_ERR PFX "Cannot map register space, aborting.\n");
rc = -ENOMEM;
goto err_out_release;
}
else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
!(bp->flags & PCIX_FLAG)) {
- dev_err(&pdev->dev,
- "5706 A1 can only be used in a PCIX bus, aborting.\n");
+ printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, "
+ "aborting.\n");
goto err_out_unmap;
}
if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
BNX2_DEV_INFO_SIGNATURE_MAGIC) {
- dev_err(&pdev->dev, "Firmware not running, aborting.\n");
+ printk(KERN_ERR PFX "Firmware not running, aborting.\n");
rc = -ENODEV;
goto err_out_unmap;
}
bp->mac_addr[5] = (u8) reg;
bp->tx_ring_size = MAX_TX_DESC_CNT;
- bnx2_set_rx_ring_size(bp, 255);
+ bnx2_set_rx_ring_size(bp, 100);
bp->rx_csum = 1;
}
}
- if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B1))
+ if (CHIP_NUM(bp) == CHIP_NUM_5708)
bp->flags |= NO_WOL_FLAG;
if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
#endif
if ((rc = register_netdev(dev))) {
- dev_err(&pdev->dev, "Cannot register net device\n");
+ printk(KERN_ERR PFX "Cannot register net device\n");
if (bp->regview)
iounmap(bp->regview);
pci_release_regions(pdev);
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
#ifdef BCM_TSO
- dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN;
+ dev->features |= NETIF_F_TSO;
#endif
netif_carrier_off(bp->dev);
netif_device_detach(dev);
del_timer_sync(&bp->timer);
if (bp->flags & NO_WOL_FLAG)
- reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN;
+ reset_code = BNX2_DRV_MSG_CODE_UNLOAD;
else if (bp->wol)
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
else