* Written by: Michael Chan (mchan@broadcom.com)
*/
+#include <linux/config.h>
+
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < 0x020500)
+#if defined(CONFIG_MODVERSIONS) && defined(MODULE) && ! defined(MODVERSIONS)
+#define MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
#include <linux/module.h>
+#if (LINUX_VERSION_CODE >= 0x020600)
#include <linux/moduleparam.h>
+#endif
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#if (LINUX_VERSION_CODE >= 0x020600)
#include <linux/dma-mapping.h>
+#endif
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <net/tcp.h>
#include <net/checksum.h>
#define BCM_TSO 1
+#ifndef NETIF_F_GSO
+#define gso_size tso_size
#endif
+#endif
+#if (LINUX_VERSION_CODE >= 0x020600)
#include <linux/workqueue.h>
+#endif
+#ifndef BNX2_BOOT_DISK
#include <linux/crc32.h>
+#endif
#include <linux/prefetch.h>
#include <linux/cache.h>
#include <linux/zlib.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.43f"
+#define DRV_MODULE_RELDATE "June 26, 2006"
#define RUN_AT(x) (jiffies + (x))
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
+#if (LINUX_VERSION_CODE >= 0x20600)
static int disable_msi = 0;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+#endif
typedef enum {
BCM5706 = 0,
MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
+#ifdef BNX2_BOOT_DISK
+u32 ether_crc_le(size_t len, unsigned char const *p)
+{
+ u32 crc = ~0;
+ int i;
+#define CRCPOLY_LE 0xedb88320
+
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+ }
+ return crc;
+}
+#endif
+
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);
{
atomic_inc(&bp->intr_sem);
bnx2_disable_int(bp);
+#if (LINUX_VERSION_CODE >= 0x2051c)
synchronize_irq(bp->pdev->irq);
+#else
+ synchronize_irq();
+#endif
}
static void
{
int i, status_blk_size;
- bp->tx_buf_ring = kzalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
+ bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
GFP_KERNEL);
if (bp->tx_buf_ring == NULL)
return -ENOMEM;
+ memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT);
bp->tx_desc_ring = pci_alloc_consistent(bp->pdev,
sizeof(struct tx_bd) *
TX_DESC_CNT,
/* wait for an acknowledgement. */
for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) {
- msleep(10);
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ / 100);
val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
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)->gso_size) {
u16 last_idx, last_ring_idx;
last_idx = sw_cons +
}
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);
}
+
}
static inline void
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);
}
+#ifdef CONFIG_PCI_MSI
/* MSI ISR - The only difference between this and the INTx ISR
* is that the MSI interrupt is always serviced.
*/
return IRQ_HANDLED;
}
+#endif
static irqreturn_t
bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
(pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
PCI_PM_CTRL_PME_STATUS);
- if (pmcsr & PCI_PM_CTRL_STATE_MASK)
+ if (pmcsr & PCI_PM_CTRL_STATE_MASK) {
/* delay required during transition out of D3hot */
- msleep(20);
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ / 50);
+ }
val = REG_RD(bp, BNX2_EMAC_MODE);
val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
rc = 0;
if (val & 0x40000000) {
-
/* Flash interface has been reconfigured */
for (j = 0, flash = &flash_table[0]; j < entry_count;
j++, flash++) {
REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
- (CHIP_ID(bp) == CHIP_ID_5706_A1))
- msleep(15);
+ (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ / 50);
+ }
/* Reset takes approximate 30 usec */
for (i = 0; i < 10; i++) {
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);
}
}
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);
break;
}
- msleep_interruptible(10);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ / 100);
}
if (i < 10)
return 0;
if (rc)
return rc;
+#ifdef CONFIG_PCI_MSI
if ((CHIP_ID(bp) != CHIP_ID_5706_A0) &&
(CHIP_ID(bp) != CHIP_ID_5706_A1) &&
!disable_msi) {
}
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,
+ else
+#endif
+ {
+ rc = request_irq(bp->pdev->irq, bnx2_interrupt, SA_SHIRQ,
dev->name, dev);
}
if (rc) {
if (rc) {
free_irq(bp->pdev->irq, dev);
+#ifdef CONFIG_PCI_MSI
if (bp->flags & USING_MSI_FLAG) {
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
}
+#endif
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
return rc;
bnx2_enable_int(bp);
+#ifdef CONFIG_PCI_MSI
if (bp->flags & USING_MSI_FLAG) {
/* Test MSI to make sure it is working
* If MSI test fails, go back to INTx mode
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);
if (bp->flags & USING_MSI_FLAG) {
printk(KERN_INFO PFX "%s: using MSI\n", dev->name);
}
+#endif
netif_start_queue(dev);
struct bnx2 *bp = netdev_priv(dev);
/* This allows the netif to be shutdown gracefully before resetting */
+#if (LINUX_VERSION_CODE >= 0x20600)
schedule_work(&bp->reset_task);
+#else
+ schedule_task(&bp->reset_task);
+#endif
}
#ifdef BCM_VLAN
}
#endif
+/* Test for DMA addresses > 40-bit.
+ * Only 64-bit systems without IOMMU requires DMA address checking.
+ */
+static inline int bnx2_40bit_overflow_test(struct bnx2 *bp, dma_addr_t mapping,
+ int len)
+{
+#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
+ if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ return (((u64) mapping + len) > DMA_40BIT_MASK);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
+/* Workaround 40-bit hardware DMA bugs. */
+static int bnx2_dma_hwbug_workaround(struct bnx2 *bp, struct sk_buff **skb,
+ u16 *last_plus_one, u32 base_flags,
+ u32 mss)
+{
+ struct sk_buff *new_skb = skb_copy(*skb, GFP_ATOMIC);
+ dma_addr_t new_addr = 0;
+ int i, ret = 0;
+ u16 hw_prod = *last_plus_one;
+ u16 start, hw_start, prod;
+
+ prod = TX_RING_IDX(hw_prod);
+ start = prod - 1 - skb_shinfo(*skb)->nr_frags;
+ hw_start = hw_prod - 1 - skb_shinfo(*skb)->nr_frags;
+ start &= MAX_TX_DESC_CNT;
+ if (start > prod) {
+ start--;
+ hw_start--;
+ }
+
+ if (!new_skb) {
+ ret = -1;
+ } else {
+ struct tx_bd *txbd;
+
+ /* New SKB is guaranteed to be linear. */
+ new_addr = pci_map_single(bp->pdev, new_skb->data, new_skb->len,
+ PCI_DMA_TODEVICE);
+ txbd = &bp->tx_desc_ring[start];
+
+ txbd->tx_bd_haddr_hi = (u64) new_addr >> 32;
+ txbd->tx_bd_haddr_lo = (u64) new_addr & 0xffffffff;
+ txbd->tx_bd_mss_nbytes = new_skb->len | (mss << 16);
+ txbd->tx_bd_vlan_tag_flags = base_flags | TX_BD_FLAGS_START |
+ TX_BD_FLAGS_END;
+
+ *last_plus_one = NEXT_TX_BD(hw_start);
+ }
+
+ /* Now clean up the sw ring entries. */
+ i = 0;
+ while (start != prod) {
+ int len;
+
+ if (i == 0)
+ len = skb_headlen(*skb);
+ else
+ len = skb_shinfo(*skb)->frags[i-1].size;
+
+ pci_unmap_single(bp->pdev,
+ pci_unmap_addr(&tp->tx_buf_ring[start],
+ mapping),
+ len, PCI_DMA_TODEVICE);
+ if (i == 0) {
+ bp->tx_buf_ring[start].skb = new_skb;
+ pci_unmap_addr_set(&bp->tx_buf_ring[start], mapping,
+ new_addr);
+ }
+ hw_start = NEXT_TX_BD(hw_start);
+ start = TX_RING_IDX(hw_start);
+ i++;
+ }
+
+ dev_kfree_skb(*skb);
+
+ *skb = new_skb;
+
+ return ret;
+}
+#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)
struct sw_bd *tx_buf;
u32 len, vlan_tag_flags, last_frag, mss;
u16 prod, ring_prod;
- int i;
+ int i, would_hit_hwbug = 0;
if (unlikely(bnx2_tx_avail(bp) < (skb_shinfo(skb)->nr_frags + 1))) {
netif_stop_queue(dev);
vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
}
+#ifdef BCM_VLAN
if (bp->vlgrp != 0 && vlan_tx_tag_present(skb)) {
vlan_tag_flags |=
(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
}
+#endif
#ifdef BCM_TSO
if ((mss = skb_shinfo(skb)->gso_size) &&
(skb->len > (bp->dev->mtu + ETH_HLEN))) {
u32 tcp_opt_len, ip_tcp_len;
+#if (LINUX_VERSION_CODE > 0x2060b)
if (skb_header_cloned(skb) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
+#endif
tcp_opt_len = ((skb->h.th->doff - 5) * 4);
vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
txbd->tx_bd_mss_nbytes = len | (mss << 16);
txbd->tx_bd_vlan_tag_flags = vlan_tag_flags;
+ if (bnx2_40bit_overflow_test(bp, mapping, len))
+ would_hit_hwbug = 1;
}
+
txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END;
prod = NEXT_TX_BD(prod);
+
+#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
+ if (unlikely(would_hit_hwbug)) {
+ /* If the workaround fails due to memory/mapping
+ * failure, silently drop this packet.
+ */
+ if (bnx2_dma_hwbug_workaround(bp, &skb, &prod,
+ vlan_tag_flags, mss))
+ return NETDEV_TX_OK;
+
+ }
+#endif
+
bp->tx_prod_bseq += skb->len;
REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
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;
* linkwatch_event() may be on the workqueue and it will try to get
* the rtnl_lock which we are holding.
*/
- while (bp->in_reset_task)
- msleep(1);
+ while (bp->in_reset_task) {
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(1);
+ }
bnx2_netif_stop(bp);
del_timer_sync(&bp->timer);
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
bnx2_reset_chip(bp, reset_code);
free_irq(bp->pdev->irq, dev);
+#ifdef CONFIG_PCI_MSI
if (bp->flags & USING_MSI_FLAG) {
pci_disable_msi(bp->pdev);
bp->flags &= ~USING_MSI_FLAG;
}
+#endif
bnx2_free_skbs(bp);
bnx2_free_mem(bp);
bp->link_up = 0;
bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
spin_unlock_bh(&bp->phy_lock);
- msleep(20);
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ / 50);
spin_lock_bh(&bp->phy_lock);
if (CHIP_NUM(bp) == CHIP_NUM_5706) {
return 0;
}
+#if (LINUX_VERSION_CODE >= 0x20418)
static int
bnx2_get_eeprom_len(struct net_device *dev)
{
return (int) bp->flash_size;
}
+#endif
+#ifdef ETHTOOL_GEEPROM
static int
bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 *eebuf)
return rc;
}
+#endif
+#ifdef ETHTOOL_SEEPROM
static int
bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 *eebuf)
return rc;
}
+#endif
static int
bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
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
static struct {
}
/* wait for link up */
- msleep_interruptible(3000);
- if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG))
- msleep_interruptible(4000);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(3 * HZ);
+ if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG)) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(4 * HZ);
+ }
}
if (bnx2_test_nvram(bp) != 0) {
BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
BNX2_EMAC_LED_TRAFFIC);
}
- msleep_interruptible(500);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ / 2);
if (signal_pending(current))
break;
}
.set_wol = bnx2_set_wol,
.nway_reset = bnx2_nway_reset,
.get_link = ethtool_op_get_link,
+#if (LINUX_VERSION_CODE >= 0x20418)
.get_eeprom_len = bnx2_get_eeprom_len,
+#endif
+#ifdef ETHTOOL_GEEPROM
.get_eeprom = bnx2_get_eeprom,
+#endif
+#ifdef ETHTOOL_SEEPROM
.set_eeprom = bnx2_set_eeprom,
+#endif
.get_coalesce = bnx2_get_coalesce,
.set_coalesce = bnx2_set_coalesce,
.get_ringparam = bnx2_get_ringparam,
.get_rx_csum = bnx2_get_rx_csum,
.set_rx_csum = bnx2_set_rx_csum,
.get_tx_csum = ethtool_op_get_tx_csum,
+#if (LINUX_VERSION_CODE >= 0x20418)
.set_tx_csum = ethtool_op_set_tx_csum,
+#endif
.get_sg = ethtool_op_get_sg,
.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,
.phys_id = bnx2_phys_id,
.get_stats_count = bnx2_get_stats_count,
.get_ethtool_stats = bnx2_get_ethtool_stats,
+#ifdef ETHTOOL_GPERMADDR
.get_perm_addr = ethtool_op_get_perm_addr,
+#endif
};
/* Called with rtnl_lock */
static int
bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
+#if (LINUX_VERSION_CODE >= 0x020607)
struct mii_ioctl_data *data = if_mii(ifr);
+#else
+ struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_ifru;
+#endif
struct bnx2 *bp = netdev_priv(dev);
int err;
{
struct bnx2 *bp = netdev_priv(dev);
- disable_irq(bp->pdev->irq);
- bnx2_interrupt(bp->pdev->irq, dev, NULL);
- enable_irq(bp->pdev->irq);
+#if defined(RED_HAT_LINUX_KERNEL) && (LINUX_VERSION_CODE < 0x020600)
+ if (netdump_mode) {
+ bnx2_interrupt(bp->pdev->irq, dev, NULL);
+ if (dev->poll_list.prev) {
+ int budget = 64;
+
+ bnx2_poll(dev, &budget);
+ }
+ }
+ else
+#endif
+ {
+ disable_irq(bp->pdev->irq);
+ bnx2_interrupt(bp->pdev->irq, dev, NULL);
+ enable_irq(bp->pdev->irq);
+ }
}
#endif
unsigned long mem_len;
int rc;
u32 reg;
+ u64 dma_mask, persist_dma_mask;
SET_MODULE_OWNER(dev);
+#if (LINUX_VERSION_CODE >= 0x20419)
SET_NETDEV_DEV(dev, &pdev->dev);
+#endif
bp = netdev_priv(dev);
bp->flags = 0;
/* 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");
- 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");
- 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 "Cannot find PCIX capability, aborting.\n");
rc = -EIO;
goto err_out_release;
}
bp->pdev = pdev;
spin_lock_init(&bp->phy_lock);
+ spin_lock_init(&bp->tx_lock);
+#if (LINUX_VERSION_CODE >= 0x20600)
INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
+#else
+ INIT_TQUEUE(&bp->reset_task, bnx2_reset_task, bp);
+#endif
dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
mem_len = MB_GET_CID_ADDR(17);
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;
}
bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+ /* 5708 cannot support DMA addresses > 40-bit.
+ * On 64-bit systems with IOMMU, use 40-bit dma_mask.
+ * On 64-bit systems without IOMMU, use 64-bit dma_mask and
+ * do DMA address check in bnx2_start_xmit().
+ */
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ persist_dma_mask = dma_mask = DMA_40BIT_MASK;
+#ifdef CONFIG_HIGHMEM
+ dma_mask = DMA_64BIT_MASK;
+#endif
+ } else
+ persist_dma_mask = dma_mask = DMA_64BIT_MASK;
+
+ /* Configure DMA attributes. */
+ if (pci_set_dma_mask(pdev, dma_mask) == 0) {
+ dev->features |= NETIF_F_HIGHDMA;
+ rc = pci_set_consistent_dma_mask(pdev, persist_dma_mask);
+ if (rc) {
+ printk(KERN_ERR PFX "pci_set_consistent_dma_mask "
+ "failed, aborting.\n");
+ goto err_out_unmap;
+ }
+ } else if ((rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) != 0) {
+ printk(KERN_ERR PFX "System does not support DMA, aborting.\n");
+ goto err_out_unmap;
+ }
+
/* Get bus information. */
reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
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;
printk(KERN_INFO "%s", version);
/* dev zeroed in init_etherdev */
+#if (LINUX_VERSION_CODE >= 0x20418)
dev = alloc_etherdev(sizeof(*bp));
+#else
+ dev = init_etherdev(NULL, sizeof(*bp));
+#endif
if (!dev)
return -ENOMEM;
rc = bnx2_init_board(pdev, dev);
if (rc < 0) {
+#if (LINUX_VERSION_CODE >= 0x20418)
free_netdev(dev);
+#else
+ unregister_netdev(dev);
+ kfree(dev);
+#endif
return rc;
}
dev->poll_controller = poll_bnx2;
#endif
+#if (LINUX_VERSION_CODE >= 0x20418)
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);
free_netdev(dev);
return rc;
}
+#endif
pci_set_drvdata(pdev, dev);
memcpy(dev->dev_addr, bp->mac_addr, 6);
+#ifdef ETHTOOL_GPERMADDR
memcpy(dev->perm_addr, bp->mac_addr, 6);
+#endif
bp->name = board_info[ent->driver_data].name,
printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
"IRQ %d, ",
printk("%2.2x", dev->dev_addr[i]);
printk("\n");
- dev->features |= NETIF_F_SG;
- if (bp->flags & USING_DAC_FLAG)
- dev->features |= NETIF_F_HIGHDMA;
- dev->features |= NETIF_F_IP_CSUM;
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
#ifdef BCM_VLAN
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);
struct net_device *dev = pci_get_drvdata(pdev);
struct bnx2 *bp = netdev_priv(dev);
+#if (LINUX_VERSION_CODE >= 0x20600)
flush_scheduled_work();
+#endif
unregister_netdev(dev);
if (bp->regview)
iounmap(bp->regview);
+#if (LINUX_VERSION_CODE >= 0x20418)
free_netdev(dev);
+#else
+ kfree(dev);
+#endif
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
if (!netif_running(dev))
return 0;
- flush_scheduled_work();
bnx2_netif_stop(bp);
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
reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
bnx2_reset_chip(bp, reset_code);
bnx2_free_skbs(bp);
+#if (LINUX_VERSION_CODE < 0x2060b)
+ bnx2_set_power_state(bp, state);
+#else
bnx2_set_power_state(bp, pci_choose_state(pdev, state));
+#endif
return 0;
}