lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 370/575] wcn36xx: add proper DMA memory barriers in rx path
    Date
    From: Benjamin Li <benl@squareup.com>

    [ Upstream commit 9bfe38e064af5decba2ffce66a2958ab8b10eaa4 ]

    This is essentially exactly following the dma_wmb()/dma_rmb() usage
    instructions in Documentation/memory-barriers.txt.

    The theoretical races here are:

    1. DXE (the DMA Transfer Engine in the Wi-Fi subsystem) seeing the
    dxe->ctrl & WCN36xx_DXE_CTRL_VLD write before the dxe->dst_addr_l
    write, thus performing DMA into the wrong address.

    2. CPU reading dxe->dst_addr_l before DXE unsets dxe->ctrl &
    WCN36xx_DXE_CTRL_VLD. This should generally be harmless since DXE
    doesn't write dxe->dst_addr_l (no risk of freeing the wrong skb).

    Fixes: 8e84c2582169 ("wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware")
    Signed-off-by: Benjamin Li <benl@squareup.com>
    Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
    Link: https://lore.kernel.org/r/20211023001528.3077822-1-benl@squareup.com
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/wireless/ath/wcn36xx/dxe.c | 12 +++++++++++-
    1 file changed, 11 insertions(+), 1 deletion(-)

    diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
    index 70c46c327512f..cf4eb0fb28151 100644
    --- a/drivers/net/wireless/ath/wcn36xx/dxe.c
    +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
    @@ -606,6 +606,10 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
    dxe = ctl->desc;

    while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) {
    + /* do not read until we own DMA descriptor */
    + dma_rmb();
    +
    + /* read/modify DMA descriptor */
    skb = ctl->skb;
    dma_addr = dxe->dst_addr_l;
    ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl, GFP_ATOMIC);
    @@ -616,9 +620,15 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
    dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
    DMA_FROM_DEVICE);
    wcn36xx_rx_skb(wcn, skb);
    - } /* else keep old skb not submitted and use it for rx DMA */
    + }
    + /* else keep old skb not submitted and reuse it for rx DMA
    + * (dropping the packet that it contained)
    + */

    + /* flush descriptor changes before re-marking as valid */
    + dma_wmb();
    dxe->ctrl = ctrl;
    +
    ctl = ctl->next;
    dxe = ctl->desc;
    }
    --
    2.33.0


    \
     
     \ /
      Last update: 2021-11-15 21:40    [W:2.892 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site