Commit db30efc4 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/spare/repo/netdev-2.6/pcnet32

into pobox.com:/spare/repo/net-drivers-2.6
parents 0908cab4 8f7bb917
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
*************************************************************************/ *************************************************************************/
#define DRV_NAME "pcnet32" #define DRV_NAME "pcnet32"
#define DRV_VERSION "1.30c" #define DRV_VERSION "1.30f"
#define DRV_RELDATE "05.25.2004" #define DRV_RELDATE "06.16.2004"
#define PFX DRV_NAME ": " #define PFX DRV_NAME ": "
static const char *version = static const char *version =
...@@ -245,6 +245,11 @@ static int full_duplex[MAX_UNITS]; ...@@ -245,6 +245,11 @@ static int full_duplex[MAX_UNITS];
* v1.30b 24 May 2004 Don Fry fix bogus tx carrier errors with 79c973, * v1.30b 24 May 2004 Don Fry fix bogus tx carrier errors with 79c973,
* assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>. * assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>.
* v1.30c 25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart. * v1.30c 25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart.
* v1.30d 01 Jun 2004 Don Fry discard oversize rx packets.
* v1.30e 11 Jun 2004 Don Fry recover after fifo error and rx hang.
* v1.30f 16 Jun 2004 Don Fry cleanup IRQ to allow 0 and 1 for PCI,
* expanding on suggestions from Ralf Baechle <ralf@linux-mips.org>,
* and Brian Murphy <brian@murphy.dk>.
*/ */
...@@ -360,7 +365,7 @@ struct pcnet32_private { ...@@ -360,7 +365,7 @@ struct pcnet32_private {
static void pcnet32_probe_vlbus(void); static void pcnet32_probe_vlbus(void);
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
static int pcnet32_probe1(unsigned long, unsigned int, int, struct pci_dev *); static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
static int pcnet32_open(struct net_device *); static int pcnet32_open(struct net_device *);
static int pcnet32_init_ring(struct net_device *); static int pcnet32_init_ring(struct net_device *);
static int pcnet32_start_xmit(struct sk_buff *, struct net_device *); static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
...@@ -958,7 +963,7 @@ pcnet32_probe_vlbus(void) ...@@ -958,7 +963,7 @@ pcnet32_probe_vlbus(void)
if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) { if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) {
/* check if there is really a pcnet chip on that ioaddr */ /* check if there is really a pcnet chip on that ioaddr */
if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) { if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) {
pcnet32_probe1(ioaddr, 0, 0, NULL); pcnet32_probe1(ioaddr, 0, NULL);
} else { } else {
release_region(ioaddr, PCNET32_TOTAL_SIZE); release_region(ioaddr, PCNET32_TOTAL_SIZE);
} }
...@@ -999,7 +1004,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -999,7 +1004,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
return -EBUSY; return -EBUSY;
} }
return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev); return pcnet32_probe1(ioaddr, 1, pdev);
} }
...@@ -1008,8 +1013,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1008,8 +1013,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
* pdev will be NULL when called from pcnet32_probe_vlbus. * pdev will be NULL when called from pcnet32_probe_vlbus.
*/ */
static int __devinit static int __devinit
pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
struct pci_dev *pdev)
{ {
struct pcnet32_private *lp; struct pcnet32_private *lp;
dma_addr_t lp_dma_addr; dma_addr_t lp_dma_addr;
...@@ -1270,11 +1274,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1270,11 +1274,8 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private,
init_block)) >> 16); init_block)) >> 16);
if (irq_line) { if (pdev) { /* use the IRQ provided by PCI */
dev->irq = irq_line; dev->irq = pdev->irq;
}
if (dev->irq >= 2) {
if (pcnet32_debug & NETIF_MSG_PROBE) if (pcnet32_debug & NETIF_MSG_PROBE)
printk(" assigned IRQ %d.\n", dev->irq); printk(" assigned IRQ %d.\n", dev->irq);
} else { } else {
...@@ -1362,8 +1363,7 @@ pcnet32_open(struct net_device *dev) ...@@ -1362,8 +1363,7 @@ pcnet32_open(struct net_device *dev)
int rc; int rc;
unsigned long flags; unsigned long flags;
if (dev->irq == 0 || if (request_irq(dev->irq, &pcnet32_interrupt,
request_irq(dev->irq, &pcnet32_interrupt,
lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) { lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) {
return -EAGAIN; return -EAGAIN;
} }
...@@ -1531,14 +1531,16 @@ pcnet32_purge_tx_ring(struct net_device *dev) ...@@ -1531,14 +1531,16 @@ pcnet32_purge_tx_ring(struct net_device *dev)
int i; int i;
for (i = 0; i < TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) { if (lp->tx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
dev_kfree_skb_any(lp->tx_skbuff[i]); dev_kfree_skb_any(lp->tx_skbuff[i]);
}
lp->tx_skbuff[i] = NULL; lp->tx_skbuff[i] = NULL;
lp->tx_dma_addr[i] = 0; lp->tx_dma_addr[i] = 0;
} }
}
} }
...@@ -1566,21 +1568,23 @@ pcnet32_init_ring(struct net_device *dev) ...@@ -1566,21 +1568,23 @@ pcnet32_init_ring(struct net_device *dev)
skb_reserve (rx_skbuff, 2); skb_reserve (rx_skbuff, 2);
} }
rmb();
if (lp->rx_dma_addr[i] == 0) if (lp->rx_dma_addr[i] == 0)
lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail,
PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]);
lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ);
wmb(); /* Make sure owner changes after all others are visible */
lp->rx_ring[i].status = le16_to_cpu(0x8000); lp->rx_ring[i].status = le16_to_cpu(0x8000);
} }
/* The Tx buffer address is filled in as needed, but we do need to clear /* The Tx buffer address is filled in as needed, but we do need to clear
* the upper ownership bit. */ * the upper ownership bit. */
for (i = 0; i < TX_RING_SIZE; i++) { for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
lp->tx_ring[i].base = 0; lp->tx_ring[i].base = 0;
lp->tx_ring[i].status = 0;
lp->tx_dma_addr[i] = 0; lp->tx_dma_addr[i] = 0;
} }
wmb(); /* Make sure all changes are visible */
lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
...@@ -1589,9 +1593,14 @@ pcnet32_init_ring(struct net_device *dev) ...@@ -1589,9 +1593,14 @@ pcnet32_init_ring(struct net_device *dev)
offsetof(struct pcnet32_private, rx_ring)); offsetof(struct pcnet32_private, rx_ring));
lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
offsetof(struct pcnet32_private, tx_ring)); offsetof(struct pcnet32_private, tx_ring));
wmb(); /* Make sure all changes are visible */
return 0; return 0;
} }
/* the pcnet32 has been issued a stop or reset. Wait for the stop bit
* then flush the pending transmit operations, re-initialize the ring,
* and tell the chip to initialize.
*/
static void static void
pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
{ {
...@@ -1599,6 +1608,15 @@ pcnet32_restart(struct net_device *dev, unsigned int csr0_bits) ...@@ -1599,6 +1608,15 @@ pcnet32_restart(struct net_device *dev, unsigned int csr0_bits)
unsigned long ioaddr = dev->base_addr; unsigned long ioaddr = dev->base_addr;
int i; int i;
/* wait for stop */
for (i=0; i<100; i++)
if (lp->a.read_csr(ioaddr, 0) & 0x0004)
break;
if (i >= 100 && netif_msg_drv(lp))
printk(KERN_ERR "%s: pcnet32_restart timed out waiting for stop.\n",
dev->name);
pcnet32_purge_tx_ring(dev); pcnet32_purge_tx_ring(dev);
if (pcnet32_init_ring(dev)) if (pcnet32_init_ring(dev))
return; return;
...@@ -1857,15 +1875,16 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1857,15 +1875,16 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
} }
if (must_restart) { if (must_restart) {
/* stop the chip to clear the error condition, then restart */ /* reset the chip to clear the error condition, then restart */
lp->a.write_csr (ioaddr, 0, 0x0004); lp->a.reset(ioaddr);
lp->a.write_csr(ioaddr, 4, 0x0915);
pcnet32_restart(dev, 0x0002); pcnet32_restart(dev, 0x0002);
netif_wake_queue(dev); netif_wake_queue(dev);
} }
} }
/* Clear any other interrupt, and set interrupt enable. */ /* Set interrupt enable. */
lp->a.write_csr (ioaddr, 0, 0x7940); lp->a.write_csr (ioaddr, 0, 0x0040);
lp->a.write_rap (ioaddr,rap); lp->a.write_rap (ioaddr,rap);
if (netif_msg_intr(lp)) if (netif_msg_intr(lp))
...@@ -1907,7 +1926,13 @@ pcnet32_rx(struct net_device *dev) ...@@ -1907,7 +1926,13 @@ pcnet32_rx(struct net_device *dev)
short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4;
struct sk_buff *skb; struct sk_buff *skb;
if (pkt_len < 60) { /* Discard oversize frames. */
if (unlikely(pkt_len > PKT_BUF_SZ - 2)) {
if (netif_msg_drv(lp))
printk(KERN_ERR "%s: Impossible packet size %d!\n",
dev->name, pkt_len);
lp->stats.rx_errors++;
} else if (pkt_len < 60) {
if (netif_msg_rx_err(lp)) if (netif_msg_rx_err(lp))
printk(KERN_ERR "%s: Runt packet!\n", dev->name); printk(KERN_ERR "%s: Runt packet!\n", dev->name);
lp->stats.rx_errors++; lp->stats.rx_errors++;
......
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