t7xx_dpmaif_release_tx_buffer() iterates release_cnt times over the
TX ring, advancing cur_idx and updating txq->drb_release_rd_idx on
each iteration. When a PD DRB has no associated skb, the loop hits
the "invalid skb" error path and does a bare continue, skipping the
ring index advance and the budget notification.
The loop counter i still increments, so the function returns a
release count that does not match the number of DRBs actually
consumed from the ring. The caller t7xx_dpmaif_tx_release() then
compares real_rel_cnt against rel_cnt and may keep returning
-EAGAIN, causing the TX reclaim path to spin without making forward
progress on the stuck entry.
Advance the ring index and update drb_release_rd_idx before
continuing, so every iteration consumes exactly one DRB and the
returned count stays consistent with the ring state.
Reviewed-by: Weibin Liu <redacted>
Signed-off-by: Liu Chao <redacted>
---
drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
index 8dab025a0..a51bad54d 100644
--- a/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
+++ b/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_tx.c
@@ -103,16 +103,15 @@ static unsigned int t7xx_dpmaif_release_tx_buffer(struct dpmaif_ctrl *dpmaif_ctr
dma_unmap_single(dpmaif_ctrl->dev, cur_drb_skb->bus_addr,
cur_drb_skb->data_len, DMA_TO_DEVICE);
- if (!FIELD_GET(DRB_HDR_CONT, le32_to_cpu(cur_drb->header))) {
- if (!cur_drb_skb->skb) {
- dev_err(dpmaif_ctrl->dev,
- "txq%u: DRB check fail, invalid skb\n", q_num);
- continue;
+ if (!FIELD_GET(DRB_HDR_CONT, le32_to_cpu(cur_drb->header))) {
+ if (!cur_drb_skb->skb) {
+ dev_err(dpmaif_ctrl->dev,
+ "txq%u: DRB check fail, invalid skb\n", q_num);
+ } else {
+ dev_kfree_skb_any(cur_drb_skb->skb);
+ }
}
- dev_kfree_skb_any(cur_drb_skb->skb);
- }
-
cur_drb_skb->skb = NULL;
}
--
2.50.1