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 return snd_card_register(snd->card); 213 } 214 215 /** 216 * virtsnd_validate() - Validate if the device can be started. 217 * @vdev: VirtIO parent device. 218 * 219 * Context: Any context. 220 * Return: 0 on success, -EINVAL on failure. 221 */ 222 static int virtsnd_validate(struct virtio_device *vdev) 223 { 224 if (!vdev->config->get) { 225 dev_err(&vdev->dev, "configuration access disabled\n"); 226 return -EINVAL; 227 } 228 229 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { 230 dev_err(&vdev->dev, 231 "device does not comply with spec version 1.x\n"); 232 return -EINVAL; 233 } 234 235 if (!virtsnd_msg_timeout_ms) { 236 dev_err(&vdev->dev, "msg_timeout_ms value cannot be zero\n"); 237 return -EINVAL; 238 } 239 240 return 0; 241 } 242 243 /** 244 * virtsnd_probe() - Create and initialize the device. 245 * @vdev: VirtIO parent device. 246 * 247 * Context: Any context that permits to sleep. 248 * Return: 0 on success, -errno on failure. 249 */ 250 static int virtsnd_probe(struct virtio_device *vdev) 251 { 252 struct virtio_snd *snd; 253 unsigned int i; 254 int rc; 255 256 snd = devm_kzalloc(&vdev->dev, sizeof(*snd), GFP_KERNEL); 257 if (!snd) 258 return -ENOMEM; 259 260 snd->vdev = vdev; 261 INIT_LIST_HEAD(&snd->ctl_msgs); 262 263 vdev->priv = snd; 264 265 for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i) 266 spin_lock_init(&snd->queues[i].lock); 267 268 rc = virtsnd_find_vqs(snd); 269 if (rc) 270 goto on_exit; 271 272 virtio_device_ready(vdev); 273 274 rc = virtsnd_build_devs(snd); 275 if (rc) 276 goto on_exit; 277 278 virtsnd_enable_event_vq(snd); 279 280 on_exit: 281 if (rc) 282 virtsnd_remove(vdev); 283 284 return rc; 285 } 286 287 /** 288 * virtsnd_remove() - Remove VirtIO and ALSA devices. 289 * @vdev: VirtIO parent device. 290 * 291 * Context: Any context that permits to sleep. 292 */ 293 static void virtsnd_remove(struct virtio_device *vdev) 294 { 295 struct virtio_snd *snd = vdev->priv; 296 297 virtsnd_disable_event_vq(snd); 298 virtsnd_ctl_msg_cancel_all(snd); 299 300 if (snd->card) 301 snd_card_free(snd->card); 302 303 vdev->config->del_vqs(vdev); 304 vdev->config->reset(vdev); 305 306 kfree(snd->event_msgs); 307 } 308 309 static const struct virtio_device_id id_table[] = { 310 { VIRTIO_ID_SOUND, VIRTIO_DEV_ANY_ID }, 311 { 0 }, 312 }; 313 314 static struct virtio_driver virtsnd_driver = { 315 .driver.name = KBUILD_MODNAME, 316 .driver.owner = THIS_MODULE, 317 .id_table = id_table, 318 .validate = virtsnd_validate, 319 .probe = virtsnd_probe, 320 .remove = virtsnd_remove, 321 }; 322 323 static int __init init(void) 324 { 325 return register_virtio_driver(&virtsnd_driver); 326 } 327 module_init(init); 328 329 static void __exit fini(void) 330 { 331 unregister_virtio_driver(&virtsnd_driver); 332 } 333 module_exit(fini); 334 335 MODULE_DEVICE_TABLE(virtio, id_table); 336 MODULE_DESCRIPTION("Virtio sound card driver"); 337 MODULE_LICENSE("GPL"); 338