Re: [virtio-dev] virtio-snd comments/questions

Radu Ocica
2023-11-03T19:05:40Z

[-- Attachment #1: Type: text/plain, Size: 13934 bytes --]

Hi Matias,

I will answer to your comments:

> I agree that the STOP command could be better explain it. In our
implementation[1], we implemented as your last point defines it, i.e.,
stop host's pcm stream and keep messages in tx/rx. The STOP control
command is marked as completed immediately. The virtio spec does not
indicate that STOP requires to mark pending io messages as completed
thus we do not do that. A note about this in the spec would help.

In our implementation we made the assumption that STOP is meant to be implemented as pause, thus if the host stream supports the pause operation we pause it and keep io messages in tx/rx queue; the host stream is stopped (via the drop operation) and io messages are marked in this case as completed and returned to the guest driver only when receiving the RELEASE control request.

However, if the host stream does not support pause the only option left is to perform a drop operation on the host stream and in this case all pending messages in the tx/rx queue need to be returned to the guest as completed, because at the next start possibly all messages will be needed to prime the host stream (in the case of playback). A host stream prepare will also be needed to be issued internally by the device if a START is issued by the guest right after the STOP. And there is some uncertainty whether a guest driver will send new io messages before or after the START control request.

I think the difficulty of describing a clear behavior for STOP stems from attempting a minimal spec, with a minimal number of control requests. If dedicated STOP vs PAUSE requests were used, it would be more straightforward to specify an unambiguous behavior for each.

> Checking the Linux kernel driver, the STOP cmd is issued when getting
SNDRV_PCM_TRIGGER_PAUSE_PUSH. Documentation does not indicate when this
msg is sent though. The RELEASE cmd is issued only during
virtsnd_pcm_sync_stop(). In this sense, I would guess that STOP behaves
like a PAUSE whereas RELEASE behaves like a STOP and dropping all
pending IO messages. The spec left for the implementation if device
would still playback those buffer or just drop them. I think you may
find interesting the discussion we started at this thread[2] regarding
the RELEASE control cmd semantics.

We have made the call to never have the device drain the host pcm stream. If the host pcm stream supports pause, then STOP pauses it and RELEASE performs a drop and returns immediately all io messages as completed to the guest driver. If the host pcm stream does not support pause, then STOP results in a drop operation and return of all io messages as completed to the guest driver, and the RELEASE is a no-op. A drain like behavior for playback can be obtained if the guest driver stops writing new data and waits to underrun, time at which it sends STOP and RELEASE. This seems to work fine with the existing reference linux/android guest driver for success path handling. There are questions regarding failure path handling (failure of control or io requests) and what variability can/should be expected in terms of guest driver behavior.

> Right, we discussed about this issue at [3]. I've recently proposed the
following patch to fix that: '[PATCH v3] ALSA: virtio: use ack callback'

This looks promising. I found it already at https://github.com/torvalds/linux/blob/master/sound/virtio/ and will give it a try. Is there a repository for this driver code where both this fix and the audio control support is available?

Thank you for your comments and the very valuable information on the ack callback patch.

Regards,

Radu

________________________________
From: Matias Ezequiel Vara Larsen <mvaralar@redhat.com>
Sent: Tuesday, October 24, 2023 6:18:17 AM
To: Radu Ocica
Cc: virtio-comment@lists.oasis-open.org; virtio-dev@lists.oasis-open.org; anton.yakovlev@opensynergy.com
Subject: Re: [virtio-dev] virtio-snd comments/questions

CAUTION - This email is from an external source. Please be cautious with links and attachments. (go/taginfo)

Hello Radu,

I CC Anton too. This email responds part of the questions.

On Wed, Oct 18, 2023 at 03:32:21PM +0000, Radu Ocica wrote:
> Hi,
> I am working on implementing a virtio-snd vdev. During my work on different aspects of the implementation I stumbled across the following issues with the virtio sound device specification (that is part of the virtio 1.3 draft). In some cases additional clarifications might be enough to address the issue, in others additional features might be required. Below is a list of the issues, with some suggestions on how the issues could be addressed.
> PCM playback and capture
> Unclear semantics of PCM_STOP/PCM_START operations
> The virtio-snd specification is not clear on the expectations on how the PCM_STOP control request is to be handled by the vdev, in terms of whether to:
>
> * drop the remaining buffered audio in the host pcm stream and return pending io messages to the guest driver
> * drop the remaining buffered audio in the host pcm stream and keep pending io messages in order to be able to prime the host pcm stream in case PCM_STOP is followed by PCM_START; return pending io messages only when receiving PCM_RELEASE
> * drain the remaining buffered audio in the host pcm stream and send a PCM_STOP response upon drain completion, return pending io messages to the guest driver as they are completed (before PCM_STOP response); drain capability might or might not be available for the host pcm stream
> * start draining the remaining buffered audio in the host pcm stream and send a PCM_STOP response immediately, return pending io messages to the guest driver as they are completed (after PCM_STOP response); if receiving PCM_RELEASE before drain completion hold off the response until all pending io messages are completed and returned to the guest driver; drain capability might or might not be available for the host pcm stream
> * pause the host pcm stream and maintain buffered audio / pending io messages as is; pause capability might or might not be available for the host pcm stream
>

I agree that the STOP command could be better explain it. In our
implementation[1], we implemented as your last point defines it, i.e.,
stop host's pcm stream and keep messages in tx/rx. The STOP control
command is marked as completed immediately. The virtio spec does not
indicate that STOP requires to mark pending io messages as completed
thus we do not do that. A note about this in the spec would help.

> If the thinking is that the vdev on the host can decide on how to implement PCM_STOP based on the host stream capabilities, the guest driver has no information about the choice made by the vdev. In our opinion the choice made by the vdev in implementing PCM_STOP dictates what the possible transitions after PCM_STOP can be (if PCM_STOP is implemented as pause, PCM_START and PCM_RELEASE are possible transitions, but if PCM_STOP is implemented as drain, the only valid transition is PCM_RELEASE and if PCM_STOP is implemented as drop and all pending io messages have been returned to the guest driver, again the only valid transition seems to be PCM_RELEASE), but the guest driver is the one issuing the next request and it might at the best be able to make an educated guess how the vdev implemented PCM_STOP based on whether all the pending io messages are returned or not to the guest driver. To make such a guess possible, more clarifications would be required in the spec to identify which of the scenarios listed above are considered by the spec.

Checking the Linux kernel driver, the STOP cmd is issued when getting
SNDRV_PCM_TRIGGER_PAUSE_PUSH. Documentation does not indicate when this
msg is sent though. The RELEASE cmd is issued only during
virtsnd_pcm_sync_stop(). In this sense, I would guess that STOP behaves
like a PAUSE whereas RELEASE behaves like a STOP and dropping all
pending IO messages. The spec left for the implementation if device
would still playback those buffer or just drop them. I think you may
find interesting the discussion we started at this thread[2] regarding
the RELEASE control cmd semantics.

> Note 1: The reference virtio-snd linux/android guest driver explicitly doesn't support the ALSA SNDRV_PCM_INFO_DRAIN_TRIGGER feature flag, which might indicate there was no intent to support drain semantics.
> Note 2: The reference virtio-snd linux/android guest driver explicitly does support the ALSA SNDRV_PCM_INFO_PAUSE feature flag, which seems to indicate intent to support pause semantics, along with drop semantics.
> Note 3: The Android Audio HAL and tinyalsa/tinyplay don't have any notion of drain or pause. At the end of a playback session there is a wait for previously buffered data to complete playing using the tinyalsa pcm_wait() function, and then a PCM_STOP request is issued after the buffered audio has completed playing. Drop semantics are assumed for PCM_STOP in this context.
> Information on period alignment and max audio buffer size
> No information about period alignment and min/max audio buffer/period size is currently available in struct virtio_snd_pcm_info. Ideally the period size used for io messages should match the period size used on the host. That will guarantee consistency in timing, precise accounting of available room to write more data or available data to read, across host and guest. A workaround is possible, where the device will fail a PCM_SET_PARAMETERS request that specifies an unsupported period alignment or audio buffer/period size and the guest is forced to use a period and buffer size that is known to be supported by the host device (this can be done in an Android guest, by hard coding the android audio HAL period size and the number of periods and thus effectively the audio buffer size that is used for the virtio sound devices in the guest; in android and linux guests it can be done also by setting the virtio_snd module parameters, to the effect of locking down the period and buffer size).
> General Issues
>
> * There is no statement regarding the endianness of PCM data exchanged via txq and rxq queues and the virtio sound PCM format definitions do not include endianness.
> * There is currently no requirement for the guest driver to enqueue an io message only after it has completed writing data to it (playback) or reading data from it (capture). The linux/android guest driver currently enqueues an io message for playback immediately after calling snd_pcm_period_elapsed(). snd_pcm_period_elapsed() makes it possible for the guest client app to write new data, but upon the return of this function there is no guarantee that the guest client app has already written new data. If the vdev dequeues the io message immediately and copies the PCM data for that io request before the guest client app has actually written new data to it, it results in out-of-sequence/stale data being played back.

Right, we discussed about this issue at [3]. I've recently proposed the
following patch to fix that: '[PATCH v3] ALSA: virtio: use ack callback'

> * There is no statement how the guest driver should react to a control request failing.
>
> * For PCM control requests the spec details what the "possible transitions" are after each control request. It doesn't specify whether this applies only to successful control requests, or irrespective of the success of the control requests. For instance for PCM_START only PCM_STOP is listed as a valid transition. What happens if PCM_START fails though? Is PCM_STOP still a valid transition? Is a repeat of PCM_START valid, since the previous PCM_START failed? Is a PCM_RELEASE required in order for the guest driver to recover the io request descriptors that were sent to the vdev before PCM_START? Is a PCM_STOP required in this case, in order to be able to send PCM_RELEASE (because of valid sequences considerations)? It was seen that the reference linux/android guest driver ignores a PCM_START failure and still sends io requests after the failed PCM_START.

We've also spotted that the spec does not specify what to do with
invalid transitions. I think in those cases the transition cannot be
taken and thus spec only refers to successful transitions. IIUC, in
Crosvm, for example, if a cmd is executed in a invalid state, the device
returns error to the guest but the transition does not happen.

I will send a second email to address the remainder points.

Thanks, Matias.

[1] https://urldefense.com/v3/__https://github.com/rust-vmm/vhost-device/tree/main/staging/vhost-device-sound__;!!JoeW-IhCUkS0Jg!bYrKkBHywrzvbKqKlnT9sd2r8yt3hdxcPMpipjtExqsI3lIusGdbwOM5n1sT_BE1-GB4xdvBalxdvUzFVHM$
[2] https://urldefense.com/v3/__https://lore.kernel.org/all/1a54feab-5de9-4b39-a4ce-7ff22e23cf52@opensynergy.com/T/__;!!JoeW-IhCUkS0Jg!bYrKkBHywrzvbKqKlnT9sd2r8yt3hdxcPMpipjtExqsI3lIusGdbwOM5n1sT_BE1-GB4xdvBalxdg5pM9y4$
[3] https://urldefense.com/v3/__https://lore.kernel.org/all/f28d4604-b169-4583-b9ab-d53e6d08ce63@opensynergy.com/T/__;!!JoeW-IhCUkS0Jg!bYrKkBHywrzvbKqKlnT9sd2r8yt3hdxcPMpipjtExqsI3lIusGdbwOM5n1sT_BE1-GB4xdvBalxdHbWqCWs$ .

----------------------------------------------------------------------
This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful.

[-- Attachment #2: Type: text/html, Size: 17731 bytes --]