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

Reply via email to