summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2022-05-06 08:23:45 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2022-05-11 16:08:46 +0200
commit204a4873d7f4fdc08e3ab736aa9e6e3cd3f42155 (patch)
treeda7ce5b907f54e25f77647d954c541ce38618337
parentif_atsam: Optimize transmit (diff)
downloadrtems-libbsd-204a4873d7f4fdc08e3ab736aa9e6e3cd3f42155.tar.bz2
if_atsam: Optimize receive
Do not use the interface mutex in the receive loop. Avoid multiple reads of DMA descriptor words. Use a compile-time constant for the receive DMA descriptor count to simplify calculations. Update #4651.
-rw-r--r--rtemsbsd/sys/dev/atsam/if_atsam.c188
1 files changed, 72 insertions, 116 deletions
diff --git a/rtemsbsd/sys/dev/atsam/if_atsam.c b/rtemsbsd/sys/dev/atsam/if_atsam.c
index 96895fc0..ef2b3401 100644
--- a/rtemsbsd/sys/dev/atsam/if_atsam.c
+++ b/rtemsbsd/sys/dev/atsam/if_atsam.c
@@ -95,26 +95,26 @@
/** RX Defines */
#define GMAC_RX_BUFFER_SIZE 1536
#define GMAC_RX_BUF_DESC_ADDR_MASK 0xFFFFFFFC
-#define GMAC_RX_SET_OFFSET (1u << 15)
-#define GMAC_RX_SET_USED_WRAP ((1u << 1) | (1u << 0))
-#define GMAC_RX_SET_WRAP (1u << 1)
-#define GMAC_RX_SET_USED (1u << 0)
#define GMAC_DESCRIPTOR_ALIGNMENT 8
/** Events */
#define ATSAMV7_ETH_RX_EVENT_INTERRUPT RTEMS_EVENT_1
-#define ATSAMV7_ETH_RX_DATA_OFFSET 2
-
-#define WATCHDOG_TIMEOUT 5
-
/* FIXME: Make these configurable */
#define MDIO_RETRIES 10
#define MDIO_PHY MII_PHY_ANY
-#define RXBUF_COUNT 8
#define IGNORE_RX_ERR false
+#define RX_DESC_LOG2 3
+#define RX_DESC_COUNT (1U << RX_DESC_LOG2)
+#define RX_DESC_WRAP(idx) \
+ ((((idx) + 1) & RX_DESC_COUNT) >> (RX_DESC_LOG2 - 1))
+RTEMS_STATIC_ASSERT(RX_DESC_WRAP(RX_DESC_COUNT - 1) ==
+ GMAC_RX_WRAP_BIT, rx_desc_wrap);
+RTEMS_STATIC_ASSERT(RX_DESC_WRAP(RX_DESC_COUNT - 2) ==
+ 0, rx_desc_no_wrap);
+
#define TX_DESC_LOG2 6
#define TX_DESC_COUNT (1U << TX_DESC_LOG2)
#define TX_DESC_WRAP(idx) \
@@ -137,6 +137,10 @@ struct if_atsam_tx_bds {
volatile sGmacTxDescriptor bds[TX_DESC_COUNT];
};
+struct if_atsam_rx_bds {
+ volatile sGmacRxDescriptor bds[RX_DESC_COUNT];
+};
+
/*
* Per-device data
*/
@@ -152,12 +156,11 @@ typedef struct if_atsam_softc {
size_t tx_idx_tail;
struct if_atsam_tx_bds *tx;
struct mbuf *tx_mbufs[TX_DESC_COUNT];
+ struct if_atsam_rx_bds *rx;
+ struct mbuf *rx_mbufs[RX_DESC_COUNT];
uint8_t GMacAddress[6];
rtems_id rx_daemon_tid;
rtems_vector_number interrupt_number;
- struct mbuf **rx_mbuf;
- size_t rx_bd_fill_idx;
- size_t amount_rx_buf;
struct callout tick_ch;
/*
@@ -242,27 +245,6 @@ static void if_atsam_poll_hw_stats(struct if_atsam_softc *sc);
#define IF_ATSAM_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
-static void if_atsam_event_send(rtems_id task, rtems_event_set event)
-{
- rtems_event_send(task, event);
-}
-
-
-static void if_atsam_event_receive(if_atsam_softc *sc, rtems_event_set in)
-{
- rtems_event_set out;
-
- IF_ATSAM_UNLOCK(sc);
- rtems_event_receive(
- in,
- RTEMS_EVENT_ANY | RTEMS_WAIT,
- RTEMS_NO_TIMEOUT,
- &out
- );
- IF_ATSAM_LOCK(sc);
-}
-
-
static struct mbuf *if_atsam_new_mbuf(struct ifnet *ifp)
{
struct mbuf *m;
@@ -425,17 +407,17 @@ static void if_atsam_interrupt_handler(void *arg)
/* Erase the interrupts for RX completion and errors */
pHw->GMAC_IDR = GMAC_IER_RCOMP | GMAC_IER_ROVR;
- (void)if_atsam_event_send(sc->rx_daemon_tid,
+ (void)rtems_event_send(sc->rx_daemon_tid,
ATSAMV7_ETH_RX_EVENT_INTERRUPT);
}
}
-static void rx_update_mbuf(struct mbuf *m,
- volatile sGmacRxDescriptor *buffer_desc)
+static void
+if_atsam_rx_update_mbuf(struct mbuf *m, uint32_t status)
{
int frame_len;
- frame_len = (int) (buffer_desc->status.bm.len);
+ frame_len = (int)(status & GMAC_LENGTH_FRAME);
m->m_data = mtod(m, char*)+ETHER_ALIGN;
m->m_len = frame_len;
@@ -443,7 +425,7 @@ static void rx_update_mbuf(struct mbuf *m,
/* check checksum offload result */
m->m_pkthdr.csum_flags = 0;
- switch (buffer_desc->status.bm.typeIDMatchOrCksumResult) {
+ switch ((status >> 22) & 0x3) {
case GMAC_RXDESC_ST_CKSUM_RESULT_IP_CHECKED:
m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID;
m->m_pkthdr.csum_data = 0xffff;
@@ -464,12 +446,12 @@ static void if_atsam_rx_daemon(void *arg)
{
if_atsam_softc *sc = (if_atsam_softc *)arg;
struct ifnet *ifp = sc->ifp;
- void *rx_bd_base;
- struct mbuf *m;
- struct mbuf *n;
- volatile sGmacRxDescriptor *buffer_desc;
- uint32_t tmp_rx_bd_address;
+ volatile sGmacRxDescriptor *base;
+ struct if_atsam_rx_bds *rx;
Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+ size_t idx;
+ struct mbuf **mbufs;
+ struct mbuf *m;
IF_ATSAM_LOCK(sc);
@@ -480,47 +462,37 @@ static void if_atsam_rx_daemon(void *arg)
}
/* Allocate memory space for priority queue descriptor list */
- rx_bd_base = rtems_cache_coherent_allocate(sizeof(sGmacRxDescriptor),
+ base = rtems_cache_coherent_allocate(sizeof(*base),
GMAC_DESCRIPTOR_ALIGNMENT, 0);
- assert(rx_bd_base != NULL);
+ assert(base != NULL);
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base;
- buffer_desc->addr.val = GMAC_RX_SET_USED_WRAP;
- buffer_desc->status.val = 0;
+ base->addr.val = GMAC_RX_OWNERSHIP_BIT | GMAC_RX_WRAP_BIT;
+ base->status.val = 0;
- GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 1);
- GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 2);
+ GMAC_SetRxQueue(pHw, (uint32_t)base, 1);
+ GMAC_SetRxQueue(pHw, (uint32_t)base, 2);
/* Allocate memory space for buffer descriptor list */
- rx_bd_base = rtems_cache_coherent_allocate(
- sc->amount_rx_buf * sizeof(sGmacRxDescriptor),
+ rx = rtems_cache_coherent_allocate(sizeof(*rx),
GMAC_DESCRIPTOR_ALIGNMENT, 0);
- assert(rx_bd_base != NULL);
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base;
+ assert(rx != NULL);
+ sc->rx = rx;
+ mbufs = &sc->rx_mbufs[0];
/* Create descriptor list and mark as empty */
- for (sc->rx_bd_fill_idx = 0; sc->rx_bd_fill_idx < sc->amount_rx_buf;
- ++sc->rx_bd_fill_idx) {
+ for (idx = 0; idx < RX_DESC_COUNT; ++idx) {
m = if_atsam_new_mbuf(ifp);
assert(m != NULL);
- sc->rx_mbuf[sc->rx_bd_fill_idx] = m;
- buffer_desc->addr.val = ((uint32_t)m->m_data) &
- GMAC_RX_BUF_DESC_ADDR_MASK;
- buffer_desc->status.val = 0;
- if (sc->rx_bd_fill_idx == (sc->amount_rx_buf - 1)) {
- buffer_desc->addr.bm.bWrap = 1;
- } else {
- buffer_desc++;
- }
+ mbufs[idx] = m;
+ rx->bds[idx].addr.val = mtod(m, uint32_t) | RX_DESC_WRAP(idx);
}
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base;
/* Set 2 Byte Receive Buffer Offset */
- pHw->GMAC_NCFGR |= GMAC_RX_SET_OFFSET;
+ pHw->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(2);
/* Write Buffer Queue Base Address Register */
GMAC_ReceiveEnable(pHw, 0);
- GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 0);
+ GMAC_SetRxQueue(pHw, (uint32_t)&rx->bds[0], 0);
/* Set address for address matching */
GMAC_SetAddress(pHw, 0, sc->GMacAddress);
@@ -528,58 +500,50 @@ static void if_atsam_rx_daemon(void *arg)
/* Enable Receiving of data */
GMAC_ReceiveEnable(pHw, 1);
- /* Setup the interrupts for RX completion and errors */
- GMAC_EnableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0);
+ IF_ATSAM_UNLOCK(sc);
- sc->rx_bd_fill_idx = 0;
+ idx = 0;
while (true) {
- /* Wait for events */
- if_atsam_event_receive(sc, ATSAMV7_ETH_RX_EVENT_INTERRUPT);
+ rtems_event_set out;
+
+ /* Enable RX interrupts */
+ pHw->GMAC_IER = GMAC_IER_RCOMP | GMAC_IER_ROVR;
+
+ (void) rtems_event_receive(ATSAMV7_ETH_RX_EVENT_INTERRUPT,
+ RTEMS_EVENT_ALL | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &out);
+
+ while (true) {
+ uint32_t addr;
+ uint32_t status;
+
+ addr = rx->bds[idx].addr.val;
+ if ((addr & GMAC_RX_OWNERSHIP_BIT) == 0) {
+ break;
+ }
- /*
- * Check for all packets with a set ownership bit
- */
- while (buffer_desc->addr.bm.bOwnership == 1) {
- if (buffer_desc->status.bm.bEof == 1) {
- m = sc->rx_mbuf[sc->rx_bd_fill_idx];
+ status = rx->bds[idx].status.val;
+ m = mbufs[idx];
+
+ if (__predict_true((status & GMAC_RX_EOF_BIT) != 0)) {
+ struct mbuf *n;
- /* New mbuf for desc */
n = if_atsam_new_mbuf(ifp);
if (n != NULL) {
- rx_update_mbuf(m, buffer_desc);
-
- IF_ATSAM_UNLOCK(sc);
- sc->ifp->if_input(ifp, m);
- IF_ATSAM_LOCK(sc);
+ if_atsam_rx_update_mbuf(m, status);
+ (*ifp->if_input)(ifp, m);
m = n;
}
- sc->rx_mbuf[sc->rx_bd_fill_idx] = m;
- tmp_rx_bd_address = (uint32_t)m->m_data &
- GMAC_RX_BUF_DESC_ADDR_MASK;
-
- /* Switch pointer to next buffer descriptor */
- if (sc->rx_bd_fill_idx ==
- (sc->amount_rx_buf - 1)) {
- tmp_rx_bd_address |= GMAC_RX_SET_WRAP;
- sc->rx_bd_fill_idx = 0;
- } else {
- ++sc->rx_bd_fill_idx;
- }
+ } else {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ }
- /*
- * Give ownership to GMAC for further processing
- */
- tmp_rx_bd_address &= ~GMAC_RX_SET_USED;
- _ARM_Data_synchronization_barrier();
- buffer_desc->addr.val = tmp_rx_bd_address;
+ mbufs[idx] = m;
+ rx->bds[idx].addr.val = mtod(m, uint32_t) |
+ RX_DESC_WRAP(idx);
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base
- + sc->rx_bd_fill_idx;
- }
+ idx = (idx + 1) % RX_DESC_COUNT;
}
- /* Setup the interrupts for RX completion and errors */
- GMAC_EnableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0);
}
}
@@ -944,12 +908,6 @@ if_atsam_init(if_atsam_softc *sc)
GMAC_StatisticsWriteEnable(sc->Gmac_inst.gGmacd.pHw, 1);
- /*
- * Allocate mbuf pointers
- */
- sc->rx_mbuf = malloc(sc->amount_rx_buf * sizeof *sc->rx_mbuf,
- M_TEMP, M_WAITOK | M_ZERO);
-
/* Install interrupt handler */
status = rtems_interrupt_handler_install(sc->interrupt_number,
"Ethernet",
@@ -1417,8 +1375,6 @@ static int if_atsam_driver_attach(device_t dev)
memcpy(sc->GMacAddress, eaddr, ETHER_ADDR_LEN);
- sc->amount_rx_buf = RXBUF_COUNT;
-
/* Set Initial Link Speed */
sc->link_speed = GMAC_SPEED_100M;
sc->link_duplex = GMAC_DUPLEX_FULL;