@@ -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;
}
@@ -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");
@@ -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