From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anssi Hannula Subject: [PATCH 2/3] net: macb: fix dropped RX frames due to a race Date: Fri, 30 Nov 2018 20:21:36 +0200 Message-ID: <20181130182137.27974-3-anssi.hannula@bitwise.fi> References: <20181130182137.27974-1-anssi.hannula@bitwise.fi> Cc: netdev@vger.kernel.org To: Nicolas Ferre , "David S. Miller" Return-path: Received: from mail.bitwise.fi ([109.204.228.163]:52804 "EHLO mail.bitwise.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725754AbeLAFco (ORCPT ); Sat, 1 Dec 2018 00:32:44 -0500 In-Reply-To: <20181130182137.27974-1-anssi.hannula@bitwise.fi> Sender: netdev-owner@vger.kernel.org List-ID: Bit RX_USED set to 0 in the address field allows the controller to write data to the receive buffer descriptor. The driver does not ensure the ctrl field is ready (cleared) when the controller sees the RX_USED=0 written by the driver. The ctrl field might only be cleared after the controller has already updated it according to a newly received frame, causing the frame to be discarded in gem_rx() due to unexpected ctrl field contents. A message is logged when the above scenario occurs: macb ff0b0000.ethernet eth0: not whole frame pointed by descriptor Fix the issue by ensuring that when the controller sees RX_USED=0 the ctrl field is already cleared. This issue was observed on a ZynqMP based system. Signed-off-by: Anssi Hannula Fixes: 4df95131ea80 ("net/macb: change RX path for GEM") Cc: Nicolas Ferre --- drivers/net/ethernet/cadence/macb_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 0bc2aab7be40..430b7a0f5436 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -935,14 +935,19 @@ static void gem_rx_refill(struct macb_queue *queue) if (entry == bp->rx_ring_size - 1) paddr |= MACB_BIT(RX_WRAP); - macb_set_addr(bp, desc, paddr); desc->ctrl = 0; + /* Setting addr clears RX_USED and allows reception, + * make sure ctrl is cleared first to avoid a race. + */ + dma_wmb(); + macb_set_addr(bp, desc, paddr); /* properly align Ethernet header */ skb_reserve(skb, NET_IP_ALIGN); } else { - desc->addr &= ~MACB_BIT(RX_USED); desc->ctrl = 0; + dma_wmb(); + desc->addr &= ~MACB_BIT(RX_USED); } } -- 2.17.2