net/mlx5e: RX, Fix page_pool allocation failure recovery for legacy rq

When a page allocation fails during refill in mlx5e_refill_rx_wqes, the
page will be released again on the next refill call. This triggers the
page_pool negative page fragment count warning below:

 [  338.326070] WARNING: CPU: 4 PID: 0 at include/net/page_pool/helpers.h:130 mlx5e_page_release_fragmented.isra.0+0x42/0x50 [mlx5_core]
  ...
 [  338.328993] RIP: 0010:mlx5e_page_release_fragmented.isra.0+0x42/0x50 [mlx5_core]
 [  338.329094] Call Trace:
 [  338.329097]  <IRQ>
 [  338.329100]  ? __warn+0x7d/0x120
 [  338.329105]  ? mlx5e_page_release_fragmented.isra.0+0x42/0x50 [mlx5_core]
 [  338.329173]  ? report_bug+0x155/0x180
 [  338.329179]  ? handle_bug+0x3c/0x60
 [  338.329183]  ? exc_invalid_op+0x13/0x60
 [  338.329187]  ? asm_exc_invalid_op+0x16/0x20
 [  338.329192]  ? mlx5e_page_release_fragmented.isra.0+0x42/0x50 [mlx5_core]
 [  338.329259]  mlx5e_post_rx_wqes+0x210/0x5a0 [mlx5_core]
 [  338.329327]  ? mlx5e_poll_rx_cq+0x88/0x6f0 [mlx5_core]
 [  338.329394]  mlx5e_napi_poll+0x127/0x6b0 [mlx5_core]
 [  338.329461]  __napi_poll+0x25/0x1a0
 [  338.329465]  net_rx_action+0x28a/0x300
 [  338.329468]  __do_softirq+0xcd/0x279
 [  338.329473]  irq_exit_rcu+0x6a/0x90
 [  338.329477]  common_interrupt+0x82/0xa0
 [  338.329482]  </IRQ>

This patch fixes the legacy rq case by releasing all allocated fragments
and then setting the skip flag on all released fragments. It is
important to note that the number of released fragments will be higher
than the number of allocated fragments when an allocation error occurs.

Fixes: 3f93f82988bc ("net/mlx5e: RX, Defer page release in legacy rq for better recycling")
Tested-by: Chris Mason <clm@fb.com>
Reported-by: Chris Mason <clm@fb.com>
Closes: https://lore.kernel.org/netdev/117FF31A-7BE0-4050-B2BB-E41F224FF72F@meta.com
Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
Dragos Tatulea 2023-09-29 17:31:49 +03:00 committed by Saeed Mahameed
parent be43b7489a
commit ef9369e9c3

View File

@ -457,26 +457,41 @@ static int mlx5e_alloc_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
static int mlx5e_refill_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
{
int remaining = wqe_bulk;
int i = 0;
int total_alloc = 0;
int refill_alloc;
int refill;
/* The WQE bulk is split into smaller bulks that are sized
* according to the page pool cache refill size to avoid overflowing
* the page pool cache due to too many page releases at once.
*/
do {
int refill = min_t(u16, rq->wqe.info.refill_unit, remaining);
int alloc_count;
refill = min_t(u16, rq->wqe.info.refill_unit, remaining);
mlx5e_free_rx_wqes(rq, ix + i, refill);
alloc_count = mlx5e_alloc_rx_wqes(rq, ix + i, refill);
i += alloc_count;
if (unlikely(alloc_count != refill))
break;
mlx5e_free_rx_wqes(rq, ix + total_alloc, refill);
refill_alloc = mlx5e_alloc_rx_wqes(rq, ix + total_alloc, refill);
if (unlikely(refill_alloc != refill))
goto err_free;
total_alloc += refill_alloc;
remaining -= refill;
} while (remaining);
return i;
return total_alloc;
err_free:
mlx5e_free_rx_wqes(rq, ix, total_alloc + refill_alloc);
for (int i = 0; i < total_alloc + refill; i++) {
int j = mlx5_wq_cyc_ctr2ix(&rq->wqe.wq, ix + i);
struct mlx5e_wqe_frag_info *frag;
frag = get_frag(rq, j);
for (int k = 0; k < rq->wqe.info.num_frags; k++, frag++)
frag->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
}
return 0;
}
static void