Skip to content

Commit 0dbc1b4

Browse files
elic307imstsirkin
authored andcommitted
vdpa/mlx5: Avoid using reslock in event_handler
event_handler runs under atomic context and may not acquire reslock. We can still guarantee that the handler won't be called after suspend by clearing nb_registered, unregistering the handler and flushing the workqueue. Signed-off-by: Eli Cohen <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 1ab5376 commit 0dbc1b4

File tree

1 file changed

+4
-12
lines changed

1 file changed

+4
-12
lines changed

drivers/vdpa/mlx5/net/mlx5_vnet.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,8 +2845,8 @@ static int mlx5_vdpa_suspend(struct vdpa_device *vdev)
28452845
int i;
28462846

28472847
down_write(&ndev->reslock);
2848-
mlx5_notifier_unregister(mvdev->mdev, &ndev->nb);
28492848
ndev->nb_registered = false;
2849+
mlx5_notifier_unregister(mvdev->mdev, &ndev->nb);
28502850
flush_workqueue(ndev->mvdev.wq);
28512851
for (i = 0; i < ndev->cur_num_vqs; i++) {
28522852
mvq = &ndev->vqs[i];
@@ -3024,7 +3024,7 @@ static void update_carrier(struct work_struct *work)
30243024
else
30253025
ndev->config.status &= cpu_to_mlx5vdpa16(mvdev, ~VIRTIO_NET_S_LINK_UP);
30263026

3027-
if (ndev->config_cb.callback)
3027+
if (ndev->nb_registered && ndev->config_cb.callback)
30283028
ndev->config_cb.callback(ndev->config_cb.private);
30293029

30303030
kfree(wqent);
@@ -3041,21 +3041,13 @@ static int event_handler(struct notifier_block *nb, unsigned long event, void *p
30413041
switch (eqe->sub_type) {
30423042
case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
30433043
case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
3044-
down_read(&ndev->reslock);
3045-
if (!ndev->nb_registered) {
3046-
up_read(&ndev->reslock);
3047-
return NOTIFY_DONE;
3048-
}
30493044
wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC);
3050-
if (!wqent) {
3051-
up_read(&ndev->reslock);
3045+
if (!wqent)
30523046
return NOTIFY_DONE;
3053-
}
30543047

30553048
wqent->mvdev = &ndev->mvdev;
30563049
INIT_WORK(&wqent->work, update_carrier);
30573050
queue_work(ndev->mvdev.wq, &wqent->work);
3058-
up_read(&ndev->reslock);
30593051
ret = NOTIFY_OK;
30603052
break;
30613053
default:
@@ -3242,8 +3234,8 @@ static void mlx5_vdpa_dev_del(struct vdpa_mgmt_dev *v_mdev, struct vdpa_device *
32423234
struct workqueue_struct *wq;
32433235

32443236
if (ndev->nb_registered) {
3245-
mlx5_notifier_unregister(mvdev->mdev, &ndev->nb);
32463237
ndev->nb_registered = false;
3238+
mlx5_notifier_unregister(mvdev->mdev, &ndev->nb);
32473239
}
32483240
wq = mvdev->wq;
32493241
mvdev->wq = NULL;

0 commit comments

Comments
 (0)