Message ID | 20230113105848.34642-3-nbd@nbd.name (mailing list archive) |
---|---|
State | Accepted |
Commit | 953519b35227d5dbbb5c5724f1f539735fbf7781 |
Delegated to: | Kalle Valo |
Headers | show |
Series | [wireless,1/3] wifi: mt76: dma: do not increment queue head if mt76_dma_add_buf fails | expand |
On 13.01.23 11:58, Felix Fietkau wrote: > When adding WED support, mt76_dma_add_buf was accidentally changed to set > the skip_buf0 flag for tx buffers on the wrong queue descriptor entry. > Additionally, there is a rxwi leak when rx buffer allocation fails. thx for working on this > Fix this and make the code more readable by adding a separate function for > adding rx buffers. > > Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> > Tested-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> Many thx for taking care of this. There is one small thing to improve, please add the following tags here to make things easier for future code archaeologists and give proper credit: Link: https://lore.kernel.org/r/CABXGCsMEnQd=gYKTd1knRsWuxCb=Etv5nAre%2BXJS_s5FgVteYA@mail.gmail.com/ Reported-by: Mike Lothian <mike@fireburn.co.uk> Link: https://bugzilla.kernel.org/show_bug.cgi?id=216829 Reported-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/lkml/20230112171706.294550-1-angelogioacchino.delregno@collabora.com/ To explain: Linus[1] and others considered proper link tags important in cases like this, as they allow anyone to look into the backstory of a fix weeks or years later. That's nothing new, the documentation[2] for some time says to place such tags in cases like this. I care personally (and made it a bit more explicit in the docs a while ago), because these tags make my regression tracking efforts a whole lot easier, as they allow my tracking bot 'regzbot' to automatically connect reports with patches posted or committed to fix tracked regressions. Apropos regzbot, let me tell regzbot to monitor this thread: #regzbot ^backmonitor: https://lore.kernel.org/r/CABXGCsMEnQd=gYKTd1knRsWuxCb=Etv5nAre%2BXJS_s5FgVteYA@mail.gmail.com/ > [...] Ciao, Thorsten (wearing his 'the Linux kernel's regression tracker' hat) [1] for details, see: https://lore.kernel.org/all/CAHk-=wjMmSZzMJ3Xnskdg4+GGz=5p5p+GSYyFBTh0f-DgvdBWg@mail.gmail.com/ https://lore.kernel.org/all/CAHk-=wgs38ZrfPvy=nOwVkVzjpM3VFU1zobP37Fwd_h9iAD5JQ@mail.gmail.com/ https://lore.kernel.org/all/CAHk-=wjxzafG-=J8oT30s7upn4RhBs6TX-uVFZ5rME+L5_DoJA@mail.gmail.com/ [2] see Documentation/process/submitting-patches.rst (http://docs.kernel.org/process/submitting-patches.html) and Documentation/process/5.Posting.rst (https://docs.kernel.org/process/5.Posting.html) -- Everything you wanna know about Linux kernel regression tracking: https://linux-regtracking.leemhuis.info/about/#tldr If I did something stupid, please tell me, as explained on that page.
"Linux kernel regression tracking (Thorsten Leemhuis)" <regressions@leemhuis.info> writes: > On 13.01.23 11:58, Felix Fietkau wrote: >> When adding WED support, mt76_dma_add_buf was accidentally changed to set >> the skip_buf0 flag for tx buffers on the wrong queue descriptor entry. >> Additionally, there is a rxwi leak when rx buffer allocation fails. > > thx for working on this > >> Fix this and make the code more readable by adding a separate function for >> adding rx buffers. >> >> Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> >> Tested-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> > > Many thx for taking care of this. There is one small thing to improve, > please add the following tags here to make things easier for future code > archaeologists and give proper credit: I can add those. > Link: > https://lore.kernel.org/r/CABXGCsMEnQd=gYKTd1knRsWuxCb=Etv5nAre%2BXJS_s5FgVteYA@mail.gmail.com/ > Reported-by: Mike Lothian <mike@fireburn.co.uk> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216829 > Reported-by: AngeloGioacchino Del Regno But the email is missing for AngeloGioacchino.
On 13.01.23 16:57, Kalle Valo wrote: > "Linux kernel regression tracking (Thorsten Leemhuis)" > <regressions@leemhuis.info> writes: > >> On 13.01.23 11:58, Felix Fietkau wrote: >>> When adding WED support, mt76_dma_add_buf was accidentally changed to set >>> the skip_buf0 flag for tx buffers on the wrong queue descriptor entry. >>> Additionally, there is a rxwi leak when rx buffer allocation fails. >> >> thx for working on this >> >>> Fix this and make the code more readable by adding a separate function for >>> adding rx buffers. >>> >>> Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> >>> Tested-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com> >> >> Many thx for taking care of this. There is one small thing to improve, >> please add the following tags here to make things easier for future code >> archaeologists and give proper credit: > > I can add those. Great, many thx! >> Link: >> https://lore.kernel.org/r/CABXGCsMEnQd=gYKTd1knRsWuxCb=Etv5nAre%2BXJS_s5FgVteYA@mail.gmail.com/ >> Reported-by: Mike Lothian <mike@fireburn.co.uk> >> Link: https://bugzilla.kernel.org/show_bug.cgi?id=216829 >> Reported-by: AngeloGioacchino Del Regno > > But the email is missing for AngeloGioacchino. /me wonders how that happened Sorry for that. Here it is again: Reported-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Ciao, Thorsten
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 61a8ab9e1db5..06161815c180 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -205,6 +205,52 @@ mt76_dma_queue_reset(struct mt76_dev *dev, struct mt76_queue *q) mt76_dma_sync_idx(dev, q); } +static int +mt76_dma_add_rx_buf(struct mt76_dev *dev, struct mt76_queue *q, + struct mt76_queue_buf *buf, void *data) +{ + struct mt76_desc *desc = &q->desc[q->head]; + struct mt76_queue_entry *entry = &q->entry[q->head]; + struct mt76_txwi_cache *txwi = NULL; + u32 buf1 = 0, ctrl; + int idx = q->head; + int rx_token; + + ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); + + if ((q->flags & MT_QFLAG_WED) && + FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) { + txwi = mt76_get_rxwi(dev); + if (!txwi) + return -ENOMEM; + + rx_token = mt76_rx_token_consume(dev, data, txwi, buf->addr); + if (rx_token < 0) { + mt76_put_rxwi(dev, txwi); + return -ENOMEM; + } + + buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token); + ctrl |= MT_DMA_CTL_TO_HOST; + } + + WRITE_ONCE(desc->buf0, cpu_to_le32(buf->addr)); + WRITE_ONCE(desc->buf1, cpu_to_le32(buf1)); + WRITE_ONCE(desc->ctrl, cpu_to_le32(ctrl)); + WRITE_ONCE(desc->info, 0); + + entry->dma_addr[0] = buf->addr; + entry->dma_len[0] = buf->len; + entry->txwi = txwi; + entry->buf = data; + entry->wcid = 0xffff; + entry->skip_buf1 = true; + q->head = (q->head + 1) % q->ndesc; + q->queued++; + + return idx; +} + static int mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, struct mt76_queue_buf *buf, int nbufs, u32 info, @@ -215,6 +261,11 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, int i, idx = -1; u32 ctrl, next; + if (txwi) { + q->entry[q->head].txwi = DMA_DUMMY_DATA; + q->entry[q->head].skip_buf0 = true; + } + for (i = 0; i < nbufs; i += 2, buf += 2) { u32 buf0 = buf[0].addr, buf1 = 0; @@ -224,51 +275,28 @@ mt76_dma_add_buf(struct mt76_dev *dev, struct mt76_queue *q, desc = &q->desc[idx]; entry = &q->entry[idx]; - if ((q->flags & MT_QFLAG_WED) && - FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) { - struct mt76_txwi_cache *t = txwi; - int rx_token; - - if (!t) - return -ENOMEM; - - rx_token = mt76_rx_token_consume(dev, (void *)skb, t, - buf[0].addr); - if (rx_token < 0) - return -ENOMEM; - - buf1 |= FIELD_PREP(MT_DMA_CTL_TOKEN, rx_token); - ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len) | - MT_DMA_CTL_TO_HOST; - } else { - if (txwi) { - q->entry[next].txwi = DMA_DUMMY_DATA; - q->entry[next].skip_buf0 = true; - } - - if (buf[0].skip_unmap) - entry->skip_buf0 = true; - entry->skip_buf1 = i == nbufs - 1; - - entry->dma_addr[0] = buf[0].addr; - entry->dma_len[0] = buf[0].len; - - ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); - if (i < nbufs - 1) { - entry->dma_addr[1] = buf[1].addr; - entry->dma_len[1] = buf[1].len; - buf1 = buf[1].addr; - ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len); - if (buf[1].skip_unmap) - entry->skip_buf1 = true; - } - - if (i == nbufs - 1) - ctrl |= MT_DMA_CTL_LAST_SEC0; - else if (i == nbufs - 2) - ctrl |= MT_DMA_CTL_LAST_SEC1; + if (buf[0].skip_unmap) + entry->skip_buf0 = true; + entry->skip_buf1 = i == nbufs - 1; + + entry->dma_addr[0] = buf[0].addr; + entry->dma_len[0] = buf[0].len; + + ctrl = FIELD_PREP(MT_DMA_CTL_SD_LEN0, buf[0].len); + if (i < nbufs - 1) { + entry->dma_addr[1] = buf[1].addr; + entry->dma_len[1] = buf[1].len; + buf1 = buf[1].addr; + ctrl |= FIELD_PREP(MT_DMA_CTL_SD_LEN1, buf[1].len); + if (buf[1].skip_unmap) + entry->skip_buf1 = true; } + if (i == nbufs - 1) + ctrl |= MT_DMA_CTL_LAST_SEC0; + else if (i == nbufs - 2) + ctrl |= MT_DMA_CTL_LAST_SEC1; + WRITE_ONCE(desc->buf0, cpu_to_le32(buf0)); WRITE_ONCE(desc->buf1, cpu_to_le32(buf1)); WRITE_ONCE(desc->info, cpu_to_le32(info)); @@ -581,17 +609,9 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) spin_lock_bh(&q->lock); while (q->queued < q->ndesc - 1) { - struct mt76_txwi_cache *t = NULL; struct mt76_queue_buf qbuf; void *buf = NULL; - if ((q->flags & MT_QFLAG_WED) && - FIELD_GET(MT_QFLAG_WED_TYPE, q->flags) == MT76_WED_Q_RX) { - t = mt76_get_rxwi(dev); - if (!t) - break; - } - buf = page_frag_alloc(rx_page, q->buf_size, GFP_ATOMIC); if (!buf) break; @@ -605,7 +625,7 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q) qbuf.addr = addr + offset; qbuf.len = len - offset; qbuf.skip_unmap = false; - if (mt76_dma_add_buf(dev, q, &qbuf, 1, 0, buf, t) < 0) { + if (mt76_dma_add_rx_buf(dev, q, &qbuf, buf) < 0) { dma_unmap_single(dev->dma_dev, addr, len, DMA_FROM_DEVICE); skb_free_frag(buf);