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 } 59 60 /** 61 * virtsnd_event_notify_cb() - Dispatch all reported events from the event queue. 62 * @vqueue: Underlying event virtqueue. 63 * 64 * This callback function is called upon a vring interrupt request from the 65 * device. 66 * 67 * Context: Interrupt context. 68 */ 69 static void virtsnd_event_notify_cb(struct virtqueue *vqueue) 70 { 71 struct virtio_snd *snd = vqueue->vdev->priv; 72 struct virtio_snd_queue *queue = virtsnd_event_queue(snd); 73 struct virtio_snd_event *event; 74 u32 length; 75 unsigned long flags; 76 77 spin_lock_irqsave(&queue->lock, flags); 78 do { 79 virtqueue_disable_cb(vqueue); 80 while ((event = virtqueue_get_buf(vqueue, &length))) { 81 virtsnd_event_dispatch(snd, event); 82 virtsnd_event_send(vqueue, event, true, GFP_ATOMIC); 83 } 84 if (unlikely(virtqueue_is_broken(vqueue))) 85 break; 86 } while (!virtqueue_enable_cb(vqueue)); 87 spin_unlock_irqrestore(&queue->lock, flags); 88 } 89 90 /** 91 * virtsnd_find_vqs() - Enumerate and initialize all virtqueues. 92 * @snd: VirtIO sound device. 93 * 94 * After calling this function, the event queue is disabled. 95 * 96 * Context: Any context. 97 * Return: 0 on success, -errno on failure. 98 */ 99 static int virtsnd_find_vqs(struct virtio_snd *snd) 100 { 101 struct virtio_device *vdev = snd->vdev; 102 static vq_callback_t *callbacks[VIRTIO_SND_VQ_MAX] = { 103 [VIRTIO_SND_VQ_CONTROL] = virtsnd_ctl_notify_cb, 104 [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb 105 }; 106 static const char *names[VIRTIO_SND_VQ_MAX] = { 107 [VIRTIO_SND_VQ_CONTROL] = "virtsnd-ctl", 108 [VIRTIO_SND_VQ_EVENT] = "virtsnd-event" 109 }; 110 struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 }; 111 unsigned int i; 112 unsigned int n; 113 int rc; 114 115 rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, callbacks, names, 116 NULL); 117 if (rc) { 118 dev_err(&vdev->dev, "failed to initialize virtqueues\n"); 119 return rc; 120 } 121 122 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i) 123 snd->queues[i].vqueue = vqs[i]; 124 125 /* Allocate events and populate the event queue */ 126 virtqueue_disable_cb(vqs[VIRTIO_SND_VQ_EVENT]); 127 128 n = virtqueue_get_vring_size(vqs[VIRTIO_SND_VQ_EVENT]); 129 130 snd->event_msgs = kmalloc_array(n, sizeof(*snd->event_msgs), 131 GFP_KERNEL); 132 if (!snd->event_msgs) 133 return -ENOMEM; 134 135 for (i = 0; i < n; ++i) 136 virtsnd_event_send(vqs[VIRTIO_SND_VQ_EVENT], 137 &snd->event_msgs[i], false, GFP_KERNEL); 138 139 return 0; 140 } 141 142 /** 143 * virtsnd_enable_event_vq() - Enable the event virtqueue. 144 * @snd: VirtIO sound device. 145 * 146 * Context: Any context. 147 */ 148 static void virtsnd_enable_event_vq(struct virtio_snd *snd) 149 { 150 struct virtio_snd_queue *queue = virtsnd_event_queue(snd); 151 152 if (!virtqueue_enable_cb(queue->vqueue)) 153 virtsnd_event_notify_cb(queue->vqueue); 154 } 155 156 /** 157 * virtsnd_disable_event_vq() - Disable the event virtqueue. 158 * @snd: VirtIO sound device. 159 * 160 * Context: Any context. 161 */ 162 static void virtsnd_disable_event_vq(struct virtio_snd *snd) 163 { 164 struct virtio_snd_queue *queue = virtsnd_event_queue(snd); 165 struct virtio_snd_event *event; 166 u32 length; 167 unsigned long flags; 168 169 if (queue->vqueue) { 170 spin_lock_irqsave(&queue->lock, flags); 171 virtqueue_disable_cb(queue->vqueue); 172 while ((event = virtqueue_get_buf(queue->vqueue, &length))) 173 virtsnd_event_dispatch(snd, event); 174 spin_unlock_irqrestore(&queue->lock, flags); 175 } 176 } 177 178 /** 179 * virtsnd_build_devs() - Read configuration and build ALSA devices. 180 * @snd: VirtIO sound device. 181 * 182 * Context: Any context that permits to sleep. 183 * Return: 0 on success, -errno on failure. 184 */ 185 static int virtsnd_build_devs(struct virtio_snd *snd) 186 { 187 struct virtio_device *vdev = snd->vdev; 188 struct device *dev = &vdev->dev; 189 int rc; 190 191 rc = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 192 THIS_MODULE, 0, &snd->card); 193 if (rc < 0) 194 return rc; 195 196 snd->card->private_data = snd; 197 198 strscpy(snd->card->driver, VIRTIO_SND_CARD_DRIVER, 199 sizeof(snd->card->driver)); 200 strscpy(snd->card->shortname, VIRTIO_SND_CARD_NAME, 201 sizeof(snd->card->shortname)); 202 if (dev->parent->bus) 203 snprintf(snd->card->longname, sizeof(snd->card->longname), 204 VIRTIO_SND_CARD_NAME " at %s/%s/%s", 205 dev->parent->bus->name, dev_name(dev->parent), 206 dev_name(dev)); 207 else 208 snprintf(snd->card->longname, sizeof(snd->card->longname), 209 VIRTIO_SND_CARD_NAME " at %s/%s", 210 dev_name(dev->parent), dev_name(dev)); 211 212 rc = virtsnd_pcm_parse_cfg(snd); 213 if (rc) 214 return rc; 215 216 if (snd->nsubstreams) { 217 rc = virtsnd_pcm_build_devs(snd); 218 if (rc) 219 return rc; 220 } 221 222 return snd_card_register(snd->card); 223 } 224 225 /** 226 * virtsnd_validate() - Validate if the device can be started. 227 * @vdev: VirtIO parent device. 228 * 229 * Context: Any context. 230 * Return: 0 on success, -EINVAL on failure. 231 */ 232 static int virtsnd_validate(struct virtio_device *vdev) 233 { 234 if (!vdev->config->get) { 235 dev_err(&vdev->dev, "configuration access disabled\n"); 236 return -EINVAL; 237 } 238 239 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { 240 dev_err(&vdev->dev, 241 "device does not comply with spec version 1.x\n"); 242 return -EINVAL; 243 } 244 245 if (!virtsnd_msg_timeout_ms) { 246 dev_err(&vdev->dev, "msg_timeout_ms value cannot be zero\n"); 247 return -EINVAL; 248 } 249 250 if (virtsnd_pcm_validate(vdev)) 251 return -EINVAL; 252 253 return 0; 254 } 255 256 /** 257 * virtsnd_probe() - Create and initialize the device. 258 * @vdev: VirtIO parent device. 259 * 260 * Context: Any context that permits to sleep. 261 * Return: 0 on success, -errno on failure. 262 */ 263 static int virtsnd_probe(struct virtio_device *vdev) 264 { 265 struct virtio_snd *snd; 266 unsigned int i; 267 int rc; 268 269 snd = devm_kzalloc(&vdev->dev, sizeof(*snd), GFP_KERNEL); 270 if (!snd) 271 return -ENOMEM; 272 273 snd->vdev = vdev; 274 INIT_LIST_HEAD(&snd->ctl_msgs); 275 INIT_LIST_HEAD(&snd->pcm_list); 276 277 vdev->priv = snd; 278 279 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i) 280 spin_lock_init(&snd->queues[i].lock); 281 282 rc = virtsnd_find_vqs(snd); 283 if (rc) 284 goto on_exit; 285 286 virtio_device_ready(vdev); 287 288 rc = virtsnd_build_devs(snd); 289 if (rc) 290 goto on_exit; 291 292 virtsnd_enable_event_vq(snd); 293 294 on_exit: 295 if (rc) 296 virtsnd_remove(vdev); 297 298 return rc; 299 } 300 301 /** 302 * virtsnd_remove() - Remove VirtIO and ALSA devices. 303 * @vdev: VirtIO parent device. 304 * 305 * Context: Any context that permits to sleep. 306 */ 307 static void virtsnd_remove(struct virtio_device *vdev) 308 { 309 struct virtio_snd *snd = vdev->priv; 310 unsigned int i; 311 312 virtsnd_disable_event_vq(snd); 313 virtsnd_ctl_msg_cancel_all(snd); 314 315 if (snd->card) 316 snd_card_free(snd->card); 317 318 vdev->config->del_vqs(vdev); 319 vdev->config->reset(vdev); 320 321 for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) 322 cancel_work_sync(&snd->substreams[i].elapsed_period); 323 324 kfree(snd->event_msgs); 325 } 326 327 static const struct virtio_device_id id_table[] = { 328 { VIRTIO_ID_SOUND, VIRTIO_DEV_ANY_ID }, 329 { 0 }, 330 }; 331 332 static struct virtio_driver virtsnd_driver = { 333 .driver.name = KBUILD_MODNAME, 334 .driver.owner = THIS_MODULE, 335 .id_table = id_table, 336 .validate = virtsnd_validate, 337 .probe = virtsnd_probe, 338 .remove = virtsnd_remove, 339 }; 340 341 static int __init init(void) 342 { 343 return register_virtio_driver(&virtsnd_driver); 344 } 345 module_init(init); 346 347 static void __exit fini(void) 348 { 349 unregister_virtio_driver(&virtsnd_driver); 350 } 351 module_exit(fini); 352 353 MODULE_DEVICE_TABLE(virtio, id_table); 354 MODULE_DESCRIPTION("Virtio sound card driver"); 355 MODULE_LICENSE("GPL"); 356