Message ID | 20211023001528.3077822-1-benl@squareup.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 9bfe38e064af5decba2ffce66a2958ab8b10eaa4 |
Delegated to: | Kalle Valo |
Headers | show |
Series | wcn36xx: add proper DMA memory barriers in rx path | expand |
Benjamin Li <benl@squareup.com> wrote: > 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> Patch applied to ath-next branch of ath.git, thanks. 9bfe38e064af wcn36xx: add proper DMA memory barriers in rx path
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 8e1dbfda6538..93994b2e8e03 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -613,6 +613,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); @@ -623,9 +627,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; }
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> --- drivers/net/wireless/ath/wcn36xx/dxe.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)