[rtems-libbsd commit] if_lpe.c: Use interface transmit

Sebastian Huber sebh at rtems.org
Tue Sep 6 11:17:48 UTC 2022


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Jun 22 15:39:15 2022 +0200

if_lpe.c: Use interface transmit

This avoids the need for a transmit task and transmit interrupts.

---

 rtemsbsd/sys/arm/lpc/if_lpe.c | 510 +++++++++++++++++-------------------------
 1 file changed, 207 insertions(+), 303 deletions(-)

diff --git a/rtemsbsd/sys/arm/lpc/if_lpe.c b/rtemsbsd/sys/arm/lpc/if_lpe.c
index df9af15b..901cd6f0 100755
--- a/rtemsbsd/sys/arm/lpc/if_lpe.c
+++ b/rtemsbsd/sys/arm/lpc/if_lpe.c
@@ -7,13 +7,7 @@
  */
 
 /*
- * Copyright (c) 2009-2012 embedded brains GmbH.  All rights reserved.
- *
- *  embedded brains GmbH
- *  Obere Lagerstr. 30
- *  82178 Puchheim
- *  Germany
- *  <rtems at embedded-brains.de>
+ * Copyright (C) 2009, 2022 embedded brains GmbH
  *
  * The license and distribution terms for this file may be
  * found in the file LICENSE in this distribution or at
@@ -264,8 +258,6 @@ static volatile lpc_eth_controller *const lpc_eth =
 
 #define LPC_ETH_EVENT_INIT_TX RTEMS_EVENT_1
 
-#define LPC_ETH_EVENT_TXSTART RTEMS_EVENT_2
-
 #define LPC_ETH_EVENT_INTERRUPT RTEMS_EVENT_3
 
 #define LPC_ETH_EVENT_STOP RTEMS_EVENT_4
@@ -275,9 +267,6 @@ static volatile lpc_eth_controller *const lpc_eth =
 #define LPC_ETH_INTERRUPT_RECEIVE \
   (ETH_INT_RX_ERROR | ETH_INT_RX_FINISHED | ETH_INT_RX_DONE)
 
-#define LPC_ETH_INTERRUPT_TRANSMIT \
-  (ETH_INT_TX_DONE | ETH_INT_TX_FINISHED | ETH_INT_TX_ERROR)
-
 #define LPC_ETH_RX_STAT_ERRORS \
   (ETH_RX_STAT_CRC_ERROR \
     | ETH_RX_STAT_SYMBOL_ERROR \
@@ -317,7 +306,6 @@ typedef struct {
   uint32_t anlpar;
   struct callout watchdog_callout;
   rtems_id receive_task;
-  rtems_id transmit_task;
   unsigned rx_unit_count;
   unsigned tx_unit_count;
   volatile lpc_eth_transfer_descriptor *rx_desc_table;
@@ -331,7 +319,6 @@ typedef struct {
   unsigned received_frames;
   unsigned receive_interrupts;
   unsigned transmitted_frames;
-  unsigned transmit_interrupts;
   unsigned receive_drop_errors;
   unsigned receive_overrun_errors;
   unsigned receive_fragment_errors;
@@ -435,26 +422,14 @@ static void lpc_eth_interrupt_handler(void *arg)
   } else if ((is & LPC_ETH_INTERRUPT_RECEIVE) != 0) {
     re = LPC_ETH_EVENT_INTERRUPT;
     ie |= LPC_ETH_INTERRUPT_RECEIVE;
+    ++e->receive_interrupts;
   }
 
   /* Send events to receive task */
   if (re != 0) {
-    ++e->receive_interrupts;
     (void) rtems_event_send(e->receive_task, re);
   }
 
-  /* Check transmit interrupts */
-  if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
-    te = LPC_ETH_EVENT_INTERRUPT;
-    ie |= LPC_ETH_INTERRUPT_TRANSMIT;
-  }
-
-  /* Send events to transmit task */
-  if (te != 0) {
-    ++e->transmit_interrupts;
-    (void) rtems_event_send(e->transmit_task, te);
-  }
-
   LPC_ETH_PRINTK("interrupt: rx = 0x%08x, tx = 0x%08x\n", re, te);
 
   /* Update interrupt mask */
@@ -482,24 +457,6 @@ static void lpc_eth_disable_receive_interrupts(void)
   rtems_interrupt_enable(level);
 }
 
