Skip to content

Commit 07841f9

Browse files
shamoyadavem330
authored andcommitted
net/mlx4_en: Schedule napi when RX buffers allocation fails
When system is out of memory, refilling of RX buffers fails while the driver continue to pass the received packets to the kernel stack. At some point, when all RX buffers deplete, driver may fall into a sleep, and not recover when memory for new RX buffers is once again availible. This is because hardware does not have valid descriptors, so no interrupt will be generated for the driver to return to work in napi context. Fix it by schedule the napi poll function from stats_task delayed workqueue, as long as the allocations fail. Signed-off-by: Ido Shamay <[email protected]> Signed-off-by: Amir Vadai <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c232d8a commit 07841f9

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

drivers/net/ethernet/mellanox/mlx4/en_netdev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,7 @@ static void mlx4_en_service_task(struct work_struct *work)
14671467
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
14681468
mlx4_en_ptp_overflow_check(mdev);
14691469

1470+
mlx4_en_recover_from_oom(priv);
14701471
queue_delayed_work(mdev->workqueue, &priv->service_task,
14711472
SERVICE_TASK_DELAY);
14721473
}

drivers/net/ethernet/mellanox/mlx4/en_rx.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
244244
return mlx4_en_alloc_frags(priv, rx_desc, frags, ring->page_alloc, gfp);
245245
}
246246

247+
static inline bool mlx4_en_is_ring_empty(struct mlx4_en_rx_ring *ring)
248+
{
249+
BUG_ON((u32)(ring->prod - ring->cons) > ring->actual_size);
250+
return ring->prod == ring->cons;
251+
}
252+
247253
static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
248254
{
249255
*ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
@@ -315,8 +321,7 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
315321
ring->cons, ring->prod);
316322

317323
/* Unmap and free Rx buffers */
318-
BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size);
319-
while (ring->cons != ring->prod) {
324+
while (!mlx4_en_is_ring_empty(ring)) {
320325
index = ring->cons & ring->size_mask;
321326
en_dbg(DRV, priv, "Processing descriptor:%d\n", index);
322327
mlx4_en_free_rx_desc(priv, ring, index);
@@ -491,6 +496,23 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
491496
return err;
492497
}
493498

499+
/* We recover from out of memory by scheduling our napi poll
500+
* function (mlx4_en_process_cq), which tries to allocate
501+
* all missing RX buffers (call to mlx4_en_refill_rx_buffers).
502+
*/
503+
void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv)
504+
{
505+
int ring;
506+
507+
if (!priv->port_up)
508+
return;
509+
510+
for (ring = 0; ring < priv->rx_ring_num; ring++) {
511+
if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
512+
napi_reschedule(&priv->rx_cq[ring]->napi);
513+
}
514+
}
515+
494516
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
495517
struct mlx4_en_rx_ring **pring,
496518
u32 size, u16 stride)

drivers/net/ethernet/mellanox/mlx4/mlx4_en.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
774774
void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
775775
struct mlx4_en_tx_ring *ring);
776776
void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev);
777+
void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv);
777778
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
778779
struct mlx4_en_rx_ring **pring,
779780
u32 size, u16 stride, int node);

0 commit comments

Comments
 (0)