1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * virtio-snd: Virtio sound device 4 * Copyright (C) 2021 OpenSynergy GmbH 5 */ 6 #include <linux/module.h> 7 #include <linux/moduleparam.h> 8 #include <linux/virtio_config.h> 9 #include <sound/initval.h> 10 #include <uapi/linux/virtio_ids.h> 11 12 #include "virtio_card.h" 13 14 u32 virtsnd_msg_timeout_ms = MSEC_PER_SEC; 15 module_param_named(msg_timeout_ms, virtsnd_msg_timeout_ms, uint, 0644); 16 MODULE_PARM_DESC(msg_timeout_ms, "Message completion timeout in milliseconds"); 17 18 static void virtsnd_remove(struct virtio_device *vdev); 19 20 /** 21 * virtsnd_event_send() - Add an event to the event queue. 22 * @vqueue: Underlying event virtqueue. 23 * @event: Event. 24 * @notify: Indicates whether or not to send a notification to the device. 25 * @gfp: Kernel flags for memory allocation. 26 * 27 * Context: Any context. 28 */ 29 static void virtsnd_event_send(struct virtqueue *vqueue, 30 struct virtio_snd_event *event, bool notify, 31 gfp_t gfp) 32 { 33 struct scatterlist sg; 34 struct scatterlist *psgs[1] = { &sg }; 35 36 /* reset event content */ 37 memset(event, 0, sizeof(*event)); 38 39 sg_init_one(&sg, event, sizeof(*event)); 40 41 if (virtqueue_add_sgs(vqueue, psgs, 0, 1, event, gfp) || !notify) 42 return; 43 44 if (virtqueue_kick_prepare(vqueue)) 45 virtqueue_notify(vqueue); 46 } 47 48 /** 49 * virtsnd_event_dispatch() - Dispatch an event from the device side. 50 * @snd: VirtIO sound device. 51 * @event: VirtIO sound event. 52 * 53 * Context: Any context. 54 */ 55 static void virtsnd_event_dispatch(struct virtio_snd *snd, 56 struct virtio_snd_event *event) 57 { 58 switch (le32_to_cpu(event->hdr.code)) { 59 case VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED: 60 case VIRTIO_SND_EVT_PCM_XRUN: 61 virtsnd_pcm_event(snd, event); 62 break; 63 } 64 } 65 66 /** 67 * virtsnd_event_notify_cb() - Dispatch all reported events from the event queue. 68 * @vqueue: Underlying event virtqueue. 69 * 70 * This callback function is called upon a vring interrupt request from the 71 * device. 72 * 73 * Context: Interrupt context. 74 */ 75 static void virtsnd_event_notify_cb(struct virtqueue *vqueue) 76 { 77 struct virtio_snd *snd = vqueue->vdev->priv; 78 struct virtio_snd_queue *queue = virtsnd_event_queue(snd); 79 struct virtio_snd_event *event; 80 u32 length; 81 unsigned long flags; 82 83 spin_lock_irqsave(&queue->lock, flags); 84 do { 85 virtqueue_disable_cb(vqueue); 86 while ((event = virtqueue_get_buf(vqueue, &length))) { 87 virtsnd_event_dispatch(snd, event); 88 virtsnd_event_send(vqueue, event, true, GFP_ATOMIC); 89 } 90 if (unlikely(virtqueue_is_broken(vqueue))) 91 break; 92 } while (!virtqueue_enable_cb(vqueue)); 93 spin_unlock_irqrestore(&queue->lock, flags); 94 } 95 96 /** 97 * virtsnd_find_vqs() - Enumerate and initialize all virtqueues. 98 * @snd: VirtIO sound device. 99 * 100 * After calling this function, the event queue is disabled. 101 * 102 * Context: Any context. 103 * Return: 0 on success, -errno on failure. 104 */ 105 static int virtsnd_find_vqs(struct virtio_snd *snd) 106 { 107 struct virtio_device *vdev = snd->vdev; 108 static vq_callback_t *callbacks[VIRTIO_SND_VQ_MAX] = { 109 [VIRTIO_SND_VQ_CONTROL] = virtsnd_ctl_notify_cb, 110 [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb, 111 [VIRTIO_SND_VQ_TX] = virtsnd_pcm_tx_notify_cb, 112 [VIRTIO_SND_VQ_RX] = virtsnd_pcm_rx_notify_cb 113 }; 114 static const char *names[VIRTIO_SND_VQ_MAX] = { 115 [VIRTIO_SND_VQ_CONTROL] = "virtsnd-ctl", 116 [VIRTIO_SND_VQ_EVENT] = "virtsnd-event", 117 [VIRTIO_SND_VQ_TX] = "virtsnd-tx", 118 [VIRTIO_SND_VQ_RX] = "virtsnd-rx" 119 }; 120 struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 }; 121 unsigned int i; 122 unsigned int n; 123 int rc; 124 125 rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, callbacks, names, 126 NULL); 127 if (rc) { 128 dev_err(&vdev->dev, "failed to initialize virtqueues\n"); 129 return rc; 130 } 131 132 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i) 133 snd->queues[i].vqueue = vqs[i]; 134 135 /* Allocate events and populate the event queue */ 136 virtqueue_disable_cb(vqs[VIRTIO_SND_VQ_EVENT]); 137 138 n = virtqueue_get_vring_size(vqs[VIRTIO_SND_VQ_EVENT]); 139 140 snd->event_msgs = kmalloc_array(n, sizeof(*snd->event_msgs), 141 GFP_KERNEL); 142 if (!snd->event_msgs) 143 return -ENOMEM; 144 145 for (i = 0; i < n; ++i) 146 virtsnd_event_send(vqs[VIRTIO_SND_VQ_EVENT], 147 &snd->event_msgs[i], false, GFP_KERNEL); 148 149 return 0; 150 } 151 152 /** 153 * virtsnd_enable_event_vq() - Enable the event virtqueue. 154 * @snd: VirtIO sound device. 155 * 156 * Context: Any context. 157 */ 158 static void virtsnd_enable_event_vq(struct virtio_snd *snd) 159 { 160 struct virtio_snd_queue *queue = virtsnd_event_queue(snd); 161 162 if (!virtqueue_enable_cb(queue->vqueue)) 163 virtsnd_event_notify_cb(queue->vqueue); 164 } 165 166 /** 167 * virtsnd_disable_event_vq() - Disable the event virtqueue. 168 * @snd: VirtIO sound device. 169 * 170 * Context: Any context. 171 */ 172 static void virtsnd_disable_event_vq(struct virtio_snd *snd) 173 { 174 struct virtio_snd_queue *queue = virtsnd_event_queue(snd); 175 struct virtio_snd_event *event; 176 u32 length; 177 unsigned long flags; 178 179 if (queue->vqueue) { 180 spin_lock_irqsave(&queue->lock, flags); 181 virtqueue_disable_cb(queue->vqueue); 182 while ((event = virtqueue_get_buf(queue->vqueue, &length))) 183 virtsnd_event_dispatch(snd, event); 184 spin_unlock_irqrestore(&queue->lock, flags); 185 } 186 } 187 188 /** 189 * virtsnd_build_devs() - Read configuration and build ALSA devices. 190 * @snd: VirtIO sound device. 191 * 192 * Context: Any context that permits to sleep. 193 * Return: 0 on success, -errno on failure. 194 */ 195 static int virtsnd_build_devs(struct virtio_snd *snd) 196 { 197 struct virtio_device *vdev = snd->vdev; 198 struct device *dev = &vdev->dev; 199 int rc; 200 201 rc = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 202 THIS_MODULE, 0, &snd->card); 203 if (rc < 0) 204 return rc; 205 206 snd->card->private_data = snd; 207 208 strscpy(snd->card->driver, VIRTIO_SND_CARD_DRIVER, 209 sizeof(snd->card->driver)); 210 strscpy(snd->card->shortname, VIRTIO_SND_CARD_NAME, 211 sizeof(snd->card->shortname)); 212 if (dev->parent->bus) 213 snprintf(snd->card->longname, sizeof(snd->card->longname), 214 VIRTIO_SND_CARD_NAME " at %s/%s/%s", 215 dev->parent->bus->name, dev_name(dev->parent), 216 dev_name(dev)); 217 else 218 snprintf(snd->card->longname, sizeof(snd->card->longname), 219 VIRTIO_SND_CARD_NAME " at %s/%s", 220 dev_name(dev->parent), dev_name(dev)); 221 222 rc = virtsnd_pcm_parse_cfg(snd); 223 if (rc) 224 return rc; 225 226 if (snd->nsubstreams) { 227 rc = virtsnd_pcm_build_devs(snd); 228 if (rc) 229 return rc; 230 } 231 232 return snd_card_register(snd->card); 233 } 234 235 /** 236 * virtsnd_validate() - Validate if the device can be started. 237 * @vdev: VirtIO parent device. 238 * 239 * Context: Any context. 240 * Return: 0 on success, -EINVAL on failure. 241 */ 242 static int virtsnd_validate(struct virtio_device *vdev) 243 { 244 if (!vdev->config->get) { 245 dev_err(&vdev->dev, "configuration access disabled\n"); 246 return -EINVAL; 247 } 248 249 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { 250 dev_err(&vdev->dev, 251 "device does not comply with spec version 1.x\n"); 252 return -EINVAL; 253 } 254 255 if (!virtsnd_msg_timeout_ms) { 256 dev_err(&vdev->dev, "msg_timeout_ms value cannot be zero\n"); 257 return -EINVAL; 258 } 259 260 if (virtsnd_pcm_validate(vdev)) 261 return -EINVAL; 262 263 return 0; 264 } 265 266 /** 267 * virtsnd_probe() - Create and initialize the device. 268 * @vdev: VirtIO parent device. 269 * 270 * Context: Any context that permits to sleep. 271 * Return: 0 on success, -errno on failure. 272 */ 273 static int virtsnd_probe(struct virtio_device *vdev) 274 { 275 struct virtio_snd *snd; 276 unsigned int i; 277 int rc; 278 279 snd = devm_kzalloc(&vdev->dev, sizeof(*snd), GFP_KERNEL); 280 if (!snd) 281 return -ENOMEM; 282 283 snd->vdev = vdev; 284 INIT_LIST_HEAD(&snd->ctl_msgs); 285 INIT_LIST_HEAD(&snd->pcm_list); 286 287 vdev->priv = snd; 288 289 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i) 290 spin_lock_init(&snd->queues[i].lock); 291 292 rc = virtsnd_find_vqs(snd); 293 if (rc) 294 goto on_exit; 295 296 virtio_device_ready(vdev); 297 298 rc = virtsnd_build_devs(snd); 299 if (rc) 300 goto on_exit; 301 302 virtsnd_enable_event_vq(snd); 303 304 on_exit: 305 if (rc) 306 virtsnd_remove(vdev); 307 308 return rc; 309 } 310 311 /** 312 * virtsnd_remove() - Remove VirtIO and ALSA devices. 313 * @vdev: VirtIO parent device. 314 * 315 * Context: Any context that permits to sleep. 316 */ 317 static void virtsnd_remove(struct virtio_device *vdev) 318 { 319 struct virtio_snd *snd = vdev->priv; 320 unsigned int i; 321 322 virtsnd_disable_event_vq(snd); 323 virtsnd_ctl_msg_cancel_all(snd); 324 325 if (snd->card) 326 snd_card_free(snd->card); 327 328 vdev->config->del_vqs(vdev); 329 vdev->config->reset(vdev); 330 331 for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) { 332 struct virtio_pcm_substream *vss = &snd->substreams[i]; 333 334 cancel_work_sync(&vss->elapsed_period); 335 virtsnd_pcm_msg_free(vss); 336 } 337 338 kfree(snd->event_msgs); 339 } 340 341 static const struct virtio_device_id id_table[] = { 342 { VIRTIO_ID_SOUND, VIRTIO_DEV_ANY_ID }, 343 { 0 }, 344 }; 345 346 static struct virtio_driver virtsnd_driver = { 347 .driver.name = KBUILD_MODNAME, 348 .driver.owner = THIS_MODULE, 349 .id_table = id_table, 350 .validate = virtsnd_validate, 351 .probe = virtsnd_probe, 352 .remove = virtsnd_remove, 353 }; 354 355 static int __init init(void) 356 { 357 return register_virtio_driver(&virtsnd_driver); 358 } 359 module_init(init); 360 361 static void __exit fini(void) 362 { 363 unregister_virtio_driver(&virtsnd_driver); 364 } 365 module_exit(fini); 366 367 MODULE_DEVICE_TABLE(virtio, id_table); 368 MODULE_DESCRIPTION("Virtio sound card driver"); 369 MODULE_LICENSE("GPL"); 370