A signal can end the interruptible wait while a STOP or RELEASE request is still pending. A later teardown may then submit another RELEASE before the first request completes.
Keep both waits non-interruptible and use the existing message timeout. Other control requests remain interruptible. Device reset still cancels the pending request and wakes the waiter. Assisted-by: LLM Signed-off-by: Joonho Lee <[email protected]> --- sound/virtio/virtio_ctl_msg.c | 15 ++++++++++++++- sound/virtio/virtio_ctl_msg.h | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sound/virtio/virtio_ctl_msg.c b/sound/virtio/virtio_ctl_msg.c index 2e0ff15e729d..e50e6c7f3b8d 100644 --- a/sound/virtio/virtio_ctl_msg.c +++ b/sound/virtio/virtio_ctl_msg.c @@ -314,7 +314,20 @@ int virtsnd_ctl_msg_send(struct virtio_snd *snd, struct virtio_snd_msg *msg, */ virtsnd_ctl_msg_unref(msg); } else if (!nowait) { - rc = wait_for_completion_interruptible_timeout(&msg->notify, js); + /* + * Teardown must observe completion even with a pending signal. + * Otherwise a subsequent open can retry RELEASE while the device + * is still processing the previous teardown request. + */ + switch (le32_to_cpu(request->code)) { + case VIRTIO_SND_R_PCM_STOP: + case VIRTIO_SND_R_PCM_RELEASE: + rc = wait_for_completion_timeout(&msg->notify, js); + break; + default: + rc = wait_for_completion_interruptible_timeout(&msg->notify, js); + break; + } if (!rc) { dev_err(&vdev->dev, "control message (0x%08x) timeout\n", diff --git a/sound/virtio/virtio_ctl_msg.h b/sound/virtio/virtio_ctl_msg.h index f867b9b9233d..d84f0740fcb0 100644 --- a/sound/virtio/virtio_ctl_msg.h +++ b/sound/virtio/virtio_ctl_msg.h @@ -47,6 +47,9 @@ int virtsnd_ctl_msg_send(struct virtio_snd *snd, struct virtio_snd_msg *msg, * The msg_timeout_ms module parameter defines the message completion timeout. * If the message is not completed within this time, the function will return an * error. + * PCM STOP and RELEASE wait through pending signals within this timeout. + * Other requests remain interruptible. Device reset cancels and wakes either + * kind of waiter. * * Context: Any context that permits to sleep. * Return: 0 on success, -errno on failure.

