diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-12-14 09:40:44 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-12-18 11:22:18 +0100 |
commit | e5a7f8469a2c3f7ab7c092c387c02380e6bde453 (patch) | |
tree | 0cf5f6df802802bccf397be9b498778e8e959537 | |
parent | bsp/lpc32xx: Add UART_CLKMODE settings (diff) | |
download | rtems-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.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 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); |