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 */
virtsnd_event_send(struct virtqueue * vqueue,struct virtio_snd_event * event,bool notify,gfp_t gfp)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 */
virtsnd_event_dispatch(struct virtio_snd * snd,struct virtio_snd_event * event)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_JACK_CONNECTED:
60 case VIRTIO_SND_EVT_JACK_DISCONNECTED:
61 virtsnd_jack_event(snd, event);
62 break;
63 case VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED:
64 case VIRTIO_SND_EVT_PCM_XRUN:
65 virtsnd_pcm_event(snd, event);
66 break;
67 case VIRTIO_SND_EVT_CTL_NOTIFY:
68 virtsnd_kctl_event(snd, event);
69 break;
70 }
71 }
72
73 /**
74 * virtsnd_event_notify_cb() - Dispatch all reported events from the event queue.
75 * @vqueue: Underlying event virtqueue.
76 *
77 * This callback function is called upon a vring interrupt request from the
78 * device.
79 *
80 * Context: Interrupt context.
81 */
virtsnd_event_notify_cb(struct virtqueue * vqueue)82 static void virtsnd_event_notify_cb(struct virtqueue *vqueue)
83 {
84 struct virtio_snd *snd = vqueue->vdev->priv;
85 struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
86 struct virtio_snd_event *event;
87 u32 length;
88
89 guard(spinlock_irqsave)(&queue->lock);
90 do {
91 virtqueue_disable_cb(vqueue);
92 while ((event = virtqueue_get_buf(vqueue, &length))) {
93 virtsnd_event_dispatch(snd, event);
94 virtsnd_event_send(vqueue, event, true, GFP_ATOMIC);
95 }
96 } while (!virtqueue_enable_cb(vqueue));
97 }
98
99 /**
100 * virtsnd_find_vqs() - Enumerate and initialize all virtqueues.
101 * @snd: VirtIO sound device.
102 *
103 * After calling this function, the event queue is disabled.
104 *
105 * Context: Any context.
106 * Return: 0 on success, -errno on failure.
107 */
virtsnd_find_vqs(struct virtio_snd * snd)108 static int virtsnd_find_vqs(struct virtio_snd *snd)
109 {
110 struct virtio_device *vdev = snd->vdev;
111 struct virtqueue_info vqs_info[VIRTIO_SND_VQ_MAX] = {
112 [VIRTIO_SND_VQ_CONTROL] = { "virtsnd-ctl",
113 virtsnd_ctl_notify_cb },
114 [VIRTIO_SND_VQ_EVENT] = { "virtsnd-event",
115 virtsnd_event_notify_cb },
116 [VIRTIO_SND_VQ_TX] = { "virtsnd-tx",
117 virtsnd_pcm_tx_notify_cb },
118 [VIRTIO_SND_VQ_RX] = { "virtsnd-rx",
119 virtsnd_pcm_rx_notify_cb },
120 };
121 struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 };
122 unsigned int i;
123 unsigned int n;
124 int rc;
125
126 rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, vqs_info, 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_objs(*snd->event_msgs, n);
141 if (!snd->event_msgs)
142 return -ENOMEM;
143
144 for (i = 0; i < n; ++i)
145 virtsnd_event_send(vqs[VIRTIO_SND_VQ_EVENT],
146 &snd->event_msgs[i], false, GFP_KERNEL);
147
148 return 0;
149 }
150
151 /**
152 * virtsnd_enable_event_vq() - Enable the event virtqueue.
153 * @snd: VirtIO sound device.
154 *
155 * Context: Any context.
156 */
virtsnd_enable_event_vq(struct virtio_snd * snd)157 static void virtsnd_enable_event_vq(struct virtio_snd *snd)
158 {
159 struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
160
161 if (!virtqueue_enable_cb(queue->vqueue))
162 virtsnd_event_notify_cb(queue->vqueue);
163 }
164
165 /**
166 * virtsnd_disable_event_vq() - Disable the event virtqueue.
167 * @snd: VirtIO sound device.
168 *
169 * Context: Any context.
170 */
virtsnd_disable_event_vq(struct virtio_snd * snd)171 static void virtsnd_disable_event_vq(struct virtio_snd *snd)
172 {
173 struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
174 struct virtio_snd_event *event;
175 u32 length;
176
177 if (queue->vqueue) {
178 guard(spinlock_irqsave)(&queue->lock);
179 virtqueue_disable_cb(queue->vqueue);
180 while ((event = virtqueue_get_buf(queue->vqueue, &length)))
181 virtsnd_event_dispatch(snd, event);
182 }
183 }
184
185 /**
186 * virtsnd_build_devs() - Read configuration and build ALSA devices.
187 * @snd: VirtIO sound device.
188 *
189 * Context: Any context that permits to sleep.
190 * Return: 0 on success, -errno on failure.
191 */
virtsnd_build_devs(struct virtio_snd * snd)192 static int virtsnd_build_devs(struct virtio_snd *snd)
193 {
194 struct virtio_device *vdev = snd->vdev;
195 struct device *dev = &vdev->dev;
196 int rc;
197
198 rc = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
199 THIS_MODULE, 0, &snd->card);
200 if (rc < 0)
201 return rc;
202
203 snd->card->private_data = snd;
204
205 strscpy(snd->card->driver, VIRTIO_SND_CARD_DRIVER,
206 sizeof(snd->card->driver));
207 strscpy(snd->card->shortname, VIRTIO_SND_CARD_NAME,
208 sizeof(snd->card->shortname));
209 if (dev->parent->bus)
210 snprintf(snd->card->longname, sizeof(snd->card->longname),
211 VIRTIO_SND_CARD_NAME " at %s/%s/%s",
212 dev->parent->bus->name, dev_name(dev->parent),
213 dev_name(dev));
214 else
215 snprintf(snd->card->longname, sizeof(snd->card->longname),
216 VIRTIO_SND_CARD_NAME " at %s/%s",
217 dev_name(dev->parent), dev_name(dev));
218
219 rc = virtsnd_jack_parse_cfg(snd);
220 if (rc)
221 return rc;
222
223 rc = virtsnd_pcm_parse_cfg(snd);
224 if (rc)
225 return rc;
226
227 rc = virtsnd_chmap_parse_cfg(snd);
228 if (rc)
229 return rc;
230
231 if (virtio_has_feature(vdev, VIRTIO_SND_F_CTLS)) {
232 rc = virtsnd_kctl_parse_cfg(snd);
233 if (rc)
234 return rc;
235 }
236
237 if (snd->njacks) {
238 rc = virtsnd_jack_build_devs(snd);
239 if (rc)
240 return rc;
241 }
242
243 if (snd->nsubstreams) {
244 rc = virtsnd_pcm_build_devs(snd);
245 if (rc)
246 return rc;
247 }
248
249 if (snd->nchmaps) {
250 rc = virtsnd_chmap_build_devs(snd);
251 if (rc)
252 return rc;
253 }
254
255 if (snd->nkctls) {
256 rc = virtsnd_kctl_build_devs(snd);
257 if (rc)
258 return rc;
259 }
260
261 return snd_card_register(snd->card);
262 }
263
264 /**
265 * virtsnd_validate() - Validate if the device can be started.
266 * @vdev: VirtIO parent device.
267 *
268 * Context: Any context.
269 * Return: 0 on success, -EINVAL on failure.
270 */
virtsnd_validate(struct virtio_device * vdev)271 static int virtsnd_validate(struct virtio_device *vdev)
272 {
273 if (!vdev->config->get) {
274 dev_err(&vdev->dev, "configuration access disabled\n");
275 return -EINVAL;
276 }
277
278 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
279 dev_err(&vdev->dev,
280 "device does not comply with spec version 1.x\n");
281 return -EINVAL;
282 }
283
284 if (!virtsnd_msg_timeout_ms) {
285 dev_err(&vdev->dev, "msg_timeout_ms value cannot be zero\n");
286 return -EINVAL;
287 }
288
289 if (virtsnd_pcm_validate(vdev))
290 return -EINVAL;
291
292 return 0;
293 }
294
295 /**
296 * virtsnd_probe() - Create and initialize the device.
297 * @vdev: VirtIO parent device.
298 *
299 * Context: Any context that permits to sleep.
300 * Return: 0 on success, -errno on failure.
301 */
virtsnd_probe(struct virtio_device * vdev)302 static int virtsnd_probe(struct virtio_device *vdev)
303 {
304 struct virtio_snd *snd;
305 unsigned int i;
306 int rc;
307
308 snd = devm_kzalloc(&vdev->dev, sizeof(*snd), GFP_KERNEL);
309 if (!snd)
310 return -ENOMEM;
311
312 snd->vdev = vdev;
313 INIT_LIST_HEAD(&snd->ctl_msgs);
314 INIT_LIST_HEAD(&snd->pcm_list);
315
316 vdev->priv = snd;
317
318 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i)
319 spin_lock_init(&snd->queues[i].lock);
320
321 rc = virtsnd_find_vqs(snd);
322 if (rc)
323 goto on_exit;
324
325 virtio_device_ready(vdev);
326
327 rc = virtsnd_build_devs(snd);
328 if (rc)
329 goto on_exit;
330
331 virtsnd_enable_event_vq(snd);
332
333 on_exit:
334 if (rc)
335 virtsnd_remove(vdev);
336
337 return rc;
338 }
339
340 /**
341 * virtsnd_remove() - Remove VirtIO and ALSA devices.
342 * @vdev: VirtIO parent device.
343 *
344 * Context: Any context that permits to sleep.
345 */
virtsnd_remove(struct virtio_device * vdev)346 static void virtsnd_remove(struct virtio_device *vdev)
347 {
348 struct virtio_snd *snd = vdev->priv;
349 unsigned int i;
350
351 virtsnd_disable_event_vq(snd);
352 virtsnd_ctl_msg_cancel_all(snd);
353
354 if (snd->card)
355 snd_card_free(snd->card);
356
357 vdev->config->del_vqs(vdev);
358 virtio_reset_device(vdev);
359
360 for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) {
361 struct virtio_pcm_substream *vss = &snd->substreams[i];
362
363 cancel_work_sync(&vss->elapsed_period);
364 virtsnd_pcm_msg_free(vss);
365 }
366
367 kfree(snd->event_msgs);
368 }
369
370 #ifdef CONFIG_PM_SLEEP
371 /**
372 * virtsnd_freeze() - Suspend device.
373 * @vdev: VirtIO parent device.
374 *
375 * Context: Any context.
376 * Return: 0 on success, -errno on failure.
377 */
virtsnd_freeze(struct virtio_device * vdev)378 static int virtsnd_freeze(struct virtio_device *vdev)
379 {
380 struct virtio_snd *snd = vdev->priv;
381 unsigned int i;
382
383 virtsnd_disable_event_vq(snd);
384 virtsnd_ctl_msg_cancel_all(snd);
385
386 vdev->config->del_vqs(vdev);
387 virtio_reset_device(vdev);
388
389 for (i = 0; i < snd->nsubstreams; ++i)
390 cancel_work_sync(&snd->substreams[i].elapsed_period);
391
392 kfree(snd->event_msgs);
393 snd->event_msgs = NULL;
394
395 return 0;
396 }
397
398 /**
399 * virtsnd_restore() - Resume device.
400 * @vdev: VirtIO parent device.
401 *
402 * Context: Any context.
403 * Return: 0 on success, -errno on failure.
404 */
virtsnd_restore(struct virtio_device * vdev)405 static int virtsnd_restore(struct virtio_device *vdev)
406 {
407 struct virtio_snd *snd = vdev->priv;
408 int rc;
409
410 rc = virtsnd_find_vqs(snd);
411 if (rc)
412 return rc;
413
414 virtio_device_ready(vdev);
415
416 virtsnd_enable_event_vq(snd);
417
418 return 0;
419 }
420 #endif /* CONFIG_PM_SLEEP */
421
422 static const struct virtio_device_id id_table[] = {
423 { VIRTIO_ID_SOUND, VIRTIO_DEV_ANY_ID },
424 { 0 },
425 };
426
427 static unsigned int features[] = {
428 VIRTIO_SND_F_CTLS
429 };
430
431 static struct virtio_driver virtsnd_driver = {
432 .driver.name = KBUILD_MODNAME,
433 .id_table = id_table,
434 .feature_table = features,
435 .feature_table_size = ARRAY_SIZE(features),
436 .validate = virtsnd_validate,
437 .probe = virtsnd_probe,
438 .remove = virtsnd_remove,
439 #ifdef CONFIG_PM_SLEEP
440 .freeze = virtsnd_freeze,
441 .restore = virtsnd_restore,
442 #endif
443 };
444
445 module_virtio_driver(virtsnd_driver);
446
447 MODULE_DEVICE_TABLE(virtio, id_table);
448 MODULE_DESCRIPTION("Virtio sound card driver");
449 MODULE_LICENSE("GPL");
450