diff options
Diffstat (limited to 'drivers/net/bnx2.c')
-rw-r--r-- | drivers/net/bnx2.c | 312 |
1 files changed, 175 insertions, 137 deletions
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 7635736cc79..6b4edb63c4c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -9,7 +9,6 @@ * Written by: Michael Chan (mchan@broadcom.com) */ -#include <linux/config.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -57,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.42" -#define DRV_MODULE_RELDATE "June 12, 2006" +#define DRV_MODULE_VERSION "1.4.45" +#define DRV_MODULE_RELDATE "September 29, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -149,7 +148,7 @@ static struct flash_spec flash_table[] = SAIFUN_FLASH_BYTE_ADDR_MASK, 0, "Entry 0100"}, /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */ - {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, + {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406, 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE, ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2, "Entry 0101: ST M45PE10 (128kB non-bufferred)"}, @@ -210,8 +209,10 @@ MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); static inline u32 bnx2_tx_avail(struct bnx2 *bp) { - u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons); + u32 diff; + 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); @@ -316,7 +317,7 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val) BNX2_EMAC_MDIO_COMM_COMMAND_WRITE | BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT; REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1); - + for (i = 0; i < 50; i++) { udelay(10); @@ -584,7 +585,7 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) u32 local_adv, remote_adv; bp->flow_ctrl = 0; - if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != + if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) { if (bp->duplex == DUPLEX_FULL) { @@ -1086,7 +1087,7 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) #define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \ ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA) - + #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL) static int @@ -1119,7 +1120,7 @@ bnx2_setup_copper_phy(struct bnx2 *bp) new_adv_reg |= ADVERTISE_100FULL; if (bp->advertising & ADVERTISED_1000baseT_Full) new_adv1000_reg |= ADVERTISE_1000FULL; - + new_adv_reg |= ADVERTISE_CSMA; new_adv_reg |= bnx2_phy_get_pause_adv(bp); @@ -1156,7 +1157,7 @@ bnx2_setup_copper_phy(struct bnx2 *bp) bnx2_read_phy(bp, MII_BMSR, &bmsr); bnx2_read_phy(bp, MII_BMSR, &bmsr); - + if (bmsr & BMSR_LSTATUS) { /* Force link down */ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); @@ -1546,7 +1547,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) } static void -bnx2_set_mac_addr(struct bnx2 *bp) +bnx2_set_mac_addr(struct bnx2 *bp) { u32 val; u8 *mac_addr = bp->dev->dev_addr; @@ -1555,7 +1556,7 @@ bnx2_set_mac_addr(struct bnx2 *bp) REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val); - val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | + val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]; REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val); @@ -1570,7 +1571,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; unsigned long align; - skb = dev_alloc_skb(bp->rx_buf_size); + skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); if (skb == NULL) { return -ENOMEM; } @@ -1579,7 +1580,6 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) 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); @@ -1638,9 +1638,9 @@ bnx2_tx_int(struct bnx2 *bp) tx_buf = &bp->tx_buf_ring[sw_ring_cons]; skb = tx_buf->skb; -#ifdef BCM_TSO +#ifdef BCM_TSO /* partial BD completions possible with TSO packets */ - if (skb_shinfo(skb)->gso_size) { + if (skb_is_gso(skb)) { u16 last_idx, last_ring_idx; last_idx = sw_cons + @@ -1676,7 +1676,7 @@ bnx2_tx_int(struct bnx2 *bp) tx_free_bd += last + 1; - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); hw_cons = bp->hw_tx_cons = sblk->status_tx_quick_consumer_index0; @@ -1687,15 +1687,20 @@ bnx2_tx_int(struct bnx2 *bp) } 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))) { - spin_lock(&bp->tx_lock); + if (unlikely(netif_queue_stopped(bp->dev)) && + (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) { + netif_tx_lock(bp->dev); if ((netif_queue_stopped(bp->dev)) && - (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) { - + (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) netif_wake_queue(bp->dev); - } - spin_unlock(&bp->tx_lock); + netif_tx_unlock(bp->dev); } } @@ -1787,7 +1792,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) { struct sk_buff *new_skb; - new_skb = dev_alloc_skb(len + 2); + new_skb = netdev_alloc_skb(bp->dev, len + 2); if (new_skb == NULL) goto reuse_rx; @@ -1798,7 +1803,6 @@ bnx2_rx_int(struct bnx2 *bp, int budget) 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); @@ -1824,7 +1828,7 @@ reuse_rx: if ((len > (bp->dev->mtu + ETH_HLEN)) && (ntohs(skb->protocol) != 0x8100)) { - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); goto next_rx; } @@ -1980,12 +1984,12 @@ bnx2_poll(struct net_device *dev, int *budget) if (orig_budget > dev->quota) orig_budget = dev->quota; - + work_done = bnx2_rx_int(bp, orig_budget); *budget -= work_done; dev->quota -= work_done; } - + bp->last_status_idx = bp->status_blk->status_idx; rmb(); @@ -2318,7 +2322,7 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT; cpu_reg.spad_base = BNX2_RXP_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - + fw.ver_major = bnx2_RXP_b06FwReleaseMajor; fw.ver_minor = bnx2_RXP_b06FwReleaseMinor; fw.ver_fix = bnx2_RXP_b06FwReleaseFix; @@ -2370,7 +2374,7 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT; cpu_reg.spad_base = BNX2_TXP_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - + fw.ver_major = bnx2_TXP_b06FwReleaseMajor; fw.ver_minor = bnx2_TXP_b06FwReleaseMinor; fw.ver_fix = bnx2_TXP_b06FwReleaseFix; @@ -2422,7 +2426,7 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT; cpu_reg.spad_base = BNX2_TPAT_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - + fw.ver_major = bnx2_TPAT_b06FwReleaseMajor; fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor; fw.ver_fix = bnx2_TPAT_b06FwReleaseFix; @@ -2474,7 +2478,7 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT; cpu_reg.spad_base = BNX2_COM_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - + fw.ver_major = bnx2_COM_b06FwReleaseMajor; fw.ver_minor = bnx2_COM_b06FwReleaseMinor; fw.ver_fix = bnx2_COM_b06FwReleaseFix; @@ -2737,7 +2741,7 @@ bnx2_enable_nvram_access(struct bnx2 *bp) val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); /* Enable both bits, even on read. */ - REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, + REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN); } @@ -2748,7 +2752,7 @@ bnx2_disable_nvram_access(struct bnx2 *bp) val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE); /* Disable both bits, even after read. */ - REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, + REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, val & ~(BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN)); } @@ -3139,7 +3143,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, /* Find the data_start addr */ data_start = (written == 0) ? offset32 : page_start; /* Find the data_end addr */ - data_end = (page_end > offset32 + len32) ? + data_end = (page_end > offset32 + len32) ? (offset32 + len32) : page_end; /* Request access to the flash interface. */ @@ -3160,8 +3164,8 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, cmd_flags |= BNX2_NVM_COMMAND_LAST; } rc = bnx2_nvram_read_dword(bp, - page_start + j, - &flash_buffer[j], + page_start + j, + &flash_buffer[j], cmd_flags); if (rc) @@ -3188,7 +3192,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if (bp->flash_info->buffered == 0) { for (addr = page_start; addr < data_start; addr += 4, i += 4) { - + rc = bnx2_nvram_write_dword(bp, addr, &flash_buffer[i], cmd_flags); @@ -3222,7 +3226,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if (bp->flash_info->buffered == 0) { for (addr = data_end; addr < page_end; addr += 4, i += 4) { - + if (addr == page_end-4) { cmd_flags = BNX2_NVM_COMMAND_LAST; } @@ -3347,9 +3351,9 @@ bnx2_init_chip(struct bnx2 *bp) val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP | BNX2_DMA_CONFIG_DATA_WORD_SWAP | #ifdef __BIG_ENDIAN - BNX2_DMA_CONFIG_CNTL_BYTE_SWAP | + BNX2_DMA_CONFIG_CNTL_BYTE_SWAP | #endif - BNX2_DMA_CONFIG_CNTL_WORD_SWAP | + BNX2_DMA_CONFIG_CNTL_WORD_SWAP | DMA_READ_CHANS << 12 | DMA_WRITE_CHANS << 16; @@ -3442,7 +3446,7 @@ bnx2_init_chip(struct bnx2 *bp) REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H, (u64) bp->stats_blk_mapping >> 32); - REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, + REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip); REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP, @@ -3504,8 +3508,10 @@ bnx2_init_tx_ring(struct bnx2 *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; txbd->tx_bd_haddr_lo = (u64) bp->tx_desc_mapping & 0xffffffff; @@ -3513,7 +3519,7 @@ bnx2_init_tx_ring(struct bnx2 *bp) bp->tx_cons = 0; bp->hw_tx_cons = 0; bp->tx_prod_bseq = 0; - + val = BNX2_L2CTX_TYPE_TYPE_L2; val |= BNX2_L2CTX_TYPE_SIZE_L2; CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val); @@ -3534,7 +3540,7 @@ bnx2_init_rx_ring(struct bnx2 *bp) { struct rx_bd *rxbd; int i; - u16 prod, ring_prod; + u16 prod, ring_prod; u32 val; /* 8 for CRC and VLAN */ @@ -3546,7 +3552,7 @@ bnx2_init_rx_ring(struct bnx2 *bp) bp->rx_cons = 0; bp->hw_rx_cons = 0; bp->rx_prod_bseq = 0; - + for (i = 0; i < bp->rx_max_ring; i++) { int j; @@ -3643,7 +3649,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) skb_shinfo(skb)->frags[j].size, PCI_DMA_TODEVICE); } - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); i += j + 1; } @@ -3669,7 +3675,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp) rx_buf->skb = NULL; - dev_kfree_skb_any(skb); + dev_kfree_skb(skb); } } @@ -3921,7 +3927,7 @@ bnx2_test_memory(struct bnx2 *bp) return ret; } } - + return ret; } @@ -3953,7 +3959,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) return -EINVAL; pkt_size = 1514; - skb = dev_alloc_skb(pkt_size); + skb = netdev_alloc_skb(bp->dev, pkt_size); if (!skb) return -ENOMEM; packet = skb_put(skb, pkt_size); @@ -3999,7 +4005,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) udelay(5); pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_prod) { goto loopback_test_done; @@ -4118,7 +4124,7 @@ bnx2_test_link(struct bnx2 *bp) bnx2_read_phy(bp, MII_BMSR, &bmsr); bnx2_read_phy(bp, MII_BMSR, &bmsr); spin_unlock_bh(&bp->phy_lock); - + if (bmsr & BMSR_LSTATUS) { return 0; } @@ -4261,11 +4267,11 @@ bnx2_open(struct net_device *dev) } else { rc = request_irq(bp->pdev->irq, bnx2_interrupt, - SA_SHIRQ, dev->name, dev); + IRQF_SHARED, dev->name, dev); } } else { - rc = request_irq(bp->pdev->irq, bnx2_interrupt, SA_SHIRQ, + rc = request_irq(bp->pdev->irq, bnx2_interrupt, IRQF_SHARED, dev->name, dev); } if (rc) { @@ -4285,7 +4291,7 @@ bnx2_open(struct net_device *dev) bnx2_free_mem(bp); return rc; } - + mod_timer(&bp->timer, jiffies + bp->current_interval); atomic_set(&bp->intr_sem, 0); @@ -4312,7 +4318,7 @@ bnx2_open(struct net_device *dev) if (!rc) { rc = request_irq(bp->pdev->irq, bnx2_interrupt, - SA_SHIRQ, dev->name, dev); + IRQF_SHARED, dev->name, dev); } if (rc) { bnx2_free_skbs(bp); @@ -4391,10 +4397,8 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) #endif /* Called with netif_tx_lock. - * 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. + * bnx2_tx_int() runs without netif_tx_lock unless it needs to call + * netif_wake_queue(). */ static int bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -4419,7 +4423,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) ring_prod = TX_RING_IDX(prod); vlan_tag_flags = 0; - if (skb->ip_summed == CHECKSUM_HW) { + if (skb->ip_summed == CHECKSUM_PARTIAL) { vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; } @@ -4427,7 +4431,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } -#ifdef BCM_TSO +#ifdef BCM_TSO if ((mss = skb_shinfo(skb)->gso_size) && (skb->len > (bp->dev->mtu + ETH_HLEN))) { u32 tcp_opt_len, ip_tcp_len; @@ -4466,7 +4470,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) } mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE); - + tx_buf = &bp->tx_buf_ring[ring_prod]; tx_buf->skb = skb; pci_unmap_addr_set(tx_buf, mapping, mapping); @@ -4513,12 +4517,9 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) 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) > MAX_SKB_FRAGS) + if (bnx2_tx_avail(bp) > bp->tx_wake_thresh) netif_wake_queue(dev); - spin_unlock(&bp->tx_lock); } return NETDEV_TX_OK; @@ -4541,7 +4542,7 @@ bnx2_close(struct net_device *dev) bnx2_netif_stop(bp); del_timer_sync(&bp->timer); if (bp->flags & NO_WOL_FLAG) - reset_code = BNX2_DRV_MSG_CODE_UNLOAD; + reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; else if (bp->wol) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; else @@ -4599,23 +4600,23 @@ bnx2_get_stats(struct net_device *dev) net_stats->tx_bytes = GET_NET_STATS(stats_blk->stat_IfHCOutOctets); - net_stats->multicast = + net_stats->multicast = GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts); - net_stats->collisions = + net_stats->collisions = (unsigned long) stats_blk->stat_EtherStatsCollisions; - net_stats->rx_length_errors = + net_stats->rx_length_errors = (unsigned long) (stats_blk->stat_EtherStatsUndersizePkts + stats_blk->stat_EtherStatsOverrsizePkts); - net_stats->rx_over_errors = + net_stats->rx_over_errors = (unsigned long) stats_blk->stat_IfInMBUFDiscards; - net_stats->rx_frame_errors = + net_stats->rx_frame_errors = (unsigned long) stats_blk->stat_Dot3StatsAlignmentErrors; - net_stats->rx_crc_errors = + net_stats->rx_crc_errors = (unsigned long) stats_blk->stat_Dot3StatsFCSErrors; net_stats->rx_errors = net_stats->rx_length_errors + @@ -4636,7 +4637,7 @@ bnx2_get_stats(struct net_device *dev) } net_stats->tx_errors = - (unsigned long) + (unsigned long) stats_blk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors + net_stats->tx_aborted_errors + @@ -4697,7 +4698,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) return 0; } - + static int bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { @@ -4710,7 +4711,7 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) if (cmd->autoneg == AUTONEG_ENABLE) { autoneg |= AUTONEG_SPEED; - cmd->advertising &= ETHTOOL_ALL_COPPER_SPEED; + cmd->advertising &= ETHTOOL_ALL_COPPER_SPEED; /* allow advertising 1 speed */ if ((cmd->advertising == ADVERTISED_10baseT_Half) || @@ -4987,7 +4988,7 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) bp->rx_ticks = (u16) coal->rx_coalesce_usecs; if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff; - bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames; + bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames; if (bp->rx_quick_cons_trip > 0xff) bp->rx_quick_cons_trip = 0xff; bp->rx_ticks_int = (u16) coal->rx_coalesce_usecs_irq; @@ -5128,6 +5129,16 @@ bnx2_set_rx_csum(struct net_device *dev, u32 data) 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 { @@ -5195,46 +5206,46 @@ static const unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = { STATS_OFFSET32(stat_IfHCOutMulticastPkts_hi), STATS_OFFSET32(stat_IfHCOutBroadcastPkts_hi), STATS_OFFSET32(stat_emac_tx_stat_dot3statsinternalmactransmiterrors), - STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors), - STATS_OFFSET32(stat_Dot3StatsFCSErrors), - STATS_OFFSET32(stat_Dot3StatsAlignmentErrors), - STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames), - STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames), - STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions), - STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions), - STATS_OFFSET32(stat_Dot3StatsLateCollisions), - STATS_OFFSET32(stat_EtherStatsCollisions), - STATS_OFFSET32(stat_EtherStatsFragments), - STATS_OFFSET32(stat_EtherStatsJabbers), - STATS_OFFSET32(stat_EtherStatsUndersizePkts), - STATS_OFFSET32(stat_EtherStatsOverrsizePkts), - STATS_OFFSET32(stat_EtherStatsPktsRx64Octets), - STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets), - STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets), - STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets), - STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets), - STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets), - STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx64Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets), - STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets), - STATS_OFFSET32(stat_XonPauseFramesReceived), - STATS_OFFSET32(stat_XoffPauseFramesReceived), - STATS_OFFSET32(stat_OutXonSent), - STATS_OFFSET32(stat_OutXoffSent), - STATS_OFFSET32(stat_MacControlFramesReceived), - STATS_OFFSET32(stat_IfInFramesL2FilterDiscards), - STATS_OFFSET32(stat_IfInMBUFDiscards), + STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors), + STATS_OFFSET32(stat_Dot3StatsFCSErrors), + STATS_OFFSET32(stat_Dot3StatsAlignmentErrors), + STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames), + STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames), + STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions), + STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions), + STATS_OFFSET32(stat_Dot3StatsLateCollisions), + STATS_OFFSET32(stat_EtherStatsCollisions), + STATS_OFFSET32(stat_EtherStatsFragments), + STATS_OFFSET32(stat_EtherStatsJabbers), + STATS_OFFSET32(stat_EtherStatsUndersizePkts), + STATS_OFFSET32(stat_EtherStatsOverrsizePkts), + STATS_OFFSET32(stat_EtherStatsPktsRx64Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets), + STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx64Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets), + STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets), + STATS_OFFSET32(stat_XonPauseFramesReceived), + STATS_OFFSET32(stat_XoffPauseFramesReceived), + STATS_OFFSET32(stat_OutXonSent), + STATS_OFFSET32(stat_OutXoffSent), + STATS_OFFSET32(stat_MacControlFramesReceived), + STATS_OFFSET32(stat_IfInFramesL2FilterDiscards), + STATS_OFFSET32(stat_IfInMBUFDiscards), STATS_OFFSET32(stat_FwRxDrop), }; /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are * skipped because of errata. - */ + */ static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = { 8,0,8,8,8,8,8,8,8,8, 4,0,4,4,4,4,4,4,4,4, @@ -5418,7 +5429,7 @@ bnx2_phys_id(struct net_device *dev, u32 data) return 0; } -static struct ethtool_ops bnx2_ethtool_ops = { +static const struct ethtool_ops bnx2_ethtool_ops = { .get_settings = bnx2_get_settings, .set_settings = bnx2_set_settings, .get_drvinfo = bnx2_get_drvinfo, @@ -5445,7 +5456,7 @@ static struct ethtool_ops bnx2_ethtool_ops = { .set_sg = ethtool_op_set_sg, #ifdef BCM_TSO .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, + .set_tso = bnx2_set_tso, #endif .self_test_count = bnx2_self_test_count, .self_test = bnx2_self_test, @@ -5566,20 +5577,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) /* enable device (incl. PCI PM wakeup), and bus-mastering */ rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "Cannot enable PCI device, aborting."); + dev_err(&pdev->dev, "Cannot enable PCI device, aborting."); goto err_out; } if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "Cannot find PCI device base address, " - "aborting.\n"); + dev_err(&pdev->dev, + "Cannot find PCI device base address, aborting.\n"); rc = -ENODEV; goto err_out_disable; } rc = pci_request_regions(pdev, DRV_MODULE_NAME); if (rc) { - printk(KERN_ERR PFX "Cannot obtain PCI resources, aborting.\n"); + dev_err(&pdev->dev, "Cannot obtain PCI resources, aborting.\n"); goto err_out_disable; } @@ -5587,15 +5598,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) 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"); + dev_err(&pdev->dev, + "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) { - printk(KERN_ERR PFX "Cannot find PCIX capability, aborting.\n"); + dev_err(&pdev->dev, "Cannot find PCIX capability, aborting.\n"); rc = -EIO; goto err_out_release; } @@ -5603,14 +5614,14 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) 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) { - printk(KERN_ERR PFX "pci_set_consistent_dma_mask " - "failed, aborting.\n"); + 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) { - printk(KERN_ERR PFX "System does not support DMA, aborting.\n"); + dev_err(&pdev->dev, "System does not support DMA, aborting.\n"); rc = -EIO; goto err_out_release; } @@ -5619,7 +5630,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) 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); @@ -5630,7 +5640,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->regview = ioremap_nocache(dev->base_addr, mem_len); if (!bp->regview) { - printk(KERN_ERR PFX "Cannot map register space, aborting.\n"); + dev_err(&pdev->dev, "Cannot map register space, aborting.\n"); rc = -ENOMEM; goto err_out_release; } @@ -5655,7 +5665,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->flags |= PCIX_FLAG; clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS); - + clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET; switch (clkreg) { case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ: @@ -5702,8 +5712,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) && !(bp->flags & PCIX_FLAG)) { - printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, " - "aborting.\n"); + dev_err(&pdev->dev, + "5706 A1 can only be used in a PCIX bus, aborting.\n"); goto err_out_unmap; } @@ -5724,7 +5734,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) != BNX2_DEV_INFO_SIGNATURE_MAGIC) { - printk(KERN_ERR PFX "Firmware not running, aborting.\n"); + dev_err(&pdev->dev, "Firmware not running, aborting.\n"); rc = -ENODEV; goto err_out_unmap; } @@ -5742,7 +5752,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->mac_addr[5] = (u8) reg; bp->tx_ring_size = MAX_TX_DESC_CNT; - bnx2_set_rx_ring_size(bp, 100); + bnx2_set_rx_ring_size(bp, 255); bp->rx_csum = 1; @@ -5752,7 +5762,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->tx_quick_cons_trip = 20; bp->tx_ticks_int = 80; bp->tx_ticks = 80; - + bp->rx_quick_cons_trip_int = 6; bp->rx_quick_cons_trip = 6; bp->rx_ticks_int = 18; @@ -5795,6 +5805,34 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->cmd_ticks_int = bp->cmd_ticks; } + /* Disable MSI on 5706 if AMD 8132 bridge is found. + * + * MSI is defined to be 32-bit write. The 5706 does 64-bit MSI writes + * with byte enables disabled on the unused 32-bit word. This is legal + * but causes problems on the AMD 8132 which will eventually stop + * responding after a while. + * + * AMD believes this incompatibility is unique to the 5706, and + * prefers to locally disable MSI rather than globally disabling it + * using pci_msi_quirk. + */ + if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) { + struct pci_dev *amd_8132 = NULL; + + while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_8132_BRIDGE, + amd_8132))) { + u8 rev; + + pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev); + if (rev >= 0x10 && rev <= 0x13) { + disable_msi = 1; + pci_dev_put(amd_8132); + break; + } + } + } + bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL; bp->req_line_speed = 0; if (bp->phy_flags & PHY_SERDES_FLAG) { @@ -5886,7 +5924,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #endif if ((rc = register_netdev(dev))) { - printk(KERN_ERR PFX "Cannot register net device\n"); + dev_err(&pdev->dev, "Cannot register net device\n"); if (bp->regview) iounmap(bp->regview); pci_release_regions(pdev); @@ -5926,7 +5964,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; #endif #ifdef BCM_TSO - dev->features |= NETIF_F_TSO; + dev->features |= NETIF_F_TSO | NETIF_F_TSO_ECN; #endif netif_carrier_off(bp->dev); @@ -5968,7 +6006,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) netif_device_detach(dev); del_timer_sync(&bp->timer); if (bp->flags & NO_WOL_FLAG) - reset_code = BNX2_DRV_MSG_CODE_UNLOAD; + reset_code = BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN; else if (bp->wol) reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL; else @@ -6006,7 +6044,7 @@ static struct pci_driver bnx2_pci_driver = { static int __init bnx2_init(void) { - return pci_module_init(&bnx2_pci_driver); + return pci_register_driver(&bnx2_pci_driver); } static void __exit bnx2_cleanup(void) |