Commit 96b021f3 authored by David S. Miller's avatar David S. Miller

Update broadcom b44 net driver:

* return errors from phy read/write
* correct rx header logic
* add missing cleanup-on-close code
parent 621ce5a8
...@@ -13,8 +13,8 @@ ...@@ -13,8 +13,8 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,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.1" #define DRV_MODULE_VERSION "0.6"
#define DRV_MODULE_RELDATE "Nov 6, 2002" #define DRV_MODULE_RELDATE "Nov 11, 2002"
#define B44_DEF_MSG_ENABLE \ #define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \ (NETIF_MSG_DRV | \
...@@ -63,7 +63,6 @@ ...@@ -63,7 +63,6 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP)) (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1)) #define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
/* XXX check this */
#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64) #define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64)
/* minimum number of free TX descriptors required to wake up TX process */ /* minimum number of free TX descriptors required to wake up TX process */
...@@ -97,8 +96,8 @@ static void b44_halt(struct b44 *); ...@@ -97,8 +96,8 @@ static void b44_halt(struct b44 *);
static void b44_init_rings(struct b44 *); static void b44_init_rings(struct b44 *);
static int b44_init_hw(struct b44 *); static int b44_init_hw(struct b44 *);
static void b44_wait_bit(struct b44 *bp, unsigned long reg, static int b44_wait_bit(struct b44 *bp, unsigned long reg,
u32 bit, unsigned long timeout, int clear) u32 bit, unsigned long timeout, const int clear)
{ {
unsigned long i; unsigned long i;
...@@ -117,7 +116,9 @@ static void b44_wait_bit(struct b44 *bp, unsigned long reg, ...@@ -117,7 +116,9 @@ static void b44_wait_bit(struct b44 *bp, unsigned long reg,
bp->dev->name, bp->dev->name,
bit, reg, bit, reg,
(clear ? "clear" : "set")); (clear ? "clear" : "set"));
return -ENODEV;
} }
return 0;
} }
/* Sonics SiliconBackplane support routines. ROFL, you should see all the /* Sonics SiliconBackplane support routines. ROFL, you should see all the
...@@ -302,15 +303,18 @@ static void b44_enable_ints(struct b44 *bp) ...@@ -302,15 +303,18 @@ static void b44_enable_ints(struct b44 *bp)
static int b44_readphy(struct b44 *bp, int reg, u32 *val) static int b44_readphy(struct b44 *bp, int reg, u32 *val)
{ {
int err;
bw32(B44_EMAC_ISTAT, EMAC_INT_MII); bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START | bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
(MDIO_OP_READ << MDIO_DATA_OP_SHIFT) | (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
(bp->phy_addr << MDIO_DATA_PMD_SHIFT) | (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
(reg << MDIO_DATA_RA_SHIFT) | (reg << MDIO_DATA_RA_SHIFT) |
(MDIO_TA_VALID << MDIO_DATA_TA_SHIFT))); (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0); err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
*val = br32(B44_MDIO_DATA) & MDIO_DATA_DATA; *val = br32(B44_MDIO_DATA) & MDIO_DATA_DATA;
return 0;
return err;
} }
static int b44_writephy(struct b44 *bp, int reg, u32 val) static int b44_writephy(struct b44 *bp, int reg, u32 val)
...@@ -322,8 +326,7 @@ static int b44_writephy(struct b44 *bp, int reg, u32 val) ...@@ -322,8 +326,7 @@ static int b44_writephy(struct b44 *bp, int reg, u32 val)
(reg << MDIO_DATA_RA_SHIFT) | (reg << MDIO_DATA_RA_SHIFT) |
(MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) | (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT) |
(val & MDIO_DATA_DATA))); (val & MDIO_DATA_DATA)));
b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0); return b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
return 0;
} }
static int b44_phy_reset(struct b44 *bp) static int b44_phy_reset(struct b44 *bp)
...@@ -576,7 +579,6 @@ static void b44_tx(struct b44 *bp) ...@@ -576,7 +579,6 @@ static void b44_tx(struct b44 *bp)
if (unlikely(skb == NULL)) if (unlikely(skb == NULL))
BUG(); BUG();
pci_unmap_single(bp->pdev, pci_unmap_single(bp->pdev,
pci_unmap_addr(rp, mapping), pci_unmap_addr(rp, mapping),
skb->len, skb->len,
...@@ -593,10 +595,16 @@ static void b44_tx(struct b44 *bp) ...@@ -593,10 +595,16 @@ static void b44_tx(struct b44 *bp)
bw32(B44_GPTIMER, 0); bw32(B44_GPTIMER, 0);
} }
/* Works like this. This chip writes a 'struct rx_header" 30 bytes
* before the DMA address you give it. So we allocate 30 more bytes
* for the RX buffer, DMA map all of it, skb_reserve the 30 bytes, then
* point the chip at 30 bytes past where the rx_header will go.
*/
static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
{ {
struct dma_desc *dp; struct dma_desc *dp;
struct ring_info *src_map, *map; struct ring_info *src_map, *map;
struct rx_header *rh;
struct sk_buff *skb; struct sk_buff *skb;
dma_addr_t mapping; dma_addr_t mapping;
int dest_idx; int dest_idx;
...@@ -617,6 +625,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) ...@@ -617,6 +625,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
skb_reserve(skb, bp->rx_offset); skb_reserve(skb, bp->rx_offset);
rh = (struct rx_header *)
(skb->data - bp->rx_offset);
rh->len = 0;
rh->flags = 0;
map->skb = skb; map->skb = skb;
pci_unmap_addr_set(map, mapping, mapping); pci_unmap_addr_set(map, mapping, mapping);
...@@ -638,6 +651,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) ...@@ -638,6 +651,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
{ {
struct dma_desc *src_desc, *dest_desc; struct dma_desc *src_desc, *dest_desc;
struct ring_info *src_map, *dest_map; struct ring_info *src_map, *dest_map;
struct rx_header *rh;
int dest_idx; int dest_idx;
u32 ctrl; u32 ctrl;
...@@ -648,6 +662,10 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) ...@@ -648,6 +662,10 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
src_map = &bp->rx_buffers[src_idx]; src_map = &bp->rx_buffers[src_idx];
dest_map->skb = src_map->skb; dest_map->skb = src_map->skb;
rh = (struct rx_header *)
(src_map->skb->data - bp->rx_offset);
rh->len = 0;
rh->flags = 0;
pci_unmap_addr_set(dest_map, mapping, pci_unmap_addr_set(dest_map, mapping,
pci_unmap_addr(src_map, mapping)); pci_unmap_addr(src_map, mapping));
...@@ -681,7 +699,8 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -681,7 +699,8 @@ static int b44_rx(struct b44 *bp, int budget)
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
rh = (struct rx_header *) (skb->data - bp->rx_offset); rh = (struct rx_header *) (skb->data - bp->rx_offset);
len = cpu_to_le16(rh->len); len = cpu_to_le16(rh->len);
if (rh->flags & cpu_to_le16(RX_FLAG_ERRORS)) { if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
(rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
drop_it: drop_it:
b44_recycle_rx(bp, cons, bp->rx_prod); b44_recycle_rx(bp, cons, bp->rx_prod);
drop_it_no_recycle: drop_it_no_recycle:
...@@ -689,6 +708,21 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -689,6 +708,21 @@ static int b44_rx(struct b44 *bp, int budget)
goto next_pkt; goto next_pkt;
} }
if (len == 0) {
int i = 0;
do {
udelay(2);
barrier();
len = cpu_to_le16(rh->len);
} while (len == 0 && i++ < 5);
if (len == 0)
goto drop_it;
}
/* Omit CRC. */
len -= 4;
if (len > RX_COPY_THRESHOLD) { if (len > RX_COPY_THRESHOLD) {
int skb_size; int skb_size;
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod); skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
...@@ -928,7 +962,7 @@ static void b44_free_rings(struct b44 *bp) ...@@ -928,7 +962,7 @@ static void b44_free_rings(struct b44 *bp)
continue; continue;
pci_unmap_single(bp->pdev, pci_unmap_single(bp->pdev,
pci_unmap_addr(rp, mapping), pci_unmap_addr(rp, mapping),
RX_PKT_BUF_SZ - bp->rx_offset, RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(rp->skb); dev_kfree_skb_any(rp->skb);
rp->skb = NULL; rp->skb = NULL;
...@@ -1054,7 +1088,10 @@ static void b44_chip_reset(struct b44 *bp) ...@@ -1054,7 +1088,10 @@ static void b44_chip_reset(struct b44 *bp)
b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1); b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
bw32(B44_DMATX_CTRL, 0); bw32(B44_DMATX_CTRL, 0);
bp->tx_prod = bp->tx_cons = 0; bp->tx_prod = bp->tx_cons = 0;
b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE, 100, 0); if (br32(B44_DMARX_STAT) & DMARX_STAT_EMASK) {
b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
100, 0);
}
bw32(B44_DMARX_CTRL, 0); bw32(B44_DMARX_CTRL, 0);
bp->rx_prod = bp->rx_cons = 0; bp->rx_prod = bp->rx_cons = 0;
} else { } else {
...@@ -1233,7 +1270,18 @@ static int b44_close(struct net_device *dev) ...@@ -1233,7 +1270,18 @@ static int b44_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
del_timer_sync(&bp->timer);
spin_lock_irq(&bp->lock); spin_lock_irq(&bp->lock);
#if 0
b44_dump_state(bp);
#endif
b44_halt(bp);
b44_free_rings(bp);
bp->flags &= ~B44_FLAG_INIT_COMPLETE;
netif_carrier_off(bp->dev);
spin_unlock_irq(&bp->lock); spin_unlock_irq(&bp->lock);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
...@@ -1810,10 +1858,6 @@ static struct pci_driver b44_driver = { ...@@ -1810,10 +1858,6 @@ static struct pci_driver b44_driver = {
.id_table = b44_pci_tbl, .id_table = b44_pci_tbl,
.probe = b44_init_one, .probe = b44_init_one,
.remove = __devexit_p(b44_remove_one), .remove = __devexit_p(b44_remove_one),
#if 0
.suspend = b44_suspend,
.resume = b44_resume
#endif
}; };
static int __init b44_init(void) static int __init b44_init(void)
...@@ -1828,3 +1872,4 @@ static void __exit b44_cleanup(void) ...@@ -1828,3 +1872,4 @@ static void __exit b44_cleanup(void)
module_init(b44_init); module_init(b44_init);
module_exit(b44_cleanup); module_exit(b44_cleanup);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment