Commit 3f4b7e6a authored by Finn Thain's avatar Finn Thain Committed by David S. Miller

net/sonic: Quiesce SONIC before re-initializing descriptor memory

Make sure the SONIC's DMA engine is idle before altering the transmit
and receive descriptors. Add a helper for this as it will be needed
again.

Fixes: 1da177e4 ("Linux-2.6.12-rc2")
Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 89ba879e
...@@ -116,6 +116,24 @@ static int sonic_open(struct net_device *dev) ...@@ -116,6 +116,24 @@ static int sonic_open(struct net_device *dev)
return 0; return 0;
} }
/* Wait for the SONIC to become idle. */
static void sonic_quiesce(struct net_device *dev, u16 mask)
{
struct sonic_local * __maybe_unused lp = netdev_priv(dev);
int i;
u16 bits;
for (i = 0; i < 1000; ++i) {
bits = SONIC_READ(SONIC_CMD) & mask;
if (!bits)
return;
if (irqs_disabled() || in_interrupt())
udelay(20);
else
usleep_range(100, 200);
}
WARN_ONCE(1, "command deadline expired! 0x%04x\n", bits);
}
/* /*
* Close the SONIC device * Close the SONIC device
...@@ -132,6 +150,9 @@ static int sonic_close(struct net_device *dev) ...@@ -132,6 +150,9 @@ static int sonic_close(struct net_device *dev)
/* /*
* stop the SONIC, disable interrupts * stop the SONIC, disable interrupts
*/ */
SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
sonic_quiesce(dev, SONIC_CR_ALL);
SONIC_WRITE(SONIC_IMR, 0); SONIC_WRITE(SONIC_IMR, 0);
SONIC_WRITE(SONIC_ISR, 0x7fff); SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
...@@ -171,6 +192,9 @@ static void sonic_tx_timeout(struct net_device *dev) ...@@ -171,6 +192,9 @@ static void sonic_tx_timeout(struct net_device *dev)
* put the Sonic into software-reset mode and * put the Sonic into software-reset mode and
* disable all interrupts before releasing DMA buffers * disable all interrupts before releasing DMA buffers
*/ */
SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
sonic_quiesce(dev, SONIC_CR_ALL);
SONIC_WRITE(SONIC_IMR, 0); SONIC_WRITE(SONIC_IMR, 0);
SONIC_WRITE(SONIC_ISR, 0x7fff); SONIC_WRITE(SONIC_ISR, 0x7fff);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RST); SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
...@@ -658,6 +682,7 @@ static int sonic_init(struct net_device *dev) ...@@ -658,6 +682,7 @@ static int sonic_init(struct net_device *dev)
*/ */
SONIC_WRITE(SONIC_CMD, 0); SONIC_WRITE(SONIC_CMD, 0);
SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
sonic_quiesce(dev, SONIC_CR_ALL);
/* /*
* initialize the receive resource area * initialize the receive resource area
......
...@@ -110,6 +110,9 @@ ...@@ -110,6 +110,9 @@
#define SONIC_CR_TXP 0x0002 #define SONIC_CR_TXP 0x0002
#define SONIC_CR_HTX 0x0001 #define SONIC_CR_HTX 0x0001
#define SONIC_CR_ALL (SONIC_CR_LCAM | SONIC_CR_RRRA | \
SONIC_CR_RXEN | SONIC_CR_TXP)
/* /*
* SONIC data configuration bits * SONIC data configuration bits
*/ */
......
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