]> git.itanic.dy.fi Git - linux-stable/commitdiff
net/mlx5e: do as little as possible in napi poll when budget is 0
authorJakub Kicinski <kuba@kernel.org>
Wed, 17 May 2023 01:59:35 +0000 (18:59 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 May 2023 12:55:33 +0000 (13:55 +0100)
commit afbed3f74830163f9559579dee382cac3cff82da upstream.

NAPI gets called with budget of 0 from netpoll, which has interrupts
disabled. We should try to free some space on Tx rings and nothing
else.

Specifically do not try to handle XDP TX or try to refill Rx buffers -
we can't use the page pool from IRQ context. Don't check if IRQs moved,
either, that makes no sense in netpoll. Netpoll calls _all_ the rings
from whatever CPU it happens to be invoked on.

In general do as little as possible, the work quickly adds up when
there's tens of rings to poll.

The immediate stack trace I was seeing is:

    __do_softirq+0xd1/0x2c0
    __local_bh_enable_ip+0xc7/0x120
    </IRQ>
    <TASK>
    page_pool_put_defragged_page+0x267/0x320
    mlx5e_free_xdpsq_desc+0x99/0xd0
    mlx5e_poll_xdpsq_cq+0x138/0x3b0
    mlx5e_napi_poll+0xc3/0x8b0
    netpoll_poll_dev+0xce/0x150

AFAIU page pool takes a BH lock, releases it and since BH is now
enabled tries to run softirqs.

Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Fixes: 60bbf7eeef10 ("mlx5: use page_pool for xdp_return_frame call")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c

index 833be29170a135c54ae011e9d959279564ccf3f6..c47c360a5d5e9545da76fc3afe154611069892c6 100644 (file)
@@ -150,20 +150,22 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget)
                }
        }
 
+       /* budget=0 means we may be in IRQ context, do as little as possible */
+       if (unlikely(!budget))
+               goto out;
+
        busy |= mlx5e_poll_xdpsq_cq(&c->xdpsq.cq);
 
        if (c->xdp)
                busy |= mlx5e_poll_xdpsq_cq(&c->rq_xdpsq.cq);
 
-       if (likely(budget)) { /* budget=0 means: don't poll rx rings */
-               if (xsk_open)
-                       work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget);
+       if (xsk_open)
+               work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget);
 
-               if (likely(budget - work_done))
-                       work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done);
+       if (likely(budget - work_done))
+               work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done);
 
-               busy |= work_done == budget;
-       }
+       busy |= work_done == budget;
 
        mlx5e_poll_ico_cq(&c->icosq.cq);
        if (mlx5e_poll_ico_cq(&c->async_icosq.cq))