qualcommax: qca_edma: refuse a frame before its preheader is pushed

The transmit routine prepends the 32-byte preheader and only then tests
whether the descriptor's slot still holds an uncompleted frame. A frame
refused there goes back to the qdisc already carrying the preheader, and
the requeue pushes a second one: the descriptor names a length that no
longer describes the frame, and the headroom the push consumed is gone.

Both refusals now precede the push, where the ring-full test already sat.
The slot test depends on nothing between the two points, so the accepted
path is unchanged.

Fixes: bdb0b722b7 ("qualcommax: add EDMA driver")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25084
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
Julius Bairaktaris authored and Robert Marko committed 2026-09-09 21:00:03 +02:00
1 parent f53100d40e
commit a9adfbf98f
1 file changed
+10 -6
@@ -589,6 +589,16 @@ static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *net
return NETDEV_TX_BUSY;
}
/* Both refusals come before the preheader is pushed: the qdisc requeues
* the frame as it was handed over, and a second push would prefix it
* twice and hand the hardware a length that no longer describes it.
*/
idx = prod & (txdesc_ring->count - 1);
if (unlikely(txdesc_ring->skb_store[idx])) {
spin_unlock_bh(&priv->tx_lock);
return NETDEV_TX_BUSY;
}
buf_len = skb_headlen(skb);
tag_info = skb_ext_find(skb, SKB_EXT_DSA_OOB);
@@ -603,12 +613,6 @@ static netdev_tx_t edma_ring_xmit(struct edma_priv *priv, struct net_device *net
txph->dst_info = dst_info;
idx = prod & (txdesc_ring->count - 1);
if (unlikely(txdesc_ring->skb_store[idx] != NULL)) {
spin_unlock_bh(&priv->tx_lock);
return NETDEV_TX_BUSY;
}
txdesc_ring->skb_store[idx] = skb;
txph->opaque = idx;