Hi people,
I have tested uCLinux-dist-20070130 with latest patch 20070130-20080131
on MCF5282 evaluation board (using kernel 2.6.x). I've payed my attention on
network applications
and I have noticed that network sometimes gets stalled and does not recover,
even
doing ifconfig down-up. I have debugged the FEC driver and it seems there's
a lost of synchronization
between FEC and the interrupt service routine attending it when packets are
received or sent.
By using my board as a web server (using Boa), I tested the network by
massively performing wget's
from my host computer (in order to retrieve a dummy file from the web
server). The result was
that, after few minutes, network stalled. Even by leaving the network quiet
for a time, I was not able
to communicate again with the board. The problem is clearly on the FEC
driver, because I could
see that interrupts were succesfully raised when packets were received but
the function handling
the RX interrupt always detected "empty packet". There was, thus, a lost of
synchronization on reading
the RX ring buffer.
I have applied some modifications on the FEC driver (see patch below) and
now network does not stall
anymore. Actually, I have been performing wget's for 12 hours and all of
them have succeeded.
Maybe someone is having the same problem. On the other hand I would be
grateful if someone having
other Coldfire based boards different from MCF5282 (e.g MCF5329, ...) could
test the patch I
attach below. In case it succeeded, I would ask for the driver matainer to
consider applying the patch.
I really can assure that the driver coming in the latest uclinux distro does
not work in all
cases (at least on my board!).
Again, patch must be applied against drivers/net/fec.c for linux 2.6.x in
uCLinux-dist-20070130 with latest patch 20070130-20080131 already applied.
Claude
****************** START OF PATCH *********************
--- fec.c 2008-02-17 00:41:12.000000000 +0100
+++ fec_new.c 2008-02-17 01:00:01.000000000 +0100
@@ -433,7 +433,7 @@
printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE);
for (i = 0 ; i < RX_RING_SIZE; i++) {
printk(" %08x: %04x %04x %08x\n",
- (uint) bdp,
+ (uint) bdp,
bdp->cbd_sc,
bdp->cbd_datlen,
(int) bdp->cbd_bufaddr);
@@ -455,19 +455,19 @@
volatile fec_t *fecp;
uint int_events;
int handled = 0;
-
+
fecp = (volatile fec_t*)dev->base_addr;
/* Get the interrupt events that caused us to be here.
*/
- while ((int_events = fecp->fec_ievent) != 0) {
- fecp->fec_ievent = int_events;
-
+ if ((int_events = (fecp->fec_ievent &
(FEC_ENET_RXF|FEC_ENET_TXF|FEC_ENET_MII))) != 0) {
+
/* Handle receive event in its own function.
*/
if (int_events & FEC_ENET_RXF) {
handled = 1;
fec_enet_rx(dev);
+ fecp->fec_ievent = FEC_ENET_RXF;
}
/* Transmit OK, or non-fatal error. Update the buffer
@@ -477,14 +477,16 @@
if (int_events & FEC_ENET_TXF) {
handled = 1;
fec_enet_tx(dev);
+ fecp->fec_ievent = FEC_ENET_TXF;
}
if (int_events & FEC_ENET_MII) {
handled = 1;
fec_enet_mii(dev);
+ fecp->fec_ievent = FEC_ENET_MII;
}
-
}
+
return IRQ_RETVAL(handled);
}
@@ -552,8 +554,9 @@
*/
if (fep->tx_full) {
fep->tx_full = 0;
- if (netif_queue_stopped(dev))
+ if (netif_queue_stopped(dev)){
netif_wake_queue(dev);
+ }
}
}
fep->dirty_tx = (cbd_t *)bdp;
@@ -580,7 +583,7 @@
#ifdef CONFIG_M532x
flush_cache_all();
#endif
-
+
fep = netdev_priv(dev);
fecp = (volatile fec_t*)dev->base_addr;
@@ -588,7 +591,8 @@
* These get messed up if we get called due to a busy condition.
*/
bdp = fep->cur_rx;
-
+
+
while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
#ifndef final_version
@@ -678,7 +682,7 @@
#endif
} /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */
fep->cur_rx = (cbd_t *)bdp;
-
+
#if 0
/* Doing this here will allow us to process all frames in the
* ring before the FEC is allowed to put more there. On a heavily
@@ -2377,7 +2381,7 @@
*/
mem_addr = __get_free_page(GFP_KERNEL);
/* XXX: missing check for allocation failure */
-
+
fec_uncache(mem_addr);
/* Initialize the BD for every fragment in the page.
@@ -2455,8 +2459,8 @@
/* Clear and enable interrupts */
fecp->fec_ievent = 0xffc00000;
- fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
- FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+ fecp->fec_imask = (FEC_ENET_TXF | /*FEC_ENET_TXB |*/
+ FEC_ENET_RXF /*| FEC_ENET_RXB */ | FEC_ENET_MII);
/* Queue up command to detect the PHY and initialize the
* remainder of the interface.
@@ -2481,6 +2485,7 @@
volatile fec_t *fecp;
int i;
+ printk("FEC restart\n");
fep = netdev_priv(dev);
fecp = fep->hwp;
@@ -2583,8 +2588,8 @@
/* Enable interrupts we wish to service.
*/
- fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
- FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+ fecp->fec_imask = (FEC_ENET_TXF | /*FEC_ENET_TXB |*/
+ FEC_ENET_RXF /*| FEC_ENET_RXB */ | FEC_ENET_MII);
}
static void
****************** END OF PATCH *********************
_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev