[ECOS] How can we fix MBUF problem on old 1.3.1 code base

Jonathan Larmour jlarmour@redhat.com
Mon Sep 18 18:07:00 GMT 2000


AshCan@aol.com wrote:
> 
> Are there are few simple fixes to the 1.3.1 code base to fix the out of MBUFs panic?  What are they?

As luck would have it, I just happened to remember seeing the relevant
patch go by. Try the attached patch, but you'll probably have to
effectively apply it by hand, or tweak the patch - I doubt it will apply
straight off. I give no guarantees whether what you end up with will work
well though - it may rely on other patches being present, so take a backup
of your existing sources.

Jifl
-- 
Red Hat, 35 Cambridge Place, Cambridge, UK. CB2 1NS  Tel: +44 (1223) 728762
"Plan to be spontaneous tomorrow."  ||  These opinions are all my own fault
Index: net/drivers/eth/common/current/ChangeLog
===================================================================
RCS file: /local/cvsfiles/ecc/ecc/net/drivers/eth/common/current/ChangeLog,v
retrieving revision 1.9
diff -u -5 -p -r1.9 ChangeLog
--- net/drivers/eth/common/current/ChangeLog    2000/03/08 19:11:19     1.9
+++ net/drivers/eth/common/current/ChangeLog    2000/03/29 13:28:42
@@ -1,5 +1,10 @@
+2000-03-28  Gary Thomas  <gthomas@redhat.com>
+ 
+        * src/eth_drv.c (eth_drv_recv): Tolerate running out of MBUFs
+        instead of "panic"ing.
+ 
 2000-03-08  Gary Thomas  <gthomas@redhat.com>
 
        * src/eth_drv.c: Add some function [block] comments.
        (eth_drv_send): Use eCos scheduler lock instead of interrupt lock.
 
Index: net/drivers/eth/common/current/src/eth_drv.c
===================================================================
RCS file: /local/cvsfiles/ecc/ecc/net/drivers/eth/common/current/src/eth_drv.c,v
retrieving revision 1.7
diff -u -5 -p -r1.7 eth_drv.c
--- net/drivers/eth/common/current/src/eth_drv.c        2000/03/08 19:11:20     1.7
+++ net/drivers/eth/common/current/src/eth_drv.c        2000/03/29 13:25:07
@@ -336,11 +336,11 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
     int sg_len;
 
     /* Pull packet off interface. */
     MGETHDR(m, M_DONTWAIT, MT_DATA);
     if (m == 0) {
-        panic("out of MBUFs");
+        diag_printf("warning: eth_recv out of MBUFs\n");
     }
 
     // Set up buffers
     // Unload ethernet header separately so IP/UDP/TCP headers are aligned
     sg_list[0].buf = (CYG_ADDRESS)eh;
@@ -348,30 +348,43 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
     sg_len = 1;
 
     // Compute total length (minus ethernet header)
     total_len -= sizeof(*eh);
 
-    m->m_pkthdr.rcvif = ifp;
-    m->m_pkthdr.len = total_len;
-    mlen = MHLEN;
     top = 0;
+    mlen = MHLEN;
     mp = ⊤
 
