[rtems commit] bsps/arm: Avoid mbuf migration in LPC ethernet

Sebastian Huber sebh at rtems.org
Tue Dec 18 10:18:04 UTC 2012


Module:    rtems
Branch:    master
Commit:    e5a7f8469a2c3f7ab7c092c387c02380e6bde453
Changeset: http://git.rtems.org/rtems/commit/?id=e5a7f8469a2c3f7ab7c092c387c02380e6bde453

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Dec 14 09:40:44 2012 +0100

bsps/arm: Avoid mbuf migration in LPC ethernet

The receive task will only hand over a mbuf if it gets a new one
immediately.  This avoids mbuf migration out of the receive task in case
of overload.

---

 .../libbsp/arm/shared/lpc/network/lpc-ethernet.c   |   86 +++++++-------------
 1 files changed, 30 insertions(+), 56 deletions(-)

diff --git a/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c b/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
index 56df8d4..b74f045 100644
--- a/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
+++ b/c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (c) 2009-2011 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Obere Lagerstr. 30
@@ -317,6 +317,7 @@ typedef struct {
   unsigned receive_interrupts;
   unsigned transmitted_frames;
   unsigned transmit_interrupts;
+  unsigned receive_drop_errors;
   unsigned receive_overrun_errors;
   unsigned receive_fragment_errors;
   unsigned receive_crc_errors;
@@ -528,14 +529,11 @@ static void lpc_eth_receive_task(void *arg)
   uint32_t const index_max = e->rx_unit_count - 1;
   uint32_t produce_index = 0;
   uint32_t consume_index = 0;
-  uint32_t receive_index = 0;
 
   LPC_ETH_PRINTF("%s\n", __func__);
 
   /* Main event loop */
   while (true) {
-    bool wait_for_mbuf = false;
-
     /* Wait for events */
     sc = rtems_bsdnet_event_receive(
       LPC_ETH_EVENT_INITIALIZE | LPC_ETH_EVENT_INTERRUPT,
@@ -592,7 +590,6 @@ static void lpc_eth_receive_task(void *arg)
       /* Initialize indices */
       produce_index = lpc_eth->rxproduceindex;
       consume_index = lpc_eth->rxconsumeindex;
-      receive_index = consume_index;
 
       /* Enable receiver */
       lpc_eth->command |= ETH_CMD_RX_ENABLE;
@@ -611,49 +608,47 @@ static void lpc_eth_receive_task(void *arg)
       /* Get current produce index */
       produce_index = lpc_eth->rxproduceindex;
 
-      if (receive_index != produce_index) {
+      if (consume_index != produce_index) {
         uint32_t stat = 0;
 
-        /* Fragment mbuf */
-        struct mbuf *m = mbufs [receive_index];
-
         /* Fragment status */
         rtems_cache_invalidate_multiple_data_lines(
-          (void *) &status [receive_index],
+          (void *) &status [consume_index],
           sizeof(status [0])
         );
-        stat = status [receive_index].info;
-
-        /* Remove mbuf from table */
-        mbufs [receive_index] = NULL;
+        stat = status [consume_index].info;
 
         if (
           (stat & ETH_RX_STAT_LAST_FLAG) != 0
             && (stat & LPC_ETH_RX_STAT_ERRORS) == 0
         ) {
-          /* Ethernet header */
-          struct ether_header *eh = mtod(m, struct ether_header *);
+          /* Received mbuf */
+          struct mbuf *m = mbufs [consume_index];
 
-          /* Discard Ethernet header and CRC */
-          int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1
-            - ETHER_HDR_LEN - ETHER_CRC_LEN;
+          if (lpc_eth_add_new_mbuf(ifp, desc, mbufs, consume_index, false)) {
+            /* Ethernet header */
+            struct ether_header *eh = mtod(m, struct ether_header *);
 
-          /* Update mbuf */
-          m->m_len = sz;
-          m->m_pkthdr.len = sz;
-          m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
+            /* Discard Ethernet header and CRC */
+            int sz = (int) (stat & ETH_RX_STAT_RXSIZE_MASK) + 1
+              - ETHER_HDR_LEN - ETHER_CRC_LEN;
 
-          LPC_ETH_PRINTF("rx: %02" PRIu32 ": %u\n", receive_index, sz);
+            /* Update mbuf */
+            m->m_len = sz;
+            m->m_pkthdr.len = sz;
+            m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
 
-          /* Hand over */
-          ether_input(ifp, eh, m);
+            LPC_ETH_PRINTF("rx: %02" PRIu32 ": %u\n", consume_index, sz);
 
-          /* Increment received frames counter */
-          ++e->received_frames;
-        } else {
-          /* Release mbuf */
-          m_free(m);
+            /* Hand over */
+            ether_input(ifp, eh, m);
 
+            /* Increment received frames counter */
+            ++e->received_frames;
+          } else {
+            ++e->receive_drop_errors;
+          }
+        } else {
           /* Update error counters */
           if ((stat & ETH_RX_STAT_OVERRUN) != 0) {
             ++e->receive_overrun_errors;
@@ -678,37 +673,15 @@ static void lpc_eth_receive_task(void *arg)
           }
         }
 
-        /* Increment receive index */
-        receive_index = lpc_eth_increment(receive_index, index_max);
+        /* Increment and update consume index */
+        consume_index = lpc_eth_increment(consume_index, index_max);
+        lpc_eth->rxconsumeindex = consume_index;
       } else {
         /* Nothing to do, enable receive interrupts */
         lpc_eth_enable_receive_interrupts();
         break;
       }
     }
-
-    /* Wait for mbuf? */
-    wait_for_mbuf =
-      lpc_eth_increment(produce_index, index_max) == consume_index;
-
-    /* Fill queue with new mbufs */
-    while (consume_index != produce_index) {
-      /* Add new mbuf to queue */
-      if (
-        !lpc_eth_add_new_mbuf(ifp, desc, mbufs, consume_index, wait_for_mbuf)
-      ) {
-        break;
-      }
-
-      /* We wait for at most one mbuf */
-      wait_for_mbuf = false;
-
-      /* Increment consume index */
-      consume_index = lpc_eth_increment(consume_index, index_max);
-
-      /* Update consume indices */
-      lpc_eth->rxconsumeindex = consume_index;
-    }
   }
 
 cleanup:
@@ -1268,6 +1241,7 @@ static void lpc_eth_interface_stats(lpc_eth_driver_entry *e)
   printf("receive interrupts:                  %u\n", e->receive_interrupts);
   printf("transmitted frames:                  %u\n", e->transmitted_frames);
   printf("transmit interrupts:                 %u\n", e->transmit_interrupts);
+  printf("receive drop errors:                 %u\n", e->receive_drop_errors);
   printf("receive overrun errors:              %u\n", e->receive_overrun_errors);
   printf("receive fragment errors:             %u\n", e->receive_fragment_errors);
   printf("receive CRC errors:                  %u\n", e->receive_crc_errors);




More information about the vc mailing list