Skip to content

Commit 2e642af

Browse files
nvmmaxSaeed Mahameed
authored andcommitted
net/mlx5e: Disable softirq in mlx5e_activate_rq to avoid race condition
When the driver activates the channels, it assumes NAPI isn't running yet. mlx5e_activate_rq posts a NOP WQE to ICOSQ to trigger a hardware interrupt and start NAPI, which will run mlx5e_alloc_rx_mpwqe and post UMR WQEs to ICOSQ to be able to receive packets with striding RQ. Unfortunately, a race condition is possible if NAPI is triggered by something else (for example, TX) at a bad timing, before mlx5e_activate_rq finishes. In this case, mlx5e_alloc_rx_mpwqe may post UMR WQEs to ICOSQ, and with the bad timing, the wqe_info of the first UMR may be overwritten by the wqe_info of the NOP posted by mlx5e_activate_rq. The consequence is that icosq->db.wqe_info[0].num_wqebbs will be changed from MLX5E_UMR_WQEBBS to 1, disrupting the integrity of the array-based linked list in wqe_info[]. mlx5e_poll_ico_cq will hang in an infinite loop after processing wqe_info[0], because after the corruption, the next item to be processed will be wqe_info[1], which is filled with zeros, and `sqcc += wi->num_wqebbs` will never move further. This commit fixes this race condition by using async_icosq to post the NOP and trigger the interrupt. async_icosq is always protected with a spinlock, eliminating the race condition. Fixes: bc77b24 ("net/mlx5e: Add fragmented memory support for RX multi packet WQE") Signed-off-by: Maxim Mikityanskiy <[email protected]> Reported-by: Karsten Nielsen <[email protected]> Reviewed-by: Tariq Toukan <[email protected]> Reviewed-by: Gal Pressman <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 1f2856c commit 2e642af

File tree

7 files changed

+31
-11
lines changed

7 files changed

+31
-11
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,7 @@ struct mlx5e_rq {
764764
u8 wq_type;
765765
u32 rqn;
766766
struct mlx5_core_dev *mdev;
767+
struct mlx5e_channel *channel;
767768
u32 umr_mkey;
768769
struct mlx5e_dma_info wqe_overflow;
769770

@@ -1076,6 +1077,9 @@ void mlx5e_close_cq(struct mlx5e_cq *cq);
10761077
int mlx5e_open_locked(struct net_device *netdev);
10771078
int mlx5e_close_locked(struct net_device *netdev);
10781079

1080+
void mlx5e_trigger_napi_icosq(struct mlx5e_channel *c);
1081+
void mlx5e_trigger_napi_sched(struct napi_struct *napi);
1082+
10791083
int mlx5e_open_channels(struct mlx5e_priv *priv,
10801084
struct mlx5e_channels *chs);
10811085
void mlx5e_close_channels(struct mlx5e_channels *chs);

drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c)
736736
if (test_bit(MLX5E_PTP_STATE_RX, c->state)) {
737737
mlx5e_ptp_rx_set_fs(c->priv);
738738
mlx5e_activate_rq(&c->rq);
739+
mlx5e_trigger_napi_sched(&c->napi);
739740
}
740741
}
741742

drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ static int mlx5e_rx_reporter_err_icosq_cqe_recover(void *ctx)
123123
xskrq->stats->recover++;
124124
}
125125

126+
mlx5e_trigger_napi_icosq(icosq->channel);
127+
126128
mutex_unlock(&icosq->channel->icosq_recovery_lock);
127129

128130
return 0;
@@ -166,6 +168,10 @@ static int mlx5e_rx_reporter_err_rq_cqe_recover(void *ctx)
166168
clear_bit(MLX5E_RQ_STATE_RECOVERING, &rq->state);
167169
mlx5e_activate_rq(rq);
168170
rq->stats->recover++;
171+
if (rq->channel)
172+
mlx5e_trigger_napi_icosq(rq->channel);
173+
else
174+
mlx5e_trigger_napi_sched(rq->cq.napi);
169175
return 0;
170176
out:
171177
clear_bit(MLX5E_RQ_STATE_RECOVERING, &rq->state);

