summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2022-06-01 09:45:13 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2022-06-01 09:55:25 +0200
commit29f9822bace17fe6189a0048b7591a5188cdc329 (patch)
tree257d05218689bee945853ab7877efb5158ab1a08
parentif_atsam: Shorten sysctl names (diff)
downloadrtems-libbsd-29f9822bace17fe6189a0048b7591a5188cdc329.tar.bz2
if_atsam: Recover from receive freezes
Under unknown conditions the receive path ended up in a frozen state. In this state, the DMA and driver descriptor head were equal and all receive descriptors had the used bit set. So, the DMA was unable to store received frames. However, the receive daemon was never woken up to refill the receive buffers. It seems that the RXUBR interrupt can be used to recover from this state. Update #4651.
-rw-r--r--rtemsbsd/sys/dev/atsam/if_atsam.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/rtemsbsd/sys/dev/atsam/if_atsam.c b/rtemsbsd/sys/dev/atsam/if_atsam.c
index fff21c65..21a28fcd 100644
--- a/rtemsbsd/sys/dev/atsam/if_atsam.c
+++ b/rtemsbsd/sys/dev/atsam/if_atsam.c
@@ -108,6 +108,8 @@
#define MDIO_PHY MII_PHY_ANY
#define IGNORE_RX_ERR false
+#define RX_INTERRUPTS (GMAC_ISR_RCOMP | GMAC_ISR_RXUBR | GMAC_ISR_ROVR)
+
#define RX_DESC_LOG2 3
#define RX_DESC_COUNT (1U << RX_DESC_LOG2)
#define RX_DESC_WRAP(idx) \
@@ -187,6 +189,7 @@ typedef struct if_atsam_softc {
struct if_atsam_stats {
/* Software */
uint32_t rx_overrun_errors;
+ uint32_t rx_used_bit_reads;
uint32_t rx_interrupts;
uint32_t tx_tur_errors;
uint32_t tx_rlex_errors;
@@ -400,15 +403,19 @@ static void if_atsam_interrupt_handler(void *arg)
}
/* Check receive interrupts */
- if (__predict_true((is & (GMAC_IER_ROVR | GMAC_IER_RCOMP)) != 0)) {
- if (__predict_false((is & GMAC_IER_ROVR) != 0)) {
+ if (__predict_true((is & RX_INTERRUPTS) != 0)) {
+ if (__predict_false((is & GMAC_ISR_RXUBR) != 0)) {
+ ++sc->stats.rx_used_bit_reads;
+ }
+
+ if (__predict_false((is & GMAC_ISR_ROVR) != 0)) {
++sc->stats.rx_overrun_errors;
}
++sc->stats.rx_interrupts;
- /* Erase the interrupts for RX completion and errors */
- pHw->GMAC_IDR = GMAC_IER_RCOMP | GMAC_IER_ROVR;
+ /* Disable RX interrupts */
+ pHw->GMAC_IDR = RX_INTERRUPTS;
(void)rtems_event_send(sc->rx_daemon_tid,
ATSAMV7_ETH_RX_EVENT_INTERRUPT);
@@ -511,7 +518,7 @@ if_atsam_rx_daemon(rtems_task_argument arg)
sc->rx_idx_head = idx;
/* Enable RX interrupts */
- pHw->GMAC_IER = GMAC_IER_RCOMP | GMAC_IER_ROVR;
+ pHw->GMAC_IER = RX_INTERRUPTS;
(void) rtems_event_receive(ATSAMV7_ETH_RX_EVENT_INTERRUPT,
RTEMS_EVENT_ALL | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &out);
@@ -1292,6 +1299,9 @@ if_atsam_add_sysctls(device_t dev)
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_overrun_errors",
CTLFLAG_RD, &sc->stats.rx_overrun_errors, 0,
"RX overrun errors");
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_used_bit_reads",
+ CTLFLAG_RD, &sc->stats.rx_used_bit_reads, 0,
+ "RX used bit reads");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_interrupts",
CTLFLAG_RD, &sc->stats.rx_interrupts, 0,
"Rx interrupts");