Commit be1f6b36 authored by Pekka Pietikäinen's avatar Pekka Pietikäinen Committed by Jeff Garzik

[netdrvr b44] tons of fixes. should work now.

parent cd8e2b44
/* b44.c: Broadcom 4400 device driver. /* b44.c: Broadcom 4400 device driver.
* *
* 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)
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -14,6 +15,7 @@ ...@@ -14,6 +15,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/version.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -23,8 +25,8 @@ ...@@ -23,8 +25,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.6" #define DRV_MODULE_VERSION "0.9"
#define DRV_MODULE_RELDATE "Nov 11, 2002" #define DRV_MODULE_RELDATE "Jul 14, 2003"
#define B44_DEF_MSG_ENABLE \ #define B44_DEF_MSG_ENABLE \
(NETIF_MSG_DRV | \ (NETIF_MSG_DRV | \
...@@ -78,6 +80,15 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value"); ...@@ -78,6 +80,15 @@ MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
static int b44_debug = -1; /* -1 == use B44_DEF_MSG_ENABLE as value */ static int b44_debug = -1; /* -1 == use B44_DEF_MSG_ENABLE as value */
#ifndef PCI_DEVICE_ID_BCM4401
#define PCI_DEVICE_ID_BCM4401 0x4401
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define IRQ_RETVAL(x)
#define irqreturn_t void
#endif
static struct pci_device_id b44_pci_tbl[] __devinitdata = { static struct pci_device_id b44_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
...@@ -259,7 +270,7 @@ static int ssb_is_core_up(struct b44 *bp) ...@@ -259,7 +270,7 @@ static int ssb_is_core_up(struct b44 *bp)
== SBTMSLOW_CLOCK); == SBTMSLOW_CLOCK);
} }
static void __b44_cam_write(struct b44 *bp, char *data, int index) static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
{ {
u32 val; u32 val;
...@@ -521,7 +532,7 @@ static void b44_check_phy(struct b44 *bp) ...@@ -521,7 +532,7 @@ static void b44_check_phy(struct b44 *bp)
/* Link now up */ /* Link now up */
netif_carrier_on(bp->dev); netif_carrier_on(bp->dev);
b44_link_report(bp); b44_link_report(bp);
} else if (netif_carrier_ok(bp->dev)) { } else if (netif_carrier_ok(bp->dev) && !(bmsr & BMSR_LSTATUS)) {
/* Link now down */ /* Link now down */
netif_carrier_off(bp->dev); netif_carrier_off(bp->dev);
b44_link_report(bp); b44_link_report(bp);
...@@ -650,8 +661,7 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) ...@@ -650,8 +661,7 @@ 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 *) rh = (struct rx_header *) src_map->skb->data;
(src_map->skb->data - bp->rx_offset);
rh->len = 0; rh->len = 0;
rh->flags = 0; rh->flags = 0;
pci_unmap_addr_set(dest_map, mapping, pci_unmap_addr_set(dest_map, mapping,
...@@ -660,9 +670,12 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked) ...@@ -660,9 +670,12 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
ctrl = src_desc->ctrl; ctrl = src_desc->ctrl;
if (dest_idx == (B44_RX_RING_SIZE - 1)) if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= cpu_to_le32(DESC_CTRL_EOT); ctrl |= cpu_to_le32(DESC_CTRL_EOT);
else
ctrl &= cpu_to_le32(~DESC_CTRL_EOT);
dest_desc->ctrl = ctrl; dest_desc->ctrl = ctrl;
dest_desc->addr = src_desc->addr; dest_desc->addr = src_desc->addr;
src_map->skb = NULL;
} }
static int b44_rx(struct b44 *bp, int budget) static int b44_rx(struct b44 *bp, int budget)
...@@ -685,7 +698,7 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -685,7 +698,7 @@ static int b44_rx(struct b44 *bp, int budget)
pci_dma_sync_single(bp->pdev, map, pci_dma_sync_single(bp->pdev, map,
RX_PKT_BUF_SZ, RX_PKT_BUF_SZ,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
rh = (struct rx_header *) (skb->data - bp->rx_offset); rh = (struct rx_header *) skb->data;
len = cpu_to_le16(rh->len); len = cpu_to_le16(rh->len);
if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) || if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
(rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) { (rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
...@@ -718,7 +731,9 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -718,7 +731,9 @@ static int b44_rx(struct b44 *bp, int budget)
goto drop_it; goto drop_it;
pci_unmap_single(bp->pdev, map, pci_unmap_single(bp->pdev, map,
skb_size, PCI_DMA_FROMDEVICE); skb_size, PCI_DMA_FROMDEVICE);
skb_put(skb, len); /* Leave out rx_header */
skb_put(skb, len+bp->rx_offset);
skb_pull(skb,bp->rx_offset);
} else { } else {
struct sk_buff *copy_skb; struct sk_buff *copy_skb;
...@@ -730,8 +745,8 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -730,8 +745,8 @@ static int b44_rx(struct b44 *bp, int budget)
copy_skb->dev = bp->dev; copy_skb->dev = bp->dev;
skb_reserve(copy_skb, 2); skb_reserve(copy_skb, 2);
skb_put(copy_skb, len); skb_put(copy_skb, len);
/* DMA sync done above */ /* DMA sync done above, copy just the actual packet */
memcpy(copy_skb->data, skb->data, len); memcpy(copy_skb->data, skb->data+bp->rx_offset, len);
skb = copy_skb; skb = copy_skb;
} }
...@@ -748,6 +763,7 @@ static int b44_rx(struct b44 *bp, int budget) ...@@ -748,6 +763,7 @@ static int b44_rx(struct b44 *bp, int budget)
} }
bp->rx_cons = cons; bp->rx_cons = cons;
bw32(B44_DMARX_PTR, cons * sizeof(struct dma_desc));
return received; return received;
} }
...@@ -764,6 +780,7 @@ static int b44_poll(struct net_device *netdev, int *budget) ...@@ -764,6 +780,7 @@ static int b44_poll(struct net_device *netdev, int *budget)
b44_tx(bp); b44_tx(bp);
/* spin_unlock(&bp->tx_lock); */ /* spin_unlock(&bp->tx_lock); */
} }
spin_unlock_irq(&bp->lock);
done = 1; done = 1;
if (bp->istat & ISTAT_RX) { if (bp->istat & ISTAT_RX) {
...@@ -783,10 +800,12 @@ static int b44_poll(struct net_device *netdev, int *budget) ...@@ -783,10 +800,12 @@ static int b44_poll(struct net_device *netdev, int *budget)
} }
if (bp->istat & ISTAT_ERRORS) { if (bp->istat & ISTAT_ERRORS) {
spin_lock_irq(&bp->lock);
b44_halt(bp); b44_halt(bp);
b44_init_rings(bp); b44_init_rings(bp);
b44_init_hw(bp); b44_init_hw(bp);
netif_wake_queue(bp->dev); netif_wake_queue(bp->dev);
spin_unlock_irq(&bp->lock);
done = 1; done = 1;
} }
...@@ -794,7 +813,6 @@ static int b44_poll(struct net_device *netdev, int *budget) ...@@ -794,7 +813,6 @@ static int b44_poll(struct net_device *netdev, int *budget)
netif_rx_complete(netdev); netif_rx_complete(netdev);
b44_enable_ints(bp); b44_enable_ints(bp);
} }
spin_unlock_irq(&bp->lock);
return (done ? 0 : 1); return (done ? 0 : 1);
} }
...@@ -885,7 +903,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -885,7 +903,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
ctrl |= DESC_CTRL_EOT; ctrl |= DESC_CTRL_EOT;
bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl); bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping); bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
entry = NEXT_TX(entry); entry = NEXT_TX(entry);
...@@ -1173,8 +1191,8 @@ static int b44_init_hw(struct b44 *bp) ...@@ -1173,8 +1191,8 @@ static int b44_init_hw(struct b44 *bp)
__b44_set_rx_mode(bp->dev); __b44_set_rx_mode(bp->dev);
/* MTU + eth header + possible VLAN tag + struct rx_header */ /* MTU + eth header + possible VLAN tag + struct rx_header */
bw32(B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + 24); bw32(B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
bw32(B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + 24); bw32(B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
bw32(B44_TX_WMARK, 56); /* XXX magic */ bw32(B44_TX_WMARK, 56); /* XXX magic */
bw32(B44_DMATX_CTRL, DMATX_CTRL_ENABLE); bw32(B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
...@@ -1184,6 +1202,7 @@ static int b44_init_hw(struct b44 *bp) ...@@ -1184,6 +1202,7 @@ static int b44_init_hw(struct b44 *bp)
bw32(B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); bw32(B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(B44_DMARX_PTR, bp->rx_pending); bw32(B44_DMARX_PTR, bp->rx_pending);
bp->rx_prod = bp->rx_pending;
bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
...@@ -1345,6 +1364,8 @@ static void __b44_set_rx_mode(struct net_device *dev) ...@@ -1345,6 +1364,8 @@ static void __b44_set_rx_mode(struct net_device *dev)
__b44_load_mcast(bp, dev); __b44_load_mcast(bp, dev);
bw32(B44_RXCONFIG, val); bw32(B44_RXCONFIG, val);
val = br32(B44_CAM_CTRL);
bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
} }
} }
...@@ -1678,8 +1699,9 @@ static int __devinit b44_get_invariants(struct b44 *bp) ...@@ -1678,8 +1699,9 @@ 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 = ssb_get_addr(bp, SBID_PCI_DMA, 0); bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0);
bp->flags |= B44_FLAG_BUGGY_TXPTR; /* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
*/
out: out:
return err; return err;
} }
......
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
#define MDIO_OP_READ 2 #define MDIO_OP_READ 2
#define MDIO_DATA_SB_MASK 0xc0000000 /* Start Bits */ #define MDIO_DATA_SB_MASK 0xc0000000 /* Start Bits */
#define MDIO_DATA_SB_SHIFT 30 #define MDIO_DATA_SB_SHIFT 30
#define MDIO_DATA_SB_START 0x10000000 /* Start Of Frame */ #define MDIO_DATA_SB_START 0x40000000 /* Start Of Frame */
#define B44_EMAC_IMASK 0x0418UL /* EMAC Interrupt Mask */ #define B44_EMAC_IMASK 0x0418UL /* EMAC Interrupt Mask */
#define B44_EMAC_ISTAT 0x041CUL /* EMAC Interrupt Status */ #define B44_EMAC_ISTAT 0x041CUL /* EMAC Interrupt Status */
#define EMAC_INT_MII 0x00000001 /* MII MDIO Interrupt */ #define EMAC_INT_MII 0x00000001 /* MII MDIO Interrupt */
......
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