Skip to content

Commit

Permalink
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/mst/vhost

Pull virtio fixes from Michael Tsirkin:
 "Fixes and cleanups:

   - A couple of mlx5 fixes related to cvq

   - A couple of reverts dropping useless code (code that used it got
     reverted earlier)"

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost:
  vdpa: mlx5: synchronize driver status with CVQ
  vdpa: mlx5: prevent cvq work from hogging CPU
  Revert "virtio_config: introduce a new .enable_cbs method"
  Revert "virtio: use virtio_device_ready() in virtio_device_restore()"
  • Loading branch information
Linus Torvalds committed Apr 5, 2022
2 parents e2a1256 + 1c80cf0 commit 3e732eb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 30 deletions.
62 changes: 41 additions & 21 deletions drivers/vdpa/mlx5/net/mlx5_vnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ struct mlx5_vdpa_net {
u32 cur_num_vqs;
struct notifier_block nb;
struct vdpa_callback config_cb;
struct mlx5_vdpa_wq_ent cvq_ent;
};

static void free_resources(struct mlx5_vdpa_net *ndev);
Expand Down Expand Up @@ -1658,6 +1659,12 @@ static void mlx5_cvq_kick_handler(struct work_struct *work)
mvdev = wqent->mvdev;
ndev = to_mlx5_vdpa_ndev(mvdev);
cvq = &mvdev->cvq;

mutex_lock(&ndev->reslock);

if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
goto out;

if (!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VQ)))
goto out;

Expand Down Expand Up @@ -1696,17 +1703,20 @@ static void mlx5_cvq_kick_handler(struct work_struct *work)

if (vringh_need_notify_iotlb(&cvq->vring))
vringh_notify(&cvq->vring);

queue_work(mvdev->wq, &wqent->work);
break;
}

out:
kfree(wqent);
mutex_unlock(&ndev->reslock);
}

static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx)
{
struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
struct mlx5_vdpa_virtqueue *mvq;
struct mlx5_vdpa_wq_ent *wqent;

if (!is_index_valid(mvdev, idx))
return;
Expand All @@ -1715,13 +1725,7 @@ static void mlx5_vdpa_kick_vq(struct vdpa_device *vdev, u16 idx)
if (!mvdev->wq || !mvdev->cvq.ready)
return;

wqent = kzalloc(sizeof(*wqent), GFP_ATOMIC);
if (!wqent)
return;

wqent->mvdev = mvdev;
INIT_WORK(&wqent->work, mlx5_cvq_kick_handler);
queue_work(mvdev->wq, &wqent->work);
queue_work(mvdev->wq, &ndev->cvq_ent.work);
return;
}

Expand Down Expand Up @@ -2180,7 +2184,7 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb
goto err_mr;

if (!(mvdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
return 0;
goto err_mr;

restore_channels_info(ndev);
err = setup_driver(mvdev);
Expand All @@ -2195,12 +2199,14 @@ static int mlx5_vdpa_change_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb
return err;
}

/* reslock must be held for this function */
static int setup_driver(struct mlx5_vdpa_dev *mvdev)
{
struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
int err;

mutex_lock(&ndev->reslock);
WARN_ON(!mutex_is_locked(&ndev->reslock));

if (ndev->setup) {
mlx5_vdpa_warn(mvdev, "setup driver called for already setup driver\n");
err = 0;
Expand Down Expand Up @@ -2230,7 +2236,6 @@ static int setup_driver(struct mlx5_vdpa_dev *mvdev)
goto err_fwd;
}
ndev->setup = true;
mutex_unlock(&ndev->reslock);

return 0;

Expand All @@ -2241,23 +2246,23 @@ static int setup_driver(struct mlx5_vdpa_dev *mvdev)
err_rqt:
teardown_virtqueues(ndev);
out:
mutex_unlock(&ndev->reslock);
return err;
}

/* reslock must be held for this function */
static void teardown_driver(struct mlx5_vdpa_net *ndev)
{
mutex_lock(&ndev->reslock);

WARN_ON(!mutex_is_locked(&ndev->reslock));

if (!ndev->setup)
goto out;
return;

remove_fwd_to_tir(ndev);
destroy_tir(ndev);
destroy_rqt(ndev);
teardown_virtqueues(ndev);
ndev->setup = false;
out:
mutex_unlock(&ndev->reslock);
}

static void clear_vqs_ready(struct mlx5_vdpa_net *ndev)
Expand All @@ -2278,6 +2283,8 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)

