It is much easier to migrate an array of structs than individual structs that are accessed via a pointer to a pointer to an array of pointers to struct.
For this reason, allocate an array of streams in virtio_snd_realize() and initialise all stream variables that are constant at runtime immediately after allocation. This makes it easier to remove the virtio_snd_set_pcm_params() and virtio_snd_pcm_prepare() calls in the realisation phase and to migrate the audio streams of the virtio sound device after the next few patches. Signed-off-by: Volker Rümelin <vr_q...@t-online.de> --- hw/audio/virtio-snd.c | 37 ++++++++++++++++++++++------------- include/hw/audio/virtio-snd.h | 1 + 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 7ed5f3de3e..e5497b6bf6 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -448,12 +448,9 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) stream = virtio_snd_pcm_get_stream(s, stream_id); if (stream == NULL) { - stream = g_new0(VirtIOSoundPCMStream, 1); + stream = &s->streams[stream_id]; stream->active = false; - stream->id = stream_id; stream->pcm = s->pcm; - stream->s = s; - QSIMPLEQ_INIT(&stream->queue); /* * stream_id >= s->snd_conf.streams was checked before so this is @@ -463,14 +460,6 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) } virtio_snd_get_qemu_audsettings(&as, params); - stream->info.direction = stream_id < s->snd_conf.streams / 2 + - (s->snd_conf.streams & 1) ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT; - stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID; - stream->info.features = 0; - stream->info.channels_min = 1; - stream->info.channels_max = as.nchannels; - stream->info.formats = supported_formats; - stream->info.rates = supported_rates; stream->params = *params; stream->positions[0] = VIRTIO_SND_CHMAP_FL; @@ -1040,6 +1029,25 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) vsnd->vmstate = qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); + vsnd->streams = g_new0(VirtIOSoundPCMStream, vsnd->snd_conf.streams); + + for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { + VirtIOSoundPCMStream *stream = &vsnd->streams[i]; + + stream->id = i; + stream->s = vsnd; + QSIMPLEQ_INIT(&stream->queue); + stream->info.hdr.hda_fn_nid = VIRTIO_SOUND_HDA_FN_NID; + stream->info.features = 0; + stream->info.formats = supported_formats; + stream->info.rates = supported_rates; + stream->info.direction = + i < vsnd->snd_conf.streams / 2 + (vsnd->snd_conf.streams & 1) + ? VIRTIO_SND_D_OUTPUT : VIRTIO_SND_D_INPUT; + stream->info.channels_min = 1; + stream->info.channels_max = 2; + } + vsnd->pcm = g_new0(VirtIOSoundPCM, 1); vsnd->pcm->snd = vsnd; vsnd->pcm->streams = @@ -1280,14 +1288,13 @@ static void virtio_snd_unrealize(DeviceState *dev) qemu_del_vm_change_state_handler(vsnd->vmstate); trace_virtio_snd_unrealize(vsnd); - if (vsnd->pcm) { + if (vsnd->streams) { if (vsnd->pcm->streams) { for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { stream = vsnd->pcm->streams[i]; if (stream) { virtio_snd_process_cmdq(stream->s); virtio_snd_pcm_close(stream); - g_free(stream); } } g_free(vsnd->pcm->streams); @@ -1295,6 +1302,8 @@ static void virtio_snd_unrealize(DeviceState *dev) g_free(vsnd->pcm->pcm_params); g_free(vsnd->pcm); vsnd->pcm = NULL; + g_free(vsnd->streams); + vsnd->streams = NULL; } AUD_remove_card(&vsnd->card); virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]); diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h index a2868067fb..95aef8192a 100644 --- a/include/hw/audio/virtio-snd.h +++ b/include/hw/audio/virtio-snd.h @@ -215,6 +215,7 @@ struct VirtIOSound { VirtQueue *queues[VIRTIO_SND_VQ_MAX]; uint64_t features; VirtIOSoundPCM *pcm; + VirtIOSoundPCMStream *streams; QEMUSoundCard card; VMChangeStateEntry *vmstate; virtio_snd_config snd_conf; -- 2.35.3