-static void lpc_eth_enable_transmit_interrupts(void)
-{
-  rtems_interrupt_level level;
-
-  rtems_interrupt_disable(level);
-  lpc_eth->intenable |= LPC_ETH_INTERRUPT_TRANSMIT;
-  rtems_interrupt_enable(level);
-}
-
-static void lpc_eth_disable_transmit_interrupts(void)
-{
-  rtems_interrupt_level level;
-
-  rtems_interrupt_disable(level);
-  lpc_eth->intenable &= ~LPC_ETH_INTERRUPT_TRANSMIT;
-  rtems_interrupt_enable(level);
-}
-
 static void lpc_eth_initialize_transmit(lpc_eth_driver_entry *e)
 {
   volatile uint32_t *const status = e->tx_status_table;
@@ -512,9 +469,6 @@ static void lpc_eth_initialize_transmit(lpc_eth_driver_entry *e)
   #endif
   uint32_t produce_index;
 
-  /* Disable transmit interrupts */
-  lpc_eth_disable_transmit_interrupts();
-
   /* Disable transmitter */
   lpc_eth->command &= ~ETH_CMD_TX_ENABLE;
 
@@ -526,9 +480,6 @@ static void lpc_eth_initialize_transmit(lpc_eth_driver_entry *e)
   /* Reset */
   lpc_eth->command |= ETH_CMD_TX_RESET;
 
-  /* Clear transmit interrupts */
-  lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
-
   /* Transmit descriptors */
   lpc_eth->txdescriptornum = index_max;
   lpc_eth->txdescriptor = (uint32_t) desc;
@@ -537,12 +488,8 @@ static void lpc_eth_initialize_transmit(lpc_eth_driver_entry *e)
   #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
     /* Discard outstanding fragments (= data loss) */
     for (produce_index = 0; produce_index <= index_max; ++produce_index) {
-      struct mbuf *victim = mbufs [produce_index];
-
-      if (victim != NULL) {
-        m_free(victim);
-        mbufs [produce_index] = NULL;
-      }
+      m_freem(mbufs [produce_index]);
+      mbufs [produce_index] = NULL;
     }
   #else
     /* Initialize descriptor table */
@@ -815,20 +762,10 @@ static struct mbuf *lpc_eth_next_fragment(
   uint32_t *ctrl
 )
 {
-  struct mbuf *n = NULL;
-  int size = 0;
+  struct mbuf *n;
+  int size;
 
   while (true) {
-    if (m == NULL) {
-      /* Dequeue first fragment of the next frame */
-      IF_DEQUEUE(&ifp->if_snd, m);
-
-      /* Empty queue? */
-      if (m == NULL) {
-        return m;
-      }
-    }
-
     /* Get fragment size */
     size = m->m_len;
 
@@ -836,8 +773,12 @@ static struct mbuf *lpc_eth_next_fragment(
       /* Now we have a not empty fragment */
       break;
     } else {
-      /* Discard empty fragments */
-      m = m_free(m);
+      /* Skip empty fragments */
+      m = m->m_next;
+
+      if (m == NULL) {
+        return NULL;
+      }
     }
   }
 
@@ -859,266 +800,224 @@ static struct mbuf *lpc_eth_next_fragment(
   return m;
 }
 
-static void lpc_eth_transmit_task(rtems_task_argument arg)
+static void lpc_eth_tx_reclaim(lpc_eth_driver_entry *e, struct ifnet *ifp)
 {
-  rtems_status_code sc = RTEMS_SUCCESSFUL;
-  rtems_event_set events = 0;
-  lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) arg;
-  struct ifnet *ifp = e->ifp;
-  volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
   volatile uint32_t *const status = e->tx_status_table;
+  volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
   #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
     struct mbuf **const mbufs = e->tx_buf_table;
   #else
     char *const buf = e->tx_buf_table;
   #endif
-  struct mbuf *m = NULL;
   uint32_t const index_max = e->tx_unit_count - 1;
-  uint32_t ctrl = 0;
-
-  LPC_ETH_PRINTF("%s\n", __func__);
+  uint32_t consume_index = e->tx_consume_index;
 
-  /* Main event loop */
+  /* Free consumed fragments */
   while (true) {
-    uint32_t produce_index;
-    uint32_t consume_index;
-    #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
-      uint32_t frame_length;
-      char *frame_buffer;
-    #endif
-
-    /* Wait for events */
-    sc = rtems_event_receive(
-      LPC_ETH_EVENT_STOP
-        | LPC_ETH_EVENT_TXSTART
-        | LPC_ETH_EVENT_INTERRUPT,
-      RTEMS_EVENT_ANY | RTEMS_WAIT,
-      RTEMS_NO_TIMEOUT,
-      &events
-    );
-    BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
+    /* Save last known consume index */
+    uint32_t c = consume_index;
 
-    LPC_ETH_PRINTF("tx: wake up: 0x%08" PRIx32 "\n", events);
-
-    /* Stop transmitter? */
-    if ((events & LPC_ETH_EVENT_STOP) != 0) {
-      lpc_eth_control_request_complete(e);
+    /* Get new consume index */
+    consume_index = lpc_eth->txconsumeindex;
 
-      /* Wait for events */
-      continue;
+    /* Nothing consumed in the meantime? */
+    if (c == consume_index) {
+      break;
     }
 
-    LPE_LOCK(e);
-
-    /* Get indices */
-    produce_index = e->tx_produce_index;
-    consume_index = e->tx_consume_index;
+    while (c != consume_index) {
+      uint32_t s = status [c];
 
-    #ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
-      /* Fresh frame length and buffer start */
-      frame_length = 0;
-      frame_buffer = (char *) desc [produce_index].start;
-    #endif
+      /* Update error counters */
+      if ((s & (ETH_TX_STAT_ERROR | ETH_TX_STAT_NO_DESCRIPTOR)) != 0) {
+        if ((s & ETH_TX_STAT_UNDERRUN) != 0) {
+          ++e->transmit_underrun_errors;
+        }
+        if ((s & ETH_TX_STAT_LATE_COLLISION) != 0) {
+          ++e->transmit_late_collision_errors;
+        }
+        if ((s & ETH_TX_STAT_EXCESSIVE_COLLISION) != 0) {
+          ++e->transmit_excessive_collision_errors;
+        }
+        if ((s & ETH_TX_STAT_EXCESSIVE_DEFER) != 0) {
+          ++e->transmit_excessive_defer_errors;
+        }
+        if ((s & ETH_TX_STAT_NO_DESCRIPTOR) != 0) {
+          ++e->transmit_no_descriptor_errors;
+        }
+      }
 
-    /* Free consumed fragments */
-    while (true) {
-      /* Save last known consume index */
-      uint32_t c = consume_index;
+      #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+        /* Release mbuf */
+        m_freem(mbufs [c]);
+        mbufs [c] = NULL;
+      #endif
 
-      /* Clear transmit interrupt status */
-      lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
+      /* Next consume index */
+      c = lpc_eth_increment(c, index_max);
+    }
+  }
 
-      /* Get new consume index */
-      consume_index = lpc_eth->txconsumeindex;
+  e->tx_consume_index = consume_index;
+}
 
-      /* Nothing consumed in the meantime? */
-      if (c == consume_index) {
-        break;
-      }
+static int lpc_eth_tx_enqueue(
+  lpc_eth_driver_entry *e,
+  struct ifnet *ifp,
+  struct mbuf *m0
+)
+{
+  volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
+  #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+    struct mbuf **const mbufs = e->tx_buf_table;
+  #else
+    char *const buf = e->tx_buf_table;
+    uint32_t frame_length;
+    char *frame_buffer;
+  #endif
+  uint32_t const index_max = e->tx_unit_count - 1;
+  uint32_t produce_index = e->tx_produce_index;
+  uint32_t consume_index = e->tx_consume_index;
+  struct mbuf *m = m0;
 
-      while (c != consume_index) {
-        uint32_t s = status [c];
+  while (true) {
+    uint32_t ctrl;
 
-        /* Update error counters */
-        if ((s & (ETH_TX_STAT_ERROR | ETH_TX_STAT_NO_DESCRIPTOR)) != 0) {
-          if ((s & ETH_TX_STAT_UNDERRUN) != 0) {
-            ++e->transmit_underrun_errors;
-          }
-          if ((s & ETH_TX_STAT_LATE_COLLISION) != 0) {
-            ++e->transmit_late_collision_errors;
-          }
-          if ((s & ETH_TX_STAT_EXCESSIVE_COLLISION) != 0) {
-            ++e->transmit_excessive_collision_errors;
-          }
-          if ((s & ETH_TX_STAT_EXCESSIVE_DEFER) != 0) {
-            ++e->transmit_excessive_defer_errors;
-          }
-          if ((s & ETH_TX_STAT_NO_DESCRIPTOR) != 0) {
-            ++e->transmit_no_descriptor_errors;
-          }
-        }
+    /* Compute next produce index */
+    uint32_t p = lpc_eth_increment(produce_index, index_max);
 
-        #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
-          /* Release mbuf */
-          m_free(mbufs [c]);
-          mbufs [c] = NULL;
-        #endif
+    /* Queue full? */
+    if (p == consume_index) {
+      LPC_ETH_PRINTF("tx: full queue: 0x%08x\n", m);
 
-        /* Next consume index */
-        c = lpc_eth_increment(c, index_max);
-      }
+      /* The queue is full */
+      return ENOBUFS;
     }
 
-    /* Transmit new fragments */
-    while (true) {
-      /* Compute next produce index */
-      uint32_t p = lpc_eth_increment(produce_index, index_max);
+    /* Get next fragment and control value */
+    m = lpc_eth_next_fragment(ifp, m, &ctrl);
 
-      /* Get next fragment and control value */
-      m = lpc_eth_next_fragment(ifp, m, &ctrl);
+    /* New fragment? */
+    if (m != NULL) {
+      #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
+        /* Set the transfer data */
+        rtems_cache_flush_multiple_data_lines(
+          mtod(m, const void *),
+          (size_t) m->m_len
+        );
+        desc [produce_index].start = mtod(m, uint32_t);
+        desc [produce_index].control = ctrl;
+        rtems_cache_flush_multiple_data_lines(
+          (void *) &desc [produce_index],
+          sizeof(desc [0])
+         );
+
+        LPC_ETH_PRINTF(
+          "tx: %02" PRIu32 ": %u %s\n",
+          produce_index, m->m_len,
+          (ctrl & ETH_TX_CTRL_LAST) != 0 ? "L" : ""
+        );
 
-      /* Queue full? */
-      if (p == consume_index) {
-        LPC_ETH_PRINTF("tx: full queue: 0x%08x\n", m);
+        /* Next produce index */
+        produce_index = p;
 
-        /* The queue is full, wait for transmit interrupt */
-        break;
-      }
+        /* Last fragment of a frame? */
+        if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
+          /* Update the produce index */
+          lpc_eth->txproduceindex = produce_index;
+          e->tx_produce_index = produce_index;
 
-      /* New fragment? */
-      if (m != NULL) {
-        #ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
-          /* Set the transfer data */
-          rtems_cache_flush_multiple_data_lines(
-            mtod(m, const void *),
-            (size_t) m->m_len
-          );
-          desc [produce_index].start = mtod(m, uint32_t);
-          desc [produce_index].control = ctrl;
-          rtems_cache_flush_multiple_data_lines(
-            (void *) &desc [produce_index],
-            sizeof(desc [0])
-           );
-          mbufs [produce_index] = m;
+          mbufs [produce_index] = m0;
 
-          LPC_ETH_PRINTF(
-            "tx: %02" PRIu32 ": %u %s\n",
-            produce_index, m->m_len,
-            (ctrl & ETH_TX_CTRL_LAST) != 0 ? "L" : ""
-          );
+          /* Increment transmitted frames counter */
+          ++e->transmitted_frames;
 
-          /* Next produce index */
-          produce_index = p;
+          return 0;
+        }
 
-          /* Last fragment of a frame? */
-          if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
-            /* Update the produce index */
-            lpc_eth->txproduceindex = produce_index;
+        /* Next fragment of the frame */
+        m = m->m_next;
+      #else
+        size_t fragment_length = (size_t) m->m_len;
+        void *fragment_start = mtod(m, void *);
+        uint32_t new_frame_length = frame_length + fragment_length;
 
-            /* Increment transmitted frames counter */
-            ++e->transmitted_frames;
-          }
+        /* Check buffer size */
+        if (new_frame_length > LPC_ETH_CONFIG_TX_BUF_SIZE) {
+          LPC_ETH_PRINTF("tx: overflow\n");
 
-          /* Next fragment of the frame */
-          m = m->m_next;
-        #else
-          size_t fragment_length = (size_t) m->m_len;
-          void *fragment_start = mtod(m, void *);
-          uint32_t new_frame_length = frame_length + fragment_length;
+          /* Discard overflow data */
+          new_frame_length = LPC_ETH_CONFIG_TX_BUF_SIZE;
+          fragment_length = new_frame_length - frame_length;
 
-          /* Check buffer size */
-          if (new_frame_length > LPC_ETH_CONFIG_TX_BUF_SIZE) {
-            LPC_ETH_PRINTF("tx: overflow\n");
+          /* Finalize frame */
+          ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS;
+
+          /* Update error counter */
+          ++e->transmit_overflow_errors;
+        }
 
-            /* Discard overflow data */
-            new_frame_length = LPC_ETH_CONFIG_TX_BUF_SIZE;
-            fragment_length = new_frame_length - frame_length;
+        LPC_ETH_PRINTF(
+          "tx: copy: %" PRIu32 "%s%s\n",
+          fragment_length,
+          (m->m_flags & M_EXT) != 0 ? ", E" : "",
+          (m->m_flags & M_PKTHDR) != 0 ? ", H" : ""
+        );
 
-            /* Finalize frame */
-            ctrl |= LPC_ETH_LAST_FRAGMENT_FLAGS;
+        /* Copy fragment to buffer in Ethernet RAM */
+        memcpy(frame_buffer, fragment_start, fragment_length);
 
-            /* Update error counter */
-            ++e->transmit_overflow_errors;
-          }
+        if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
+          /* Finalize descriptor */
+          desc [produce_index].control = (ctrl & ~ETH_TX_CTRL_SIZE_MASK)
+            | (new_frame_length - 1);
 
           LPC_ETH_PRINTF(
-            "tx: copy: %" PRIu32 "%s%s\n",
-            fragment_length,
-            (m->m_flags & M_EXT) != 0 ? ", E" : "",
-            (m->m_flags & M_PKTHDR) != 0 ? ", H" : ""
+            "tx: %02" PRIu32 ": %" PRIu32 "\n",
+            produce_index,
+            new_frame_length
           );
 
-          /* Copy fragment to buffer in Ethernet RAM */
-          memcpy(frame_buffer, fragment_start, fragment_length);
-
-          if ((ctrl & ETH_TX_CTRL_LAST) != 0) {
-            /* Finalize descriptor */
-            desc [produce_index].control = (ctrl & ~ETH_TX_CTRL_SIZE_MASK)
-              | (new_frame_length - 1);
-
-            LPC_ETH_PRINTF(
-              "tx: %02" PRIu32 ": %" PRIu32 "\n",
-              produce_index,
-              new_frame_length
-            );
-
-            /* Cache flush of data */
-            rtems_cache_flush_multiple_data_lines(
-              (const void *) desc [produce_index].start,
-              new_frame_length 
-            );
-
-            /* Cache flush of descriptor  */
-            rtems_cache_flush_multiple_data_lines(
-              (void *) &desc [produce_index],
-              sizeof(desc [0])
-            );
-
-            /* Next produce index */
-            produce_index = p;
+          /* Cache flush of data */
+          rtems_cache_flush_multiple_data_lines(
+            (const void *) desc [produce_index].start,
+            new_frame_length
+          );
 
-            /* Update the produce index */
-            lpc_eth->txproduceindex = produce_index;
+          /* Cache flush of descriptor  */
+          rtems_cache_flush_multiple_data_lines(
+            (void *) &desc [produce_index],
+            sizeof(desc [0])
+          );
 
-            /* Fresh frame length and buffer start */
-            frame_length = 0;
-            frame_buffer = (char *) desc [produce_index].start;
+          /* Next produce index */
+          produce_index = p;
 
-            /* Increment transmitted frames counter */
-            ++e->transmitted_frames;
-          } else {
-            /* New frame length */
-            frame_length = new_frame_length;
+          /* Update the produce index */
+          lpc_eth->txproduceindex = produce_index;
 
-            /* Update current frame buffer start */
-            frame_buffer += fragment_length;
-          }
+          /* Fresh frame length and buffer start */
+          frame_length = 0;
+          frame_buffer = (char *) desc [produce_index].start;
 
-          /* Free mbuf and get next */
-          m = m_free(m);
-        #endif
-      } else {
-        /* Nothing to transmit */
-        break;
-      }
-    }
+          /* Increment transmitted frames counter */
+          ++e->transmitted_frames;
+        } else {
+          /* New frame length */
+          frame_length = new_frame_length;
 
-    /* Save indices */
-    e->tx_produce_index = produce_index;
-    e->tx_consume_index = consume_index;
+          /* Update current frame buffer start */
+          frame_buffer += fragment_length;
+        }
 
-    /* No more fragments? */
-    if (m == NULL) {
-      /* Interface is now inactive */
-      ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+        /* Free mbuf and get next */
+        m = m_free(m);
+      #endif
     } else {
-      LPC_ETH_PRINTF("tx: enable interrupts\n");
-
-      /* Enable transmit interrupts */
-      lpc_eth_enable_transmit_interrupts();
+      /* Nothing to transmit */
+      m_freem(m0);
+      return 0;
     }
-
-    LPE_UNLOCK(e);
   }
 }
 
@@ -1484,9 +1383,8 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
     );
     BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
 
