From: Feng Liu <feliu@xxxxxxxxxx> Synchronous command helper function is exposed at virtio layer, so that ctrl virtqueue and admin virtqueues can reuse this helper function to send synchronous commands. Signed-off-by: Feng Liu <feliu@xxxxxxxxxx> Reviewed-by: Parav Pandit <parav@xxxxxxxxxx> Reviewed-by: Jiri Pirko <jiri@xxxxxxxxxx> Signed-off-by: Yishai Hadas <yishaih@xxxxxxxxxx> --- drivers/net/virtio_net.c | 21 ++++++--------------- drivers/virtio/virtio_ring.c | 27 +++++++++++++++++++++++++++ include/linux/virtio.h | 7 +++++++ 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index fe7f314d65c9..65c210b0fb9e 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -2451,7 +2451,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, struct scatterlist *out) { struct scatterlist *sgs[4], hdr, stat; - unsigned out_num = 0, tmp; + unsigned int out_num = 0; int ret; /* Caller should know better */ @@ -2472,23 +2472,14 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, sgs[out_num] = &stat; BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); - ret = virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); - if (ret < 0) { - dev_warn(&vi->vdev->dev, - "Failed to add sgs for command vq: %d\n.", ret); + ret = virtqueue_exec_cmd(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); + if (ret) { + dev_err(&vi->vdev->dev, + "Failed to exec command vq(%s,%d): %d\n", + vi->cvq->name, vi->cvq->index, ret); return false; } - if (unlikely(!virtqueue_kick(vi->cvq))) - return vi->ctrl->status == VIRTIO_NET_OK; - - /* Spin for a response, the kick causes an ioport write, trapping - * into the hypervisor, so the request should be handled immediately. - */ - while (!virtqueue_get_buf(vi->cvq, &tmp) && - !virtqueue_is_broken(vi->cvq)) - cpu_relax(); - return vi->ctrl->status == VIRTIO_NET_OK; } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 51d8f3299c10..253905c0b008 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -3251,4 +3251,31 @@ void virtqueue_dma_sync_single_range_for_device(struct virtqueue *_vq, } EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_device); +int virtqueue_exec_cmd(struct virtqueue *vq, + struct scatterlist **sgs, + unsigned int out_num, + unsigned int in_num, + void *data, + gfp_t gfp) +{ + int ret, len; + + ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, data, gfp); + if (ret < 0) + return ret; + + if (unlikely(!virtqueue_kick(vq))) + return -EIO; + + /* Spin for a response, the kick causes an ioport write, trapping + * into the hypervisor, so the request should be handled immediately. + */ + while (!virtqueue_get_buf(vq, &len) && + !virtqueue_is_broken(vq)) + cpu_relax(); + + return 0; +} +EXPORT_SYMBOL_GPL(virtqueue_exec_cmd); + MODULE_LICENSE("GPL"); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 4cc614a38376..9d39706bed10 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -103,6 +103,13 @@ int virtqueue_resize(struct virtqueue *vq, u32 num, int virtqueue_reset(struct virtqueue *vq, void (*recycle)(struct virtqueue *vq, void *buf)); +int virtqueue_exec_cmd(struct virtqueue *vq, + struct scatterlist **sgs, + unsigned int out_num, + unsigned int in_num, + void *data, + gfp_t gfp); + /** * struct virtio_device - representation of a device using virtio * @index: unique position on the virtio bus -- 2.27.0