mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
net: stmmac: fix RX coalesce frames counter
The RX refill path should set the IC bit once every rx_coal_frames descriptors and leave the rest to the RX watchdog (RIWT), as done by commitd429b66e2e("net: stmmac: Implement RX Coalesce Frames setting"). Since commit6fa9d691b9("net: stmmac: Prevent divide-by-zero") the counter is increased by N+1 for each descriptor and then compared against N, so it is always reset to 0. With a non-zero rx-frames, IC is therefore set on every descriptor and every frame raises an interrupt. Fix this by counting one descriptor at a time in a helper used by both stmmac_rx_refill() and stmmac_rx_refill_zc(). Platforms without RIWT (IC on every descriptor) are unaffected. Cc: stable+noautosel@kernel.org # never worked Fixes:6fa9d691b9("net: stmmac: Prevent divide-by-zero") Signed-off-by: Pengfei Zhang <zhangfeionline@gmail.com> Link: https://patch.msgid.link/20261009111138.320089-1-zhangfeionline@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
7684c2c796
commit
0d20963e0a
|
|
@ -5110,6 +5110,22 @@ static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
|
||||
static bool stmmac_rx_need_ic(struct stmmac_priv *priv,
|
||||
struct stmmac_rx_queue *rx_q, u32 queue)
|
||||
{
|
||||
u32 frames = priv->rx_coal_frames[queue];
|
||||
|
||||
/* without the RX watchdog every descriptor needs IC */
|
||||
if (!priv->use_riwt)
|
||||
return true;
|
||||
|
||||
if (!frames || ++rx_q->rx_count_frames < frames)
|
||||
return false;
|
||||
|
||||
rx_q->rx_count_frames = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_rx_refill - refill used skb preallocated buffers
|
||||
* @priv: driver private structure
|
||||
|
|
@ -5155,15 +5171,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
|
|||
stmmac_rx_check_buf2_cap(priv));
|
||||
stmmac_refill_desc3(priv, rx_q, p);
|
||||
|
||||
rx_q->rx_count_frames++;
|
||||
rx_q->rx_count_frames += priv->rx_coal_frames[queue];
|
||||
if (rx_q->rx_count_frames > priv->rx_coal_frames[queue])
|
||||
rx_q->rx_count_frames = 0;
|
||||
|
||||
use_rx_wd = !priv->rx_coal_frames[queue];
|
||||
use_rx_wd |= rx_q->rx_count_frames > 0;
|
||||
if (!priv->use_riwt)
|
||||
use_rx_wd = false;
|
||||
use_rx_wd = !stmmac_rx_need_ic(priv, rx_q, queue);
|
||||
|
||||
dma_wmb();
|
||||
stmmac_set_rx_owner(priv, p, use_rx_wd);
|
||||
|
|
@ -5573,15 +5581,7 @@ static bool stmmac_rx_refill_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
|
|||
stmmac_set_desc_sec_addr(priv, rx_desc, 0, false);
|
||||
stmmac_refill_desc3(priv, rx_q, rx_desc);
|
||||
|
||||
rx_q->rx_count_frames++;
|
||||
rx_q->rx_count_frames += priv->rx_coal_frames[queue];
|
||||
if (rx_q->rx_count_frames > priv->rx_coal_frames[queue])
|
||||
rx_q->rx_count_frames = 0;
|
||||
|
||||
use_rx_wd = !priv->rx_coal_frames[queue];
|
||||
use_rx_wd |= rx_q->rx_count_frames > 0;
|
||||
if (!priv->use_riwt)
|
||||
use_rx_wd = false;
|
||||
use_rx_wd = !stmmac_rx_need_ic(priv, rx_q, queue);
|
||||
|
||||
dma_wmb();
|
||||
stmmac_set_rx_owner(priv, rx_desc, use_rx_wd);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user