+    if (m) {
+        m->m_pkthdr.rcvif = ifp;
+        m->m_pkthdr.len = total_len;
+    } else {
+        sg_list[sg_len].buf = (CYG_ADDRESS)0;
+        sg_list[sg_len].len = min(total_len, MCLBYTES);
+        sg_len++;
+        total_len = 0;
+    }
+
     while (total_len > 0) {
         if (top) {
             MGET(m, M_DONTWAIT, MT_DATA);
             if (m == 0) {
                 m_freem(top);
-                panic("out of MBUFs");
+                panic("out of MBUFs [2]");
             }
             mlen = MLEN;
         }
         if (total_len >= MINCLSIZE) {
             MCLGET(m, M_DONTWAIT);
             if ((m->m_flags & M_EXT) == 0) {
                 m_freem(top);
-                panic("out of MBUFs");
+                diag_printf("warning: eth_recv out of MBUFs\n");
+                sg_list[sg_len].buf = (CYG_ADDRESS)0;
+                sg_list[sg_len].len = min(total_len, MCLBYTES);
+                sg_len++;
+                top = 0;
+                break;
             }
             mlen = MCLBYTES;
         }
         m->m_len = mlen = min(total_len, mlen);
         total_len -= mlen;
@@ -386,11 +399,13 @@ eth_drv_recv(struct eth_drv_sc *sc, int 
     // Ask hardware to unload buffers
     (sc->funs->recv)(sc, sg_list, sg_len);
 
     if (net_debug) {
         for (i = 0;  i < sg_len;  i++) {
-            diag_dump_buf((void *)sg_list[i].buf, sg_list[i].len);
+            if (sg_list[i].buf) {
+                diag_dump_buf((void *)sg_list[i].buf, sg_list[i].len);
+            }
         }
     }
 
     m = top;
     if (m == 0) {
Index: net/drivers/eth/edb7xxx/current/ChangeLog
===================================================================
RCS file: /local/cvsfiles/ecc/ecc/net/drivers/eth/edb7xxx/current/ChangeLog,v
retrieving revision 1.8
diff -u -5 -p -r1.8 ChangeLog
--- net/drivers/eth/edb7xxx/current/ChangeLog   2000/03/06 15:52:28     1.8
+++ net/drivers/eth/edb7xxx/current/ChangeLog   2000/03/29 13:28:17
@@ -1,5 +1,10 @@
+2000-03-28  Gary Thomas  <gthomas@redhat.com>
+
+        * src/if_edb7xxx.c (cs8900_recv): Handle case where there were
+        no buffers (and thus the sg_list[] has NULL pointers).
+
 2000-03-06  Gary Thomas  <gthomas@redhat.com>
 
        * src/if_edb7xxx.c: Use new driver API.
 
 2000-02-29  Gary Thomas  <gthomas@cygnus.co.uk>
Index: net/drivers/eth/edb7xxx/current/src/if_edb7xxx.c
===================================================================
RCS file: /local/cvsfiles/ecc/ecc/net/drivers/eth/edb7xxx/current/src/if_edb7xxx.c,v
retrieving revision 1.6
diff -u -5 -p -r1.6 if_edb7xxx.c
--- net/drivers/eth/edb7xxx/current/src/if_edb7xxx.c    2000/03/06 15:52:29     1.6
+++ net/drivers/eth/edb7xxx/current/src/if_edb7xxx.c    2000/03/29 13:25:07
@@ -330,24 +330,29 @@ cs8900_RxEvent(struct eth_drv_sc *sc)
 //
 static void
 cs8900_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
 {
     int i, mlen;
-    unsigned short *data;
-    unsigned char *cp;
+    unsigned short *data, val;
+    unsigned char *cp, cval;
 
     for (i = 0;  i < sg_len;  i++) {
         data = (unsigned short *)sg_list[i].buf;
         mlen = sg_list[i].len;
         while (mlen >= sizeof(*data)) {
-            *data++ = CS8900_RTDATA;
+            val = CS8900_RTDATA;
+            if (data) {
+                *data++ = val;
+            }
             mlen -= sizeof(*data);
         }
         if (mlen) {
             // Fetch last odd byte
-            cp = (unsigned char *)data;
-            *cp = CS8900_RTDATA & 0xFF;
+            cval = CS8900_RTDATA & 0xFF;
+            if (cp = (unsigned char *)data) {
+                *cp = cval;
+            }
         }
     }
 }
 
 static void
Index: net/drivers/eth/quicc/current/ChangeLog
===================================================================
RCS file: /local/cvsfiles/ecc/ecc/net/drivers/eth/quicc/current/ChangeLog,v
retrieving revision 1.8
diff -u -5 -p -r1.8 ChangeLog
--- net/drivers/eth/quicc/current/ChangeLog     2000/03/06 15:52:29     1.8
+++ net/drivers/eth/quicc/current/ChangeLog     2000/03/29 13:27:47
@@ -1,5 +1,10 @@
+2000-03-28  Gary Thomas  <gthomas@redhat.com>
+
+        * src/if_quicc.c (quicc_eth_recv): Handle case where there were
+        no buffers (and thus the sg_list[] contains NULL pointers).
+
 2000-03-06  Gary Thomas  <gthomas@redhat.com>
 
        * src/if_quicc.c: New driver API.
 
 2000-03-05  Gary Thomas  <gthomas@redhat.com>
Index: net/drivers/eth/quicc/current/src/if_quicc.c
===================================================================
RCS file: /local/cvsfiles/ecc/ecc/net/drivers/eth/quicc/current/src/if_quicc.c,v
retrieving revision 1.9
diff -u -5 -p -r1.9 if_quicc.c
--- net/drivers/eth/quicc/current/src/if_quicc.c        2000/03/06 15:52:30     1.9
+++ net/drivers/eth/quicc/current/src/if_quicc.c        2000/03/29 13:25:07
@@ -463,12 +463,14 @@ quicc_eth_recv(struct eth_drv_sc *sc, st
     HAL_DCACHE_IS_ENABLED(cache_state);
     if (cache_state) {
         HAL_DCACHE_INVALIDATE(qi->rxbd->buffer, qi->rxbd->length);  // Make sure no stale data
     }
     for (i = 0;  i < sg_len;  i++) {
-        bcopy(bp, (void *)sg_list[i].buf, sg_list[i].len);
-        bp += sg_list[i].len;
+        if (sg_list[i].buf != 0) {
+            bcopy(bp, (void *)sg_list[i].buf, sg_list[i].len);
+            bp += sg_list[i].len;
+        }
     }
 }
 
 static void
 quicc_eth_TxEvent(struct eth_drv_sc *sc, int stat)


More information about the Ecos-discuss mailing list