-    /* Stop tasks */
+    /* Stop task */
     lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_STOP);
-    lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_STOP);
 
     lpc_eth_soft_reset();
     lpc_eth_phy_down(e);
@@ -1604,17 +1502,38 @@ static int lpc_eth_interface_ioctl(
   return eno;
 }
 
-static void lpc_eth_interface_start(struct ifnet *ifp)
+static int lpc_eth_interface_transmit(struct ifnet *ifp, struct mbuf *m)
 {
-  rtems_status_code sc = RTEMS_SUCCESSFUL;
   lpc_eth_driver_entry *e = (lpc_eth_driver_entry *) ifp->if_softc;
+  int eno;
 
-  ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+  LPE_LOCK(e);
 
   if (e->state == LPC_ETH_STATE_UP) {
-    sc = rtems_event_send(e->transmit_task, LPC_ETH_EVENT_TXSTART);
-    BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
+    eno = lpc_eth_tx_enqueue(e, ifp, m);
+    lpc_eth_tx_reclaim(e, ifp);
+
+    if (__predict_false(eno != 0)) {
+      struct mbuf *n;
+
+      n = m_defrag(m, M_NOWAIT);
+      if (n != NULL) {
+        m = n;
+      }
+
+      eno = lpc_eth_tx_enqueue(e, ifp, m);
+    }
+  } else {
+    eno = ENETDOWN;
   }
+
+  if (eno != 0) {
+    m_freem(m);
+    if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
+  }
+
+  LPE_UNLOCK(e);
+  return eno;
 }
 
 static void lpc_eth_interface_watchdog(void *arg)