print_status(mvdev, status, true);

mutex_lock(&ndev->reslock);

if ((status ^ ndev->mvdev.status) & VIRTIO_CONFIG_S_DRIVER_OK) {
if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
err = setup_driver(mvdev);
Expand All @@ -2287,16 +2294,19 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status)
}
} else {
mlx5_vdpa_warn(mvdev, "did not expect DRIVER_OK to be cleared\n");
return;
goto err_clear;
}
}

ndev->mvdev.status = status;
mutex_unlock(&ndev->reslock);
return;

err_setup:
mlx5_vdpa_destroy_mr(&ndev->mvdev);
ndev->mvdev.status |= VIRTIO_CONFIG_S_FAILED;
err_clear:
mutex_unlock(&ndev->reslock);
}

static int mlx5_vdpa_reset(struct vdpa_device *vdev)
Expand All @@ -2306,6 +2316,8 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev)

print_status(mvdev, 0, true);
mlx5_vdpa_info(mvdev, "performing device reset\n");

mutex_lock(&ndev->reslock);
teardown_driver(ndev);
clear_vqs_ready(ndev);
mlx5_vdpa_destroy_mr(&ndev->mvdev);
Expand All @@ -2318,6 +2330,7 @@ static int mlx5_vdpa_reset(struct vdpa_device *vdev)
if (mlx5_vdpa_create_mr(mvdev, NULL))
mlx5_vdpa_warn(mvdev, "create MR failed\n");
}
mutex_unlock(&ndev->reslock);

return 0;
}
Expand Down Expand Up @@ -2353,19 +2366,24 @@ static u32 mlx5_vdpa_get_generation(struct vdpa_device *vdev)
static int mlx5_vdpa_set_map(struct vdpa_device *vdev, struct vhost_iotlb *iotlb)
{
struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
bool change_map;
int err;

mutex_lock(&ndev->reslock);

err = mlx5_vdpa_handle_set_map(mvdev, iotlb, &change_map);
if (err) {
mlx5_vdpa_warn(mvdev, "set map failed(%d)\n", err);
return err;
goto err;
}

if (change_map)
return mlx5_vdpa_change_map(mvdev, iotlb);
err = mlx5_vdpa_change_map(mvdev, iotlb);

return 0;
err:
mutex_unlock(&ndev->reslock);
return err;
}

static void mlx5_vdpa_free(struct vdpa_device *vdev)
Expand Down Expand Up @@ -2740,6 +2758,8 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name,
if (err)
goto err_mr;

ndev->cvq_ent.mvdev = mvdev;
INIT_WORK(&ndev->cvq_ent.work, mlx5_cvq_kick_handler);
mvdev->wq = create_singlethread_workqueue("mlx5_vdpa_wq");
if (!mvdev->wq) {
err = -ENOMEM;
Expand Down
5 changes: 2 additions & 3 deletions drivers/virtio/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,9 +526,8 @@ int virtio_device_restore(struct virtio_device *dev)
goto err;
}

/* If restore didn't do it, mark device DRIVER_OK ourselves. */
if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK))
virtio_device_ready(dev);
/* Finally, tell the device we're all set */
virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);

virtio_config_enable(dev);

Expand Down
6 changes: 0 additions & 6 deletions include/linux/virtio_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ struct virtio_shm_region {
* any of @get/@set, @get_status/@set_status, or @get_features/
* @finalize_features are NOT safe to be called from an atomic
* context.
* @enable_cbs: enable the callbacks
* vdev: the virtio_device
* @get: read the value of a configuration field
* vdev: the virtio_device
* offset: the offset of the configuration field
Expand Down Expand Up @@ -78,7 +76,6 @@ struct virtio_shm_region {
*/
typedef void vq_callback_t(struct virtqueue *);
struct virtio_config_ops {
void (*enable_cbs)(struct virtio_device *vdev);
void (*get)(struct virtio_device *vdev, unsigned offset,
void *buf, unsigned len);
void (*set)(struct virtio_device *vdev, unsigned offset,
Expand Down Expand Up @@ -233,9 +230,6 @@ void virtio_device_ready(struct virtio_device *dev)
{
unsigned status = dev->config->get_status(dev);

if (dev->config->enable_cbs)
dev->config->enable_cbs(dev);

BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
}
Expand Down

0 comments on commit 3e732eb

Please sign in to comment.