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 uClinux-dev@uclinux.org http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by uclinux-dev@uclinux.org To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev