Commit 6b5501ef authored by Jeff Garzik's avatar Jeff Garzik

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

into redhat.com:/spare/repo/net-drivers-2.6
parents bcb15a27 7b29c58b
...@@ -132,6 +132,8 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { ...@@ -132,6 +132,8 @@ static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = {
}; };
#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
#define PCNET32_NUM_REGS 146
#define MAX_UNITS 8 /* More are supported, limit only on options */ #define MAX_UNITS 8 /* More are supported, limit only on options */
static int options[MAX_UNITS]; static int options[MAX_UNITS];
static int full_duplex[MAX_UNITS]; static int full_duplex[MAX_UNITS];
...@@ -234,7 +236,9 @@ static int full_duplex[MAX_UNITS]; ...@@ -234,7 +236,9 @@ static int full_duplex[MAX_UNITS];
* Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test. * Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
* Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections. * Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
* v1.29 6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical * v1.29 6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
* identification code (blink led's). * identification code (blink led's) and register dump.
* Don Fry added timer for 971/972 so skbufs don't remain on tx ring
* forever.
*/ */
...@@ -372,6 +376,9 @@ static void pcnet32_ethtool_test(struct net_device *dev, ...@@ -372,6 +376,9 @@ static void pcnet32_ethtool_test(struct net_device *dev,
static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
static int pcnet32_phys_id(struct net_device *dev, u32 data); static int pcnet32_phys_id(struct net_device *dev, u32 data);
static void pcnet32_led_blink_callback(struct net_device *dev); static void pcnet32_led_blink_callback(struct net_device *dev);
static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
enum pci_flags_bit { enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
...@@ -492,9 +499,9 @@ static struct pcnet32_access pcnet32_dwio = { ...@@ -492,9 +499,9 @@ static struct pcnet32_access pcnet32_dwio = {
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
static void pcnet32_poll_controller(struct net_device *dev) static void pcnet32_poll_controller(struct net_device *dev)
{ {
disable_irq(dev->irq); disable_irq(dev->irq);
pcnet32_interrupt(0, dev, NULL); pcnet32_interrupt(0, dev, NULL);
enable_irq(dev->irq); enable_irq(dev->irq);
} }
#endif #endif
...@@ -681,7 +688,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) ...@@ -681,7 +688,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
for (i=0; i<6; i++) for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i]; *packet++ = dev->dev_addr[i];
for (i=0; i<6; i++) for (i=0; i<6; i++)
*packet++ = dev->dev_addr[i]; *packet++ = dev->dev_addr[i];
/* type */ /* type */
*packet++ = 0x08; *packet++ = 0x08;
*packet++ = 0x06; *packet++ = 0x06;
...@@ -837,6 +844,72 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data) ...@@ -837,6 +844,72 @@ static int pcnet32_phys_id(struct net_device *dev, u32 data)
return 0; return 0;
} }
int pcnet32_get_regs_len(struct net_device *dev)
{
return(PCNET32_NUM_REGS * sizeof(u16));
}
void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr)
{
int i, csr0;
u16 *buff = ptr;
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
int ticks;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
csr0 = a->read_csr(ioaddr, 0);
if (!(csr0 & 0x0004)) { /* If not stopped */
/* set SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0001);
/* poll waiting for bit to be set */
ticks = 0;
while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
spin_unlock_irqrestore(&lp->lock, flags);
mdelay(1);
spin_lock_irqsave(&lp->lock, flags);
ticks++;
if (ticks > 200) {
if (netif_msg_hw(lp))
printk(KERN_DEBUG "%s: Error getting into suspend!\n",
dev->name);
break;
}
}
}
/* read address PROM */
for (i=0; i<16; i += 2)
*buff++ = inw(ioaddr + i);
for (i = 0; i <= 89; i++) {
*buff++ = a->read_csr(ioaddr, i);
}
*buff++ = a->read_csr(ioaddr, 112);
*buff++ = a->read_csr(ioaddr, 114);
for (i = 0; i <= 35; i++) {
*buff++ = a->read_bcr(ioaddr, i);
}
if (!(csr0 & 0x0004)) { /* If not stopped */
/* clear SUSPEND (SPND) - CSR5 bit 0 */
a->write_csr(ioaddr, 5, 0x0000);
}
i = buff - (u16 *)ptr;
for (; i < PCNET32_NUM_REGS; i++)
*buff++ = 0;
spin_unlock_irqrestore(&lp->lock, flags);
}
static struct ethtool_ops pcnet32_ethtool_ops = { static struct ethtool_ops pcnet32_ethtool_ops = {
.get_settings = pcnet32_get_settings, .get_settings = pcnet32_get_settings,
.set_settings = pcnet32_set_settings, .set_settings = pcnet32_set_settings,
...@@ -853,6 +926,8 @@ static struct ethtool_ops pcnet32_ethtool_ops = { ...@@ -853,6 +926,8 @@ static struct ethtool_ops pcnet32_ethtool_ops = {
.self_test_count = pcnet32_self_test_count, .self_test_count = pcnet32_self_test_count,
.self_test = pcnet32_ethtool_test, .self_test = pcnet32_ethtool_test,
.phys_id = pcnet32_phys_id, .phys_id = pcnet32_phys_id,
.get_regs_len = pcnet32_get_regs_len,
.get_regs = pcnet32_get_regs,
}; };
/* only probes for non-PCI devices, the rest are handled by /* only probes for non-PCI devices, the rest are handled by
...@@ -1032,6 +1107,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared, ...@@ -1032,6 +1107,13 @@ pcnet32_probe1(unsigned long ioaddr, unsigned int irq_line, int shared,
ltint = 1; ltint = 1;
} }
if (ltint) {
/* Enable timer to prevent skbuffs from remaining on the tx ring
* forever if no other tx being done. Set timer period to about
* 122 ms */
a->write_bcr(ioaddr, 31, 0x253b);
}
dev = alloc_etherdev(0); dev = alloc_etherdev(0);
if (!dev) { if (!dev) {
if (pcnet32_debug & NETIF_MSG_PROBE) if (pcnet32_debug & NETIF_MSG_PROBE)
...@@ -1371,13 +1453,18 @@ pcnet32_open(struct net_device *dev) ...@@ -1371,13 +1453,18 @@ pcnet32_open(struct net_device *dev)
/* Re-initialize the PCNET32, and start it when done. */ /* Re-initialize the PCNET32, and start it when done. */
lp->a.write_csr (ioaddr, 1, (lp->dma_addr + lp->a.write_csr (ioaddr, 1, (lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) & 0xffff); offsetof(struct pcnet32_private, init_block)) & 0xffff);
lp->a.write_csr (ioaddr, 2, (lp->dma_addr + lp->a.write_csr (ioaddr, 2, (lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) >> 16); offsetof(struct pcnet32_private, init_block)) >> 16);
lp->a.write_csr (ioaddr, 4, 0x0915); lp->a.write_csr (ioaddr, 4, 0x0915);
lp->a.write_csr (ioaddr, 0, 0x0001); lp->a.write_csr (ioaddr, 0, 0x0001);
if (lp->ltint) {
/* start the software timer */
lp->a.write_csr(ioaddr, 7, 0x0400); /* set STINTE */
}
netif_start_queue(dev); netif_start_queue(dev);
/* If we have mii, print the link status and start the watchdog */ /* If we have mii, print the link status and start the watchdog */
...@@ -1579,13 +1666,13 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -1579,13 +1666,13 @@ pcnet32_start_xmit(struct sk_buff *skb, struct net_device *dev)
int entry; int entry;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
if (netif_msg_tx_queued(lp)) { if (netif_msg_tx_queued(lp)) {
printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
dev->name, lp->a.read_csr(ioaddr, 0)); dev->name, lp->a.read_csr(ioaddr, 0));
} }
spin_lock_irqsave(&lp->lock, flags);
/* Default status -- will not enable Successful-TxDone /* Default status -- will not enable Successful-TxDone
* interrupt when that option is available to us. * interrupt when that option is available to us.
*/ */
...@@ -1646,7 +1733,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1646,7 +1733,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
struct pcnet32_private *lp; struct pcnet32_private *lp;
unsigned long ioaddr; unsigned long ioaddr;
u16 csr0,rap; u16 csr0, csr7, rap;
int boguscnt = max_interrupt_work; int boguscnt = max_interrupt_work;
int must_restart; int must_restart;
...@@ -1663,13 +1750,19 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1663,13 +1750,19 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
spin_lock(&lp->lock); spin_lock(&lp->lock);
rap = lp->a.read_rap(ioaddr); rap = lp->a.read_rap(ioaddr);
while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { csr0 = lp->a.read_csr (ioaddr, 0);
csr7 = lp->ltint ? lp->a.read_csr(ioaddr, 7) : 0;
while ((csr0 & 0x8600 || csr7 & 0x0800) && --boguscnt >= 0) {
if (csr0 == 0xffff) { if (csr0 == 0xffff) {
break; /* PCMCIA remove happened */ break; /* PCMCIA remove happened */
} }
/* Acknowledge all of the current interrupt sources ASAP. */ /* Acknowledge all of the current interrupt sources ASAP. */
lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f);
if (csr7 & 0x0800)
lp->a.write_csr(ioaddr, 7, csr7);
must_restart = 0; must_restart = 0;
if (netif_msg_intr(lp)) if (netif_msg_intr(lp))
...@@ -1679,7 +1772,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1679,7 +1772,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (csr0 & 0x0400) /* Rx interrupt */ if (csr0 & 0x0400) /* Rx interrupt */
pcnet32_rx(dev); pcnet32_rx(dev);
if (csr0 & 0x0200) { /* Tx-done interrupt */ if (csr0 & 0x0200 || csr7 & 0x0800) { /* Tx-done or Timer interrupt */
unsigned int dirty_tx = lp->dirty_tx; unsigned int dirty_tx = lp->dirty_tx;
int delta; int delta;
...@@ -1786,6 +1879,9 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs) ...@@ -1786,6 +1879,9 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp->a.write_csr (ioaddr, 0, 0x0004); lp->a.write_csr (ioaddr, 0, 0x0004);
pcnet32_restart(dev, 0x0002); pcnet32_restart(dev, 0x0002);
} }
csr0 = lp->a.read_csr (ioaddr, 0);
csr7 = lp->ltint ? lp->a.read_csr(ioaddr, 7) : 0;
} }
/* Clear any other interrupt, and set interrupt enable. */ /* Clear any other interrupt, and set interrupt enable. */
...@@ -1872,6 +1968,7 @@ pcnet32_rx(struct net_device *dev) ...@@ -1872,6 +1968,7 @@ pcnet32_rx(struct net_device *dev)
if (i > RX_RING_SIZE -2) { if (i > RX_RING_SIZE -2) {
lp->stats.rx_dropped++; lp->stats.rx_dropped++;
lp->rx_ring[entry].status |= le16_to_cpu(0x8000); lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
wmb(); /* Make sure adapter sees owner change */
lp->cur_rx++; lp->cur_rx++;
} }
break; break;
...@@ -1935,6 +2032,10 @@ pcnet32_close(struct net_device *dev) ...@@ -1935,6 +2032,10 @@ pcnet32_close(struct net_device *dev)
/* We stop the PCNET32 here -- it occasionally polls memory if we don't. */ /* We stop the PCNET32 here -- it occasionally polls memory if we don't. */
lp->a.write_csr (ioaddr, 0, 0x0004); lp->a.write_csr (ioaddr, 0, 0x0004);
if (lp->ltint) { /* Disable timer interrupts */
lp->a.write_csr(ioaddr, 7, 0x0000);
}
/* /*
* Switch back to 16bit mode to avoid problems with dumb * Switch back to 16bit mode to avoid problems with dumb
* DOS packet driver after a warm reboot * DOS packet driver after a warm reboot
...@@ -1945,9 +2046,12 @@ pcnet32_close(struct net_device *dev) ...@@ -1945,9 +2046,12 @@ pcnet32_close(struct net_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
spin_lock_irqsave(&lp->lock, flags);
/* free all allocated skbuffs */ /* free all allocated skbuffs */
for (i = 0; i < RX_RING_SIZE; i++) { for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_ring[i].status = 0; lp->rx_ring[i].status = 0;
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) { if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
...@@ -1958,6 +2062,8 @@ pcnet32_close(struct net_device *dev) ...@@ -1958,6 +2062,8 @@ pcnet32_close(struct net_device *dev)
} }
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);
...@@ -1967,6 +2073,8 @@ pcnet32_close(struct net_device *dev) ...@@ -1967,6 +2073,8 @@ pcnet32_close(struct net_device *dev)
lp->tx_dma_addr[i] = 0; lp->tx_dma_addr[i] = 0;
} }
spin_unlock_irqrestore(&lp->lock, flags);
return 0; return 0;
} }
......
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