@@ -1772,7 +1691,7 @@ static int lpc_eth_attach(device_t dev)
   if_initname(ifp, device_get_name(dev), device_get_unit(dev));
   ifp->if_init = lpc_eth_interface_init;
   ifp->if_ioctl = lpc_eth_interface_ioctl;
-  ifp->if_start = lpc_eth_interface_start;
+  ifp->if_transmit = lpc_eth_interface_transmit;
   ifp->if_qflush = if_qflush;
   ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
   IFQ_SET_MAXLEN(&ifp->if_snd, LPC_ETH_CONFIG_TX_UNIT_COUNT_MAX - 1);
@@ -1798,21 +1717,6 @@ static int lpc_eth_attach(device_t dev)
     (rtems_task_argument)e
   );
   BSD_ASSERT(status == RTEMS_SUCCESSFUL);
-  status = rtems_task_create(
-    rtems_build_name('n', 't', 't', 'x'),
-    rtems_bsd_get_task_priority(device_get_name(e->dev)),
-    4096,
-    RTEMS_DEFAULT_MODES,
-    RTEMS_DEFAULT_ATTRIBUTES,
-    &e->transmit_task
-  );
-  BSD_ASSERT(status == RTEMS_SUCCESSFUL);
-  status = rtems_task_start(
-    e->transmit_task,
-    lpc_eth_transmit_task,
-    (rtems_task_argument)e
-  );
-  BSD_ASSERT(status == RTEMS_SUCCESSFUL);
 
   if_link_state_change(e->ifp, LINK_STATE_UP);
 



More information about the vc mailing list