From ee840c74da669d5e12884bc51f79adb43c7c8699 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Sat, 2 Feb 2019 21:56:20 +0000 Subject: [PATCH] Merged in antmerlino/nuttx/samv7_emac_bna_fix (pull request #824) arch/arm/src/samv7/sam_emac.c: Fixes rxdesc index logic to handle Buffer Not Available (BNA) condition. If a SOF is found, but no EOF, don't move past the frame. Instead, keep the index at the SOF buffer until the rest of the data is written. This fixes a receiver lockup condition where the peripheral and this driver get out of sync with there head pointers. In this case the driver has moved past buffers it owns, without clearing ownership, which results in the peripheral and driver in a deadlock with each other. Approved-by: GregoryN --- arch/arm/src/samv7/sam_emac.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/samv7/sam_emac.c b/arch/arm/src/samv7/sam_emac.c index f30b618a7a3..3cad26a4932 100644 --- a/arch/arm/src/samv7/sam_emac.c +++ b/arch/arm/src/samv7/sam_emac.c @@ -1873,9 +1873,23 @@ static int sam_recvframe(struct sam_emac_s *priv, int qid) (uintptr_t)rxdesc + sizeof(struct emac_rxdesc_s)); } - /* No packet was found */ + /* isframe indicates that we have found a SOF. If we've received a SOF, but not + * an EOF in the sequential buffers we own, it must mean that we have a partial + * packet. This should only happen if there was a Buffer Not Available (BNA) error. + * When bursts of data come in, quickly filling the available buffers, before our + * interrupts can even service them. Eventually, the ring buffer loops back on + * itself and the peripheral sees it cannot write the next fragment of the packet. + * + * In this case, we keep the rxndx at the start of the last frame, since the peripheral + * will finish writing the packet there next. + * + */ + + if (!isframe) + { + xfrq->rxndx = rxndx; + } - xfrq->rxndx = rxndx; ninfo("Exit rxndx[%d]: %d\n", qid, xfrq->rxndx); return -EAGAIN; }