summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-12-14 09:40:44 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-12-18 11:22:18 +0100
commite5a7f8469a2c3f7ab7c092c387c02380e6bde453 (patch)
tree0cf5f6df802802bccf397be9b498778e8e959537
parentbsp/lpc32xx: Add UART_CLKMODE settings (diff)
downloadrtems-e5a7f8469a2c3f7ab7c092c387c02380e6bde453.tar.bz2
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.
-rw-r--r--c/src/lib/libbsp/arm/shared/lpc/network/lpc-ethernet.c86
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 56df8d4fef..b74f045ddc 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);