drivers/net/ethernet/mellanox/mlx5/core/en/trap.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ static void mlx5e_activate_trap(struct mlx5e_trap *trap)
179179
{
180180
napi_enable(&trap->napi);
181181
mlx5e_activate_rq(&trap->rq);
182+
mlx5e_trigger_napi_sched(&trap->napi);
182183
}
183184

184185
void mlx5e_deactivate_trap(struct mlx5e_priv *priv)

drivers/net/ethernet/mellanox/mlx5/core/en/xsk/pool.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ static int mlx5e_xsk_enable_locked(struct mlx5e_priv *priv,
117117
goto err_remove_pool;
118118

119119
mlx5e_activate_xsk(c);
120+
mlx5e_trigger_napi_icosq(c);
120121

121122
/* Don't wait for WQEs, because the newer xdpsock sample doesn't provide
122123
* any Fill Ring entries at the setup stage.

drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ static int mlx5e_init_xsk_rq(struct mlx5e_channel *c,
6464
rq->clock = &mdev->clock;
6565
rq->icosq = &c->icosq;
6666
rq->ix = c->ix;
67+
rq->channel = c;
6768
rq->mdev = mdev;
6869
rq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
6970
rq->xdpsq = &c->rq_xdpsq;
@@ -179,10 +180,6 @@ void mlx5e_activate_xsk(struct mlx5e_channel *c)
179180
mlx5e_reporter_icosq_resume_recovery(c);
180181

181182
/* TX queue is created active. */
182-
183-
spin_lock_bh(&c->async_icosq_lock);
184-
mlx5e_trigger_irq(&c->async_icosq);
185-
spin_unlock_bh(&c->async_icosq_lock);
186183
}
187184

188185
void mlx5e_deactivate_xsk(struct mlx5e_channel *c)

drivers/net/ethernet/mellanox/mlx5/core/en_main.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ static int mlx5e_init_rxq_rq(struct mlx5e_channel *c, struct mlx5e_params *param
475475
rq->clock = &mdev->clock;
476476
rq->icosq = &c->icosq;
477477
rq->ix = c->ix;
478+
rq->channel = c;
478479
rq->mdev = mdev;
479480
rq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu);
480481
rq->xdpsq = &c->rq_xdpsq;
@@ -1066,13 +1067,6 @@ int mlx5e_open_rq(struct mlx5e_params *params, struct mlx5e_rq_param *param,
10661067
void mlx5e_activate_rq(struct mlx5e_rq *rq)
10671068
{
10681069
set_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
1069-
if (rq->icosq) {
1070-
mlx5e_trigger_irq(rq->icosq);
1071-
} else {
1072-
local_bh_disable();
1073-
napi_schedule(rq->cq.napi);
1074-
local_bh_enable();
1075-
}
10761070
}
10771071

10781072
void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
@@ -2227,6 +2221,20 @@ static int mlx5e_channel_stats_alloc(struct mlx5e_priv *priv, int ix, int cpu)
22272221
return 0;
22282222
}
22292223

2224+
void mlx5e_trigger_napi_icosq(struct mlx5e_channel *c)
2225+
{
2226+
spin_lock_bh(&c->async_icosq_lock);
2227+
mlx5e_trigger_irq(&c->async_icosq);
2228+
spin_unlock_bh(&c->async_icosq_lock);
2229+
}
2230+
2231+
void mlx5e_trigger_napi_sched(struct napi_struct *napi)
2232+
{
2233+
local_bh_disable();
2234+
napi_schedule(napi);
2235+
local_bh_enable();
2236+
}
2237+
22302238
static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
22312239
struct mlx5e_params *params,
22322240
struct mlx5e_channel_param *cparam,
@@ -2308,6 +2316,8 @@ static void mlx5e_activate_channel(struct mlx5e_channel *c)
23082316

23092317
if (test_bit(MLX5E_CHANNEL_STATE_XSK, c->state))
23102318
mlx5e_activate_xsk(c);
2319+
2320+
mlx5e_trigger_napi_icosq(c);
23112321
}
23122322

23132323
static void mlx5e_deactivate_channel(struct mlx5e_channel *c)

0 commit comments

Comments
 (0)