Message ID | 20210409192759.3895104-1-olteanv@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next] net: enetc: fix TX ring interrupt storm | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Link |
netdev/fixes_present | success | Link |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | success | CCed 5 of 5 maintainers |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Link |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 0 this patch: 0 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | Link |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 15 lines checked |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 0 this patch: 0 |
netdev/header_inline | success | Link |
On 09.04.2021 22:27, Vladimir Oltean wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > The blamed commit introduced a bit in the TX software buffer descriptor > structure for determining whether a BD is final or not; we rearm the TX > interrupt vector for every frame (hence final BD) transmitted. > > But there is a problem with the patch: it replaced a condition whose > expression is a bool which was evaluated at the beginning of the "while" > loop with a bool expression that is evaluated on the spot: tx_swbd->is_eof. > > The problem with the latter expression is that the tx_swbd has already > been incremented at that stage, so the tx_swbd->is_eof check is in fact > with the _next_ software BD. Which is _not_ final. > > The effect is that the CPU is in 100% load with ksoftirqd because it > does not acknowledge the TX interrupt, so the handler keeps getting > called again and again. > > The fix is to restore the code structure, and keep the local bool is_eof > variable, just to assign it the tx_swbd->is_eof value instead of > !!tx_swbd->skb. > > Fixes: d504498d2eb3 ("net: enetc: add a dedicated is_eof bit in the TX software BD") > Reported-by: Alex Marginean <alexandru.marginean@nxp.com> > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Claudiu Manoil <claudiu.manoil@nxp.com>
On Sat, 10 Apr 2021 00:29:23 +0300 Claudiu Manoil wrote: > On 09.04.2021 22:27, Vladimir Oltean wrote: > > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > > > The blamed commit introduced a bit in the TX software buffer descriptor > > structure for determining whether a BD is final or not; we rearm the TX > > interrupt vector for every frame (hence final BD) transmitted. > > > > But there is a problem with the patch: it replaced a condition whose > > expression is a bool which was evaluated at the beginning of the "while" > > loop with a bool expression that is evaluated on the spot: tx_swbd->is_eof. > > > > The problem with the latter expression is that the tx_swbd has already > > been incremented at that stage, so the tx_swbd->is_eof check is in fact > > with the _next_ software BD. Which is _not_ final. > > > > The effect is that the CPU is in 100% load with ksoftirqd because it > > does not acknowledge the TX interrupt, so the handler keeps getting > > called again and again. > > > > The fix is to restore the code structure, and keep the local bool is_eof > > variable, just to assign it the tx_swbd->is_eof value instead of > > !!tx_swbd->skb. > > > > Fixes: d504498d2eb3 ("net: enetc: add a dedicated is_eof bit in the TX software BD") > > Reported-by: Alex Marginean <alexandru.marginean@nxp.com> > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> > > Reviewed-by: Claudiu Manoil <claudiu.manoil@nxp.com> Applied, thanks!
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 57049ae97201..65f7f63c9bad 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -406,6 +406,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget) while (bds_to_clean && tx_frm_cnt < ENETC_DEFAULT_TX_WORK) { struct xdp_frame *xdp_frame = enetc_tx_swbd_get_xdp_frame(tx_swbd); struct sk_buff *skb = enetc_tx_swbd_get_skb(tx_swbd); + bool is_eof = tx_swbd->is_eof; if (unlikely(tx_swbd->check_wb)) { struct enetc_ndev_priv *priv = netdev_priv(ndev); @@ -453,7 +454,7 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget) } /* BD iteration loop end */ - if (tx_swbd->is_eof) { + if (is_eof) { tx_frm_cnt++; /* re-arm interrupt source */ enetc_wr_reg_hot(tx_ring->idr, BIT(tx_ring->index) |