brintos

brintos / linux-shallow public Read only

0
0
Text · 6.0 KiB · e5de6f5 Raw
197 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3.. _writing_virtio_drivers:4 5======================6Writing Virtio Drivers7======================8 9Introduction10============11 12This document serves as a basic guideline for driver programmers that13need to hack a new virtio driver or understand the essentials of the14existing ones. See :ref:`Virtio on Linux <virtio>` for a general15overview of virtio.16 17 18Driver boilerplate19==================20 21As a bare minimum, a virtio driver needs to register in the virtio bus22and configure the virtqueues for the device according to its spec, the23configuration of the virtqueues in the driver side must match the24virtqueue definitions in the device. A basic driver skeleton could look25like this::26 27	#include <linux/virtio.h>28	#include <linux/virtio_ids.h>29	#include <linux/virtio_config.h>30	#include <linux/module.h>31 32	/* device private data (one per device) */33	struct virtio_dummy_dev {34		struct virtqueue *vq;35	};36 37	static void virtio_dummy_recv_cb(struct virtqueue *vq)38	{39		struct virtio_dummy_dev *dev = vq->vdev->priv;40		char *buf;41		unsigned int len;42 43		while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) {44			/* process the received data */45		}46	}47 48	static int virtio_dummy_probe(struct virtio_device *vdev)49	{50		struct virtio_dummy_dev *dev = NULL;51 52		/* initialize device data */53		dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL);54		if (!dev)55			return -ENOMEM;56 57		/* the device has a single virtqueue */58		dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, "input");59		if (IS_ERR(dev->vq)) {60			kfree(dev);61			return PTR_ERR(dev->vq);62 63		}64		vdev->priv = dev;65 66		/* from this point on, the device can notify and get callbacks */67		virtio_device_ready(vdev);68 69		return 0;70	}71 72	static void virtio_dummy_remove(struct virtio_device *vdev)73	{74		struct virtio_dummy_dev *dev = vdev->priv;75 76		/*77		 * disable vq interrupts: equivalent to78		 * vdev->config->reset(vdev)79		 */80		virtio_reset_device(vdev);81 82		/* detach unused buffers */83		while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) {84			kfree(buf);85		}86 87		/* remove virtqueues */88		vdev->config->del_vqs(vdev);89 90		kfree(dev);91	}92 93	static const struct virtio_device_id id_table[] = {94		{ VIRTIO_ID_DUMMY, VIRTIO_DEV_ANY_ID },95		{ 0 },96	};97 98	static struct virtio_driver virtio_dummy_driver = {99		.driver.name =  KBUILD_MODNAME,100		.id_table =     id_table,101		.probe =        virtio_dummy_probe,102		.remove =       virtio_dummy_remove,103	};104 105	module_virtio_driver(virtio_dummy_driver);106	MODULE_DEVICE_TABLE(virtio, id_table);107	MODULE_DESCRIPTION("Dummy virtio driver");108	MODULE_LICENSE("GPL");109 110The device id ``VIRTIO_ID_DUMMY`` here is a placeholder, virtio drivers111should be added only for devices that are defined in the spec, see112include/uapi/linux/virtio_ids.h. Device ids need to be at least reserved113in the virtio spec before being added to that file.114 115If your driver doesn't have to do anything special in its ``init`` and116``exit`` methods, you can use the module_virtio_driver() helper to117reduce the amount of boilerplate code.118 119The ``probe`` method does the minimum driver setup in this case120(memory allocation for the device data) and initializes the121virtqueue. virtio_device_ready() is used to enable the virtqueue and to122notify the device that the driver is ready to manage the device123("DRIVER_OK"). The virtqueues are anyway enabled automatically by the124core after ``probe`` returns.125 126.. kernel-doc:: include/linux/virtio_config.h127    :identifiers: virtio_device_ready128 129In any case, the virtqueues need to be enabled before adding buffers to130them.131 132Sending and receiving data133==========================134 135The virtio_dummy_recv_cb() callback in the code above will be triggered136when the device notifies the driver after it finishes processing a137descriptor or descriptor chain, either for reading or writing. However,138that's only the second half of the virtio device-driver communication139process, as the communication is always started by the driver regardless140of the direction of the data transfer.141 142To configure a buffer transfer from the driver to the device, first you143have to add the buffers -- packed as `scatterlists` -- to the144appropriate virtqueue using any of the virtqueue_add_inbuf(),145virtqueue_add_outbuf() or virtqueue_add_sgs(), depending on whether you146need to add one input `scatterlist` (for the device to fill in), one147output `scatterlist` (for the device to consume) or multiple148`scatterlists`, respectively. Then, once the virtqueue is set up, a call149to virtqueue_kick() sends a notification that will be serviced by the150hypervisor that implements the device::151 152	struct scatterlist sg[1];153	sg_init_one(sg, buffer, BUFLEN);154	virtqueue_add_inbuf(dev->vq, sg, 1, buffer, GFP_ATOMIC);155	virtqueue_kick(dev->vq);156 157.. kernel-doc:: drivers/virtio/virtio_ring.c158    :identifiers: virtqueue_add_inbuf159 160.. kernel-doc:: drivers/virtio/virtio_ring.c161    :identifiers: virtqueue_add_outbuf162 163.. kernel-doc:: drivers/virtio/virtio_ring.c164    :identifiers: virtqueue_add_sgs165 166Then, after the device has read or written the buffers prepared by the167driver and notifies it back, the driver can call virtqueue_get_buf() to168read the data produced by the device (if the virtqueue was set up with169input buffers) or simply to reclaim the buffers if they were already170consumed by the device:171 172.. kernel-doc:: drivers/virtio/virtio_ring.c173    :identifiers: virtqueue_get_buf_ctx174 175The virtqueue callbacks can be disabled and re-enabled using the176virtqueue_disable_cb() and the family of virtqueue_enable_cb() functions177respectively. See drivers/virtio/virtio_ring.c for more details:178 179.. kernel-doc:: drivers/virtio/virtio_ring.c180    :identifiers: virtqueue_disable_cb181 182.. kernel-doc:: drivers/virtio/virtio_ring.c183    :identifiers: virtqueue_enable_cb184 185But note that some spurious callbacks can still be triggered under186certain scenarios. The way to disable callbacks reliably is to reset the187device or the virtqueue (virtio_reset_device()).188 189 190References191==========192 193_`[1]` Virtio Spec v1.2:194https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html195 196Check for later versions of the spec as well.197