xref: /linux/sound/virtio/virtio_card.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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