From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anssi Hannula Subject: [PATCH 1/3] net: macb: fix random memory corruption on RX with 64-bit DMA Date: Fri, 30 Nov 2018 20:21:35 +0200 Message-ID: <20181130182137.27974-2-anssi.hannula@bitwise.fi> References: <20181130182137.27974-1-anssi.hannula@bitwise.fi> Cc: netdev@vger.kernel.org, Harini Katakam , Michal Simek To: Nicolas Ferre , "David S. Miller" Return-path: Received: from mail.bitwise.fi ([109.204.228.163]:52744 "EHLO mail.bitwise.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725754AbeLAFcf (ORCPT ); Sat, 1 Dec 2018 00:32:35 -0500 In-Reply-To: <20181130182137.27974-1-anssi.hannula@bitwise.fi> Sender: netdev-owner@vger.kernel.org List-ID: 64-bit DMA addresses are split in upper and lower halves that are written in separate fields on GEM. For RX, bit 0 of the address is used as the ownership bit (RX_USED). When the RX_USED bit is unset the controller is allowed to write data to the buffer. The driver does not guarantee that the controller already sees the upper half when the RX_USED bit is cleared, possibly resulting in the controller writing an incoming frame to an address with an incorrect upper half and therefore possibly corrupting unrelated system memory. Fix that by adding the necessary DMA memory barrier between the writes. This corruption was observed on a ZynqMP based system. Signed-off-by: Anssi Hannula Fixes: fff8019a08b6 ("net: macb: Add 64 bit addressing support for GEM") Cc: Nicolas Ferre Cc: Harini Katakam Cc: Michal Simek --- drivers/net/ethernet/cadence/macb_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index d8c7ca037ae3..0bc2aab7be40 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -682,6 +682,11 @@ static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_ if (bp->hw_dma_cap & HW_DMA_CAP_64B) { desc_64 = macb_64b_desc(bp, desc); desc_64->addrh = upper_32_bits(addr); + /* The low bits of RX address contain the RX_USED bit, clearing + * of which allows packet RX. Make sure the high bits are also + * visible to HW at that point. + */ + dma_wmb(); } #endif desc->addr = lower_32_bits(addr); -- 2.17.2