Commit 6f45ab3e authored by Daniel Jurgens's avatar Daniel Jurgens Committed by Paolo Abeni
Browse files

virtio_net: Add a lock for the command VQ.



The command VQ will no longer be protected by the RTNL lock. Use a
mutex to protect the control buffer header and the VQ.

Signed-off-by: default avatarDaniel Jurgens <danielj@nvidia.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Reviewed-by: default avatarHeng Qi <hengqi@linux.alibaba.com>
Tested-by: default avatarHeng Qi <hengqi@linux.alibaba.com>
Acked-by: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent ff7c7d9f
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -411,6 +411,9 @@ struct virtnet_info {
	/* Has control virtqueue */
	bool has_cvq;

	/* Lock to protect the control VQ */
	struct mutex cvq_lock;

	/* Host can handle any s/g split between our header and packet data */
	bool any_header_sg;

@@ -2675,6 +2678,7 @@ static bool virtnet_send_command_reply(struct virtnet_info *vi, u8 class, u8 cmd
	/* Caller should know better */
	BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));

	mutex_lock(&vi->cvq_lock);
	vi->ctrl->status = ~0;
	vi->ctrl->hdr.class = class;
	vi->ctrl->hdr.cmd = cmd;
@@ -2697,11 +2701,12 @@ static bool virtnet_send_command_reply(struct virtnet_info *vi, u8 class, u8 cmd
	if (ret < 0) {
		dev_warn(&vi->vdev->dev,
			 "Failed to add sgs for command vq: %d\n.", ret);
		mutex_unlock(&vi->cvq_lock);
		return false;
	}

	if (unlikely(!virtqueue_kick(vi->cvq)))
		return vi->ctrl->status == VIRTIO_NET_OK;
		goto unlock;

	/* Spin for a response, the kick causes an ioport write, trapping
	 * into the hypervisor, so the request should be handled immediately.
@@ -2712,6 +2717,8 @@ static bool virtnet_send_command_reply(struct virtnet_info *vi, u8 class, u8 cmd
		cpu_relax();
	}

unlock:
	mutex_unlock(&vi->cvq_lock);
	return vi->ctrl->status == VIRTIO_NET_OK;
}

@@ -5736,6 +5743,8 @@ static int virtnet_probe(struct virtio_device *vdev)
	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
		vi->has_cvq = true;

	mutex_init(&vi->cvq_lock);

	if (virtio_has_feature(vdev, VIRTIO_NET_F_MTU)) {
		mtu = virtio_cread16(vdev,
				     offsetof(struct virtio_net_config,