|
@@ -2,6 +2,7 @@
|
|
*
|
|
*
|
|
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
|
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
|
|
* Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
|
|
* Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
|
|
|
|
+ * Copyright (C) 2006 Broadcom Corporation.
|
|
*
|
|
*
|
|
* Distribute under GPL.
|
|
* Distribute under GPL.
|
|
*/
|
|
*/
|
|
@@ -28,8 +29,8 @@
|
|
|
|
|
|
#define DRV_MODULE_NAME "b44"
|
|
#define DRV_MODULE_NAME "b44"
|
|
#define PFX DRV_MODULE_NAME ": "
|
|
#define PFX DRV_MODULE_NAME ": "
|
|
-#define DRV_MODULE_VERSION "0.97"
|
|
|
|
-#define DRV_MODULE_RELDATE "Nov 30, 2005"
|
|
|
|
|
|
+#define DRV_MODULE_VERSION "1.00"
|
|
|
|
+#define DRV_MODULE_RELDATE "Apr 7, 2006"
|
|
|
|
|
|
#define B44_DEF_MSG_ENABLE \
|
|
#define B44_DEF_MSG_ENABLE \
|
|
(NETIF_MSG_DRV | \
|
|
(NETIF_MSG_DRV | \
|
|
@@ -136,7 +137,7 @@ static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
|
|
return readl(bp->regs + reg);
|
|
return readl(bp->regs + reg);
|
|
}
|
|
}
|
|
|
|
|
|
-static inline void bw32(const struct b44 *bp,
|
|
|
|
|
|
+static inline void bw32(const struct b44 *bp,
|
|
unsigned long reg, unsigned long val)
|
|
unsigned long reg, unsigned long val)
|
|
{
|
|
{
|
|
writel(val, bp->regs + reg);
|
|
writel(val, bp->regs + reg);
|
|
@@ -286,13 +287,13 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
|
|
val |= ((u32) data[4]) << 8;
|
|
val |= ((u32) data[4]) << 8;
|
|
val |= ((u32) data[5]) << 0;
|
|
val |= ((u32) data[5]) << 0;
|
|
bw32(bp, B44_CAM_DATA_LO, val);
|
|
bw32(bp, B44_CAM_DATA_LO, val);
|
|
- val = (CAM_DATA_HI_VALID |
|
|
|
|
|
|
+ val = (CAM_DATA_HI_VALID |
|
|
(((u32) data[0]) << 8) |
|
|
(((u32) data[0]) << 8) |
|
|
(((u32) data[1]) << 0));
|
|
(((u32) data[1]) << 0));
|
|
bw32(bp, B44_CAM_DATA_HI, val);
|
|
bw32(bp, B44_CAM_DATA_HI, val);
|
|
bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
|
|
bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
|
|
(index << CAM_CTRL_INDEX_SHIFT)));
|
|
(index << CAM_CTRL_INDEX_SHIFT)));
|
|
- b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
|
|
|
|
|
|
+ b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);
|
|
}
|
|
}
|
|
|
|
|
|
static inline void __b44_disable_ints(struct b44 *bp)
|
|
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)
|
|
|
|
|
|
static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
|
|
static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
|
|
{
|
|
{
|
|
- u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE |
|
|
|
|
- B44_FLAG_RX_PAUSE);
|
|
|
|
|
|
+ u32 pause_enab = 0;
|
|
|
|
|
|
- if (local & ADVERTISE_PAUSE_CAP) {
|
|
|
|
- if (local & ADVERTISE_PAUSE_ASYM) {
|
|
|
|
- if (remote & LPA_PAUSE_CAP)
|
|
|
|
- pause_enab |= (B44_FLAG_TX_PAUSE |
|
|
|
|
- B44_FLAG_RX_PAUSE);
|
|
|
|
- else if (remote & LPA_PAUSE_ASYM)
|
|
|
|
- pause_enab |= B44_FLAG_RX_PAUSE;
|
|
|
|
- } else {
|
|
|
|
- if (remote & LPA_PAUSE_CAP)
|
|
|
|
- pause_enab |= (B44_FLAG_TX_PAUSE |
|
|
|
|
- B44_FLAG_RX_PAUSE);
|
|
|
|
- }
|
|
|
|
- } else if (local & ADVERTISE_PAUSE_ASYM) {
|
|
|
|
- if ((remote & LPA_PAUSE_CAP) &&
|
|
|
|
- (remote & LPA_PAUSE_ASYM))
|
|
|
|
- pause_enab |= B44_FLAG_TX_PAUSE;
|
|
|
|
|
|
+ /* The driver supports only rx pause by default because
|
|
|
|
+ the b44 mac tx pause mechanism generates excessive
|
|
|
|
+ pause frames.
|
|
|
|
+ Use ethtool to turn on b44 tx pause if necessary.
|
|
|
|
+ */
|
|
|
|
+ if ((local & ADVERTISE_PAUSE_CAP) &&
|
|
|
|
+ (local & ADVERTISE_PAUSE_ASYM)){
|
|
|
|
+ if ((remote & LPA_PAUSE_ASYM) &&
|
|
|
|
+ !(remote & LPA_PAUSE_CAP))
|
|
|
|
+ pause_enab |= B44_FLAG_RX_PAUSE;
|
|
}
|
|
}
|
|
|
|
|
|
__b44_set_flow_ctrl(bp, pause_enab);
|
|
__b44_set_flow_ctrl(bp, pause_enab);
|
|
@@ -1063,7 +1057,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu)
|
|
spin_unlock_irq(&bp->lock);
|
|
spin_unlock_irq(&bp->lock);
|
|
|
|
|
|
b44_enable_ints(bp);
|
|
b44_enable_ints(bp);
|
|
-
|
|
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1381,7 +1375,7 @@ static void b44_init_hw(struct b44 *bp)
|
|
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
|
|
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
|
|
|
|
|
|
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
|
|
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
|
|
- bp->rx_prod = bp->rx_pending;
|
|
|
|
|
|
+ bp->rx_prod = bp->rx_pending;
|
|
|
|
|
|
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
|
|
bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
|
|
|
|
|
|
@@ -1553,9 +1547,9 @@ static void __b44_set_rx_mode(struct net_device *dev)
|
|
val |= RXCONFIG_ALLMULTI;
|
|
val |= RXCONFIG_ALLMULTI;
|
|
else
|
|
else
|
|
i = __b44_load_mcast(bp, dev);
|
|
i = __b44_load_mcast(bp, dev);
|
|
-
|
|
|
|
|
|
+
|
|
for (; i < 64; i++) {
|
|
for (; i < 64; i++) {
|
|
- __b44_cam_write(bp, zero, i);
|
|
|
|
|
|
+ __b44_cam_write(bp, zero, i);
|
|
}
|
|
}
|
|
bw32(bp, B44_RXCONFIG, val);
|
|
bw32(bp, B44_RXCONFIG, val);
|
|
val = br32(bp, B44_CAM_CTRL);
|
|
val = br32(bp, B44_CAM_CTRL);
|
|
@@ -1737,7 +1731,7 @@ static int b44_set_ringparam(struct net_device *dev,
|
|
spin_unlock_irq(&bp->lock);
|
|
spin_unlock_irq(&bp->lock);
|
|
|
|
|
|
b44_enable_ints(bp);
|
|
b44_enable_ints(bp);
|
|
-
|
|
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1782,7 +1776,7 @@ static int b44_set_pauseparam(struct net_device *dev,
|
|
spin_unlock_irq(&bp->lock);
|
|
spin_unlock_irq(&bp->lock);
|
|
|
|
|
|
b44_enable_ints(bp);
|
|
b44_enable_ints(bp);
|
|
-
|
|
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1898,7 +1892,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
|
|
bp->core_unit = ssb_core_unit(bp);
|
|
bp->core_unit = ssb_core_unit(bp);
|
|
bp->dma_offset = SB_PCI_DMA;
|
|
bp->dma_offset = SB_PCI_DMA;
|
|
|
|
|
|
- /* XXX - really required?
|
|
|
|
|
|
+ /* XXX - really required?
|
|
bp->flags |= B44_FLAG_BUGGY_TXPTR;
|
|
bp->flags |= B44_FLAG_BUGGY_TXPTR;
|
|
*/
|
|
*/
|
|
out:
|
|
out:
|
|
@@ -1946,7 +1940,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|
"aborting.\n");
|
|
"aborting.\n");
|
|
goto err_out_free_res;
|
|
goto err_out_free_res;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
|
|
err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
|
|
if (err) {
|
|
if (err) {
|
|
printk(KERN_ERR PFX "No usable DMA configuration, "
|
|
printk(KERN_ERR PFX "No usable DMA configuration, "
|
|
@@ -2041,9 +2035,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
|
|
|
|
|
|
pci_save_state(bp->pdev);
|
|
pci_save_state(bp->pdev);
|
|
|
|
|
|
- /* Chip reset provides power to the b44 MAC & PCI cores, which
|
|
|
|
|
|
+ /* Chip reset provides power to the b44 MAC & PCI cores, which
|
|
* is necessary for MAC register access.
|
|
* is necessary for MAC register access.
|
|
- */
|
|
|
|
|
|
+ */
|
|
b44_chip_reset(bp);
|
|
b44_chip_reset(bp);
|
|
|
|
|
|
printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
|
|
printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
|
|
@@ -2091,10 +2085,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
|
|
|
|
del_timer_sync(&bp->timer);
|
|
del_timer_sync(&bp->timer);
|
|
|
|
|
|
- spin_lock_irq(&bp->lock);
|
|
|
|
|
|
+ spin_lock_irq(&bp->lock);
|
|
|
|
|
|
b44_halt(bp);
|
|
b44_halt(bp);
|
|
- netif_carrier_off(bp->dev);
|
|
|
|
|
|
+ netif_carrier_off(bp->dev);
|
|
netif_device_detach(bp->dev);
|
|
netif_device_detach(bp->dev);
|
|
b44_free_rings(bp);
|
|
b44_free_rings(bp);
|
|
|
|
|