diff options
Diffstat (limited to 'drivers/net/b44.c')
-rw-r--r-- | drivers/net/b44.c | 77 |
1 files changed, 42 insertions, 35 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index c3267e4e1bb0..3d306681919e 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) |
4 | * Fixed by Pekka Pietikainen (pp@ee.oulu.fi) | 4 | * Fixed by Pekka Pietikainen (pp@ee.oulu.fi) |
5 | * Copyright (C) 2006 Broadcom Corporation. | ||
5 | * | 6 | * |
6 | * Distribute under GPL. | 7 | * Distribute under GPL. |
7 | */ | 8 | */ |
@@ -28,8 +29,8 @@ | |||
28 | 29 | ||
29 | #define DRV_MODULE_NAME "b44" | 30 | #define DRV_MODULE_NAME "b44" |
30 | #define PFX DRV_MODULE_NAME ": " | 31 | #define PFX DRV_MODULE_NAME ": " |
31 | #define DRV_MODULE_VERSION "0.97" | 32 | #define DRV_MODULE_VERSION "1.00" |
32 | #define DRV_MODULE_RELDATE "Nov 30, 2005" | 33 | #define DRV_MODULE_RELDATE "Apr 7, 2006" |
33 | 34 | ||
34 | #define B44_DEF_MSG_ENABLE \ | 35 | #define B44_DEF_MSG_ENABLE \ |
35 | (NETIF_MSG_DRV | \ | 36 | (NETIF_MSG_DRV | \ |
@@ -136,7 +137,7 @@ static inline unsigned long br32(const struct b44 *bp, unsigned long reg) | |||
136 | return readl(bp->regs + reg); | 137 | return readl(bp->regs + reg); |
137 | } | 138 | } |
138 | 139 | ||
139 | static inline void bw32(const struct b44 *bp, | 140 | static inline void bw32(const struct b44 *bp, |
140 | unsigned long reg, unsigned long val) | 141 | unsigned long reg, unsigned long val) |
141 | { | 142 | { |
142 | writel(val, bp->regs + reg); | 143 | writel(val, bp->regs + reg); |
@@ -286,13 +287,13 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index) | |||
286 | val |= ((u32) data[4]) << 8; | 287 | val |= ((u32) data[4]) << 8; |
287 | val |= ((u32) data[5]) << 0; | 288 | val |= ((u32) data[5]) << 0; |
288 | bw32(bp, B44_CAM_DATA_LO, val); | 289 | bw32(bp, B44_CAM_DATA_LO, val); |
289 | val = (CAM_DATA_HI_VALID | | 290 | val = (CAM_DATA_HI_VALID | |
290 | (((u32) data[0]) << 8) | | 291 | (((u32) data[0]) << 8) | |
291 | (((u32) data[1]) << 0)); | 292 | (((u32) data[1]) << 0)); |
292 | bw32(bp, B44_CAM_DATA_HI, val); | 293 | bw32(bp, B44_CAM_DATA_HI, val); |
293 | bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE | | 294 | bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE | |
294 | (index << CAM_CTRL_INDEX_SHIFT))); | 295 | (index << CAM_CTRL_INDEX_SHIFT))); |
295 | b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1); | 296 | b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1); |
296 | } | 297 | } |
297 | 298 | ||
298 | static inline void __b44_disable_ints(struct b44 *bp) | 299 | static inline void __b44_disable_ints(struct b44 *bp) |
@@ -410,25 +411,18 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags) | |||
410 | 411 | ||
411 | static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote) | 412 | static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote) |
412 | { | 413 | { |
413 | u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE | | 414 | u32 pause_enab = 0; |
414 | B44_FLAG_RX_PAUSE); | ||
415 | 415 | ||
416 | if (local & ADVERTISE_PAUSE_CAP) { | 416 | /* The driver supports only rx pause by default because |
417 | if (local & ADVERTISE_PAUSE_ASYM) { | 417 | the b44 mac tx pause mechanism generates excessive |
418 | if (remote & LPA_PAUSE_CAP) | 418 | pause frames. |
419 | pause_enab |= (B44_FLAG_TX_PAUSE | | 419 | Use ethtool to turn on b44 tx pause if necessary. |
420 | B44_FLAG_RX_PAUSE); | 420 | */ |
421 | else if (remote & LPA_PAUSE_ASYM) | 421 | if ((local & ADVERTISE_PAUSE_CAP) && |
422 | pause_enab |= B44_FLAG_RX_PAUSE; | 422 | (local & ADVERTISE_PAUSE_ASYM)){ |
423 | } else { | 423 | if ((remote & LPA_PAUSE_ASYM) && |
424 | if (remote & LPA_PAUSE_CAP) | 424 | !(remote & LPA_PAUSE_CAP)) |
425 | pause_enab |= (B44_FLAG_TX_PAUSE | | 425 | pause_enab |= B44_FLAG_RX_PAUSE; |
426 | B44_FLAG_RX_PAUSE); | ||
427 | } | ||
428 | } else if (local & ADVERTISE_PAUSE_ASYM) { | ||
429 | if ((remote & LPA_PAUSE_CAP) && | ||
430 | (remote & LPA_PAUSE_ASYM)) | ||
431 | pause_enab |= B44_FLAG_TX_PAUSE; | ||
432 | } | 426 | } |
433 | 427 | ||
434 | __b44_set_flow_ctrl(bp, pause_enab); | 428 | __b44_set_flow_ctrl(bp, pause_enab); |
@@ -608,8 +602,7 @@ static void b44_tx(struct b44 *bp) | |||
608 | struct ring_info *rp = &bp->tx_buffers[cons]; | 602 | struct ring_info *rp = &bp->tx_buffers[cons]; |
609 | struct sk_buff *skb = rp->skb; | 603 | struct sk_buff *skb = rp->skb; |
610 | 604 | ||
611 | if (unlikely(skb == NULL)) | 605 | BUG_ON(skb == NULL); |
612 | BUG(); | ||
613 | 606 | ||
614 | pci_unmap_single(bp->pdev, | 607 | pci_unmap_single(bp->pdev, |
615 | pci_unmap_addr(rp, mapping), | 608 | pci_unmap_addr(rp, mapping), |
@@ -1064,7 +1057,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu) | |||
1064 | spin_unlock_irq(&bp->lock); | 1057 | spin_unlock_irq(&bp->lock); |
1065 | 1058 | ||
1066 | b44_enable_ints(bp); | 1059 | b44_enable_ints(bp); |
1067 | 1060 | ||
1068 | return 0; | 1061 | return 0; |
1069 | } | 1062 | } |
1070 | 1063 | ||
@@ -1339,6 +1332,9 @@ static int b44_set_mac_addr(struct net_device *dev, void *p) | |||
1339 | if (netif_running(dev)) | 1332 | if (netif_running(dev)) |
1340 | return -EBUSY; | 1333 | return -EBUSY; |
1341 | 1334 | ||
1335 | if (!is_valid_ether_addr(addr->sa_data)) | ||
1336 | return -EINVAL; | ||
1337 | |||
1342 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | 1338 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); |
1343 | 1339 | ||
1344 | spin_lock_irq(&bp->lock); | 1340 | spin_lock_irq(&bp->lock); |
@@ -1379,7 +1375,7 @@ static void b44_init_hw(struct b44 *bp) | |||
1379 | bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); | 1375 | bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); |
1380 | 1376 | ||
1381 | bw32(bp, B44_DMARX_PTR, bp->rx_pending); | 1377 | bw32(bp, B44_DMARX_PTR, bp->rx_pending); |
1382 | bp->rx_prod = bp->rx_pending; | 1378 | bp->rx_prod = bp->rx_pending; |
1383 | 1379 | ||
1384 | bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); | 1380 | bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); |
1385 | 1381 | ||
@@ -1551,9 +1547,9 @@ static void __b44_set_rx_mode(struct net_device *dev) | |||
1551 | val |= RXCONFIG_ALLMULTI; | 1547 | val |= RXCONFIG_ALLMULTI; |
1552 | else | 1548 | else |
1553 | i = __b44_load_mcast(bp, dev); | 1549 | i = __b44_load_mcast(bp, dev); |
1554 | 1550 | ||
1555 | for (; i < 64; i++) { | 1551 | for (; i < 64; i++) { |
1556 | __b44_cam_write(bp, zero, i); | 1552 | __b44_cam_write(bp, zero, i); |
1557 | } | 1553 | } |
1558 | bw32(bp, B44_RXCONFIG, val); | 1554 | bw32(bp, B44_RXCONFIG, val); |
1559 | val = br32(bp, B44_CAM_CTRL); | 1555 | val = br32(bp, B44_CAM_CTRL); |
@@ -1735,7 +1731,7 @@ static int b44_set_ringparam(struct net_device *dev, | |||
1735 | spin_unlock_irq(&bp->lock); | 1731 | spin_unlock_irq(&bp->lock); |
1736 | 1732 | ||
1737 | b44_enable_ints(bp); | 1733 | b44_enable_ints(bp); |
1738 | 1734 | ||
1739 | return 0; | 1735 | return 0; |
1740 | } | 1736 | } |
1741 | 1737 | ||
@@ -1780,7 +1776,7 @@ static int b44_set_pauseparam(struct net_device *dev, | |||
1780 | spin_unlock_irq(&bp->lock); | 1776 | spin_unlock_irq(&bp->lock); |
1781 | 1777 | ||
1782 | b44_enable_ints(bp); | 1778 | b44_enable_ints(bp); |
1783 | 1779 | ||
1784 | return 0; | 1780 | return 0; |
1785 | } | 1781 | } |
1786 | 1782 | ||
@@ -1876,6 +1872,12 @@ static int __devinit b44_get_invariants(struct b44 *bp) | |||
1876 | bp->dev->dev_addr[3] = eeprom[80]; | 1872 | bp->dev->dev_addr[3] = eeprom[80]; |
1877 | bp->dev->dev_addr[4] = eeprom[83]; | 1873 | bp->dev->dev_addr[4] = eeprom[83]; |
1878 | bp->dev->dev_addr[5] = eeprom[82]; | 1874 | bp->dev->dev_addr[5] = eeprom[82]; |
1875 | |||
1876 | if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ | ||
1877 | printk(KERN_ERR PFX "Invalid MAC address found in EEPROM\n"); | ||
1878 | return -EINVAL; | ||
1879 | } | ||
1880 | |||
1879 | memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len); | 1881 | memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len); |
1880 | 1882 | ||
1881 | bp->phy_addr = eeprom[90] & 0x1f; | 1883 | bp->phy_addr = eeprom[90] & 0x1f; |
@@ -1890,7 +1892,7 @@ static int __devinit b44_get_invariants(struct b44 *bp) | |||
1890 | bp->core_unit = ssb_core_unit(bp); | 1892 | bp->core_unit = ssb_core_unit(bp); |
1891 | bp->dma_offset = SB_PCI_DMA; | 1893 | bp->dma_offset = SB_PCI_DMA; |
1892 | 1894 | ||
1893 | /* XXX - really required? | 1895 | /* XXX - really required? |
1894 | bp->flags |= B44_FLAG_BUGGY_TXPTR; | 1896 | bp->flags |= B44_FLAG_BUGGY_TXPTR; |
1895 | */ | 1897 | */ |
1896 | out: | 1898 | out: |
@@ -1938,7 +1940,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1938 | "aborting.\n"); | 1940 | "aborting.\n"); |
1939 | goto err_out_free_res; | 1941 | goto err_out_free_res; |
1940 | } | 1942 | } |
1941 | 1943 | ||
1942 | err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); | 1944 | err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); |
1943 | if (err) { | 1945 | if (err) { |
1944 | printk(KERN_ERR PFX "No usable DMA configuration, " | 1946 | printk(KERN_ERR PFX "No usable DMA configuration, " |
@@ -2033,6 +2035,11 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
2033 | 2035 | ||
2034 | pci_save_state(bp->pdev); | 2036 | pci_save_state(bp->pdev); |
2035 | 2037 | ||
2038 | /* Chip reset provides power to the b44 MAC & PCI cores, which | ||
2039 | * is necessary for MAC register access. | ||
2040 | */ | ||
2041 | b44_chip_reset(bp); | ||
2042 | |||
2036 | printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); | 2043 | printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); |
2037 | for (i = 0; i < 6; i++) | 2044 | for (i = 0; i < 6; i++) |
2038 | printk("%2.2x%c", dev->dev_addr[i], | 2045 | printk("%2.2x%c", dev->dev_addr[i], |
@@ -2078,10 +2085,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2078 | 2085 | ||
2079 | del_timer_sync(&bp->timer); | 2086 | del_timer_sync(&bp->timer); |
2080 | 2087 | ||
2081 | spin_lock_irq(&bp->lock); | 2088 | spin_lock_irq(&bp->lock); |
2082 | 2089 | ||
2083 | b44_halt(bp); | 2090 | b44_halt(bp); |
2084 | netif_carrier_off(bp->dev); | 2091 | netif_carrier_off(bp->dev); |
2085 | netif_device_detach(bp->dev); | 2092 | netif_device_detach(bp->dev); |
2086 | b44_free_rings(bp); | 2093 | b44_free_rings(bp); |
2087 | 2094 | ||