On 2019-10-24 00:23, Lorenzo Bianconi wrote: > mt76 dma layer is supposed to unmap skb data buffers while keep txwi > mapped on hw dma ring. At the moment mt76 wrongly unmap txwi or does > not unmap data fragments in even positions for non-linear skbs. This > issue may result in hw hangs with A-MSDU if the system relies on IOMMU > or SWIOTLB. Fix this behaviour properly unmapping data fragments on > non-linear skbs. > > Fixes: 17f1de56df05 ("mt76: add common code shared between multiple chipsets") > Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> > --- > drivers/net/wireless/mediatek/mt76/dma.c | 10 +++++++--- > 1 file changed, 7 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c > index c747eb24581c..8c27956875e7 100644 > --- a/drivers/net/wireless/mediatek/mt76/dma.c > +++ b/drivers/net/wireless/mediatek/mt76/dma.c > @@ -93,11 +93,14 @@ static void > mt76_dma_tx_cleanup_idx(struct mt76_dev *dev, struct mt76_queue *q, int idx, > struct mt76_queue_entry *prev_e) > { > - struct mt76_queue_entry *e = &q->entry[idx]; > __le32 __ctrl = READ_ONCE(q->desc[idx].ctrl); > + struct mt76_queue_entry *e = &q->entry[idx]; > u32 ctrl = le32_to_cpu(__ctrl); > + bool mcu = e->skb && !e->txwi; > + bool first = e->skb == DMA_DUMMY_DATA || e->txwi == DMA_DUMMY_DATA || > + (e->skb && !skb_is_nonlinear(e->skb)); It seems to me that these conditions could be true not just for the first entry, but also following entries except for the last one. I think we should add a 'bool has_txwi' field in struct mt76_queue_entry to indicate that the first dma address points to a txwi that should not be unmapped. - Felix