[PATCH] pcnet32: Cleanup rx buffers after loopback test.
More cleanup to pcnet32_loopback_test to release receive buffers if device is not up. Created common routine to free rx buffers. Tested ia32 and ppc64 Signed-off-by: Don Fry <brazilnut@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
df27f4a610
commit
ac5bfe40f9
1 changed files with 43 additions and 59 deletions
|
@ -645,6 +645,25 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pcnet32_purge_rx_ring(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct pcnet32_private *lp = dev->priv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* free all allocated skbuffs */
|
||||||
|
for (i = 0; i < lp->rx_ring_size; i++) {
|
||||||
|
lp->rx_ring[i].status = 0; /* CPU owns buffer */
|
||||||
|
wmb(); /* Make sure adapter sees owner change */
|
||||||
|
if (lp->rx_skbuff[i]) {
|
||||||
|
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
|
||||||
|
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
||||||
|
dev_kfree_skb_any(lp->rx_skbuff[i]);
|
||||||
|
}
|
||||||
|
lp->rx_skbuff[i] = NULL;
|
||||||
|
lp->rx_dma_addr[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#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)
|
||||||
{
|
{
|
||||||
|
@ -856,29 +875,27 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned long ticks;
|
unsigned long ticks;
|
||||||
|
|
||||||
*data1 = 1; /* status of test, default to fail */
|
|
||||||
rc = 1; /* default to fail */
|
rc = 1; /* default to fail */
|
||||||
|
|
||||||
if (netif_running(dev))
|
if (netif_running(dev))
|
||||||
pcnet32_close(dev);
|
pcnet32_close(dev);
|
||||||
|
|
||||||
spin_lock_irqsave(&lp->lock, flags);
|
spin_lock_irqsave(&lp->lock, flags);
|
||||||
|
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */
|
||||||
|
|
||||||
|
numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size));
|
||||||
|
|
||||||
/* Reset the PCNET32 */
|
/* Reset the PCNET32 */
|
||||||
lp->a.reset(ioaddr);
|
lp->a.reset(ioaddr);
|
||||||
|
lp->a.write_csr(ioaddr, CSR4, 0x0915);
|
||||||
|
|
||||||
/* switch pcnet32 to 32bit mode */
|
/* switch pcnet32 to 32bit mode */
|
||||||
lp->a.write_bcr(ioaddr, 20, 2);
|
lp->a.write_bcr(ioaddr, 20, 2);
|
||||||
|
|
||||||
lp->init_block.mode =
|
|
||||||
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
|
|
||||||
lp->init_block.filter[0] = 0;
|
|
||||||
lp->init_block.filter[1] = 0;
|
|
||||||
|
|
||||||
/* purge & init rings but don't actually restart */
|
/* purge & init rings but don't actually restart */
|
||||||
pcnet32_restart(dev, 0x0000);
|
pcnet32_restart(dev, 0x0000);
|
||||||
|
|
||||||
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
|
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
|
||||||
|
|
||||||
/* Initialize Transmit buffers. */
|
/* Initialize Transmit buffers. */
|
||||||
size = data_len + 15;
|
size = data_len + 15;
|
||||||
|
@ -920,14 +937,15 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */
|
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */
|
||||||
x = x | 0x0002;
|
a->write_bcr(ioaddr, 32, x | 0x0002);
|
||||||
a->write_bcr(ioaddr, 32, x);
|
|
||||||
|
|
||||||
lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */
|
/* set int loopback in CSR15 */
|
||||||
|
x = a->read_csr(ioaddr, CSR15) & 0xfffc;
|
||||||
|
lp->a.write_csr(ioaddr, CSR15, x | 0x0044);
|
||||||
|
|
||||||
teststatus = le16_to_cpu(0x8000);
|
teststatus = le16_to_cpu(0x8000);
|
||||||
lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */
|
lp->a.write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */
|
||||||
|
|
||||||
/* Check status of descriptors */
|
/* Check status of descriptors */
|
||||||
for (x = 0; x < numbuffs; x++) {
|
for (x = 0; x < numbuffs; x++) {
|
||||||
|
@ -935,7 +953,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
||||||
rmb();
|
rmb();
|
||||||
while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
|
while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
|
||||||
spin_unlock_irqrestore(&lp->lock, flags);
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
mdelay(1);
|
msleep(1);
|
||||||
spin_lock_irqsave(&lp->lock, flags);
|
spin_lock_irqsave(&lp->lock, flags);
|
||||||
rmb();
|
rmb();
|
||||||
ticks++;
|
ticks++;
|
||||||
|
@ -948,7 +966,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */
|
lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
|
||||||
wmb();
|
wmb();
|
||||||
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
|
if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
|
||||||
printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
|
printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
|
||||||
|
@ -981,25 +999,24 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
|
||||||
}
|
}
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
if (!rc) {
|
|
||||||
*data1 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
clean_up:
|
clean_up:
|
||||||
|
*data1 = rc;
|
||||||
pcnet32_purge_tx_ring(dev);
|
pcnet32_purge_tx_ring(dev);
|
||||||
x = a->read_csr(ioaddr, 15) & 0xFFFF;
|
|
||||||
a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */
|
x = a->read_csr(ioaddr, CSR15);
|
||||||
|
a->write_csr(ioaddr, CSR15, (x & ~0x0044)); /* reset bits 6 and 2 */
|
||||||
|
|
||||||
x = a->read_bcr(ioaddr, 32); /* reset internal loopback */
|
x = a->read_bcr(ioaddr, 32); /* reset internal loopback */
|
||||||
x = x & ~0x0002;
|
a->write_bcr(ioaddr, 32, (x & ~0x0002));
|
||||||
a->write_bcr(ioaddr, 32, x);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&lp->lock, flags);
|
|
||||||
|
|
||||||
if (netif_running(dev)) {
|
if (netif_running(dev)) {
|
||||||
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
pcnet32_open(dev);
|
pcnet32_open(dev);
|
||||||
} else {
|
} else {
|
||||||
|
pcnet32_purge_rx_ring(dev);
|
||||||
lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
|
lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
|
||||||
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rc);
|
return (rc);
|
||||||
|
@ -1997,16 +2014,7 @@ static int pcnet32_open(struct net_device *dev)
|
||||||
|
|
||||||
err_free_ring:
|
err_free_ring:
|
||||||
/* free any allocated skbuffs */
|
/* free any allocated skbuffs */
|
||||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
pcnet32_purge_rx_ring(dev);
|
||||||
lp->rx_ring[i].status = 0;
|
|
||||||
if (lp->rx_skbuff[i]) {
|
|
||||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
|
|
||||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
|
||||||
dev_kfree_skb(lp->rx_skbuff[i]);
|
|
||||||
}
|
|
||||||
lp->rx_skbuff[i] = NULL;
|
|
||||||
lp->rx_dma_addr[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Switch back to 16bit mode to avoid problems with dumb
|
* Switch back to 16bit mode to avoid problems with dumb
|
||||||
|
@ -2588,7 +2596,6 @@ static int pcnet32_close(struct net_device *dev)
|
||||||
{
|
{
|
||||||
unsigned long ioaddr = dev->base_addr;
|
unsigned long ioaddr = dev->base_addr;
|
||||||
struct pcnet32_private *lp = dev->priv;
|
struct pcnet32_private *lp = dev->priv;
|
||||||
int i;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
del_timer_sync(&lp->watchdog_timer);
|
del_timer_sync(&lp->watchdog_timer);
|
||||||
|
@ -2619,31 +2626,8 @@ static int pcnet32_close(struct net_device *dev)
|
||||||
|
|
||||||
spin_lock_irqsave(&lp->lock, flags);
|
spin_lock_irqsave(&lp->lock, flags);
|
||||||
|
|
||||||
/* free all allocated skbuffs */
|
pcnet32_purge_rx_ring(dev);
|
||||||
for (i = 0; i < lp->rx_ring_size; i++) {
|
pcnet32_purge_tx_ring(dev);
|
||||||
lp->rx_ring[i].status = 0;
|
|
||||||
wmb(); /* Make sure adapter sees owner change */
|
|
||||||
if (lp->rx_skbuff[i]) {
|
|
||||||
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
|
|
||||||
PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
|
|
||||||
dev_kfree_skb(lp->rx_skbuff[i]);
|
|
||||||
}
|
|
||||||
lp->rx_skbuff[i] = NULL;
|
|
||||||
lp->rx_dma_addr[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < lp->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]) {
|
|
||||||
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
|
|
||||||
lp->tx_skbuff[i]->len,
|
|
||||||
PCI_DMA_TODEVICE);
|
|
||||||
dev_kfree_skb(lp->tx_skbuff[i]);
|
|
||||||
}
|
|
||||||
lp->tx_skbuff[i] = NULL;
|
|
||||||
lp->tx_dma_addr[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&lp->lock, flags);
|
spin_unlock_irqrestore(&lp->lock, flags);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue