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.

Reply via email to