From patchwork Mon Oct 23 12:03:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432806 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A3FC2C00A8F for ; Mon, 23 Oct 2023 12:05:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfG-0005Ei-Ui; Mon, 23 Oct 2023 08:04:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfE-0005EE-RO for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:08 -0400 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfB-0001vd-6D for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:08 -0400 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-4084e49a5e5so27719495e9.3 for ; Mon, 23 Oct 2023 05:04:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062643; x=1698667443; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=h5bEh/UwZJNLOlMLBgyLw9SN22NrMuoXxTmZDmPQu4E=; b=LlWUGQw9CVPf9U67nXQr3I9tX3emM44BQcX7POkTSmPDD38619UibE0ijCUjs9CQ6/ ZR4w/h7inO+Ydl31L7mFFleCysavxzQQWuZB5IwS+qtVTc/x9sKWtELNFZc4r3VRozek t7NUGzm4eHGElW+WpE44mulnV01Y014tW2HmsjUcpWpH2eMCCG7zghUsqJWLhoa3jEpK eNS1jzpzLIeb+Z3fvi73Go7AoIwZMPCzQlsTxI0+79RZBkq1dVHjA4miilQS6f4ys7h3 be+BQHlTEXWB2bIk7YK4UYkSdGhUdwy2Z3qoicPHb19yeMb3UbRCLxefu/B/IHXN4L/q 9VAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062643; x=1698667443; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=h5bEh/UwZJNLOlMLBgyLw9SN22NrMuoXxTmZDmPQu4E=; b=hPkDnYJjSjnzukRPEmmrU6lUHebmJ23fkMaNcXwX5QCsH5WgISVq0i7eMBDy4+QQes AF5cHlhZWiwZrgB3J+veZhoAEUniTJr0GsodG2BH1++chUkWrF3XAIQQnZOtiYlbmGYb 3zh1x5gi868/pAleZG9h8Kb++1Xz8kx7NOcuD7YxkS8JUO7mmUJilvGlfO3ONdHTeGar bLYHprVs8FuIjGZD6nOXSIFXwVQ58ueqxKtGdnzncpyt85FvfKa0yMvQmr85FsMWGVvj 0h/rih2+jmrseT8MdmsK+CrzIjo6hukX8j4aUFs6wYcaO4LsWfRi576ZyRyvhwXOUj2s HW2Q== X-Gm-Message-State: AOJu0Yzqh262yQ0wWLi9FZw6AU1me/t1+oaEkZ+eKM4eaSi/2IzTC60s PeME5ByPOy+Qn3AloLVs78LSRh4WxIJfmUn5Hls= X-Google-Smtp-Source: AGHT+IG+bhjQlN7rkReHg4mDHnAia9erxJacHBFBxG1EeesGypuTOrMHvF08/DOKTVzqzfVLpCAgXQ== X-Received: by 2002:a05:600c:3b1e:b0:405:3d41:5646 with SMTP id m30-20020a05600c3b1e00b004053d415646mr7681093wms.2.1698062641896; Mon, 23 Oct 2023 05:04:01 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.03.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:00 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 01/11] Add virtio-sound device stub Date: Mon, 23 Oct 2023 15:03:18 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32f; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x32f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Add a new VIRTIO device for the virtio sound device id. Functionality will be added in the following commits. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- MAINTAINERS | 7 + hw/audio/Kconfig | 5 + hw/audio/meson.build | 1 + hw/audio/trace-events | 9 ++ hw/audio/virtio-snd.c | 233 ++++++++++++++++++++++++++++++++++ include/hw/audio/virtio-snd.h | 79 ++++++++++++ system/qdev-monitor.c | 1 + 7 files changed, 335 insertions(+) create mode 100644 hw/audio/virtio-snd.c create mode 100644 include/hw/audio/virtio-snd.h diff --git a/MAINTAINERS b/MAINTAINERS index 7f9912baa0..0e628f9e1f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2282,6 +2282,13 @@ F: hw/virtio/virtio-mem-pci.h F: hw/virtio/virtio-mem-pci.c F: include/hw/virtio/virtio-mem.h +virtio-snd +M: Gerd Hoffmann +R: Manos Pitsidianakis +S: Supported +F: hw/audio/virtio-snd.c +F: include/hw/audio/virtio-snd.h + nvme M: Keith Busch M: Klaus Jensen diff --git a/hw/audio/Kconfig b/hw/audio/Kconfig index d0993514a1..daf060e1be 100644 --- a/hw/audio/Kconfig +++ b/hw/audio/Kconfig @@ -50,3 +50,8 @@ config CS4231 config ASC bool + +config VIRTIO_SND + bool + default y + depends on VIRTIO diff --git a/hw/audio/meson.build b/hw/audio/meson.build index 8805322f5c..7a503be1fd 100644 --- a/hw/audio/meson.build +++ b/hw/audio/meson.build @@ -13,3 +13,4 @@ system_ss.add(when: 'CONFIG_PL041', if_true: files('pl041.c', 'lm4549.c')) system_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c')) system_ss.add(when: 'CONFIG_VT82C686', if_true: files('via-ac97.c')) system_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c')) +system_ss.add(when: ['CONFIG_VIRTIO_SND', 'CONFIG_VIRTIO'], if_true: files('virtio-snd.c')) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 059ce451f5..525ced2b34 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -38,3 +38,12 @@ asc_write_fifo(const char fifo, int reg, unsigned size, int wrptr, int cnt, uint asc_write_reg(int reg, unsigned size, uint64_t value) "reg=0x%03x size=%u value=0x%"PRIx64 asc_write_extreg(const char fifo, int reg, unsigned size, uint64_t value) "fifo %c reg=0x%03x size=%u value=0x%"PRIx64 asc_update_irq(int irq, int a, int b) "set IRQ to %d (A: 0x%x B: 0x%x)" + +#virtio-snd.c +virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t streams, uint32_t chmaps) "snd %p: get_config jacks=%"PRIu32" streams=%"PRIu32" chmaps=%"PRIu32"" +virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t new_jacks, uint32_t streams, uint32_t new_streams, uint32_t chmaps, uint32_t new_chmaps) "snd %p: set_config jacks from %"PRIu32"->%"PRIu32", streams from %"PRIu32"->%"PRIu32", chmaps from %"PRIu32"->%"PRIu32 +virtio_snd_get_features(void *vdev, uint64_t features) "snd %p: get_features 0x%"PRIx64 +virtio_snd_vm_state_running(void) "vm state running" +virtio_snd_vm_state_stopped(void) "vm state stopped" +virtio_snd_realize(void *snd) "snd %p: realize" +virtio_snd_unrealize(void *snd) "snd %p: unrealize" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c new file mode 100644 index 0000000000..3a4b441c20 --- /dev/null +++ b/hw/audio/virtio-snd.c @@ -0,0 +1,233 @@ +/* + * VIRTIO Sound Device conforming to + * + * "Virtual I/O Device (VIRTIO) Version 1.2 + * Committee Specification Draft 01 + * 09 May 2022" + * + * + * + * Copyright (c) 2023 Emmanouil Pitsidianakis + * Copyright (C) 2019 OpenSynergy GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/iov.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "include/qemu/lockable.h" +#include "sysemu/runstate.h" +#include "trace.h" +#include "qapi/error.h" +#include "hw/audio/virtio-snd.h" +#include "hw/core/cpu.h" + +#define VIRTIO_SOUND_VM_VERSION 1 +#define VIRTIO_SOUND_JACK_DEFAULT 0 +#define VIRTIO_SOUND_STREAM_DEFAULT 1 +#define VIRTIO_SOUND_CHMAP_DEFAULT 0 +#define VIRTIO_SOUND_HDA_FN_NID 0 + +static const VMStateDescription vmstate_virtio_snd_device = { + .name = TYPE_VIRTIO_SND, + .version_id = VIRTIO_SOUND_VM_VERSION, + .minimum_version_id = VIRTIO_SOUND_VM_VERSION, +}; + +static const VMStateDescription vmstate_virtio_snd = { + .name = TYPE_VIRTIO_SND, + .minimum_version_id = VIRTIO_SOUND_VM_VERSION, + .version_id = VIRTIO_SOUND_VM_VERSION, + .fields = (VMStateField[]) { + VMSTATE_VIRTIO_DEVICE, + VMSTATE_END_OF_LIST() + }, +}; + +static Property virtio_snd_properties[] = { + DEFINE_AUDIO_PROPERTIES(VirtIOSound, card), + DEFINE_PROP_UINT32("jacks", VirtIOSound, snd_conf.jacks, + VIRTIO_SOUND_JACK_DEFAULT), + DEFINE_PROP_UINT32("streams", VirtIOSound, snd_conf.streams, + VIRTIO_SOUND_STREAM_DEFAULT), + DEFINE_PROP_UINT32("chmaps", VirtIOSound, snd_conf.chmaps, + VIRTIO_SOUND_CHMAP_DEFAULT), + DEFINE_PROP_END_OF_LIST(), +}; + +static void +virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VirtIOSound *s = VIRTIO_SND(vdev); + virtio_snd_config *sndconfig = + (virtio_snd_config *)config; + trace_virtio_snd_get_config(vdev, + s->snd_conf.jacks, + s->snd_conf.streams, + s->snd_conf.chmaps); + + memcpy(sndconfig, &s->snd_conf, sizeof(s->snd_conf)); + cpu_to_le32s(&sndconfig->jacks); + cpu_to_le32s(&sndconfig->streams); + cpu_to_le32s(&sndconfig->chmaps); + +} + +static void +virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config) +{ + VirtIOSound *s = VIRTIO_SND(vdev); + const virtio_snd_config *sndconfig = + (const virtio_snd_config *)config; + + + trace_virtio_snd_set_config(vdev, + s->snd_conf.jacks, + sndconfig->jacks, + s->snd_conf.streams, + sndconfig->streams, + s->snd_conf.chmaps, + sndconfig->chmaps); + + memcpy(&s->snd_conf, sndconfig, sizeof(virtio_snd_config)); + le32_to_cpus(&s->snd_conf.jacks); + le32_to_cpus(&s->snd_conf.streams); + le32_to_cpus(&s->snd_conf.chmaps); + +} + +/* + * Queue handler stub. + * + * @vdev: VirtIOSound device + * @vq: virtqueue + */ +static void virtio_snd_handle_queue(VirtIODevice *vdev, VirtQueue *vq) {} + +static uint64_t get_features(VirtIODevice *vdev, uint64_t features, + Error **errp) +{ + /* + * virtio-v1.2-csd01, 5.14.3, + * Feature Bits + * None currently defined. + */ + VirtIOSound *s = VIRTIO_SND(vdev); + features |= s->features; + + trace_virtio_snd_get_features(vdev, features); + + return features; +} + +static void +virtio_snd_vm_state_change(void *opaque, bool running, + RunState state) +{ + if (running) { + trace_virtio_snd_vm_state_running(); + } else { + trace_virtio_snd_vm_state_stopped(); + } +} + +static void virtio_snd_realize(DeviceState *dev, Error **errp) +{ + ERRP_GUARD(); + VirtIOSound *vsnd = VIRTIO_SND(dev); + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + + vsnd->vmstate = + qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); + + trace_virtio_snd_realize(vsnd); + + virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); + virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); + + /* set number of jacks and streams */ + if (vsnd->snd_conf.jacks > 8) { + error_setg(errp, + "Invalid number of jacks: %"PRIu32, + vsnd->snd_conf.jacks); + return; + } + if (vsnd->snd_conf.streams < 1 || vsnd->snd_conf.streams > 10) { + error_setg(errp, + "Invalid number of streams: %"PRIu32, + vsnd->snd_conf.streams); + return; + } + + if (vsnd->snd_conf.chmaps > VIRTIO_SND_CHMAP_MAX_SIZE) { + error_setg(errp, + "Invalid number of channel maps: %"PRIu32, + vsnd->snd_conf.chmaps); + return; + } + + AUD_register_card("virtio-sound", &vsnd->card, errp); + + vsnd->queues[VIRTIO_SND_VQ_CONTROL] = + virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + vsnd->queues[VIRTIO_SND_VQ_EVENT] = + virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + vsnd->queues[VIRTIO_SND_VQ_TX] = + virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + vsnd->queues[VIRTIO_SND_VQ_RX] = + virtio_add_queue(vdev, 64, virtio_snd_handle_queue); +} + +static void virtio_snd_unrealize(DeviceState *dev) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VirtIOSound *vsnd = VIRTIO_SND(dev); + + qemu_del_vm_change_state_handler(vsnd->vmstate); + trace_virtio_snd_unrealize(vsnd); + + AUD_remove_card(&vsnd->card); + virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]); + virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]); + virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]); + virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_RX]); + virtio_cleanup(vdev); +} + + +static void virtio_snd_reset(VirtIODevice *vdev) {} + +static void virtio_snd_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + device_class_set_props(dc, virtio_snd_properties); + + dc->vmsd = &vmstate_virtio_snd; + vdc->vmsd = &vmstate_virtio_snd_device; + vdc->realize = virtio_snd_realize; + vdc->unrealize = virtio_snd_unrealize; + vdc->get_config = virtio_snd_get_config; + vdc->set_config = virtio_snd_set_config; + vdc->get_features = get_features; + vdc->reset = virtio_snd_reset; + vdc->legacy_features = 0; +} + +static const TypeInfo virtio_snd_types[] = { + { + .name = TYPE_VIRTIO_SND, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VirtIOSound), + .class_init = virtio_snd_class_init, + } +}; + +DEFINE_TYPES(virtio_snd_types) diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h new file mode 100644 index 0000000000..d08065941c --- /dev/null +++ b/include/hw/audio/virtio-snd.h @@ -0,0 +1,79 @@ +/* + * VIRTIO Sound Device conforming to + * + * "Virtual I/O Device (VIRTIO) Version 1.2 + * Committee Specification Draft 01 + * 09 May 2022" + * + * Copyright (c) 2023 Emmanouil Pitsidianakis + * Copyright (C) 2019 OpenSynergy GmbH + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#ifndef QEMU_VIRTIO_SOUND_H +#define QEMU_VIRTIO_SOUND_H + +#include "hw/virtio/virtio.h" +#include "audio/audio.h" +#include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/virtio_snd.h" + +#define TYPE_VIRTIO_SND "virtio-sound-device" +#define VIRTIO_SND(obj) \ + OBJECT_CHECK(VirtIOSound, (obj), TYPE_VIRTIO_SND) + +/* CONFIGURATION SPACE */ + +typedef struct virtio_snd_config virtio_snd_config; + +/* COMMON DEFINITIONS */ + +/* common header for request/response*/ +typedef struct virtio_snd_hdr virtio_snd_hdr; + +/* event notification */ +typedef struct virtio_snd_event virtio_snd_event; + +/* common control request to query an item information */ +typedef struct virtio_snd_query_info virtio_snd_query_info; + +/* JACK CONTROL MESSAGES */ + +typedef struct virtio_snd_jack_hdr virtio_snd_jack_hdr; + +/* jack information structure */ +typedef struct virtio_snd_jack_info virtio_snd_jack_info; + +/* jack remapping control request */ +typedef struct virtio_snd_jack_remap virtio_snd_jack_remap; + +/* + * PCM CONTROL MESSAGES + */ +typedef struct virtio_snd_pcm_hdr virtio_snd_pcm_hdr; + +/* PCM stream info structure */ +typedef struct virtio_snd_pcm_info virtio_snd_pcm_info; + +/* set PCM stream params */ +typedef struct virtio_snd_pcm_set_params virtio_snd_pcm_set_params; + +/* I/O request header */ +typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer; + +/* I/O request status */ +typedef struct virtio_snd_pcm_status virtio_snd_pcm_status; + +typedef struct VirtIOSound { + VirtIODevice parent_obj; + + VirtQueue *queues[VIRTIO_SND_VQ_MAX]; + uint64_t features; + QEMUSoundCard card; + VMChangeStateEntry *vmstate; + virtio_snd_config snd_conf; +} VirtIOSound; +#endif diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 1b8005ae55..3c0aabec4b 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -111,6 +111,7 @@ static const QDevAlias qdev_alias_table[] = { { "virtio-serial-device", "virtio-serial", QEMU_ARCH_VIRTIO_MMIO }, { "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_VIRTIO_CCW }, { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_VIRTIO_PCI}, + { "virtio-sound-device", "virtio-sound", QEMU_ARCH_VIRTIO_MMIO }, { "virtio-tablet-device", "virtio-tablet", QEMU_ARCH_VIRTIO_MMIO }, { "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_VIRTIO_CCW }, { "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_VIRTIO_PCI }, From patchwork Mon Oct 23 12:03:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432805 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 90242C004C0 for ; Mon, 23 Oct 2023 12:05:03 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfJ-0005Ez-FA; Mon, 23 Oct 2023 08:04:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfH-0005El-GS for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:11 -0400 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfF-0001wG-7o for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:11 -0400 Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-40806e40fccso23590305e9.2 for ; Mon, 23 Oct 2023 05:04:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062647; x=1698667447; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mXasUvmZk39cYcZpLbfBr96bpoK6BPmT5qu69h1GaCY=; b=R2S7M8nbH3JJqG5Cen/ww5djqIupWWW2OB1rIG1AxMm73mF6zJ7jxNXG4AHIEukyvQ BHQ/rCH82AZ+WtcwMdB8H8/5cIMCx/B1ErmdcATMGhEvOcnslXNK6ZbiWMa2AIobr/H6 qcpMn6ZY93phdLIMMYqYcgKIeFjoD9IemMsmMAAyw8qAxr2kRd/9J9C3nxFUBmXmRAfC CDQ3U/1HKVuaCoami6gf/Aa65vKaCfThJ3ewTdhPL3MG5qdwlLYAdfCFw2zXWe7pRrPV EGTDqW+pMB1GInCbU77+97Vzjm0IejzfK/+yoT/bBHQTpcylLz8x+mo+qn4ESQFOawuO YJtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062647; x=1698667447; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mXasUvmZk39cYcZpLbfBr96bpoK6BPmT5qu69h1GaCY=; b=pJEejf8d7TYpCIvIoM0wyRhWvFD4K+tMNMZ7EdU+3MhBEWX7VkDZ9A2WbHgIVIzwik SaJZU8Ap54F5VgIKMy8/sXIPdXEJpp2rJYJb654cN8HtbR/lmTawCMQgy28kJGYGAO5c KlhaV6Dkju8ZL1FaHDk8B5YjGc8XDdXfiVV+/73EcuSwor/L5OcA8msT7B9SdGmFDFxz Dh4lDkavN58RABg8JoU46BOhUMlYeerdtuD2UMxwgUWgM3JKXO/CmKawHboShFpANB0K EU26YrzBpIYmaq2+0PKI/7NjLEDQxQGeoioKiDjF5wb2sCuUi/k3Q06DCZhL14nLfrey K1QA== X-Gm-Message-State: AOJu0Yzo65Gd62aO0fnsQcwl3cHcLLdZu4n049+LN+vjg7m3vHaGMEVS iNEBU+EZYNFbgjVwX/gXSyb51rvxtKDZLn70v3U= X-Google-Smtp-Source: AGHT+IEXFbhXkYo+hdK7qs1ICGD0mVLtjGk5lSb7TC+53TVxxH8+59wTCz/g7/KE8ECNJv355qczyw== X-Received: by 2002:a05:600c:a4b:b0:3fe:2a98:a24c with SMTP id c11-20020a05600c0a4b00b003fe2a98a24cmr6637398wmq.26.1698062647191; Mon, 23 Oct 2023 05:04:07 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:06 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 02/11] Add virtio-sound-pci device Date: Mon, 23 Oct 2023 15:03:19 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x32d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch adds a PCI wrapper device for the virtio-sound device. It is necessary to instantiate a virtio-snd device in a guest. All sound logic will be added to the virtio-snd device in the following commits. To add this device with a guest, you'll need a >=5.13 kernel compiled with CONFIG_SND_VIRTIO=y, which at the time of writing most distros have off by default. Use with following flags in the invocation: Pulseaudio: -audio driver=pa,model=virtio or -audio driver=pa,model=virtio,server=/run/user/1000/pulse/native sdl: -audio driver=sdl,model=virtio coreaudio (macos/darwin): -audio driver=coreaudio,model=virtio etc. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- MAINTAINERS | 1 + hw/audio/meson.build | 1 + hw/audio/virtio-snd-pci.c | 93 +++++++++++++++++++++++++++++++++++++++ system/qdev-monitor.c | 1 + 4 files changed, 96 insertions(+) create mode 100644 hw/audio/virtio-snd-pci.c diff --git a/MAINTAINERS b/MAINTAINERS index 0e628f9e1f..07e07f6b7a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2287,6 +2287,7 @@ M: Gerd Hoffmann R: Manos Pitsidianakis S: Supported F: hw/audio/virtio-snd.c +F: hw/audio/virtio-snd-pci.c F: include/hw/audio/virtio-snd.h nvme diff --git a/hw/audio/meson.build b/hw/audio/meson.build index 7a503be1fd..2990974449 100644 --- a/hw/audio/meson.build +++ b/hw/audio/meson.build @@ -14,3 +14,4 @@ system_ss.add(when: 'CONFIG_SB16', if_true: files('sb16.c')) system_ss.add(when: 'CONFIG_VT82C686', if_true: files('via-ac97.c')) system_ss.add(when: 'CONFIG_WM8750', if_true: files('wm8750.c')) system_ss.add(when: ['CONFIG_VIRTIO_SND', 'CONFIG_VIRTIO'], if_true: files('virtio-snd.c')) +system_ss.add(when: ['CONFIG_VIRTIO_SND', 'CONFIG_VIRTIO', 'CONFIG_VIRTIO_PCI'], if_true: files('virtio-snd-pci.c')) diff --git a/hw/audio/virtio-snd-pci.c b/hw/audio/virtio-snd-pci.c new file mode 100644 index 0000000000..0f92e0752b --- /dev/null +++ b/hw/audio/virtio-snd-pci.c @@ -0,0 +1,93 @@ +/* + * VIRTIO Sound Device PCI Bindings + * + * Copyright (c) 2023 Emmanouil Pitsidianakis + * + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + */ + +#include "qemu/osdep.h" +#include "qom/object.h" +#include "qapi/error.h" +#include "hw/audio/soundhw.h" +#include "hw/virtio/virtio-pci.h" +#include "hw/audio/virtio-snd.h" + +/* + * virtio-snd-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_SND_PCI "virtio-sound-pci" +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOSoundPCI, VIRTIO_SND_PCI) + +struct VirtIOSoundPCI { + VirtIOPCIProxy parent_obj; + + VirtIOSound vdev; +}; + +static Property virtio_snd_pci_properties[] = { + DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true), + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_snd_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VirtIOSoundPCI *dev = VIRTIO_SND_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + virtio_pci_force_virtio_1(vpci_dev); + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); +} + +static void virtio_snd_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass); + + device_class_set_props(dc, virtio_snd_pci_properties); + dc->desc = "Virtio Sound"; + set_bit(DEVICE_CATEGORY_SOUND, dc->categories); + + vpciklass->realize = virtio_snd_pci_realize; +} + +static void virtio_snd_pci_instance_init(Object *obj) +{ + VirtIOSoundPCI *dev = VIRTIO_SND_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_SND); +} + +static const VirtioPCIDeviceTypeInfo virtio_snd_pci_info = { + .generic_name = TYPE_VIRTIO_SND_PCI, + .instance_size = sizeof(VirtIOSoundPCI), + .instance_init = virtio_snd_pci_instance_init, + .class_init = virtio_snd_pci_class_init, +}; + +/* Create a Virtio Sound PCI device, so '-audio driver,model=virtio' works. */ +static int virtio_snd_pci_init(PCIBus *bus, const char *audiodev) +{ + DeviceState *vdev = NULL; + VirtIOSoundPCI *dev = NULL; + + vdev = qdev_new(TYPE_VIRTIO_SND_PCI); + assert(vdev); + dev = VIRTIO_SND_PCI(vdev); + qdev_prop_set_string(DEVICE(&dev->vdev), "audiodev", audiodev); + qdev_realize_and_unref(vdev, BUS(bus), &error_fatal); + return 0; +} + +static void virtio_snd_pci_register(void) +{ + virtio_pci_types_register(&virtio_snd_pci_info); + pci_register_soundhw("virtio", "Virtio Sound", virtio_snd_pci_init); +} + +type_init(virtio_snd_pci_register); diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index 3c0aabec4b..a13db763e5 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -112,6 +112,7 @@ static const QDevAlias qdev_alias_table[] = { { "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_VIRTIO_CCW }, { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_VIRTIO_PCI}, { "virtio-sound-device", "virtio-sound", QEMU_ARCH_VIRTIO_MMIO }, + { "virtio-sound-pci", "virtio-sound", QEMU_ARCH_VIRTIO_PCI }, { "virtio-tablet-device", "virtio-tablet", QEMU_ARCH_VIRTIO_MMIO }, { "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_VIRTIO_CCW }, { "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_VIRTIO_PCI }, From patchwork Mon Oct 23 12:03:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432814 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3C5F9CDB474 for ; Mon, 23 Oct 2023 12:07:08 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfR-0005Fd-FY; Mon, 23 Oct 2023 08:04:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfN-0005FM-IS for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:18 -0400 Received: from mail-lj1-x22e.google.com ([2a00:1450:4864:20::22e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfK-0001xh-5V for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:17 -0400 Received: by mail-lj1-x22e.google.com with SMTP id 38308e7fff4ca-2c5210a1515so48423911fa.0 for ; Mon, 23 Oct 2023 05:04:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062652; x=1698667452; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2Vapy393YjsAujNegbbtzPu0Rp6eOj/GuvB/nUlNdKk=; b=iOHp1CNZ7kwZJNx5AePXqrB9Md+Nu60xq9qPRPHfhLWCtohbfejC5naO8MvQnLAZM/ GPbY3ohE6SLzfVLvAyrU51rRUZfhstkz7a2sWIAz1tFwX0a+25VQEqB2Xufn/t11lkYE eRbFFyyJT69mpASGHQoDPO44g1r8o+TiUVcJYpij387UnwJFIi/6BR8xO1p9vuib4P/i rvqLfMplutpESSXULzLs1GfOzhQOJ8OxnApDemau1tlsc+vrrTzZu4Q+S+w12yoPsmdj R47icfdJezjZzikW4T93N/bMziLcKqrDCV0ETo+Gn0gS1seLTYOEM+4gdN5/dzKgDHvO MLzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062652; x=1698667452; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2Vapy393YjsAujNegbbtzPu0Rp6eOj/GuvB/nUlNdKk=; b=vZp4KLpLp6y3b9pq+5r6OsKKVicC9nkzdSAQtLJVMY5ZtJyJl+9H+xCbq0XdKGDTcs Nill9WnUwsV3fF3Eb15MSwxtlWHcYpkwlPEYRQK1aQ6i3uRFq5gAFNR7uEXS6tHZgC32 gSw1FXUYrejYC2Cvq0rwTLNKucpD+g7cmYO3l3BhbDHUqRYB8n2cZ/o31ANZLeh9mQ/3 6kWgU2hjrEyedhAerQZqJ3RqYuSY9veaPYiSbdjEVdGVjc+2I0EyX5HVNYXQd5cex49e PoyngQ8aah/bYymOv735mVn6OKMyOEjZl/UX+XDJO2vutPxPfPRK0hLdFGMoakzrzcy2 aCCQ== X-Gm-Message-State: AOJu0Yz4IpxZ1kqw8NAR2r5SJUQvzkEP4k8kiCLSqnvFbz8cECeomHwD AWcB5kpMfkKbOH0+kPlmnv9T/MrpHb3k+3SveTs= X-Google-Smtp-Source: AGHT+IHmTuR+702b3PLBPGqvwUYfKtMFrzglXiwZ74XG+qqjojS1FL6LWqjOMEJm8F5XtE3NRr+Ojg== X-Received: by 2002:a2e:a781:0:b0:2c5:3490:9bbc with SMTP id c1-20020a2ea781000000b002c534909bbcmr8010152ljf.26.1698062651913; Mon, 23 Oct 2023 05:04:11 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:10 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 03/11] virtio-sound: handle control messages and streams Date: Mon, 23 Oct 2023 15:03:20 +0300 Message-Id: <3224aff87e7c4f2777bfe1bbbbca93b72525992c.1698062525.git.manos.pitsidianakis@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::22e; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-lj1-x22e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Receive guest requests in the control (CTRL) queue of the virtio sound device and reply with a NOT SUPPORTED error to all control commands. The receiving handler is virtio_snd_handle_ctrl(). It stores all control messages in the queue in the device's command queue. Then it calls virtio_snd_process_cmdq() to handle each message. The handler is process_cmd() which replies with VIRTIO_SND_S_NOT_SUPP. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/trace-events | 4 + hw/audio/virtio-snd.c | 487 +++++++++++++++++++++++++++++++++- include/hw/audio/virtio-snd.h | 113 +++++++- 3 files changed, 595 insertions(+), 9 deletions(-) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 525ced2b34..122d1403ef 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -47,3 +47,7 @@ virtio_snd_vm_state_running(void) "vm state running" virtio_snd_vm_state_stopped(void) "vm state stopped" virtio_snd_realize(void *snd) "snd %p: realize" virtio_snd_unrealize(void *snd) "snd %p: unrealize" +virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p" +virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s" +virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" +virtio_snd_handle_event(void) "event queue callback called" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 3a4b441c20..4eae76f638 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -32,6 +32,29 @@ #define VIRTIO_SOUND_CHMAP_DEFAULT 0 #define VIRTIO_SOUND_HDA_FN_NID 0 +static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8) + | BIT(VIRTIO_SND_PCM_FMT_U8) + | BIT(VIRTIO_SND_PCM_FMT_S16) + | BIT(VIRTIO_SND_PCM_FMT_U16) + | BIT(VIRTIO_SND_PCM_FMT_S32) + | BIT(VIRTIO_SND_PCM_FMT_U32) + | BIT(VIRTIO_SND_PCM_FMT_FLOAT); + +static uint32_t supported_rates = BIT(VIRTIO_SND_PCM_RATE_5512) + | BIT(VIRTIO_SND_PCM_RATE_8000) + | BIT(VIRTIO_SND_PCM_RATE_11025) + | BIT(VIRTIO_SND_PCM_RATE_16000) + | BIT(VIRTIO_SND_PCM_RATE_22050) + | BIT(VIRTIO_SND_PCM_RATE_32000) + | BIT(VIRTIO_SND_PCM_RATE_44100) + | BIT(VIRTIO_SND_PCM_RATE_48000) + | BIT(VIRTIO_SND_PCM_RATE_64000) + | BIT(VIRTIO_SND_PCM_RATE_88200) + | BIT(VIRTIO_SND_PCM_RATE_96000) + | BIT(VIRTIO_SND_PCM_RATE_176400) + | BIT(VIRTIO_SND_PCM_RATE_192000) + | BIT(VIRTIO_SND_PCM_RATE_384000); + static const VMStateDescription vmstate_virtio_snd_device = { .name = TYPE_VIRTIO_SND, .version_id = VIRTIO_SOUND_VM_VERSION, @@ -100,13 +123,397 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config) } +static void +virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command *cmd) +{ + g_free(cmd->elem); + g_free(cmd); +} + +/* + * Get a specific stream from the virtio sound card device. + * Returns NULL if @stream_id is invalid or not allocated. + * + * @s: VirtIOSound device + * @stream_id: stream id + */ +static VirtIOSoundPCMStream *virtio_snd_pcm_get_stream(VirtIOSound *s, + uint32_t stream_id) +{ + return stream_id >= s->snd_conf.streams ? NULL : + s->pcm->streams[stream_id]; +} + +/* + * Get params for a specific stream. + * + * @s: VirtIOSound device + * @stream_id: stream id + */ +static virtio_snd_pcm_set_params *virtio_snd_pcm_get_params(VirtIOSound *s, + uint32_t stream_id) +{ + return stream_id >= s->snd_conf.streams ? NULL + : &s->pcm->pcm_params[stream_id]; +} + +/* + * Set the given stream params. + * Called by both virtio_snd_handle_pcm_set_params and during device + * initialization. + * Returns the response status code. (VIRTIO_SND_S_*). + * + * @s: VirtIOSound device + * @params: The PCM params as defined in the virtio specification + */ +static +uint32_t virtio_snd_set_pcm_params(VirtIOSound *s, + uint32_t stream_id, + virtio_snd_pcm_set_params *params) +{ + virtio_snd_pcm_set_params *st_params; + + if (stream_id >= s->snd_conf.streams || s->pcm->pcm_params == NULL) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + virtio_error(VIRTIO_DEVICE(s), "Streams have not been initialized.\n"); + return cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + } + + st_params = virtio_snd_pcm_get_params(s, stream_id); + + if (params->channels < 1 || params->channels > AUDIO_MAX_CHANNELS) { + error_report("Number of channels is not supported."); + return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + } + if (!(supported_formats & BIT(params->format))) { + error_report("Stream format is not supported."); + return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + } + if (!(supported_rates & BIT(params->rate))) { + error_report("Stream rate is not supported."); + return cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + } + + st_params->buffer_bytes = le32_to_cpu(params->buffer_bytes); + st_params->period_bytes = le32_to_cpu(params->period_bytes); + st_params->features = le32_to_cpu(params->features); + /* the following are uint8_t, so there's no need to bswap the values. */ + st_params->channels = params->channels; + st_params->format = params->format; + st_params->rate = params->rate; + + return cpu_to_le32(VIRTIO_SND_S_OK); +} + +/* + * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_* + */ +static AudioFormat virtio_snd_get_qemu_format(uint32_t format) +{ + #define CASE(FMT) \ + case VIRTIO_SND_PCM_FMT_##FMT: \ + return AUDIO_FORMAT_##FMT; + + switch (format) { + CASE(U8) + CASE(S8) + CASE(U16) + CASE(S16) + CASE(U32) + CASE(S32) + case VIRTIO_SND_PCM_FMT_FLOAT: + return AUDIO_FORMAT_F32; + default: + g_assert_not_reached(); + } + + #undef CASE +} + +/* + * Get a QEMU Audiosystem compatible frequency value from a + * VIRTIO_SND_PCM_RATE_* + */ +static uint32_t virtio_snd_get_qemu_freq(uint32_t rate) +{ + #define CASE(RATE) \ + case VIRTIO_SND_PCM_RATE_##RATE: \ + return RATE; + + switch (rate) { + CASE(5512) + CASE(8000) + CASE(11025) + CASE(16000) + CASE(22050) + CASE(32000) + CASE(44100) + CASE(48000) + CASE(64000) + CASE(88200) + CASE(96000) + CASE(176400) + CASE(192000) + CASE(384000) + default: + g_assert_not_reached(); + } + + #undef CASE +} + +/* + * Get QEMU Audiosystem compatible audsettings from virtio based pcm stream + * params. + */ +static void virtio_snd_get_qemu_audsettings(audsettings *as, + virtio_snd_pcm_set_params *params) +{ + as->nchannels = MIN(AUDIO_MAX_CHANNELS, params->channels); + as->fmt = virtio_snd_get_qemu_format(params->format); + as->freq = virtio_snd_get_qemu_freq(params->rate); + as->endianness = target_words_bigendian() ? 1 : 0; +} + +/* + * Close a stream and free all its resources. + * + * @stream: VirtIOSoundPCMStream *stream + */ +static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) +{ +} + /* - * Queue handler stub. + * Prepares a VirtIOSound card stream. + * Returns the response status code. (VIRTIO_SND_S_*). + * + * @s: VirtIOSound device + * @stream_id: stream id + */ +static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) +{ + audsettings as; + virtio_snd_pcm_set_params *params; + VirtIOSoundPCMStream *stream; + + if (s->pcm->streams == NULL || + s->pcm->pcm_params == NULL || + stream_id >= s->snd_conf.streams) { + return cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + } + + params = virtio_snd_pcm_get_params(s, stream_id); + if (params == NULL) { + return cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + } + + stream = virtio_snd_pcm_get_stream(s, stream_id); + if (stream == NULL) { + stream = g_new0(VirtIOSoundPCMStream, 1); + stream->active = false; + stream->id = stream_id; + stream->pcm = s->pcm; + stream->s = s; + + /* + * stream_id >= s->snd_conf.streams was checked before so this is + * in-bounds + */ + s->pcm->streams[stream_id] = stream; + } + + 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; + stream->positions[1] = VIRTIO_SND_CHMAP_FR; + stream->as = as; + + return cpu_to_le32(VIRTIO_SND_S_OK); +} + +static const char *print_code(uint32_t code) +{ + #define CASE(CODE) \ + case VIRTIO_SND_R_##CODE: \ + return "VIRTIO_SND_R_"#CODE + + switch (code) { + CASE(JACK_INFO); + CASE(JACK_REMAP); + CASE(PCM_INFO); + CASE(PCM_SET_PARAMS); + CASE(PCM_PREPARE); + CASE(PCM_RELEASE); + CASE(PCM_START); + CASE(PCM_STOP); + CASE(CHMAP_INFO); + default: + return "invalid code"; + } + + #undef CASE +}; + +/* + * The actual processing done in virtio_snd_process_cmdq(). + * + * @s: VirtIOSound device + * @cmd: control command request + */ +static inline void +process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) +{ + uint32_t code; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + 0, + &cmd->ctrl, + sizeof(virtio_snd_hdr)); + + if (msg_sz != sizeof(virtio_snd_hdr)) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: virtio-snd command size incorrect %zu vs \ + %zu\n", __func__, msg_sz, sizeof(virtio_snd_hdr)); + return; + } + + code = le32_to_cpu(cmd->ctrl.code); + + trace_virtio_snd_handle_code(code, print_code(code)); + + switch (code) { + case VIRTIO_SND_R_JACK_INFO: + case VIRTIO_SND_R_JACK_REMAP: + qemu_log_mask(LOG_UNIMP, + "virtio_snd: jack functionality is unimplemented.\n"); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + break; + case VIRTIO_SND_R_PCM_INFO: + case VIRTIO_SND_R_PCM_SET_PARAMS: + case VIRTIO_SND_R_PCM_PREPARE: + case VIRTIO_SND_R_PCM_START: + case VIRTIO_SND_R_PCM_STOP: + case VIRTIO_SND_R_PCM_RELEASE: + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + break; + case VIRTIO_SND_R_CHMAP_INFO: + qemu_log_mask(LOG_UNIMP, + "virtio_snd: chmap info functionality is unimplemented.\n"); + trace_virtio_snd_handle_chmap_info(); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + break; + default: + /* error */ + error_report("virtio snd header not recognized: %"PRIu32, code); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + } + + iov_from_buf(cmd->elem->in_sg, + cmd->elem->in_num, + 0, + &cmd->resp, + sizeof(virtio_snd_hdr)); + virtqueue_push(cmd->vq, cmd->elem, sizeof(virtio_snd_hdr)); + virtio_notify(VIRTIO_DEVICE(s), cmd->vq); +} + +/* + * Consume all elements in command queue. + * + * @s: VirtIOSound device + */ +static void virtio_snd_process_cmdq(VirtIOSound *s) +{ + virtio_snd_ctrl_command *cmd; + + if (unlikely(qatomic_read(&s->processing_cmdq))) { + return; + } + + WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) { + qatomic_set(&s->processing_cmdq, true); + while (!QTAILQ_EMPTY(&s->cmdq)) { + cmd = QTAILQ_FIRST(&s->cmdq); + + /* process command */ + process_cmd(s, cmd); + + QTAILQ_REMOVE(&s->cmdq, cmd, next); + + virtio_snd_ctrl_cmd_free(cmd); + } + qatomic_set(&s->processing_cmdq, false); + } +} + +/* + * The control message handler. Pops an element from the control virtqueue, + * and stores them to VirtIOSound's cmdq queue and finally calls + * virtio_snd_process_cmdq() for processing. + * + * @vdev: VirtIOSound device + * @vq: Control virtqueue + */ +static void virtio_snd_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOSound *s = VIRTIO_SND(vdev); + VirtQueueElement *elem; + virtio_snd_ctrl_command *cmd; + + trace_virtio_snd_handle_ctrl(vdev, vq); + + if (!virtio_queue_ready(vq)) { + return; + } + + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + while (elem) { + cmd = g_new0(virtio_snd_ctrl_command, 1); + cmd->elem = elem; + cmd->vq = vq; + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); + QTAILQ_INSERT_TAIL(&s->cmdq, cmd, next); + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + } + + virtio_snd_process_cmdq(s); +} + +/* + * The event virtqueue handler. + * Not implemented yet. + * + * @vdev: VirtIOSound device + * @vq: event vq + */ +static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq) +{ + qemu_log_mask(LOG_UNIMP, "virtio_snd: event queue is unimplemented.\n"); + trace_virtio_snd_handle_event(); +} + +/* + * Stub buffer virtqueue handler. * * @vdev: VirtIOSound device * @vq: virtqueue */ -static void virtio_snd_handle_queue(VirtIODevice *vdev, VirtQueue *vq) {} +static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {} static uint64_t get_features(VirtIODevice *vdev, uint64_t features, Error **errp) @@ -140,12 +547,22 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) ERRP_GUARD(); VirtIOSound *vsnd = VIRTIO_SND(dev); VirtIODevice *vdev = VIRTIO_DEVICE(dev); + virtio_snd_pcm_set_params default_params = { 0 }; + uint32_t status; + vsnd->pcm = NULL; vsnd->vmstate = qemu_add_vm_change_state_handler(virtio_snd_vm_state_change, vsnd); trace_virtio_snd_realize(vsnd); + vsnd->pcm = g_new0(VirtIOSoundPCM, 1); + vsnd->pcm->snd = vsnd; + vsnd->pcm->streams = + g_new0(VirtIOSoundPCMStream *, vsnd->snd_conf.streams); + vsnd->pcm->pcm_params = + g_new0(virtio_snd_pcm_set_params, vsnd->snd_conf.streams); + virtio_init(vdev, VIRTIO_ID_SOUND, sizeof(virtio_snd_config)); virtio_add_feature(&vsnd->features, VIRTIO_F_VERSION_1); @@ -172,25 +589,69 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) AUD_register_card("virtio-sound", &vsnd->card, errp); + /* set default params for all streams */ + default_params.features = 0; + default_params.buffer_bytes = cpu_to_le32(8192); + default_params.period_bytes = cpu_to_le32(2048); + default_params.channels = 2; + default_params.format = VIRTIO_SND_PCM_FMT_S16; + default_params.rate = VIRTIO_SND_PCM_RATE_48000; vsnd->queues[VIRTIO_SND_VQ_CONTROL] = - virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + virtio_add_queue(vdev, 64, virtio_snd_handle_ctrl); vsnd->queues[VIRTIO_SND_VQ_EVENT] = - virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + virtio_add_queue(vdev, 64, virtio_snd_handle_event); vsnd->queues[VIRTIO_SND_VQ_TX] = - virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); vsnd->queues[VIRTIO_SND_VQ_RX] = - virtio_add_queue(vdev, 64, virtio_snd_handle_queue); + virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); + qemu_mutex_init(&vsnd->cmdq_mutex); + QTAILQ_INIT(&vsnd->cmdq); + + for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { + status = virtio_snd_set_pcm_params(vsnd, i, &default_params); + if (status != cpu_to_le32(VIRTIO_SND_S_OK)) { + error_setg(errp, + "Can't initalize stream params, device responded with %s.", + print_code(status)); + return; + } + status = virtio_snd_pcm_prepare(vsnd, i); + if (status != cpu_to_le32(VIRTIO_SND_S_OK)) { + error_setg(errp, + "Can't prepare streams, device responded with %s.", + print_code(status)); + return; + } + } } static void virtio_snd_unrealize(DeviceState *dev) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSound *vsnd = VIRTIO_SND(dev); + VirtIOSoundPCMStream *stream; qemu_del_vm_change_state_handler(vsnd->vmstate); trace_virtio_snd_unrealize(vsnd); + if (vsnd->pcm) { + 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); + } + g_free(vsnd->pcm->pcm_params); + g_free(vsnd->pcm); + vsnd->pcm = NULL; + } AUD_remove_card(&vsnd->card); + qemu_mutex_destroy(&vsnd->cmdq_mutex); virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_CONTROL]); virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_EVENT]); virtio_delete_queue(vsnd->queues[VIRTIO_SND_VQ_TX]); @@ -199,7 +660,19 @@ static void virtio_snd_unrealize(DeviceState *dev) } -static void virtio_snd_reset(VirtIODevice *vdev) {} +static void virtio_snd_reset(VirtIODevice *vdev) +{ + VirtIOSound *s = VIRTIO_SND(vdev); + virtio_snd_ctrl_command *cmd; + + WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) { + while (!QTAILQ_EMPTY(&s->cmdq)) { + cmd = QTAILQ_FIRST(&s->cmdq); + QTAILQ_REMOVE(&s->cmdq, cmd, next); + virtio_snd_ctrl_cmd_free(cmd); + } + } +} static void virtio_snd_class_init(ObjectClass *klass, void *data) { diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h index d08065941c..cc14c875ed 100644 --- a/include/hw/audio/virtio-snd.h +++ b/include/hw/audio/virtio-snd.h @@ -67,13 +67,122 @@ typedef struct virtio_snd_pcm_xfer virtio_snd_pcm_xfer; /* I/O request status */ typedef struct virtio_snd_pcm_status virtio_snd_pcm_status; -typedef struct VirtIOSound { +/* device structs */ + +typedef struct VirtIOSound VirtIOSound; + +typedef struct VirtIOSoundPCMStream VirtIOSoundPCMStream; + +typedef struct virtio_snd_ctrl_command virtio_snd_ctrl_command; + +typedef struct VirtIOSoundPCM VirtIOSoundPCM; + +struct VirtIOSoundPCM { + VirtIOSound *snd; + /* + * PCM parameters are a separate field instead of a VirtIOSoundPCMStream + * field, because the operation of PCM control requests is first + * VIRTIO_SND_R_PCM_SET_PARAMS and then VIRTIO_SND_R_PCM_PREPARE; this + * means that some times we get parameters without having an allocated + * stream yet. + */ + virtio_snd_pcm_set_params *pcm_params; + VirtIOSoundPCMStream **streams; +}; + +struct VirtIOSoundPCMStream { + VirtIOSoundPCM *pcm; + virtio_snd_pcm_info info; + virtio_snd_pcm_set_params params; + uint32_t id; + /* channel position values (VIRTIO_SND_CHMAP_XXX) */ + uint8_t positions[VIRTIO_SND_CHMAP_MAX_SIZE]; + VirtIOSound *s; + bool flushing; + audsettings as; + union { + SWVoiceIn *in; + SWVoiceOut *out; + } voice; + bool active; +}; + +/* + * PCM stream state machine. + * ------------------------- + * + * 5.14.6.6.1 PCM Command Lifecycle + * ================================ + * + * A PCM stream has the following command lifecycle: + * - `SET PARAMETERS` + * The driver negotiates the stream parameters (format, transport, etc) with + * the device. + * Possible valid transitions: `SET PARAMETERS`, `PREPARE`. + * - `PREPARE` + * The device prepares the stream (allocates resources, etc). + * Possible valid transitions: `SET PARAMETERS`, `PREPARE`, `START`, + * `RELEASE`. Output only: the driver transfers data for pre-buffing. + * - `START` + * The device starts the stream (unmute, putting into running state, etc). + * Possible valid transitions: `STOP`. + * The driver transfers data to/from the stream. + * - `STOP` + * The device stops the stream (mute, putting into non-running state, etc). + * Possible valid transitions: `START`, `RELEASE`. + * - `RELEASE` + * The device releases the stream (frees resources, etc). + * Possible valid transitions: `SET PARAMETERS`, `PREPARE`. + * + * +---------------+ +---------+ +---------+ +-------+ +-------+ + * | SetParameters | | Prepare | | Release | | Start | | Stop | + * +---------------+ +---------+ +---------+ +-------+ +-------+ + * |- | | | | + * || | | | | + * |< | | | | + * |------------->| | | | + * |<-------------| | | | + * | |- | | | + * | || | | | + * | |< | | | + * | |--------------------->| | + * | |---------->| | | + * | | | |-------->| + * | | | |<--------| + * | | |<-------------------| + * |<-------------------------| | | + * | |<----------| | | + * + * CTRL in the VirtIOSound device + * ============================== + * + * The control messages that affect the state of a stream arrive in the + * `virtio_snd_handle_ctrl()` queue callback and are of type `struct + * virtio_snd_ctrl_command`. They are stored in a queue field in the device + * type, `VirtIOSound`. This allows deferring the CTRL request completion if + * it's not immediately possible due to locking/state reasons. + * + * The CTRL message is finally handled in `process_cmd()`. + */ +struct VirtIOSound { VirtIODevice parent_obj; VirtQueue *queues[VIRTIO_SND_VQ_MAX]; uint64_t features; + VirtIOSoundPCM *pcm; QEMUSoundCard card; VMChangeStateEntry *vmstate; virtio_snd_config snd_conf; -} VirtIOSound; + QemuMutex cmdq_mutex; + QTAILQ_HEAD(, virtio_snd_ctrl_command) cmdq; + bool processing_cmdq; +}; + +struct virtio_snd_ctrl_command { + VirtQueueElement *elem; + VirtQueue *vq; + virtio_snd_hdr ctrl; + virtio_snd_hdr resp; + QTAILQ_ENTRY(virtio_snd_ctrl_command) next; +}; #endif From patchwork Mon Oct 23 12:03:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432803 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A662AC001E0 for ; Mon, 23 Oct 2023 12:05:02 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutff-0005Hd-Jy; Mon, 23 Oct 2023 08:04:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfe-0005HO-1V for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:34 -0400 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfP-0001y2-P0 for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:33 -0400 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-408425c7c10so26908425e9.0 for ; Mon, 23 Oct 2023 05:04:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062657; x=1698667457; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LmZOtgdkPmiV8HTMnM0nPx4fSedl9ZSXpPdeym2pt+I=; b=L1rNDN+GBR/ucA/g6snga0uIGLAIIt1syemOqE2U6jmceQgt+0UM5Hl6RhyQtht5cD EJi0SF2pAwoRPNv+YR+S/aoL2eaY2dCYFhclCRfRDDZHtjhTIFYnhp/1k+Z8r40yJB+L R/2ThHZ7CE17p2acKCWaxjDTC4m3zFVJBflXE+ceHmXeUQ1pDoP+yOM+N1ZPNlFVPdOh vwlEIDmU4NUuRva45bvhpAh6rocvJKhQHg+yU7tsm4fsUxUmp36YdC6fcR8za+I0zpfr VUQ9HkKl/5ErIz7KmaFHeCG6xWibKNz4lavLEXx3gk2v6qHbOEPAfgmGHIRPCBtF0yXU gJTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062657; x=1698667457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LmZOtgdkPmiV8HTMnM0nPx4fSedl9ZSXpPdeym2pt+I=; b=F08G1JMV0yfIevFlqNF0ZzyZUbz+Th7N2DPLIFM/th4xhhnX2QHTm1PcsOB5+PHrZ8 fWS93D2+sRO1REvJv4ugiP6B8Cvsz+d9FexDBMVlvyTB9bCb0sNXbbeGxgnf8jbHPBkm vw2fUg0UxChXxg5wO8qDKmXUEr4rBTin5yB+JWd6S58f9mmaYgPfzPejUehIJs0QxEYa jHcjX1oW941XVl9wFsv/wiq35ugT7G3yJ/qepqg5T0CofxwJLxA6SzyA8FpOKPzFbbsK MZUjfk0phIZcC54qgdKEHF4XHzC2MEj1/IYuMHrXS27rMi86RsaLaXGLhtF5I9xBgyoC Yy4Q== X-Gm-Message-State: AOJu0YzCAEWrPRTmXSpKHVoRSjCMdKwxnJHEsSVsbkNfUHrM6lPlO1lL vAdw8nUBBdvAnHHak2bRQG+Que78tc8Sl/cKjUE= X-Google-Smtp-Source: AGHT+IE35No9v4qdn1BywyFPYWIfy0o1+QhEuXhX42Z3s9NQdm6FgIQD3Xpt94xA6Upm9r4dEp4PPg== X-Received: by 2002:a05:600c:4ec6:b0:408:54be:d961 with SMTP id g6-20020a05600c4ec600b0040854bed961mr6420235wmq.35.1698062656743; Mon, 23 Oct 2023 05:04:16 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:15 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 04/11] virtio-sound: handle VIRTIO_SND_R_PCM_INFO request Date: Mon, 23 Oct 2023 15:03:21 +0300 Message-Id: <5ecea6ba2fb0e3957d7d90bc4dbac521a3d1f678.1698062525.git.manos.pitsidianakis@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32f; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x32f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Respond to the VIRTIO_SND_R_PCM_INFO control request with the parameters of each requested PCM stream. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/trace-events | 1 + hw/audio/virtio-snd.c | 82 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 122d1403ef..6def414f96 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -48,6 +48,7 @@ virtio_snd_vm_state_stopped(void) "vm state stopped" virtio_snd_realize(void *snd) "snd %p: realize" virtio_snd_unrealize(void *snd) "snd %p: unrealize" virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p" +virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32 virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s" virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" virtio_snd_handle_event(void) "event queue callback called" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 4eae76f638..fd0c50de6e 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -157,6 +157,86 @@ static virtio_snd_pcm_set_params *virtio_snd_pcm_get_params(VirtIOSound *s, : &s->pcm->pcm_params[stream_id]; } +/* + * Handle the VIRTIO_SND_R_PCM_INFO request. + * The function writes the info structs to the request element. + * + * @s: VirtIOSound device + * @cmd: The request command queue element from VirtIOSound cmdq field + */ +static void virtio_snd_handle_pcm_info(VirtIOSound *s, + virtio_snd_ctrl_command *cmd) +{ + uint32_t stream_id, start_id, count, size; + virtio_snd_pcm_info val; + virtio_snd_query_info req; + VirtIOSoundPCMStream *stream = NULL; + g_autofree virtio_snd_pcm_info *pcm_info = NULL; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + 0, + &req, + sizeof(virtio_snd_query_info)); + + if (msg_sz != sizeof(virtio_snd_query_info)) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: virtio-snd command size incorrect %zu vs \ + %zu\n", __func__, msg_sz, sizeof(virtio_snd_query_info)); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + + start_id = le32_to_cpu(req.start_id); + count = le32_to_cpu(req.count); + size = le32_to_cpu(req.size); + + if (iov_size(cmd->elem->in_sg, cmd->elem->in_num) < + sizeof(virtio_snd_hdr) + size * count) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + error_report("pcm info: buffer too small, got: %zu, needed: %zu", + iov_size(cmd->elem->in_sg, cmd->elem->in_num), + sizeof(virtio_snd_pcm_info)); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + + pcm_info = g_new0(virtio_snd_pcm_info, count); + for (uint32_t i = 0; i < count; i++) { + stream_id = i + start_id; + trace_virtio_snd_handle_pcm_info(stream_id); + stream = virtio_snd_pcm_get_stream(s, stream_id); + if (!stream) { + error_report("Invalid stream id: %"PRIu32, stream_id); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + val = stream->info; + val.hdr.hda_fn_nid = cpu_to_le32(val.hdr.hda_fn_nid); + val.features = cpu_to_le32(val.features); + val.formats = cpu_to_le64(val.formats); + val.rates = cpu_to_le64(val.rates); + /* + * 5.14.6.6.2.1 Device Requirements: Stream Information The device MUST + * NOT set undefined feature, format, rate and direction values. The + * device MUST initialize the padding bytes to 0. + */ + pcm_info[i] = val; + memset(&pcm_info[i].padding, 0, 5); + } + + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); + iov_from_buf(cmd->elem->in_sg, + cmd->elem->in_num, + sizeof(virtio_snd_hdr), + pcm_info, + sizeof(virtio_snd_pcm_info) * count); +} + /* * Set the given stream params. * Called by both virtio_snd_handle_pcm_set_params and during device @@ -404,6 +484,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); break; case VIRTIO_SND_R_PCM_INFO: + virtio_snd_handle_pcm_info(s, cmd); + break; case VIRTIO_SND_R_PCM_SET_PARAMS: case VIRTIO_SND_R_PCM_PREPARE: case VIRTIO_SND_R_PCM_START: From patchwork Mon Oct 23 12:03:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432808 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B5FD7C001E0 for ; Mon, 23 Oct 2023 12:05:26 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfX-0005GF-JQ; Mon, 23 Oct 2023 08:04:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfV-0005G1-7m for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:25 -0400 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfT-0001yO-6N for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:24 -0400 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-4081ccf69dcso24029535e9.0 for ; Mon, 23 Oct 2023 05:04:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062661; x=1698667461; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TLB06X5sTNzgChsCi78S9iHFPyW5nZLoQcxNbN8p+O8=; b=qPa4esDvpCQ0yn3BM+sWXVbK7x30JT1PNIPC/LdUBaLF5u8Ox2VjC2/NtyX0cGTnAD AwHgQTlIo06UyMwhB8haXfjHUQbaHur1M/cJ7xP2ICDucafwNXSYTuBCqa4S5wEbiWBI z+SLsc9orozNAul+voX/HFdUxcsTqIN4ogQx79HHXhvTSJofRupu4dHrwG1ToTnP1ruF QZZAjbdM1tIdPGff3doldH07Akdi9kcAynemAL1BmKGH9CFjKCerU+xJT7gtr4QuJtg1 KKUZopi4RqPT+7Ha/G0KZ5CoRw7s9VzBwGSQhrEEGX3uqFTU31c4k7BfOBHaAcBDjt9M Gc3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062661; x=1698667461; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TLB06X5sTNzgChsCi78S9iHFPyW5nZLoQcxNbN8p+O8=; b=m8pxbk2MUBo+RevIDjA5V6N3t9qoRP/Qfl+d/V3rQMHp+UeIudZaryRs9h1bNySgd/ l5mY3hpPLZwbF2ahfUQwkdLRusK/NdagASt4gY+KkXRpzfQrku5E3MTajJEUH73xSoN3 8gNMsCbTGAQp6oLFwhFjI++4m1WyaEvXTr2fGb2PGjM2UE/+j563xm6cO1yyqzSQxNGq m2K/WmRDwlo19OVUwGK7KbhEoFRLsILYUnMh4JqdycDvGgOsCCryPckcydaL6W0zP0vU KJ8gBfS1veCIUOrLT7oGT7dcO+k8vP+j474jCG7DrZ1OJa+TM1GliPJFr+Q7dK9uMlVl 2pkg== X-Gm-Message-State: AOJu0YyLfpwWQ86Kxe4bPFzilUtGvw+qFyHUEgMWt5ak+muqpum1EmN3 KxNA23IwJf5ZCVvVHkiq7bQ5TCCQh+ksI8L15ro= X-Google-Smtp-Source: AGHT+IHT4toYEbnmDXTX2vjY/Ffxbbfg7SDFzqONghqlL5E/dJOeYMdtWUVbf6UpcZpUkmGXSO6g2g== X-Received: by 2002:a05:600c:3789:b0:3fe:d67d:5040 with SMTP id o9-20020a05600c378900b003fed67d5040mr12510355wmr.5.1698062661587; Mon, 23 Oct 2023 05:04:21 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:20 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 05/11] virtio-sound: handle VIRTIO_SND_R_PCM_{START,STOP} Date: Mon, 23 Oct 2023 15:03:22 +0300 Message-Id: <9657dbfe3cb4a48ceb033ceb5977dc08669dfefd.1698062525.git.manos.pitsidianakis@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::330; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x330.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Handle the start and stop control messages for a stream_id. This request does nothing at the moment except for replying to it. Audio playback or capture will be started/stopped here in follow-up commits. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/trace-events | 1 + hw/audio/virtio-snd.c | 49 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 6def414f96..db48ff04fe 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -49,6 +49,7 @@ virtio_snd_realize(void *snd) "snd %p: realize" virtio_snd_unrealize(void *snd) "snd %p: unrealize" virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p" virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32 +virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32 virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s" virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" virtio_snd_handle_event(void) "event queue callback called" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index fd0c50de6e..e6791de6c6 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -446,6 +446,47 @@ static const char *print_code(uint32_t code) #undef CASE }; +/* + * Handles VIRTIO_SND_R_PCM_START. + * + * @s: VirtIOSound device + * @cmd: The request command queue element from VirtIOSound cmdq field + * @start: whether to start or stop the device + */ +static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, + virtio_snd_ctrl_command *cmd, + bool start) +{ + VirtIOSoundPCMStream *stream; + virtio_snd_pcm_hdr req; + uint32_t stream_id; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + 0, + &req, + sizeof(virtio_snd_pcm_hdr)); + + if (msg_sz != sizeof(virtio_snd_pcm_hdr)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: virtio-snd command size incorrect %zu vs \ + %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_hdr)); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + + stream_id = le32_to_cpu(req.stream_id); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); + trace_virtio_snd_handle_pcm_start_stop(start ? "VIRTIO_SND_R_PCM_START" : + "VIRTIO_SND_R_PCM_STOP", stream_id); + stream = virtio_snd_pcm_get_stream(s, stream_id); + if (stream == NULL) { + error_report("Invalid stream id: %"PRIu32, req.stream_id); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + stream->active = start; +} + /* * The actual processing done in virtio_snd_process_cmdq(). * @@ -486,10 +527,14 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) case VIRTIO_SND_R_PCM_INFO: virtio_snd_handle_pcm_info(s, cmd); break; - case VIRTIO_SND_R_PCM_SET_PARAMS: - case VIRTIO_SND_R_PCM_PREPARE: case VIRTIO_SND_R_PCM_START: + virtio_snd_handle_pcm_start_stop(s, cmd, true); + break; case VIRTIO_SND_R_PCM_STOP: + virtio_snd_handle_pcm_start_stop(s, cmd, false); + break; + case VIRTIO_SND_R_PCM_SET_PARAMS: + case VIRTIO_SND_R_PCM_PREPARE: case VIRTIO_SND_R_PCM_RELEASE: cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); break; From patchwork Mon Oct 23 12:03:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432809 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5B9CECDB474 for ; Mon, 23 Oct 2023 12:05:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfd-0005H7-Bd; Mon, 23 Oct 2023 08:04:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfb-0005Gs-7p for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:31 -0400 Received: from mail-lf1-x130.google.com ([2a00:1450:4864:20::130]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfZ-0001yo-A7 for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:31 -0400 Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-507e85ebf50so2948922e87.1 for ; Mon, 23 Oct 2023 05:04:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062667; x=1698667467; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MBRg/xWgCss1UGZUfw8fCOy1EN72mXuHqKEUcF2OZBs=; b=lqmLmEGeEkCmJwtpgk1yC1daQZ82v/pANO3YpI6SXOXPHInfIJ+V8OMHTKhC1D+qF7 UH3mnKKUCr+vQ7SI3X6Qhe9wYTr7pN9Oz3WpxQNYpVz8pN+2s/VX8PH86O4QOj2qGjux zxU3EVO7Z0ZCuTiq0TEpJxg0UBCZugmbtiq50bwlrzU5t3AbleKh1ERZh56+5kIiEyJr 5Mm7pg4UsloyoHtTujHnwaWpDLXCem+zEHxBTmUDz6tPMbe51sB0VUN5qgYeDEPF49B1 esxKXomYvn3WiiJ4B9N51nLZ+HWFrAp6LzUlZd+xZff22vTqgPHMBS4iFIFKINAxh6gp zTsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062667; x=1698667467; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MBRg/xWgCss1UGZUfw8fCOy1EN72mXuHqKEUcF2OZBs=; b=xPRdo/XDeZyuS51qmrMofaHNOCOmhQlW4fc/Am8ofTptP5F6WqbvcuANeH0IUQmhXv DW/SsxPq+7yLfSn5BWQgtNAvnOChowkV+1gFBwoonIAz6UAuf4K4mZcqsdQstaz7JELi rbTpf/bHq91EHbz7GxsD3Chx23fki+R+hjzf9fIsiB825ptKLgpgMtwZ7d+5EDX6M8DF grM4XGpmiavhufI5lHH/D6WCLhGC34RmX0df2KnAkzXOJVspxJAUHFPO5wtaeR3FKubd rJ+QuNUFl/m2siBW6ymg8sKlTCnU0rvuLW+svM2E6GByC2QVO8DiNUfuWWLPggkvkT32 GjQg== X-Gm-Message-State: AOJu0YwskmCbaa+9Yb7RvbPc+e86AEdbwt9+SafrkC3Daqe6ekEG1duK eUrVADdjReWCBgFVRDEXOsOyhrsrEGbFBPBMcPk= X-Google-Smtp-Source: AGHT+IGeNAYWV+0zPUzUEfrYdtPX/j3lG6COB3igbMvk3hl9fbHq1w1wNE6inA0rpoD/q5gQzJzv1g== X-Received: by 2002:a2e:81cc:0:b0:2c0:2ef8:9716 with SMTP id s12-20020a2e81cc000000b002c02ef89716mr6630409ljg.1.1698062667212; Mon, 23 Oct 2023 05:04:27 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:25 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 06/11] virtio-sound: handle VIRTIO_SND_R_PCM_SET_PARAMS Date: Mon, 23 Oct 2023 15:03:23 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::130; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-lf1-x130.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Handle the set parameters control request. It reconfigures a stream based on a guest's preference if the values are valid and supported. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/trace-events | 1 + hw/audio/virtio-snd.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index db48ff04fe..3badcab2e8 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -47,6 +47,7 @@ virtio_snd_vm_state_running(void) "vm state running" virtio_snd_vm_state_stopped(void) "vm state stopped" virtio_snd_realize(void *snd) "snd %p: realize" virtio_snd_unrealize(void *snd) "snd %p: unrealize" +virtio_snd_handle_pcm_set_params(uint32_t stream) "VIRTIO_SND_PCM_SET_PARAMS called for stream %"PRIu32 virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p" virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32 virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32 diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index e6791de6c6..084890e52b 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -287,6 +287,38 @@ uint32_t virtio_snd_set_pcm_params(VirtIOSound *s, return cpu_to_le32(VIRTIO_SND_S_OK); } +/* + * Handles the VIRTIO_SND_R_PCM_SET_PARAMS request. + * + * @s: VirtIOSound device + * @cmd: The request command queue element from VirtIOSound cmdq field + */ +static void virtio_snd_handle_pcm_set_params(VirtIOSound *s, + virtio_snd_ctrl_command *cmd) +{ + virtio_snd_pcm_set_params req = { 0 }; + uint32_t stream_id; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + 0, + &req, + sizeof(virtio_snd_pcm_set_params)); + + if (msg_sz != sizeof(virtio_snd_pcm_set_params)) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: virtio-snd command size incorrect %zu vs \ + %zu\n", __func__, msg_sz, sizeof(virtio_snd_pcm_set_params)); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + stream_id = le32_to_cpu(req.hdr.stream_id); + trace_virtio_snd_handle_pcm_set_params(stream_id); + cmd->resp.code = virtio_snd_set_pcm_params(s, stream_id, &req); +} + /* * Get a QEMU Audiosystem compatible format value from a VIRTIO_SND_PCM_FMT_* */ @@ -534,6 +566,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) virtio_snd_handle_pcm_start_stop(s, cmd, false); break; case VIRTIO_SND_R_PCM_SET_PARAMS: + virtio_snd_handle_pcm_set_params(s, cmd); + break; case VIRTIO_SND_R_PCM_PREPARE: case VIRTIO_SND_R_PCM_RELEASE: cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); From patchwork Mon Oct 23 12:03:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432807 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A8E38C001E0 for ; Mon, 23 Oct 2023 12:05:11 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfi-0005I4-Kx; Mon, 23 Oct 2023 08:04:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutff-0005HW-50 for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:35 -0400 Received: from mail-wm1-x330.google.com ([2a00:1450:4864:20::330]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfd-0001zQ-Du for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:34 -0400 Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-4083f613275so26558545e9.2 for ; Mon, 23 Oct 2023 05:04:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062672; x=1698667472; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=x+4RW3Zm8X6t5MTpeBt5QIrdEFSSkBf0HOZCTHYq9aI=; b=Qd/u0Sqr7VH9ASzeGw4yxNRSGx9SKhckanNh2vaaNiej2XMZAStJxEXNF/sQtDoYYP bDsyhvJ98EAaWhb4sKZ9TQ3d2Y8aWKRRH1plnlJQ+K++b0Jlu+nrPuMY5va8x/3CagiC k6AfKB9O89g5KMWFh1LUUqyDAOg4S63LQLJMtYqoIlZ3rneXBhWrVBF9nKRTzKlF7DVW fL7NUs3vLVuYiw3QOY0/mZuabrPb440Hzwgv7LxvQGaDN9X6xbosuODxSZzjEpKaaPOQ BS1vIJsZXFGSBTc1caBIOquC7hb8H8gF8kEXTmiO0tnr8eJw711EeuWSfW6LI68TaFCC OODQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062672; x=1698667472; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=x+4RW3Zm8X6t5MTpeBt5QIrdEFSSkBf0HOZCTHYq9aI=; b=MEV+lJkPck2ktb1tI/LJTmT/eZ0Sw6l96+53AEaJa+knnzTa441UI99KUjgPSxmDVI 83XJeA9kJ2xfBcGWrMhMUKup0kjNbHWWmuOZGcdDCggD+zOq7bLA5eDrvg1mJrpd87RM D6K3tlQxwEFbc+DhlJIIscLR5c/QQLufQAnupaFMHhYKVw0h7W2YoTlwlP1tN0iE3A97 eBM5+ImQX/a4K5nonGDKlggsE9DOwBdpgW/6Hl35nBM3HviPhPSqKccaIenbZneXYfV0 gNOC68WMZXN7khaXkq0HglpwtP+CO/jhi+C21GpQqyGylXUwoYqlaT4cmld9IEb1LI3k Iw4A== X-Gm-Message-State: AOJu0Yw8v4dW6030YajUMog3M4YleprExtevoBvDIwC6/VSz67CFntmU IVAMc5ho5CCR9qwsY6kt1pVnsNO4fuLKb0KuDZE= X-Google-Smtp-Source: AGHT+IEqxB6i7natNIkx2JWJRL+JU0sMR+Bou8nthTvvgJoWt8UnWZOWPRyELqTg4Q10ye+fZrpfkw== X-Received: by 2002:a05:600c:35c7:b0:406:535a:cfb4 with SMTP id r7-20020a05600c35c700b00406535acfb4mr7171939wmq.1.1698062671943; Mon, 23 Oct 2023 05:04:31 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:30 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 07/11] virtio-sound: handle VIRTIO_SND_R_PCM_PREPARE Date: Mon, 23 Oct 2023 15:03:24 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::330; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x330.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Handles the PCM prepare control request. It initializes a PCM stream when the guests asks for it. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/virtio-snd.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 084890e52b..31a1942754 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -478,6 +478,28 @@ static const char *print_code(uint32_t code) #undef CASE }; +/* + * Handles VIRTIO_SND_R_PCM_PREPARE. + * + * @s: VirtIOSound device + * @cmd: The request command queue element from VirtIOSound cmdq field + */ +static void virtio_snd_handle_pcm_prepare(VirtIOSound *s, + virtio_snd_ctrl_command *cmd) +{ + uint32_t stream_id; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + sizeof(virtio_snd_hdr), + &stream_id, + sizeof(stream_id)); + + stream_id = le32_to_cpu(stream_id); + cmd->resp.code = msg_sz == sizeof(stream_id) + ? virtio_snd_pcm_prepare(s, stream_id) + : cpu_to_le32(VIRTIO_SND_S_BAD_MSG); +} + /* * Handles VIRTIO_SND_R_PCM_START. * @@ -569,6 +591,8 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) virtio_snd_handle_pcm_set_params(s, cmd); break; case VIRTIO_SND_R_PCM_PREPARE: + virtio_snd_handle_pcm_prepare(s, cmd); + break; case VIRTIO_SND_R_PCM_RELEASE: cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); break; From patchwork Mon Oct 23 12:03:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432810 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D020DCDB474 for ; Mon, 23 Oct 2023 12:05:41 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfo-0005KL-Lr; Mon, 23 Oct 2023 08:04:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfk-0005Jz-P8 for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:40 -0400 Received: from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfi-0001zq-UZ for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:40 -0400 Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-40806e4106dso18212105e9.1 for ; Mon, 23 Oct 2023 05:04:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062676; x=1698667476; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CkUaksJx8SSG6f4MbSrYE3Lgmvmo/BOBJtXzQeolByM=; b=lPNb+bbgAJs+dXP7DimFJ2mdwabBUJ6IWejmdsK9zmygnGGcy4rwVDOZ46ArEBGRAt gTUNPa9WtDgLs8I9eRIqgUR/mCTnO9+5Gxttohg4GT56PZmoG05jEZSaG3ka9+YbXQjW eDsrxRz+dLRehNj+pSCsNgiOsIfNryYv7pyYVcC+1V34AxgJ9np7ENFslL6vmyFCmUnV xQpKHMdRmqY5k2iQru3ZOkJGEpklnyynTg+A2sw5WEDOyq3d9FUYoMoDUMm512rH7101 B53U8eMvdc7BiNxGfoADgmbb8Z+s2YUr1a9FqQQpZ3/xEO/UafTeF6bU09hQdlFlW3la oMLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062676; x=1698667476; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CkUaksJx8SSG6f4MbSrYE3Lgmvmo/BOBJtXzQeolByM=; b=vKERgPaYLaU1Bs4+sYnBDWizQccZM6DPiDCALCZ2YkkN82Q3FGK/pVoFvS1L3PSh/j qVBqjIfAJgcJyl3cYTe9a3v3aIrS0bliTA2aoKiA1PcZEO3NDg5bTNpFTfLVMd5p1kel 8SkeDB8kIh0/4cWsHxGcgsnklQEwTyafe/hE5mE1Nj9kjYMLCptK+mR9qhr9IvSmaFpN ssMUdd/V0KYfYiMHVGK0KyobIdA8Ev/ydHRP9rF0utJk98x0XMggY44oc/lr9b0B1ftG 5gEYUBpg1CEpo1MuSpzj4RDlLCGNe2eVfdnsaI+kM/DqDyumkpCqqv4/LjcGo/2Ave0H iKrg== X-Gm-Message-State: AOJu0YxRbuwZX31WjhrxUcLLI2uXz/V8fsMKeT001/42Yh7Ujg6mx5IH YWt6N08EmAGA5Q8CxE98NAfXDVy63Z73STHp4dw= X-Google-Smtp-Source: AGHT+IEfNxsrZQJJOSYeQZyky9+EwKOAc4/N2NDuW344DS3+2X3B42IxSdVye2dwBcsmHBisZFgVpQ== X-Received: by 2002:a05:600c:3789:b0:3fe:d67d:5040 with SMTP id o9-20020a05600c378900b003fed67d5040mr12511266wmr.5.1698062676218; Mon, 23 Oct 2023 05:04:36 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:35 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 08/11] virtio-sound: handle VIRTIO_SND_R_PCM_RELEASE Date: Mon, 23 Oct 2023 15:03:25 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32b; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x32b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Handle the PCM release control request, which is necessary for flushing pending sound IO. No IO is handled yet so currently it only replies to the request. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/trace-events | 1 + hw/audio/virtio-snd.c | 48 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 3badcab2e8..33e24d0011 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -51,6 +51,7 @@ virtio_snd_handle_pcm_set_params(uint32_t stream) "VIRTIO_SND_PCM_SET_PARAMS cal virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for queue %p" virtio_snd_handle_pcm_info(uint32_t stream) "VIRTIO_SND_R_PCM_INFO called for stream %"PRIu32 virtio_snd_handle_pcm_start_stop(const char *code, uint32_t stream) "%s called for stream %"PRIu32 +virtio_snd_handle_pcm_release(uint32_t stream) "VIRTIO_SND_PCM_RELEASE called for stream %"PRIu32 virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s" virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" virtio_snd_handle_event(void) "event queue callback called" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 31a1942754..9cff724f62 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -541,6 +541,52 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, stream->active = start; } +/* + * Handles VIRTIO_SND_R_PCM_RELEASE. Releases the buffer resources allocated to + * a stream. + * + * @s: VirtIOSound device + * @cmd: The request command queue element from VirtIOSound cmdq field + */ +static void virtio_snd_handle_pcm_release(VirtIOSound *s, + virtio_snd_ctrl_command *cmd) +{ + uint32_t stream_id; + VirtIOSoundPCMStream *stream; + size_t msg_sz = iov_to_buf(cmd->elem->out_sg, + cmd->elem->out_num, + sizeof(virtio_snd_hdr), + &stream_id, + sizeof(stream_id)); + + if (msg_sz != sizeof(stream_id)) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: virtio-snd command size incorrect %zu vs \ + %zu\n", __func__, msg_sz, sizeof(stream_id)); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + + stream_id = le32_to_cpu(stream_id); + trace_virtio_snd_handle_pcm_release(stream_id); + stream = virtio_snd_pcm_get_stream(s, stream_id); + if (stream == NULL) { + /* + * TODO: do we need to set DEVICE_NEEDS_RESET? + */ + error_report("already released stream %"PRIu32, stream_id); + virtio_error(VIRTIO_DEVICE(s), + "already released stream %"PRIu32, + stream_id); + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + return; + } + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); +} + /* * The actual processing done in virtio_snd_process_cmdq(). * @@ -594,7 +640,7 @@ process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) virtio_snd_handle_pcm_prepare(s, cmd); break; case VIRTIO_SND_R_PCM_RELEASE: - cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_NOT_SUPP); + virtio_snd_handle_pcm_release(s, cmd); break; case VIRTIO_SND_R_CHMAP_INFO: qemu_log_mask(LOG_UNIMP, From patchwork Mon Oct 23 12:03:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432812 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 38C73C004C0 for ; Mon, 23 Oct 2023 12:06:39 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutfv-0005Rk-Lk; Mon, 23 Oct 2023 08:04:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfp-0005Kp-SC for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:46 -0400 Received: from mail-lf1-x132.google.com ([2a00:1450:4864:20::132]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfn-00021g-8a for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:45 -0400 Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-507c8316abcso4291983e87.1 for ; Mon, 23 Oct 2023 05:04:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062681; x=1698667481; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VFMzH2ukaH5DgW91S3uYSkF7zisQ9D9LJwyv5VFmicI=; b=du0fqkCrXym3NoQKbF7vL299TITnoCuOYrI/H/CR38W0bMh1+XdBff0j0lIKkP79W5 wFDIEuQzGlaoWDrhSarrxtea1B5EcRG18i4uOg21TeZoDdAaEeE4bbiBhMtsIJHsvhsc A+f/YbKHGFi92yaMigroj+1yD0D0rKJmo2LHKQuI8YUzwDtKSLivRWNEH218LYH84fOJ x4ndemaiKjNHPV2+Qbqf9vMu74qjVm/Jg1Atm66wJWeSYkoJf9kC71WIVycHZPpVfibp kdMzw9zeBbtSJzsHRK6On7ghMqN/l4UF1ggwb6JxFO2mfR/3Fy0bPXPXpRhKRE1zW7Ow tZ1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062681; x=1698667481; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VFMzH2ukaH5DgW91S3uYSkF7zisQ9D9LJwyv5VFmicI=; b=q5pEK8Zi7QDTNEsnxRkxbZ4UtDuaTl/hjM3vvxKC+nf9Tw4DYktKndlld8y3G114UI wDiJ/FKSu2XXTw0w9QuF56YhRlSfiTTOhvVQ6ySiZ0mD5HaS3RRdJCAzgFRfp1g9635P sn0JtgFQYj859NOSKT5uFQEknh6gE7WRCxzSjsbtCcSFnCAiS0JUau01iNFonBerhzqR CLih3vLGth4xJPREDqh6vnOQl3DvKhn1n2fERpUmF2dc51Ju1xYZOoF3qBXTiIDIQkx3 y3kQ/VUwJAwVTHHq6j5+X3dqwcfUdJAZ2dQQtX5JNrcNKT7ptBTxq4JFvheXPFpfFXjG OuSw== X-Gm-Message-State: AOJu0YwG7BTirCxZ2RJ0QLeVCtRWV0m9S43yLHKhAXle5Q/l4x6yunbw ZGk47nBnB4tsvixPkTLYar0Ce8F/R9ZuGgEuzpI= X-Google-Smtp-Source: AGHT+IE2h4HkxbaBIbp4bn/vRvp2l9FeIsgHKgD8AkUJrzKbZjFGHh1ekEag8qlaVljXtAg4dVDJEA== X-Received: by 2002:a2e:be1a:0:b0:2c5:13b1:b450 with SMTP id z26-20020a2ebe1a000000b002c513b1b450mr5839161ljq.26.1698062680703; Mon, 23 Oct 2023 05:04:40 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:39 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 09/11] virtio-sound: implement audio output (TX) Date: Mon, 23 Oct 2023 15:03:26 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::132; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-lf1-x132.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Handle output IO messages in the transmit (TX) virtqueue. It allocates a VirtIOSoundPCMBuffer for each IO message and copies the data buffer to it. When the IO buffer is written to the host's sound card, the guest will be notified that it has been consumed. The lifetime of an IO message is: 1. Guest sends IO message to TX virtqueue. 2. QEMU adds it to the appropriate stream's IO buffer queue. 3. Sometime later, the host audio backend calls the output callback, virtio_snd_pcm_out_cb(), which is defined with an AUD_open_out() call. The callback gets an available number of bytes the backend can receive. Then it writes data from the IO buffer queue to the backend. If at any time a buffer is exhausted, it is returned to the guest as completed. 4. If the guest releases the stream, its buffer queue is flushed by attempting to write any leftover data to the audio backend and releasing all IO messages back to the guest. This is how according to the spec the guest knows the release was successful. Based-on: https://github.com/OpenSynergy/qemu/commit/5a2f350eec5d157b90d9c7b40a8e603f4da92471 Signed-off-by: Igor Skalkin Signed-off-by: Anton Yakovlev Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- hw/audio/trace-events | 2 + hw/audio/virtio-snd.c | 288 +++++++++++++++++++++++++++++++++- include/hw/audio/virtio-snd.h | 47 ++++++ 3 files changed, 332 insertions(+), 5 deletions(-) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 33e24d0011..884108129b 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -55,3 +55,5 @@ virtio_snd_handle_pcm_release(uint32_t stream) "VIRTIO_SND_PCM_RELEASE called fo virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PRIu32" == %s" virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" virtio_snd_handle_event(void) "event queue callback called" +virtio_snd_pcm_stream_flush(uint32_t stream) "flushing stream %"PRIu32 +virtio_snd_handle_xfer(void) "tx/rx queue callback called" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 9cff724f62..6c91d0a740 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -32,6 +32,10 @@ #define VIRTIO_SOUND_CHMAP_DEFAULT 0 #define VIRTIO_SOUND_HDA_FN_NID 0 +static void virtio_snd_pcm_out_cb(void *data, int available); +static void virtio_snd_process_cmdq(VirtIOSound *s); +static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream); + static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8) | BIT(VIRTIO_SND_PCM_FMT_U8) | BIT(VIRTIO_SND_PCM_FMT_S16) @@ -123,6 +127,13 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config) } +static void +virtio_snd_pcm_buffer_free(VirtIOSoundPCMBuffer *buffer) +{ + g_free(buffer->elem); + g_free(buffer); +} + static void virtio_snd_ctrl_cmd_free(virtio_snd_ctrl_command *cmd) { @@ -396,6 +407,13 @@ static void virtio_snd_get_qemu_audsettings(audsettings *as, */ static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) { + if (stream) { + if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { + virtio_snd_pcm_flush(stream); + AUD_close_out(&stream->pcm->snd->card, stream->voice.out); + stream->voice.out = NULL; + } + } } /* @@ -429,6 +447,9 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) stream->id = stream_id; stream->pcm = s->pcm; stream->s = s; + qemu_mutex_init(&stream->queue_mutex); + QSIMPLEQ_INIT(&stream->queue); + QSIMPLEQ_INIT(&stream->invalid); /* * stream_id >= s->snd_conf.streams was checked before so this is @@ -452,6 +473,18 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) stream->positions[1] = VIRTIO_SND_CHMAP_FR; stream->as = as; + if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { + stream->voice.out = AUD_open_out(&s->card, + stream->voice.out, + "virtio-sound.out", + stream, + virtio_snd_pcm_out_cb, + &as); + AUD_set_volume_out(stream->voice.out, 0, 255, 255); + } else { + qemu_log_mask(LOG_UNIMP, "virtio_snd: input/capture is unimplemented."); + } + return cpu_to_le32(VIRTIO_SND_S_OK); } @@ -532,9 +565,17 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); trace_virtio_snd_handle_pcm_start_stop(start ? "VIRTIO_SND_R_PCM_START" : "VIRTIO_SND_R_PCM_STOP", stream_id); + stream = virtio_snd_pcm_get_stream(s, stream_id); - if (stream == NULL) { - error_report("Invalid stream id: %"PRIu32, req.stream_id); + if (stream) { + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + stream->active = start; + } + if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { + AUD_set_active_out(stream->voice.out, start); + } + } else { + error_report("Invalid stream id: %"PRIu32, stream_id); cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); return; } @@ -542,8 +583,28 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, } /* - * Handles VIRTIO_SND_R_PCM_RELEASE. Releases the buffer resources allocated to - * a stream. + * Returns the number of I/O messages that are being processed. + * + * @stream: VirtIOSoundPCMStream + */ +static size_t virtio_snd_pcm_get_io_msgs_count(VirtIOSoundPCMStream *stream) +{ + VirtIOSoundPCMBuffer *buffer, *next; + size_t count = 0; + + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) { + count += 1; + } + QSIMPLEQ_FOREACH_SAFE(buffer, &stream->invalid, entry, next) { + count += 1; + } + } + return count; +} + +/* + * Handles VIRTIO_SND_R_PCM_RELEASE. * * @s: VirtIOSound device * @cmd: The request command queue element from VirtIOSound cmdq field @@ -584,6 +645,21 @@ static void virtio_snd_handle_pcm_release(VirtIOSound *s, cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); return; } + + if (virtio_snd_pcm_get_io_msgs_count(stream)) { + /* + * virtio-v1.2-csd01, 5.14.6.6.5.1, + * Device Requirements: Stream Release + * + * - The device MUST complete all pending I/O messages for the + * specified stream ID. + * - The device MUST NOT complete the control request while there + * are pending I/O messages for the specified stream ID. + */ + trace_virtio_snd_pcm_stream_flush(stream_id); + virtio_snd_pcm_flush(stream); + } + cmd->resp.code = cpu_to_le32(VIRTIO_SND_S_OK); } @@ -738,6 +814,108 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq) trace_virtio_snd_handle_event(); } +/* + * The tx virtqueue handler. Makes the buffers available to their respective + * streams for consumption. + * + * @vdev: VirtIOSound device + * @vq: tx virtqueue + */ +static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOSound *s = VIRTIO_SND(vdev); + VirtIOSoundPCMStream *stream = NULL; + VirtIOSoundPCMBuffer *buffer; + VirtQueueElement *elem; + size_t msg_sz, size; + virtio_snd_pcm_xfer hdr; + virtio_snd_pcm_status resp = { 0 }; + uint32_t stream_id; + /* + * If any of the I/O messages are invalid, put them in stream->invalid and + * return them after the for loop. + */ + bool must_empty_invalid_queue = false; + + if (!virtio_queue_ready(vq)) { + return; + } + trace_virtio_snd_handle_xfer(); + + for (;;) { + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } + /* get the message hdr object */ + msg_sz = iov_to_buf(elem->out_sg, + elem->out_num, + 0, + &hdr, + sizeof(virtio_snd_pcm_xfer)); + if (msg_sz != sizeof(virtio_snd_pcm_xfer)) { + goto tx_err; + } + stream_id = le32_to_cpu(hdr.stream_id); + + if (stream_id >= s->snd_conf.streams + || s->pcm->streams[stream_id] == NULL) { + goto tx_err; + } + + stream = s->pcm->streams[stream_id]; + if (stream->info.direction != VIRTIO_SND_D_OUTPUT) { + goto tx_err; + } + + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + size = iov_size(elem->out_sg, elem->out_num) - msg_sz; + + buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size); + buffer->elem = elem; + buffer->populated = false; + buffer->vq = vq; + buffer->size = size; + buffer->offset = 0; + + QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry); + } + continue; + +tx_err: + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + must_empty_invalid_queue = true; + buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer)); + buffer->elem = elem; + buffer->vq = vq; + QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry); + } + } + + if (must_empty_invalid_queue) { + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + while (!QSIMPLEQ_EMPTY(&stream->invalid)) { + buffer = QSIMPLEQ_FIRST(&stream->invalid); + + resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + iov_from_buf(buffer->elem->in_sg, + buffer->elem->in_num, + 0, + &resp, + sizeof(virtio_snd_pcm_status)); + virtqueue_push(vq, buffer->elem, sizeof(virtio_snd_pcm_status)); + QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry); + virtio_snd_pcm_buffer_free(buffer); + } + /* + * Notify vq about virtio_snd_pcm_status responses. + * Buffer responses must be notified separately later. + */ + virtio_notify(vdev, vq); + } + } +} + /* * Stub buffer virtqueue handler. * @@ -832,7 +1010,7 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) vsnd->queues[VIRTIO_SND_VQ_EVENT] = virtio_add_queue(vdev, 64, virtio_snd_handle_event); vsnd->queues[VIRTIO_SND_VQ_TX] = - virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); + virtio_add_queue(vdev, 64, virtio_snd_handle_tx); vsnd->queues[VIRTIO_SND_VQ_RX] = virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); qemu_mutex_init(&vsnd->cmdq_mutex); @@ -856,6 +1034,105 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) } } +static inline void return_tx_buffer(VirtIOSoundPCMStream *stream, + VirtIOSoundPCMBuffer *buffer) +{ + virtio_snd_pcm_status resp = { 0 }; + resp.status = cpu_to_le32(VIRTIO_SND_S_OK); + resp.latency_bytes = cpu_to_le32((uint32_t)buffer->size); + iov_from_buf(buffer->elem->in_sg, + buffer->elem->in_num, + 0, + &resp, + sizeof(virtio_snd_pcm_status)); + virtqueue_push(buffer->vq, + buffer->elem, + sizeof(virtio_snd_pcm_status)); + virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq); + QSIMPLEQ_REMOVE(&stream->queue, + buffer, + VirtIOSoundPCMBuffer, + entry); + virtio_snd_pcm_buffer_free(buffer); +} + +/* + * AUD_* output callback. + * + * @data: VirtIOSoundPCMStream stream + * @available: number of bytes that can be written with AUD_write() + */ +static void virtio_snd_pcm_out_cb(void *data, int available) +{ + VirtIOSoundPCMStream *stream = data; + VirtIOSoundPCMBuffer *buffer; + size_t size; + + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + while (!QSIMPLEQ_EMPTY(&stream->queue)) { + buffer = QSIMPLEQ_FIRST(&stream->queue); + if (!virtio_queue_ready(buffer->vq)) { + return; + } + if (!stream->active) { + /* Stream has stopped, so do not perform AUD_write. */ + return_tx_buffer(stream, buffer); + continue; + } + if (!buffer->populated) { + iov_to_buf(buffer->elem->out_sg, + buffer->elem->out_num, + sizeof(virtio_snd_pcm_xfer), + buffer->data, + buffer->size); + buffer->populated = true; + } + for (;;) { + size = AUD_write(stream->voice.out, + buffer->data + buffer->offset, + MIN(buffer->size, available)); + assert(size <= MIN(buffer->size, available)); + if (size == 0) { + /* break out of both loops */ + available = 0; + break; + } + buffer->size -= size; + buffer->offset += size; + available -= size; + if (buffer->size < 1) { + return_tx_buffer(stream, buffer); + break; + } + if (!available) { + break; + } + } + if (!available) { + break; + } + } + } +} + +/* + * Flush all buffer data from this stream's queue into the driver's virtual + * queue. + * + * @stream: VirtIOSoundPCMStream *stream + */ +static inline void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream) +{ + VirtIOSoundPCMBuffer *buffer; + + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + while (!QSIMPLEQ_EMPTY(&stream->queue)) { + buffer = QSIMPLEQ_FIRST(&stream->queue); + return_tx_buffer(stream, buffer); + } + } +} + static void virtio_snd_unrealize(DeviceState *dev) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -872,6 +1149,7 @@ static void virtio_snd_unrealize(DeviceState *dev) if (stream) { virtio_snd_process_cmdq(stream->s); virtio_snd_pcm_close(stream); + qemu_mutex_destroy(&stream->queue_mutex); g_free(stream); } } diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h index cc14c875ed..c3767f442b 100644 --- a/include/hw/audio/virtio-snd.h +++ b/include/hw/audio/virtio-snd.h @@ -77,6 +77,50 @@ typedef struct virtio_snd_ctrl_command virtio_snd_ctrl_command; typedef struct VirtIOSoundPCM VirtIOSoundPCM; +typedef struct VirtIOSoundPCMBuffer VirtIOSoundPCMBuffer; + +/* + * The VirtIO sound spec reuses layouts and values from the High Definition + * Audio spec (virtio/v1.2: 5.14 Sound Device). This struct handles each I/O + * message's buffer (virtio/v1.2: 5.14.6.8 PCM I/O Messages). + * + * In the case of TX (i.e. playback) buffers, we defer reading the raw PCM data + * from the virtqueue until QEMU's sound backsystem calls the output callback. + * This is tracked by the `bool populated;` field, which is set to true when + * data has been read into our own buffer for consumption. + * + * VirtIOSoundPCMBuffer has a dynamic size since it includes the raw PCM data + * in its allocation. It must be initialized and destroyed as follows: + * + * size_t size = [[derived from owned VQ element descriptor sizes]]; + * buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size); + * buffer->elem = [[owned VQ element]]; + * + * [..] + * + * g_free(buffer->elem); + * g_free(buffer); + */ +struct VirtIOSoundPCMBuffer { + QSIMPLEQ_ENTRY(VirtIOSoundPCMBuffer) entry; + VirtQueueElement *elem; + VirtQueue *vq; + size_t size; + /* + * In TX / Plaback, `offset` represents the first unused position inside + * `data`. If `offset == size` then there are no unused data left. + */ + uint64_t offset; + /* Used for the TX queue for lazy I/O copy from `elem` */ + bool populated; + /* + * VirtIOSoundPCMBuffer is an unsized type because it ends with an array of + * bytes. The size of `data` is determined from the I/O message's read-only + * or write-only size when allocating VirtIOSoundPCMBuffer. + */ + uint8_t data[]; +}; + struct VirtIOSoundPCM { VirtIOSound *snd; /* @@ -104,7 +148,10 @@ struct VirtIOSoundPCMStream { SWVoiceIn *in; SWVoiceOut *out; } voice; + QemuMutex queue_mutex; bool active; + QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) queue; + QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) invalid; }; /* From patchwork Mon Oct 23 12:03:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432811 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E55B9C001E0 for ; Mon, 23 Oct 2023 12:06:38 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutg4-0005gG-1y; Mon, 23 Oct 2023 08:05:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutfx-0005Wg-SF for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:56 -0400 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutfu-00022G-Qa for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:53 -0400 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-40859c46447so13310945e9.1 for ; Mon, 23 Oct 2023 05:04:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062686; x=1698667486; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+b+4iA1DfUeGgKKifQtrUjnqov07ApYPhyAo0IFGREc=; b=fUbaoFTCpupWeCBxkifsId0V4Wg8f+vZoSPKHKS+4FMK5D6PklLIL5hp2us4y5UJ5A FRbTcIWnPRyf8T9CVKQo5IBwvKL/X17hgZq818SytgSsasb0QbqTRgWVN5iKxha1Mkf3 sEYG4J0X0zKthnRn6zSUY02JYUVuyFTqlr09BP8sPBN5N+UVlEa3TGyH0BhTv/V7BgMe CJ7xzAvXcVNBDWnDdqHdl/pHppE6RU9P6swrRhF5zbjkNzyNZSj/8rgauoEc4cC9j4lx npQHzC83ePgm9n+6LENdy2A8Oo6u1l0j5dIfLkP2XJsgS0hrEGYjE3YUpNR0t0kbZxiW 8GYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062686; x=1698667486; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+b+4iA1DfUeGgKKifQtrUjnqov07ApYPhyAo0IFGREc=; b=AJZ9INxVW2JYl9lMJYRXnj/CDf3xiGcZWn6oY7Xv+jdUEsn/1jI8Ejn5PBH/K8FYAR kOL3G8IuYxWeHdbmuEKxl+voJkgOfNUHo84AsrmXdcYaAwa+JXUadCP1q7YrwLgfQldB NsLUU8nijzkY0XEPeAzUMw+y+h+FpVS2spTPdBySsLdZ8YMujegt5dj4x9PSu3/TVhlK wQXTnDdi40weBimcdXsSD0TWtqdpDAtbSzGAlD+gL9S5FpV8I8S/+zamQZtecd+F/IfH Vd315lzxkfscM6GxcS4kIIFOckOQO2AGdAHl1KlK9cFHgfetxZWWC7PhCvHwtnRmyQbR NAwQ== X-Gm-Message-State: AOJu0YyvsZVeoLiJ98KjHDrZZo/l2d4Kg4YvxVsS0jpGYX2oiyzlAOMK hbDet3G9dfjANJTB1IG4+KlrwtyGt3hd/2zpCLU= X-Google-Smtp-Source: AGHT+IEYe5jpMQ2ndznqFZLsZcFt+qZ8hxMKKrOwTtksynFxvCkGw4qVlbQOeB+I98osfH8OKPpYgg== X-Received: by 2002:a05:600c:4ecc:b0:408:37d4:b5ba with SMTP id g12-20020a05600c4ecc00b0040837d4b5bamr7797530wmq.12.1698062685188; Mon, 23 Oct 2023 05:04:45 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:44 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 10/11] virtio-sound: implement audio capture (RX) Date: Mon, 23 Oct 2023 15:03:27 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::32f; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-wm1-x32f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org To perform audio capture we duplicate the TX logic of the previous commit with the following difference: we receive data from the QEMU audio backend and write it in the virt queue IO buffers the guest sends to QEMU. When they are full (i.e. they have `period_bytes` amount of data) or when recording stops in QEMU's audio backend, the buffer is returned to the guest by notifying it. Signed-off-by: Manos Pitsidianakis Tested-by: Alex Bennée Reviewed-by: Alex Bennée --- hw/audio/trace-events | 3 +- hw/audio/virtio-snd.c | 262 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 230 insertions(+), 35 deletions(-) diff --git a/hw/audio/trace-events b/hw/audio/trace-events index 884108129b..b1870ff224 100644 --- a/hw/audio/trace-events +++ b/hw/audio/trace-events @@ -56,4 +56,5 @@ virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = %"PR virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" virtio_snd_handle_event(void) "event queue callback called" virtio_snd_pcm_stream_flush(uint32_t stream) "flushing stream %"PRIu32 -virtio_snd_handle_xfer(void) "tx/rx queue callback called" +virtio_snd_handle_tx_xfer(void) "tx queue callback called" +virtio_snd_handle_rx_xfer(void) "rx queue callback called" diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c index 6c91d0a740..a18a9949a7 100644 --- a/hw/audio/virtio-snd.c +++ b/hw/audio/virtio-snd.c @@ -28,13 +28,14 @@ #define VIRTIO_SOUND_VM_VERSION 1 #define VIRTIO_SOUND_JACK_DEFAULT 0 -#define VIRTIO_SOUND_STREAM_DEFAULT 1 +#define VIRTIO_SOUND_STREAM_DEFAULT 2 #define VIRTIO_SOUND_CHMAP_DEFAULT 0 #define VIRTIO_SOUND_HDA_FN_NID 0 static void virtio_snd_pcm_out_cb(void *data, int available); static void virtio_snd_process_cmdq(VirtIOSound *s); static void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream); +static void virtio_snd_pcm_in_cb(void *data, int available); static uint32_t supported_formats = BIT(VIRTIO_SND_PCM_FMT_S8) | BIT(VIRTIO_SND_PCM_FMT_U8) @@ -408,10 +409,13 @@ static void virtio_snd_get_qemu_audsettings(audsettings *as, static void virtio_snd_pcm_close(VirtIOSoundPCMStream *stream) { if (stream) { + virtio_snd_pcm_flush(stream); if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { - virtio_snd_pcm_flush(stream); AUD_close_out(&stream->pcm->snd->card, stream->voice.out); stream->voice.out = NULL; + } else if (stream->info.direction == VIRTIO_SND_D_INPUT) { + AUD_close_in(&stream->pcm->snd->card, stream->voice.in); + stream->voice.in = NULL; } } } @@ -482,7 +486,13 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id) &as); AUD_set_volume_out(stream->voice.out, 0, 255, 255); } else { - qemu_log_mask(LOG_UNIMP, "virtio_snd: input/capture is unimplemented."); + stream->voice.in = AUD_open_in(&s->card, + stream->voice.in, + "virtio-sound.in", + stream, + virtio_snd_pcm_in_cb, + &as); + AUD_set_volume_in(stream->voice.in, 0, 255, 255); } return cpu_to_le32(VIRTIO_SND_S_OK); @@ -573,6 +583,8 @@ static void virtio_snd_handle_pcm_start_stop(VirtIOSound *s, } if (stream->info.direction == VIRTIO_SND_D_OUTPUT) { AUD_set_active_out(stream->voice.out, start); + } else { + AUD_set_active_in(stream->voice.in, start); } } else { error_report("Invalid stream id: %"PRIu32, stream_id); @@ -814,6 +826,49 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq) trace_virtio_snd_handle_event(); } +static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOSoundPCMBuffer *buffer = NULL; + VirtIOSoundPCMStream *stream = NULL; + virtio_snd_pcm_status resp = { 0 }; + VirtIOSound *vsnd = VIRTIO_SND(vdev); + bool any = false; + + for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) { + stream = vsnd->pcm->streams[i]; + if (stream) { + any = false; + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + while (!QSIMPLEQ_EMPTY(&stream->invalid)) { + buffer = QSIMPLEQ_FIRST(&stream->invalid); + if (buffer->vq != vq) { + break; + } + any = true; + resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); + iov_from_buf(buffer->elem->in_sg, + buffer->elem->in_num, + 0, + &resp, + sizeof(virtio_snd_pcm_status)); + virtqueue_push(vq, + buffer->elem, + sizeof(virtio_snd_pcm_status)); + QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry); + virtio_snd_pcm_buffer_free(buffer); + } + if (any) { + /* + * Notify vq about virtio_snd_pcm_status responses. + * Buffer responses must be notified separately later. + */ + virtio_notify(vdev, vq); + } + } + } + } +} + /* * The tx virtqueue handler. Makes the buffers available to their respective * streams for consumption. @@ -821,7 +876,7 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq) * @vdev: VirtIOSound device * @vq: tx virtqueue */ -static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq) +static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq) { VirtIOSound *s = VIRTIO_SND(vdev); VirtIOSoundPCMStream *stream = NULL; @@ -829,7 +884,6 @@ static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq) VirtQueueElement *elem; size_t msg_sz, size; virtio_snd_pcm_xfer hdr; - virtio_snd_pcm_status resp = { 0 }; uint32_t stream_id; /* * If any of the I/O messages are invalid, put them in stream->invalid and @@ -840,7 +894,7 @@ static void virtio_snd_handle_tx(VirtIODevice *vdev, VirtQueue *vq) if (!virtio_queue_ready(vq)) { return; } - trace_virtio_snd_handle_xfer(); + trace_virtio_snd_handle_tx_xfer(); for (;;) { elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); @@ -893,36 +947,88 @@ tx_err: } if (must_empty_invalid_queue) { - WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { - while (!QSIMPLEQ_EMPTY(&stream->invalid)) { - buffer = QSIMPLEQ_FIRST(&stream->invalid); - - resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG); - iov_from_buf(buffer->elem->in_sg, - buffer->elem->in_num, - 0, - &resp, - sizeof(virtio_snd_pcm_status)); - virtqueue_push(vq, buffer->elem, sizeof(virtio_snd_pcm_status)); - QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry); - virtio_snd_pcm_buffer_free(buffer); - } - /* - * Notify vq about virtio_snd_pcm_status responses. - * Buffer responses must be notified separately later. - */ - virtio_notify(vdev, vq); - } + empty_invalid_queue(vdev, vq); } } /* - * Stub buffer virtqueue handler. + * The rx virtqueue handler. Makes the buffers available to their respective + * streams for consumption. * * @vdev: VirtIOSound device - * @vq: virtqueue + * @vq: rx virtqueue */ -static void virtio_snd_handle_xfer(VirtIODevice *vdev, VirtQueue *vq) {} +static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIOSound *s = VIRTIO_SND(vdev); + VirtIOSoundPCMStream *stream = NULL; + VirtIOSoundPCMBuffer *buffer; + VirtQueueElement *elem; + size_t msg_sz, size; + virtio_snd_pcm_xfer hdr; + uint32_t stream_id; + /* + * if any of the I/O messages are invalid, put them in stream->invalid and + * return them after the for loop. + */ + bool must_empty_invalid_queue = false; + + if (!virtio_queue_ready(vq)) { + return; + } + trace_virtio_snd_handle_rx_xfer(); + + for (;;) { + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } + /* get the message hdr object */ + msg_sz = iov_to_buf(elem->out_sg, + elem->out_num, + 0, + &hdr, + sizeof(virtio_snd_pcm_xfer)); + if (msg_sz != sizeof(virtio_snd_pcm_xfer)) { + goto rx_err; + } + stream_id = le32_to_cpu(hdr.stream_id); + + if (stream_id >= s->snd_conf.streams + || !s->pcm->streams[stream_id]) { + goto rx_err; + } + + stream = s->pcm->streams[stream_id]; + if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) { + goto rx_err; + } + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + size = iov_size(elem->in_sg, elem->in_num) - + sizeof(virtio_snd_pcm_status); + buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer) + size); + buffer->elem = elem; + buffer->vq = vq; + buffer->size = 0; + buffer->offset = 0; + QSIMPLEQ_INSERT_TAIL(&stream->queue, buffer, entry); + } + continue; + +rx_err: + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + must_empty_invalid_queue = true; + buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer)); + buffer->elem = elem; + buffer->vq = vq; + QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry); + } + } + + if (must_empty_invalid_queue) { + empty_invalid_queue(vdev, vq); + } +} static uint64_t get_features(VirtIODevice *vdev, uint64_t features, Error **errp) @@ -1010,9 +1116,9 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp) vsnd->queues[VIRTIO_SND_VQ_EVENT] = virtio_add_queue(vdev, 64, virtio_snd_handle_event); vsnd->queues[VIRTIO_SND_VQ_TX] = - virtio_add_queue(vdev, 64, virtio_snd_handle_tx); + virtio_add_queue(vdev, 64, virtio_snd_handle_tx_xfer); vsnd->queues[VIRTIO_SND_VQ_RX] = - virtio_add_queue(vdev, 64, virtio_snd_handle_xfer); + virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer); qemu_mutex_init(&vsnd->cmdq_mutex); QTAILQ_INIT(&vsnd->cmdq); @@ -1116,19 +1222,107 @@ static void virtio_snd_pcm_out_cb(void *data, int available) } /* - * Flush all buffer data from this stream's queue into the driver's virtual - * queue. + * Flush all buffer data from this input stream's queue into the driver's + * virtual queue. + * + * @stream: VirtIOSoundPCMStream *stream + */ +static inline void return_rx_buffer(VirtIOSoundPCMStream *stream, + VirtIOSoundPCMBuffer *buffer) +{ + virtio_snd_pcm_status resp = { 0 }; + resp.status = cpu_to_le32(VIRTIO_SND_S_OK); + resp.latency_bytes = 0; + /* Copy data -if any- to guest */ + iov_from_buf(buffer->elem->in_sg, + buffer->elem->in_num, + 0, + buffer->data, + buffer->size); + iov_from_buf(buffer->elem->in_sg, + buffer->elem->in_num, + buffer->size, + &resp, + sizeof(virtio_snd_pcm_status)); + virtqueue_push(buffer->vq, + buffer->elem, + sizeof(virtio_snd_pcm_status) + buffer->size); + virtio_notify(VIRTIO_DEVICE(stream->s), buffer->vq); + QSIMPLEQ_REMOVE(&stream->queue, + buffer, + VirtIOSoundPCMBuffer, + entry); + virtio_snd_pcm_buffer_free(buffer); +} + + +/* + * AUD_* input callback. + * + * @data: VirtIOSoundPCMStream stream + * @available: number of bytes that can be read with AUD_read() + */ +static void virtio_snd_pcm_in_cb(void *data, int available) +{ + VirtIOSoundPCMStream *stream = data; + VirtIOSoundPCMBuffer *buffer; + size_t size; + + WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { + while (!QSIMPLEQ_EMPTY(&stream->queue)) { + buffer = QSIMPLEQ_FIRST(&stream->queue); + if (!virtio_queue_ready(buffer->vq)) { + return; + } + if (!stream->active) { + /* Stream has stopped, so do not perform AUD_read. */ + return_rx_buffer(stream, buffer); + continue; + } + + for (;;) { + size = AUD_read(stream->voice.in, + buffer->data + buffer->size, + MIN(available, (stream->params.period_bytes - + buffer->size))); + if (!size) { + available = 0; + break; + } + buffer->size += size; + available -= size; + if (buffer->size >= stream->params.period_bytes) { + return_rx_buffer(stream, buffer); + break; + } + if (!available) { + break; + } + } + if (!available) { + break; + } + } + } +} + +/* + * Flush all buffer data from this output stream's queue into the driver's + * virtual queue. * * @stream: VirtIOSoundPCMStream *stream */ static inline void virtio_snd_pcm_flush(VirtIOSoundPCMStream *stream) { VirtIOSoundPCMBuffer *buffer; + void (*cb)(VirtIOSoundPCMStream *, VirtIOSoundPCMBuffer *) = + (stream->info.direction == VIRTIO_SND_D_OUTPUT) ? return_tx_buffer : + return_rx_buffer; WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) { while (!QSIMPLEQ_EMPTY(&stream->queue)) { buffer = QSIMPLEQ_FIRST(&stream->queue); - return_tx_buffer(stream, buffer); + cb(stream, buffer); } } } From patchwork Mon Oct 23 12:03:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Manos Pitsidianakis X-Patchwork-Id: 13432813 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 004A5CDB474 for ; Mon, 23 Oct 2023 12:06:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qutgH-00062p-H6; Mon, 23 Oct 2023 08:05:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qutg4-0005hy-16 for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:05:00 -0400 Received: from mail-lj1-x236.google.com ([2a00:1450:4864:20::236]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qutg0-000234-Uv for qemu-devel@nongnu.org; Mon, 23 Oct 2023 08:04:59 -0400 Received: by mail-lj1-x236.google.com with SMTP id 38308e7fff4ca-2c50cd16f3bso45130991fa.2 for ; Mon, 23 Oct 2023 05:04:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1698062694; x=1698667494; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tKVK/4/eu9JM7iQFa4YhCyu8AE+xNtq+qwGY5QZJ+tc=; b=KgxZZ8U1aJsSvwscL22b/Z+xup7YvMPcOKbZlpDLTVguPEmf5ViwfjPq8eDh4enCzG vPYXyrLIr12X719XflOJZesSAwts1bRYuegsL23osiK9e0zo7LRlCYcdi6GRSH9BzabJ +tD+715GXBz4amWYGIECWymy7fJFuMQFJMmS3WCogkT+Ggwpi5RsKCgjP3PcR+8a1Dzn dIksGWYMwhiiAgBbo6BhrKc2XdwFpTHX7JvZsoH+Flt4xLbHECTdffpnDvscJLkq8TML eWLDn5LCS/senQJ/2umXFsIzd6rzmroTIsOBSv2iXUO3X14P/A3yyCn9HiJOu63D5/3p xTwQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698062694; x=1698667494; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tKVK/4/eu9JM7iQFa4YhCyu8AE+xNtq+qwGY5QZJ+tc=; b=k3bOvsDUHibaYvry6ExypomZKc4xEU6OPwhPUJAneLHv1WJqAQCZko/UrBxgDYIML/ Vvn7gF4QXifzP4vHokrrVe53BS4wZ3Ca00GkKZALfQrEwpZN8KAOo2XxqGQwhagdoW8V Z8+PCRbQRaeF5fblvL5Zd26kFCrNIjKwpgnWIfbykEPAFS80PH5KLUQDn58ZEOr93RUV dQClCX2U+rfleQzHY4HrAy7AAVHJOrE9baNCf8/npVMXWviDgsvd8/lNsTVIB9aQ1HQl eBnebz/B1gdA0zuxaQZBmRXsegI873fMJT6zh8B9y/yNjTXGpgMoP5maIi8zCXnRPzxJ Yuzg== X-Gm-Message-State: AOJu0Yx74KL+Ridazvdop2udU7BJVqzMQfeTcDXidmG81VIFHyslDiI+ 7NEL0W/EayBHkoQqsiBTCS6BidKd2Emhu79MBTw= X-Google-Smtp-Source: AGHT+IEPKipknQD1PyBiiTdKLwaP8Z1Ir9l4hoSoKaOdbVNLQmsobv2JMaMICU46tZtW50DmpWf31w== X-Received: by 2002:a2e:a7cc:0:b0:2c5:fb9:49b6 with SMTP id x12-20020a2ea7cc000000b002c50fb949b6mr8812299ljp.10.1698062694149; Mon, 23 Oct 2023 05:04:54 -0700 (PDT) Received: from localhost.localdomain (adsl-69.109.242.226.tellas.gr. [109.242.226.69]) by smtp.gmail.com with ESMTPSA id p12-20020a05600c418c00b0040773c69fc0sm13819506wmh.11.2023.10.23.05.04.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 05:04:53 -0700 (PDT) From: Manos Pitsidianakis To: qemu-devel@nongnu.org, "Gerd Hoffmann" Cc: Manos Pitsidianakis , "Igor Skalkin" , "Anton Yakovlev" , "Paolo Bonzini" , "Michael S. Tsirkin" , "Marcel Apfelbaum" , =?utf-8?q?Daniel_P=2E_Berr?= =?utf-8?q?ang=C3=A9?= , "Eduardo Habkost" , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , =?utf-8?q?Volker_R=C3=BCmelin?= , =?utf-8?b?S8WRdsOh?= =?utf-8?b?Z8OzLCBab2x0w6Fu?= , =?utf-8?q?Alex_Benn?= =?utf-8?q?=C3=A9e?= , =?utf-8?q?Philippe_Mathieu-Da?= =?utf-8?q?ud=C3=A9?= , "Mark Cave-Ayland" , "Stefano Garzarella" Subject: [PATCH v13 11/11] docs/system: add basic virtio-snd documentation Date: Mon, 23 Oct 2023 15:03:28 +0300 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::236; envelope-from=manos.pitsidianakis@linaro.org; helo=mail-lj1-x236.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This commit adds basic documentation for using virtio-snd. Signed-off-by: Manos Pitsidianakis Reviewed-by: Alex Bennée Tested-by: Alex Bennée --- MAINTAINERS | 1 + docs/system/device-emulation.rst | 1 + docs/system/devices/virtio-snd.rst | 49 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 docs/system/devices/virtio-snd.rst diff --git a/MAINTAINERS b/MAINTAINERS index 07e07f6b7a..e60a9b742b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2289,6 +2289,7 @@ S: Supported F: hw/audio/virtio-snd.c F: hw/audio/virtio-snd-pci.c F: include/hw/audio/virtio-snd.h +F: docs/system/devices/virtio-snd.rst nvme M: Keith Busch diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst index 1167f3a9f2..d1f3277cb0 100644 --- a/docs/system/device-emulation.rst +++ b/docs/system/device-emulation.rst @@ -93,6 +93,7 @@ Emulated Devices devices/vhost-user.rst devices/virtio-gpu.rst devices/virtio-pmem.rst + devices/virtio-snd.rst devices/vhost-user-rng.rst devices/canokey.rst devices/usb-u2f.rst diff --git a/docs/system/devices/virtio-snd.rst b/docs/system/devices/virtio-snd.rst new file mode 100644 index 0000000000..2a9187fd70 --- /dev/null +++ b/docs/system/devices/virtio-snd.rst @@ -0,0 +1,49 @@ +virtio sound +============ + +This document explains the setup and usage of the Virtio sound device. +The Virtio sound device is a paravirtualized sound card device. + +Linux kernel support +-------------------- + +Virtio sound requires a guest Linux kernel built with the +``CONFIG_SND_VIRTIO`` option. + +Description +----------- + +Virtio sound implements capture and playback from inside a guest using the +configured audio backend of the host machine. + +Device properties +----------------- + +The Virtio sound device can be configured with the following properties: + + * ``jacks`` number of physical jacks (Unimplemented). + * ``streams`` number of PCM streams. At the moment, no stream configuration is supported: the first one will always be a playback stream, an optional second will always be a capture stream. Adding more will cycle stream directions from playback to capture. + * ``chmaps`` number of channel maps (Unimplemented). + +All streams are stereo and have the default channel positions ``Front left, right``. + +Examples +-------- + +Add an audio device and an audio backend at once with ``-audio`` and ``model=virtio``: + + * pulseaudio: ``-audio driver=pa,model=virtio`` + or ``-audio driver=pa,model=virtio,server=/run/user/1000/pulse/native`` + * sdl: ``-audio driver=sdl,model=virtio`` + * coreaudio: ``-audio driver=coreaudio,model=virtio`` + +etc. + +To specifically add virtualized sound devices, you have to specify a PCI device +and an audio backend listed with ``-audio driver=help`` that works on your host +machine, e.g.: + +:: + + -device virtio-sound-pci,audiodev=my_audiodev \ + -audiodev alsa,id=my_audiodev