Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * virtio-snd: Virtio sound device
0004  * Copyright (C) 2021 OpenSynergy GmbH
0005  */
0006 #include <linux/module.h>
0007 #include <linux/moduleparam.h>
0008 #include <linux/virtio_config.h>
0009 #include <sound/initval.h>
0010 #include <uapi/linux/virtio_ids.h>
0011 
0012 #include "virtio_card.h"
0013 
0014 u32 virtsnd_msg_timeout_ms = MSEC_PER_SEC;
0015 module_param_named(msg_timeout_ms, virtsnd_msg_timeout_ms, uint, 0644);
0016 MODULE_PARM_DESC(msg_timeout_ms, "Message completion timeout in milliseconds");
0017 
0018 static void virtsnd_remove(struct virtio_device *vdev);
0019 
0020 /**
0021  * virtsnd_event_send() - Add an event to the event queue.
0022  * @vqueue: Underlying event virtqueue.
0023  * @event: Event.
0024  * @notify: Indicates whether or not to send a notification to the device.
0025  * @gfp: Kernel flags for memory allocation.
0026  *
0027  * Context: Any context.
0028  */
0029 static void virtsnd_event_send(struct virtqueue *vqueue,
0030                    struct virtio_snd_event *event, bool notify,
0031                    gfp_t gfp)
0032 {
0033     struct scatterlist sg;
0034     struct scatterlist *psgs[1] = { &sg };
0035 
0036     /* reset event content */
0037     memset(event, 0, sizeof(*event));
0038 
0039     sg_init_one(&sg, event, sizeof(*event));
0040 
0041     if (virtqueue_add_sgs(vqueue, psgs, 0, 1, event, gfp) || !notify)
0042         return;
0043 
0044     if (virtqueue_kick_prepare(vqueue))
0045         virtqueue_notify(vqueue);
0046 }
0047 
0048 /**
0049  * virtsnd_event_dispatch() - Dispatch an event from the device side.
0050  * @snd: VirtIO sound device.
0051  * @event: VirtIO sound event.
0052  *
0053  * Context: Any context.
0054  */
0055 static void virtsnd_event_dispatch(struct virtio_snd *snd,
0056                    struct virtio_snd_event *event)
0057 {
0058     switch (le32_to_cpu(event->hdr.code)) {
0059     case VIRTIO_SND_EVT_JACK_CONNECTED:
0060     case VIRTIO_SND_EVT_JACK_DISCONNECTED:
0061         virtsnd_jack_event(snd, event);
0062         break;
0063     case VIRTIO_SND_EVT_PCM_PERIOD_ELAPSED:
0064     case VIRTIO_SND_EVT_PCM_XRUN:
0065         virtsnd_pcm_event(snd, event);
0066         break;
0067     }
0068 }
0069 
0070 /**
0071  * virtsnd_event_notify_cb() - Dispatch all reported events from the event queue.
0072  * @vqueue: Underlying event virtqueue.
0073  *
0074  * This callback function is called upon a vring interrupt request from the
0075  * device.
0076  *
0077  * Context: Interrupt context.
0078  */
0079 static void virtsnd_event_notify_cb(struct virtqueue *vqueue)
0080 {
0081     struct virtio_snd *snd = vqueue->vdev->priv;
0082     struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
0083     struct virtio_snd_event *event;
0084     u32 length;
0085     unsigned long flags;
0086 
0087     spin_lock_irqsave(&queue->lock, flags);
0088     do {
0089         virtqueue_disable_cb(vqueue);
0090         while ((event = virtqueue_get_buf(vqueue, &length))) {
0091             virtsnd_event_dispatch(snd, event);
0092             virtsnd_event_send(vqueue, event, true, GFP_ATOMIC);
0093         }
0094         if (unlikely(virtqueue_is_broken(vqueue)))
0095             break;
0096     } while (!virtqueue_enable_cb(vqueue));
0097     spin_unlock_irqrestore(&queue->lock, flags);
0098 }
0099 
0100 /**
0101  * virtsnd_find_vqs() - Enumerate and initialize all virtqueues.
0102  * @snd: VirtIO sound device.
0103  *
0104  * After calling this function, the event queue is disabled.
0105  *
0106  * Context: Any context.
0107  * Return: 0 on success, -errno on failure.
0108  */
0109 static int virtsnd_find_vqs(struct virtio_snd *snd)
0110 {
0111     struct virtio_device *vdev = snd->vdev;
0112     static vq_callback_t *callbacks[VIRTIO_SND_VQ_MAX] = {
0113         [VIRTIO_SND_VQ_CONTROL] = virtsnd_ctl_notify_cb,
0114         [VIRTIO_SND_VQ_EVENT] = virtsnd_event_notify_cb,
0115         [VIRTIO_SND_VQ_TX] = virtsnd_pcm_tx_notify_cb,
0116         [VIRTIO_SND_VQ_RX] = virtsnd_pcm_rx_notify_cb
0117     };
0118     static const char *names[VIRTIO_SND_VQ_MAX] = {
0119         [VIRTIO_SND_VQ_CONTROL] = "virtsnd-ctl",
0120         [VIRTIO_SND_VQ_EVENT] = "virtsnd-event",
0121         [VIRTIO_SND_VQ_TX] = "virtsnd-tx",
0122         [VIRTIO_SND_VQ_RX] = "virtsnd-rx"
0123     };
0124     struct virtqueue *vqs[VIRTIO_SND_VQ_MAX] = { 0 };
0125     unsigned int i;
0126     unsigned int n;
0127     int rc;
0128 
0129     rc = virtio_find_vqs(vdev, VIRTIO_SND_VQ_MAX, vqs, callbacks, names,
0130                  NULL);
0131     if (rc) {
0132         dev_err(&vdev->dev, "failed to initialize virtqueues\n");
0133         return rc;
0134     }
0135 
0136     for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i)
0137         snd->queues[i].vqueue = vqs[i];
0138 
0139     /* Allocate events and populate the event queue */
0140     virtqueue_disable_cb(vqs[VIRTIO_SND_VQ_EVENT]);
0141 
0142     n = virtqueue_get_vring_size(vqs[VIRTIO_SND_VQ_EVENT]);
0143 
0144     snd->event_msgs = kmalloc_array(n, sizeof(*snd->event_msgs),
0145                     GFP_KERNEL);
0146     if (!snd->event_msgs)
0147         return -ENOMEM;
0148 
0149     for (i = 0; i < n; ++i)
0150         virtsnd_event_send(vqs[VIRTIO_SND_VQ_EVENT],
0151                    &snd->event_msgs[i], false, GFP_KERNEL);
0152 
0153     return 0;
0154 }
0155 
0156 /**
0157  * virtsnd_enable_event_vq() - Enable the event virtqueue.
0158  * @snd: VirtIO sound device.
0159  *
0160  * Context: Any context.
0161  */
0162 static void virtsnd_enable_event_vq(struct virtio_snd *snd)
0163 {
0164     struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
0165 
0166     if (!virtqueue_enable_cb(queue->vqueue))
0167         virtsnd_event_notify_cb(queue->vqueue);
0168 }
0169 
0170 /**
0171  * virtsnd_disable_event_vq() - Disable the event virtqueue.
0172  * @snd: VirtIO sound device.
0173  *
0174  * Context: Any context.
0175  */
0176 static void virtsnd_disable_event_vq(struct virtio_snd *snd)
0177 {
0178     struct virtio_snd_queue *queue = virtsnd_event_queue(snd);
0179     struct virtio_snd_event *event;
0180     u32 length;
0181     unsigned long flags;
0182 
0183     if (queue->vqueue) {
0184         spin_lock_irqsave(&queue->lock, flags);
0185         virtqueue_disable_cb(queue->vqueue);
0186         while ((event = virtqueue_get_buf(queue->vqueue, &length)))
0187             virtsnd_event_dispatch(snd, event);
0188         spin_unlock_irqrestore(&queue->lock, flags);
0189     }
0190 }
0191 
0192 /**
0193  * virtsnd_build_devs() - Read configuration and build ALSA devices.
0194  * @snd: VirtIO sound device.
0195  *
0196  * Context: Any context that permits to sleep.
0197  * Return: 0 on success, -errno on failure.
0198  */
0199 static int virtsnd_build_devs(struct virtio_snd *snd)
0200 {
0201     struct virtio_device *vdev = snd->vdev;
0202     struct device *dev = &vdev->dev;
0203     int rc;
0204 
0205     rc = snd_card_new(dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
0206               THIS_MODULE, 0, &snd->card);
0207     if (rc < 0)
0208         return rc;
0209 
0210     snd->card->private_data = snd;
0211 
0212     strscpy(snd->card->driver, VIRTIO_SND_CARD_DRIVER,
0213         sizeof(snd->card->driver));
0214     strscpy(snd->card->shortname, VIRTIO_SND_CARD_NAME,
0215         sizeof(snd->card->shortname));
0216     if (dev->parent->bus)
0217         snprintf(snd->card->longname, sizeof(snd->card->longname),
0218              VIRTIO_SND_CARD_NAME " at %s/%s/%s",
0219              dev->parent->bus->name, dev_name(dev->parent),
0220              dev_name(dev));
0221     else
0222         snprintf(snd->card->longname, sizeof(snd->card->longname),
0223              VIRTIO_SND_CARD_NAME " at %s/%s",
0224              dev_name(dev->parent), dev_name(dev));
0225 
0226     rc = virtsnd_jack_parse_cfg(snd);
0227     if (rc)
0228         return rc;
0229 
0230     rc = virtsnd_pcm_parse_cfg(snd);
0231     if (rc)
0232         return rc;
0233 
0234     rc = virtsnd_chmap_parse_cfg(snd);
0235     if (rc)
0236         return rc;
0237 
0238     if (snd->njacks) {
0239         rc = virtsnd_jack_build_devs(snd);
0240         if (rc)
0241             return rc;
0242     }
0243 
0244     if (snd->nsubstreams) {
0245         rc = virtsnd_pcm_build_devs(snd);
0246         if (rc)
0247             return rc;
0248     }
0249 
0250     if (snd->nchmaps) {
0251         rc = virtsnd_chmap_build_devs(snd);
0252         if (rc)
0253             return rc;
0254     }
0255 
0256     return snd_card_register(snd->card);
0257 }
0258 
0259 /**
0260  * virtsnd_validate() - Validate if the device can be started.
0261  * @vdev: VirtIO parent device.
0262  *
0263  * Context: Any context.
0264  * Return: 0 on success, -EINVAL on failure.
0265  */
0266 static int virtsnd_validate(struct virtio_device *vdev)
0267 {
0268     if (!vdev->config->get) {
0269         dev_err(&vdev->dev, "configuration access disabled\n");
0270         return -EINVAL;
0271     }
0272 
0273     if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) {
0274         dev_err(&vdev->dev,
0275             "device does not comply with spec version 1.x\n");
0276         return -EINVAL;
0277     }
0278 
0279     if (!virtsnd_msg_timeout_ms) {
0280         dev_err(&vdev->dev, "msg_timeout_ms value cannot be zero\n");
0281         return -EINVAL;
0282     }
0283 
0284     if (virtsnd_pcm_validate(vdev))
0285         return -EINVAL;
0286 
0287     return 0;
0288 }
0289 
0290 /**
0291  * virtsnd_probe() - Create and initialize the device.
0292  * @vdev: VirtIO parent device.
0293  *
0294  * Context: Any context that permits to sleep.
0295  * Return: 0 on success, -errno on failure.
0296  */
0297 static int virtsnd_probe(struct virtio_device *vdev)
0298 {
0299     struct virtio_snd *snd;
0300     unsigned int i;
0301     int rc;
0302 
0303     snd = devm_kzalloc(&vdev->dev, sizeof(*snd), GFP_KERNEL);
0304     if (!snd)
0305         return -ENOMEM;
0306 
0307     snd->vdev = vdev;
0308     INIT_LIST_HEAD(&snd->ctl_msgs);
0309     INIT_LIST_HEAD(&snd->pcm_list);
0310 
0311     vdev->priv = snd;
0312 
0313     for (i = 0; i < VIRTIO_SND_VQ_MAX; ++i)
0314         spin_lock_init(&snd->queues[i].lock);
0315 
0316     rc = virtsnd_find_vqs(snd);
0317     if (rc)
0318         goto on_exit;
0319 
0320     virtio_device_ready(vdev);
0321 
0322     rc = virtsnd_build_devs(snd);
0323     if (rc)
0324         goto on_exit;
0325 
0326     virtsnd_enable_event_vq(snd);
0327 
0328 on_exit:
0329     if (rc)
0330         virtsnd_remove(vdev);
0331 
0332     return rc;
0333 }
0334 
0335 /**
0336  * virtsnd_remove() - Remove VirtIO and ALSA devices.
0337  * @vdev: VirtIO parent device.
0338  *
0339  * Context: Any context that permits to sleep.
0340  */
0341 static void virtsnd_remove(struct virtio_device *vdev)
0342 {
0343     struct virtio_snd *snd = vdev->priv;
0344     unsigned int i;
0345 
0346     virtsnd_disable_event_vq(snd);
0347     virtsnd_ctl_msg_cancel_all(snd);
0348 
0349     if (snd->card)
0350         snd_card_free(snd->card);
0351 
0352     vdev->config->del_vqs(vdev);
0353     virtio_reset_device(vdev);
0354 
0355     for (i = 0; snd->substreams && i < snd->nsubstreams; ++i) {
0356         struct virtio_pcm_substream *vss = &snd->substreams[i];
0357 
0358         cancel_work_sync(&vss->elapsed_period);
0359         virtsnd_pcm_msg_free(vss);
0360     }
0361 
0362     kfree(snd->event_msgs);
0363 }
0364 
0365 #ifdef CONFIG_PM_SLEEP
0366 /**
0367  * virtsnd_freeze() - Suspend device.
0368  * @vdev: VirtIO parent device.
0369  *
0370  * Context: Any context.
0371  * Return: 0 on success, -errno on failure.
0372  */
0373 static int virtsnd_freeze(struct virtio_device *vdev)
0374 {
0375     struct virtio_snd *snd = vdev->priv;
0376     unsigned int i;
0377 
0378     virtsnd_disable_event_vq(snd);
0379     virtsnd_ctl_msg_cancel_all(snd);
0380 
0381     vdev->config->del_vqs(vdev);
0382     virtio_reset_device(vdev);
0383 
0384     for (i = 0; i < snd->nsubstreams; ++i)
0385         cancel_work_sync(&snd->substreams[i].elapsed_period);
0386 
0387     kfree(snd->event_msgs);
0388     snd->event_msgs = NULL;
0389 
0390     return 0;
0391 }
0392 
0393 /**
0394  * virtsnd_restore() - Resume device.
0395  * @vdev: VirtIO parent device.
0396  *
0397  * Context: Any context.
0398  * Return: 0 on success, -errno on failure.
0399  */
0400 static int virtsnd_restore(struct virtio_device *vdev)
0401 {
0402     struct virtio_snd *snd = vdev->priv;
0403     int rc;
0404 
0405     rc = virtsnd_find_vqs(snd);
0406     if (rc)
0407         return rc;
0408 
0409     virtio_device_ready(vdev);
0410 
0411     virtsnd_enable_event_vq(snd);
0412 
0413     return 0;
0414 }
0415 #endif /* CONFIG_PM_SLEEP */
0416 
0417 static const struct virtio_device_id id_table[] = {
0418     { VIRTIO_ID_SOUND, VIRTIO_DEV_ANY_ID },
0419     { 0 },
0420 };
0421 
0422 static struct virtio_driver virtsnd_driver = {
0423     .driver.name = KBUILD_MODNAME,
0424     .driver.owner = THIS_MODULE,
0425     .id_table = id_table,
0426     .validate = virtsnd_validate,
0427     .probe = virtsnd_probe,
0428     .remove = virtsnd_remove,
0429 #ifdef CONFIG_PM_SLEEP
0430     .freeze = virtsnd_freeze,
0431     .restore = virtsnd_restore,
0432 #endif
0433 };
0434 
0435 module_virtio_driver(virtsnd_driver);
0436 
0437 MODULE_DEVICE_TABLE(virtio, id_table);
0438 MODULE_DESCRIPTION("Virtio sound card driver");
0439 MODULE_LICENSE("GPL");