On Mon, Jun 24, 2024 at 11:04:50AM +0200, Jiri Pirko wrote:
> @@ -73,21 +91,30 @@ static int virtqueue_exec_admin_cmd(struct
> virtio_pci_device *vp_dev,
> !((1ULL << opcode) & admin_vq->supported_cmds))
> return -EOPNOTSUPP;
>
> - ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_KERNEL);
> - if (ret < 0)
> - return -EIO;
> -
> - if (unlikely(!virtqueue_kick(vq)))
> - return -EIO;
> + init_completion(&cmd->completion);
>
> - while (!virtqueue_get_buf(vq, &len) &&
> - !virtqueue_is_broken(vq))
> - cpu_relax();
> +again:
> + spin_lock_irqsave(&admin_vq->lock, flags);
> + ret = virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_KERNEL);
> + if (ret < 0) {
> + if (ret == -ENOSPC) {
> + spin_unlock_irqrestore(&admin_vq->lock, flags);
> + cpu_relax();
> + goto again;
> + }
> + goto unlock_err;
> + }
> + if (WARN_ON_ONCE(!virtqueue_kick(vq)))
> + goto unlock_err;
> + spin_unlock_irqrestore(&admin_vq->lock, flags);
>
> - if (virtqueue_is_broken(vq))
> - return -EIO;
> + wait_for_completion(&cmd->completion);
>
> return 0;
> +
> +unlock_err:
> + spin_unlock_irqrestore(&admin_vq->lock, flags);
> + return -EIO;
> }
>
The reason we had the virtqueue_is_broken check previously,
is because this way surprise removal works: it happens to set
vq broken flag on all vqs.
So if you are changing that to a completion, I think surprise
removal needs to trigger a callback so the completion
can be signalled.
I think the cvq work also needs this, BTW.
--
MST