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