sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget` for a general overview of virtio.h](hThis document serves as a basic guideline for driver programmers that need to hack a new virtio driver or understand the essentials of the existing ones. See }(hhhhhNhNubh)}(h:ref:`Virtio on Linux `h]hinline)}(hjh]hVirtio on Linux}(hj hhhNhNubah}(h]h ](xrefstdstd-refeh"]h$]h&]uh1j hjubah}(h]h ]h"]h$]h&]refdoc(driver-api/virtio/writing_virtio_drivers refdomainjreftyperef refexplicitrefwarn reftargetvirtiouh1hhhhK hhubh" for a general overview of virtio.}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hhhhubeh}(h] introductionah ]h"] introductionah$]h&]uh1hhhhhhhhK ubh)}(hhh](h)}(hDriver boilerplateh]hDriver boilerplate}(hj@hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj=hhhhhKubh)}(hX#As a bare minimum, a virtio driver needs to register in the virtio bus and configure the virtqueues for the device according to its spec, the configuration of the virtqueues in the driver side must match the virtqueue definitions in the device. A basic driver skeleton could look like this::h]hX"As a bare minimum, a virtio driver needs to register in the virtio bus and configure the virtqueues for the device according to its spec, the configuration of the virtqueues in the driver side must match the virtqueue definitions in the device. A basic driver skeleton could look like this:}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj=hhubh literal_block)}(hX`#include #include #include #include /* device private data (one per device) */ struct virtio_dummy_dev { struct virtqueue *vq; }; static void virtio_dummy_recv_cb(struct virtqueue *vq) { struct virtio_dummy_dev *dev = vq->vdev->priv; char *buf; unsigned int len; while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) { /* process the received data */ } } static int virtio_dummy_probe(struct virtio_device *vdev) { struct virtio_dummy_dev *dev = NULL; /* initialize device data */ dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL); if (!dev) return -ENOMEM; /* the device has a single virtqueue */ dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, "input"); if (IS_ERR(dev->vq)) { kfree(dev); return PTR_ERR(dev->vq); } vdev->priv = dev; /* from this point on, the device can notify and get callbacks */ virtio_device_ready(vdev); return 0; } static void virtio_dummy_remove(struct virtio_device *vdev) { struct virtio_dummy_dev *dev = vdev->priv; /* * disable vq interrupts: equivalent to * vdev->config->reset(vdev) */ virtio_reset_device(vdev); /* detach unused buffers */ while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) { kfree(buf); } /* remove virtqueues */ vdev->config->del_vqs(vdev); kfree(dev); } static const struct virtio_device_id id_table[] = { { VIRTIO_ID_DUMMY, VIRTIO_DEV_ANY_ID }, { 0 }, }; static struct virtio_driver virtio_dummy_driver = { .driver.name = KBUILD_MODNAME, .id_table = id_table, .probe = virtio_dummy_probe, .remove = virtio_dummy_remove, }; module_virtio_driver(virtio_dummy_driver); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Dummy virtio driver"); MODULE_LICENSE("GPL");h]hX`#include #include #include #include /* device private data (one per device) */ struct virtio_dummy_dev { struct virtqueue *vq; }; static void virtio_dummy_recv_cb(struct virtqueue *vq) { struct virtio_dummy_dev *dev = vq->vdev->priv; char *buf; unsigned int len; while ((buf = virtqueue_get_buf(dev->vq, &len)) != NULL) { /* process the received data */ } } static int virtio_dummy_probe(struct virtio_device *vdev) { struct virtio_dummy_dev *dev = NULL; /* initialize device data */ dev = kzalloc(sizeof(struct virtio_dummy_dev), GFP_KERNEL); if (!dev) return -ENOMEM; /* the device has a single virtqueue */ dev->vq = virtio_find_single_vq(vdev, virtio_dummy_recv_cb, "input"); if (IS_ERR(dev->vq)) { kfree(dev); return PTR_ERR(dev->vq); } vdev->priv = dev; /* from this point on, the device can notify and get callbacks */ virtio_device_ready(vdev); return 0; } static void virtio_dummy_remove(struct virtio_device *vdev) { struct virtio_dummy_dev *dev = vdev->priv; /* * disable vq interrupts: equivalent to * vdev->config->reset(vdev) */ virtio_reset_device(vdev); /* detach unused buffers */ while ((buf = virtqueue_detach_unused_buf(dev->vq)) != NULL) { kfree(buf); } /* remove virtqueues */ vdev->config->del_vqs(vdev); kfree(dev); } static const struct virtio_device_id id_table[] = { { VIRTIO_ID_DUMMY, VIRTIO_DEV_ANY_ID }, { 0 }, }; static struct virtio_driver virtio_dummy_driver = { .driver.name = KBUILD_MODNAME, .id_table = id_table, .probe = virtio_dummy_probe, .remove = virtio_dummy_remove, }; module_virtio_driver(virtio_dummy_driver); MODULE_DEVICE_TABLE(virtio, id_table); MODULE_DESCRIPTION("Dummy virtio driver"); MODULE_LICENSE("GPL");}hj^sbah}(h]h ]h"]h$]h&]hhuh1j\hhhKhj=hhubh)}(hXThe device id ``VIRTIO_ID_DUMMY`` here is a placeholder, virtio drivers should be added only for devices that are defined in the spec, see include/uapi/linux/virtio_ids.h. Device ids need to be at least reserved in the virtio spec before being added to that file.h](hThe device id }(hjlhhhNhNubhliteral)}(h``VIRTIO_ID_DUMMY``h]hVIRTIO_ID_DUMMY}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjlubh here is a placeholder, virtio drivers should be added only for devices that are defined in the spec, see include/uapi/linux/virtio_ids.h. Device ids need to be at least reserved in the virtio spec before being added to that file.}(hjlhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKnhj=hhubh)}(hIf your driver doesn't have to do anything special in its ``init`` and ``exit`` methods, you can use the module_virtio_driver() helper to reduce the amount of boilerplate code.h](h)}(h virtio_deviceh]h virtio_device}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ]h"]h$]h&] refdomaincreftype identifier reftargetjmodnameN classnameN c:parent_keysphinx.domains.c LookupKey)}data]j ASTIdentifier)}jjAsbc.virtio_device_readyasbuh1hhj^ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj^ubhdesc_sig_punctuation)}(h*h]h*}(hjhhhNhNubah}(h]h ]pah"]h$]h&]uh1jhj^ubj>)}(hdevh]hdev}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj^ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjXubah}(h]h ]h"]h$]h&]hhuh1jVhjhhhj%hMPubeh}(h]h ]h"]h$]h&]hhƌ add_permalinkuh1jsphinx_line_type declaratorhj hhhj%hMPubah}(h]jah ](sig sig-objecteh"]h$]h&] is_multiline _toc_parts) _toc_namehuh1jhj%hMPhjhhubh desc_content)}(hhh]h)}(henable vq use in probe functionh]henable vq use in probe function}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMPhjhhubah}(h]h ]h"]h$]h&]uh1jhjhhhj%hMPubeh}(h]h ](jfunctioneh"]h$]h&]domainjobjtypejdesctypejnoindex noindexentrynocontentsentryuh1jhhhj=hNhNubh container)}(h**Parameters** ``struct virtio_device *dev`` the virtio device **Description** Driver must call this to use vqs in the probe function. **Note** vqs are enabled automatically after probe returns.h](h)}(h**Parameters**h]hstrong)}(hj*h]h Parameters}(hj.hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj(ubah}(h]h ]h"]h$]h&]uh1hhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMThj$ubhdefinition_list)}(hhh]hdefinition_list_item)}(h0``struct virtio_device *dev`` the virtio device h](hterm)}(h``struct virtio_device *dev``h]ju)}(hjQh]hstruct virtio_device *dev}(hjShhhNhNubah}(h]h ]h"]h$]h&]uh1jthjOubah}(h]h ]h"]h$]h&]uh1jMhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMQhjIubh definition)}(hhh]h)}(hthe virtio deviceh]hthe virtio device}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjfhMQhjiubah}(h]h ]h"]h$]h&]uh1jghjIubeh}(h]h ]h"]h$]h&]uh1jGhjfhMQhjDubah}(h]h ]h"]h$]h&]uh1jBhj$ubh)}(h**Description**h]j-)}(hjh]h Description}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMShj$ubh)}(h7Driver must call this to use vqs in the probe function.h]h7Driver must call this to use vqs in the probe function.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMRhj$ubh)}(h**Note**h]j-)}(hjh]hNote}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMThj$ubh)}(h2vqs are enabled automatically after probe returns.h]h2vqs are enabled automatically after probe returns.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhw/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:126: ./include/linux/virtio_config.hhMUhj$ubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hj=hhhNhNubh)}(hMIn any case, the virtqueues need to be enabled before adding buffers to them.h]hMIn any case, the virtqueues need to be enabled before adding buffers to them.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhj=hhubeh}(h]driver-boilerplateah ]h"]driver boilerplateah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hSending and receiving datah]hSending and receiving data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hXThe virtio_dummy_recv_cb() callback in the code above will be triggered when the device notifies the driver after it finishes processing a descriptor or descriptor chain, either for reading or writing. However, that's only the second half of the virtio device-driver communication process, as the communication is always started by the driver regardless of the direction of the data transfer.h]hXThe virtio_dummy_recv_cb() callback in the code above will be triggered when the device notifies the driver after it finishes processing a descriptor or descriptor chain, either for reading or writing. However, that’s only the second half of the virtio device-driver communication process, as the communication is always started by the driver regardless of the direction of the data transfer.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hXDTo configure a buffer transfer from the driver to the device, first you have to add the buffers -- packed as `scatterlists` -- to the appropriate virtqueue using any of the virtqueue_add_inbuf(), virtqueue_add_outbuf() or virtqueue_add_sgs(), depending on whether you need to add one input `scatterlist` (for the device to fill in), one output `scatterlist` (for the device to consume) or multiple `scatterlists`, respectively. Then, once the virtqueue is set up, a call to virtqueue_kick() sends a notification that will be serviced by the hypervisor that implements the device::h](hmTo configure a buffer transfer from the driver to the device, first you have to add the buffers -- packed as }(hjhhhNhNubhtitle_reference)}(h`scatterlists`h]h scatterlists}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh -- to the appropriate virtqueue using any of the virtqueue_add_inbuf(), virtqueue_add_outbuf() or virtqueue_add_sgs(), depending on whether you need to add one input }(hjhhhNhNubj)}(h `scatterlist`h]h scatterlist}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh) (for the device to fill in), one output }(hjhhhNhNubj)}(h `scatterlist`h]h scatterlist}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh) (for the device to consume) or multiple }(hjhhhNhNubj)}(h`scatterlists`h]h scatterlists}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1jhjubh, respectively. Then, once the virtqueue is set up, a call to virtqueue_kick() sends a notification that will be serviced by the hypervisor that implements the device:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj])}(hstruct scatterlist sg[1]; sg_init_one(sg, buffer, BUFLEN); virtqueue_add_inbuf(dev->vq, sg, 1, buffer, GFP_ATOMIC); virtqueue_kick(dev->vq);h]hstruct scatterlist sg[1]; sg_init_one(sg, buffer, BUFLEN); virtqueue_add_inbuf(dev->vq, sg, 1, buffer, GFP_ATOMIC); virtqueue_kick(dev->vq);}hjnsbah}(h]h ]h"]h$]h&]hhuh1j\hhhKhjhhubj)}(hhh]h}(h]h ]h"]h$]h&]entries](j virtqueue_add_inbuf (C function)c.virtqueue_add_inbufhNtauh1jhjhhhNhNubj)}(hhh](j )}(hoint virtqueue_add_inbuf (struct virtqueue *vq, struct scatterlist *sg, unsigned int num, void *data, gfp_t gfp)h]j)}(hnint virtqueue_add_inbuf(struct virtqueue *vq, struct scatterlist *sg, unsigned int num, void *data, gfp_t gfp)h](j)}(hinth]hint}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjhhhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMF ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjhhhjhMF ubj8)}(hvirtqueue_add_inbufh]j>)}(hvirtqueue_add_inbufh]hvirtqueue_add_inbuf}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjhhhjhMF ubjW)}(hW(struct virtqueue *vq, struct scatterlist *sg, unsigned int num, void *data, gfp_t gfp)h](j])}(hstruct virtqueue *vqh](jc)}(hjfh]hstruct}(hjhhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubh)}(hhh]j>)}(h virtqueueh]h virtqueue}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetjmodnameN classnameNjj)}j]j)}jjsbc.virtqueue_add_inbufasbuh1hhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(hvqh]hvq}(hj+hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(hstruct scatterlist *sgh](jc)}(hjfh]hstruct}(hjDhhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhj@ubj')}(h h]h }(hjQhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj@ubh)}(hhh]j>)}(h scatterlisth]h scatterlist}(hjbhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj_ubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetjdmodnameN classnameNjj)}j]j c.virtqueue_add_inbufasbuh1hhj@ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj@ubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj@ubj>)}(hsgh]hsg}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj@ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(hunsigned int numh](j)}(hunsignedh]hunsigned}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hinth]hint}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj>)}(hnumh]hnum}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(h void *datah](j)}(hvoidh]hvoid}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hj!hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(hdatah]hdata}(hj.hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(h gfp_t gfph](h)}(hhh]j>)}(hgfp_th]hgfp_t}(hjJhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjGubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetjLmodnameN classnameNjj)}j]j c.virtqueue_add_inbufasbuh1hhjCubj')}(h h]h }(hjhhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjCubj>)}(hgfph]hgfp}(hjvhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjCubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubeh}(h]h ]h"]h$]h&]hhuh1jVhjhhhjhMF ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhjhhhjhMF ubah}(h]jah ](jjeh"]h$]h&]jj)jhuh1jhjhMF hjhhubj)}(hhh]h)}(h!expose input buffers to other endh]h!expose input buffers to other end}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMF hjhhubah}(h]h ]h"]h$]h&]uh1jhjhhhjhMF ubeh}(h]h ](jfunctioneh"]h$]h&]jjjjjjjj j!uh1jhhhjhNhNubj#)}(hX!**Parameters** ``struct virtqueue *vq`` the struct virtqueue we're talking about. ``struct scatterlist *sg`` scatterlist (must be well-formed and terminated!) ``unsigned int num`` the number of entries in **sg** writable by other side ``void *data`` the token identifying the buffer. ``gfp_t gfp`` how to do memory allocations (if necessary). **Description** Caller must ensure we don't call this with other virtqueue operations at the same time (except where noted). Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).h](h)}(h**Parameters**h]j-)}(hjh]h Parameters}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMJ hjubjC)}(hhh](jH)}(hC``struct virtqueue *vq`` the struct virtqueue we're talking about. h](jN)}(h``struct virtqueue *vq``h]ju)}(hjh]hstruct virtqueue *vq}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMG hjubjh)}(hhh]h)}(h)the struct virtqueue we're talking about.h]h+the struct virtqueue we’re talking about.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMG hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhMG hjubjH)}(hM``struct scatterlist *sg`` scatterlist (must be well-formed and terminated!) h](jN)}(h``struct scatterlist *sg``h]ju)}(hjh]hstruct scatterlist *sg}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMH hjubjh)}(hhh]h)}(h1scatterlist (must be well-formed and terminated!)h]h1scatterlist (must be well-formed and terminated!)}(hj3hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj/hMH hj0ubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhj/hMH hjubjH)}(hL``unsigned int num`` the number of entries in **sg** writable by other side h](jN)}(h``unsigned int num``h]ju)}(hjSh]hunsigned int num}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjQubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMI hjMubjh)}(hhh]h)}(h6the number of entries in **sg** writable by other sideh](hthe number of entries in }(hjlhhhNhNubj-)}(h**sg**h]hsg}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjlubh writable by other side}(hjlhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhjhhMI hjiubah}(h]h ]h"]h$]h&]uh1jghjMubeh}(h]h ]h"]h$]h&]uh1jGhjhhMI hjubjH)}(h1``void *data`` the token identifying the buffer. h](jN)}(h``void *data``h]ju)}(hjh]h void *data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMJ hjubjh)}(hhh]h)}(h!the token identifying the buffer.h]h!the token identifying the buffer.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMJ hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhMJ hjubjH)}(h;``gfp_t gfp`` how to do memory allocations (if necessary). h](jN)}(h ``gfp_t gfp``h]ju)}(hjh]h gfp_t gfp}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMK hjubjh)}(hhh]h)}(h,how to do memory allocations (if necessary).h]h,how to do memory allocations (if necessary).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMK hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhMK hjubeh}(h]h ]h"]h$]h&]uh1jBhjubh)}(h**Description**h]j-)}(hjh]h Description}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMM hjubh)}(hlCaller must ensure we don't call this with other virtqueue operations at the same time (except where noted).h]hnCaller must ensure we don’t call this with other virtqueue operations at the same time (except where noted).}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chML hjubh)}(h;Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).h]h;Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chMO hjubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hjhhhNhNubj)}(hhh]h}(h]h ]h"]h$]h&]entries](j!virtqueue_add_outbuf (C function)c.virtqueue_add_outbufhNtauh1jhjhhhNhNubj)}(hhh](j )}(hpint virtqueue_add_outbuf (struct virtqueue *vq, struct scatterlist *sg, unsigned int num, void *data, gfp_t gfp)h]j)}(hoint virtqueue_add_outbuf(struct virtqueue *vq, struct scatterlist *sg, unsigned int num, void *data, gfp_t gfp)h](j)}(hinth]hint}(hjfhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjbhhhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM ubj')}(h h]h }(hjuhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjbhhhjthM ubj8)}(hvirtqueue_add_outbufh]j>)}(hvirtqueue_add_outbufh]hvirtqueue_add_outbuf}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjbhhhjthM ubjW)}(hW(struct virtqueue *vq, struct scatterlist *sg, unsigned int num, void *data, gfp_t gfp)h](j])}(hstruct virtqueue *vqh](jc)}(hjfh]hstruct}(hjhhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubh)}(hhh]j>)}(h virtqueueh]h virtqueue}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetjmodnameN classnameNjj)}j]j)}jjsbc.virtqueue_add_outbufasbuh1hhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(hvqh]hvq}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(hstruct scatterlist *sgh](jc)}(hjfh]hstruct}(hj hhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhj ubj')}(h h]h }(hj" hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubh)}(hhh]j>)}(h scatterlisth]h scatterlist}(hj3 hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj0 ubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetj5 modnameN classnameNjj)}j]jc.virtqueue_add_outbufasbuh1hhj ubj')}(h h]h }(hjQ hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj)}(hjh]h*}(hj_ hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj ubj>)}(hsgh]hsg}(hjl hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(hunsigned int numh](j)}(hunsignedh]hunsigned}(hj hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj)}(hinth]hint}(hj hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj>)}(hnumh]hnum}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(h void *datah](j)}(hvoidh]hvoid}(hj hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj)}(hjh]h*}(hj hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj ubj>)}(hdatah]hdata}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(h gfp_t gfph](h)}(hhh]j>)}(hgfp_th]hgfp_t}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetj modnameN classnameNjj)}j]jc.virtqueue_add_outbufasbuh1hhj ubj')}(h h]h }(hj9 hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj>)}(hgfph]hgfp}(hjG hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubeh}(h]h ]h"]h$]h&]hhuh1jVhjbhhhjthM ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhj^hhhjthM ubah}(h]jYah ](jjeh"]h$]h&]jj)jhuh1jhjthM hj[hhubj)}(hhh]h)}(h"expose output buffers to other endh]h"expose output buffers to other end}(hjq hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hjn hhubah}(h]h ]h"]h$]h&]uh1jhj[hhhjthM ubeh}(h]h ](jfunctioneh"]h$]h&]jjjj jj jj j!uh1jhhhjhNhNubj#)}(hX!**Parameters** ``struct virtqueue *vq`` the struct virtqueue we're talking about. ``struct scatterlist *sg`` scatterlist (must be well-formed and terminated!) ``unsigned int num`` the number of entries in **sg** readable by other side ``void *data`` the token identifying the buffer. ``gfp_t gfp`` how to do memory allocations (if necessary). **Description** Caller must ensure we don't call this with other virtqueue operations at the same time (except where noted). Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).h](h)}(h**Parameters**h]j-)}(hj h]h Parameters}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubjC)}(hhh](jH)}(hC``struct virtqueue *vq`` the struct virtqueue we're talking about. h](jN)}(h``struct virtqueue *vq``h]ju)}(hj h]hstruct virtqueue *vq}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jthj ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubjh)}(hhh]h)}(h)the struct virtqueue we're talking about.h]h+the struct virtqueue we’re talking about.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hM hj ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj hM hj ubjH)}(hM``struct scatterlist *sg`` scatterlist (must be well-formed and terminated!) h](jN)}(h``struct scatterlist *sg``h]ju)}(hj h]hstruct scatterlist *sg}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jthj ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubjh)}(hhh]h)}(h1scatterlist (must be well-formed and terminated!)h]h1scatterlist (must be well-formed and terminated!)}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hM hj ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj hM hj ubjH)}(hL``unsigned int num`` the number of entries in **sg** readable by other side h](jN)}(h``unsigned int num``h]ju)}(hj$ h]hunsigned int num}(hj& hhhNhNubah}(h]h ]h"]h$]h&]uh1jthj" ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubjh)}(hhh]h)}(h6the number of entries in **sg** readable by other sideh](hthe number of entries in }(hj= hhhNhNubj-)}(h**sg**h]hsg}(hjE hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj= ubh readable by other side}(hj= hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhj9 hM hj: ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj9 hM hj ubjH)}(h1``void *data`` the token identifying the buffer. h](jN)}(h``void *data``h]ju)}(hjo h]h void *data}(hjq hhhNhNubah}(h]h ]h"]h$]h&]uh1jthjm ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hji ubjh)}(hhh]h)}(h!the token identifying the buffer.h]h!the token identifying the buffer.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hM hj ubah}(h]h ]h"]h$]h&]uh1jghji ubeh}(h]h ]h"]h$]h&]uh1jGhj hM hj ubjH)}(h;``gfp_t gfp`` how to do memory allocations (if necessary). h](jN)}(h ``gfp_t gfp``h]ju)}(hj h]h gfp_t gfp}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1jthj ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubjh)}(hhh]h)}(h,how to do memory allocations (if necessary).h]h,how to do memory allocations (if necessary).}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hM hj ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj hM hj ubeh}(h]h ]h"]h$]h&]uh1jBhj ubh)}(h**Description**h]j-)}(hj h]h Description}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubh)}(hlCaller must ensure we don't call this with other virtqueue operations at the same time (except where noted).h]hnCaller must ensure we don’t call this with other virtqueue operations at the same time (except where noted).}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM hj ubh)}(h;Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).h]h;Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:160: ./drivers/virtio/virtio_ring.chM" hj ubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hjhhhNhNubj)}(hhh]h}(h]h ]h"]h$]h&]entries](jvirtqueue_add_sgs (C function)c.virtqueue_add_sgshNtauh1jhjhhhNhNubj)}(hhh](j )}(hint virtqueue_add_sgs (struct virtqueue *_vq, struct scatterlist *sgs[], unsigned int out_sgs, unsigned int in_sgs, void *data, gfp_t gfp)h]j)}(hint virtqueue_add_sgs(struct virtqueue *_vq, struct scatterlist *sgs[], unsigned int out_sgs, unsigned int in_sgs, void *data, gfp_t gfp)h](j)}(hinth]hint}(hj7 hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj3 hhhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM ubj')}(h h]h }(hjF hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj3 hhhjE hM ubj8)}(hvirtqueue_add_sgsh]j>)}(hvirtqueue_add_sgsh]hvirtqueue_add_sgs}(hjX hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjT ubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hj3 hhhjE hM ubjW)}(ht(struct virtqueue *_vq, struct scatterlist *sgs[], unsigned int out_sgs, unsigned int in_sgs, void *data, gfp_t gfp)h](j])}(hstruct virtqueue *_vqh](jc)}(hjfh]hstruct}(hjt hhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhjp ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjp ubh)}(hhh]j>)}(h virtqueueh]h virtqueue}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetj modnameN classnameNjj)}j]j)}jjZ sbc.virtqueue_add_sgsasbuh1hhjp ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjp ubj)}(hjh]h*}(hj hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjp ubj>)}(h_vqh]h_vq}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjp ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjl ubj])}(hstruct scatterlist *sgs[]h](jc)}(hjfh]hstruct}(hj hhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhj ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubh)}(hhh]j>)}(h scatterlisth]h scatterlist}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetj modnameN classnameNjj)}j]j c.virtqueue_add_sgsasbuh1hhj ubj')}(h h]h }(hj" hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj)}(hjh]h*}(hj0 hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj ubj>)}(hsgsh]hsgs}(hj= hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubj)}(h[h]h[}(hjK hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj ubj)}(h]h]h]}(hjY hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjl ubj])}(hunsigned int out_sgsh](j)}(hunsignedh]hunsigned}(hjr hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjn ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjn ubj)}(hinth]hint}(hj hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjn ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjn ubj>)}(hout_sgsh]hout_sgs}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjn ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjl ubj])}(hunsigned int in_sgsh](j)}(hunsignedh]hunsigned}(hj hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj)}(hinth]hint}(hj hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj ubj')}(h h]h }(hj hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj ubj>)}(hin_sgsh]hin_sgs}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hj ubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjl ubj])}(h void *datah](j)}(hvoidh]hvoid}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjubj')}(h h]h }(hj"hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hj0hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(hdatah]hdata}(hj=hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjl ubj])}(h gfp_t gfph](h)}(hhh]j>)}(hgfp_th]hgfp_t}(hjYhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjVubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetj[modnameN classnameNjj)}j]j c.virtqueue_add_sgsasbuh1hhjRubj')}(h h]h }(hjwhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjRubj>)}(hgfph]hgfp}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjRubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjl ubeh}(h]h ]h"]h$]h&]hhuh1jVhj3 hhhjE hM ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhj/ hhhjE hM ubah}(h]j* ah ](jjeh"]h$]h&]jj)jhuh1jhjE hM hj, hhubj)}(hhh]h)}(hexpose buffers to other endh]hexpose buffers to other end}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjhhubah}(h]h ]h"]h$]h&]uh1jhj, hhhjE hM ubeh}(h]h ](jfunctioneh"]h$]h&]jjjjjjjj j!uh1jhhhjhNhNubj#)}(hXK**Parameters** ``struct virtqueue *_vq`` the struct virtqueue we're talking about. ``struct scatterlist *sgs[]`` array of terminated scatterlists. ``unsigned int out_sgs`` the number of scatterlists readable by other side ``unsigned int in_sgs`` the number of scatterlists which are writable (after readable ones) ``void *data`` the token identifying the buffer. ``gfp_t gfp`` how to do memory allocations (if necessary). **Description** Caller must ensure we don't call this with other virtqueue operations at the same time (except where noted). Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). NB: ENOSPC is a special code that is only returned on an attempt to add a buffer to a full VQ. It indicates that some buffers are outstanding and that the operation can be retried after some buffers have been used.h](h)}(h**Parameters**h]j-)}(hjh]h Parameters}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubjC)}(hhh](jH)}(hD``struct virtqueue *_vq`` the struct virtqueue we're talking about. h](jN)}(h``struct virtqueue *_vq``h]ju)}(hjh]hstruct virtqueue *_vq}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(h)the struct virtqueue we're talking about.h]h+the struct virtqueue we’re talking about.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjubjH)}(h@``struct scatterlist *sgs[]`` array of terminated scatterlists. h](jN)}(h``struct scatterlist *sgs[]``h]ju)}(hj)h]hstruct scatterlist *sgs[]}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1jthj'ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hj#ubjh)}(hhh]h)}(h!array of terminated scatterlists.h]h!array of terminated scatterlists.}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj>hM hj?ubah}(h]h ]h"]h$]h&]uh1jghj#ubeh}(h]h ]h"]h$]h&]uh1jGhj>hM hjubjH)}(hK``unsigned int out_sgs`` the number of scatterlists readable by other side h](jN)}(h``unsigned int out_sgs``h]ju)}(hjbh]hunsigned int out_sgs}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1jthj`ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hj\ubjh)}(hhh]h)}(h1the number of scatterlists readable by other sideh]h1the number of scatterlists readable by other side}(hj{hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjwhM hjxubah}(h]h ]h"]h$]h&]uh1jghj\ubeh}(h]h ]h"]h$]h&]uh1jGhjwhM hjubjH)}(h\``unsigned int in_sgs`` the number of scatterlists which are writable (after readable ones) h](jN)}(h``unsigned int in_sgs``h]ju)}(hjh]hunsigned int in_sgs}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(hCthe number of scatterlists which are writable (after readable ones)h]hCthe number of scatterlists which are writable (after readable ones)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjubjH)}(h1``void *data`` the token identifying the buffer. h](jN)}(h``void *data``h]ju)}(hjh]h void *data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(h!the token identifying the buffer.h]h!the token identifying the buffer.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjubjH)}(h;``gfp_t gfp`` how to do memory allocations (if necessary). h](jN)}(h ``gfp_t gfp``h]ju)}(hj h]h gfp_t gfp}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthj ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(h,how to do memory allocations (if necessary).h]h,how to do memory allocations (if necessary).}(hj&hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj"hM hj#ubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhj"hM hjubeh}(h]h ]h"]h$]h&]uh1jBhjubh)}(h**Description**h]j-)}(hjHh]h Description}(hjJhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjFubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubh)}(hlCaller must ensure we don't call this with other virtqueue operations at the same time (except where noted).h]hnCaller must ensure we don’t call this with other virtqueue operations at the same time (except where noted).}(hj^hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubh)}(h;Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).h]h;Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubh)}(hNB: ENOSPC is a special code that is only returned on an attempt to add a buffer to a full VQ. It indicates that some buffers are outstanding and that the operation can be retried after some buffers have been used.h]hNB: ENOSPC is a special code that is only returned on an attempt to add a buffer to a full VQ. It indicates that some buffers are outstanding and that the operation can be retried after some buffers have been used.}(hj|hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:163: ./drivers/virtio/virtio_ring.chM hjubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hjhhhNhNubh)}(hX2Then, after the device has read or written the buffers prepared by the driver and notifies it back, the driver can call virtqueue_get_buf() to read the data produced by the device (if the virtqueue was set up with input buffers) or simply to reclaim the buffers if they were already consumed by the device:h]hX2Then, after the device has read or written the buffers prepared by the driver and notifies it back, the driver can call virtqueue_get_buf() to read the data produced by the device (if the virtqueue was set up with input buffers) or simply to reclaim the buffers if they were already consumed by the device:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj)}(hhh]h}(h]h ]h"]h$]h&]entries](j"virtqueue_get_buf_ctx (C function)c.virtqueue_get_buf_ctxhNtauh1jhjhhhNhNubj)}(hhh](j )}(hSvoid * virtqueue_get_buf_ctx (struct virtqueue *_vq, unsigned int *len, void **ctx)h]j)}(hQvoid *virtqueue_get_buf_ctx(struct virtqueue *_vq, unsigned int *len, void **ctx)h](j)}(hvoidh]hvoid}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjhhhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjhhhjhM ubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjhhhjhM ubj8)}(hvirtqueue_get_buf_ctxh]j>)}(hvirtqueue_get_buf_ctxh]hvirtqueue_get_buf_ctx}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjhhhjhM ubjW)}(h6(struct virtqueue *_vq, unsigned int *len, void **ctx)h](j])}(hstruct virtqueue *_vqh](jc)}(hjfh]hstruct}(hjhhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubh)}(hhh]j>)}(h virtqueueh]h virtqueue}(hj!hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetj#modnameN classnameNjj)}j]j)}jjsbc.virtqueue_get_buf_ctxasbuh1hhjubj')}(h h]h }(hjAhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hjOhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(h_vqh]h_vq}(hj\hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(hunsigned int *lenh](j)}(hunsignedh]hunsigned}(hjuhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjqubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjqubj)}(hinth]hint}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjqubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjqubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjqubj>)}(hlenh]hlen}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjqubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubj])}(h void **ctxh](j)}(hvoidh]hvoid}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(hctxh]hctx}(hj hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubeh}(h]h ]h"]h$]h&]hhuh1jVhjhhhjhM ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhjhhhjhM ubah}(h]jah ](jjeh"]h$]h&]jj)jhuh1jhjhM hjhhubj)}(hhh]h)}(hget the next used bufferh]hget the next used buffer}(hj3hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hj0hhubah}(h]h ]h"]h$]h&]uh1jhjhhhjhM ubeh}(h]h ](jfunctioneh"]h$]h&]jjjjKjjKjj j!uh1jhhhjhNhNubj#)}(hXj**Parameters** ``struct virtqueue *_vq`` the struct virtqueue we're talking about. ``unsigned int *len`` the length written into the buffer ``void **ctx`` extra context for the token **Description** If the device wrote data into the buffer, **len** will be set to the amount written. This means you don't need to clear the buffer beforehand to ensure there's no data leakage in the case of short writes. Caller must ensure we don't call this with other virtqueue operations at the same time (except where noted). Returns NULL if there are no used buffers, or the "data" token handed to virtqueue_add_*().h](h)}(h**Parameters**h]j-)}(hjUh]h Parameters}(hjWhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjSubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjOubjC)}(hhh](jH)}(hD``struct virtqueue *_vq`` the struct virtqueue we're talking about. h](jN)}(h``struct virtqueue *_vq``h]ju)}(hjth]hstruct virtqueue *_vq}(hjvhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjrubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjnubjh)}(hhh]h)}(h)the struct virtqueue we're talking about.h]h+the struct virtqueue we’re talking about.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjnubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjkubjH)}(h9``unsigned int *len`` the length written into the buffer h](jN)}(h``unsigned int *len``h]ju)}(hjh]hunsigned int *len}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(h"the length written into the bufferh]h"the length written into the buffer}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjkubjH)}(h+``void **ctx`` extra context for the token h](jN)}(h``void **ctx``h]ju)}(hjh]h void **ctx}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(hextra context for the tokenh]hextra context for the token}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjkubeh}(h]h ]h"]h$]h&]uh1jBhjOubh)}(h**Description**h]j-)}(hj!h]h Description}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjOubh)}(hIf the device wrote data into the buffer, **len** will be set to the amount written. This means you don't need to clear the buffer beforehand to ensure there's no data leakage in the case of short writes.h](h*If the device wrote data into the buffer, }(hj7hhhNhNubj-)}(h**len**hA]hlen}(hj?hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj7ubh will be set to the amount written. This means you don’t need to clear the buffer beforehand to ensure there’s no data leakage in the case of short writes.}(hj7hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjOubh)}(hlCaller must ensure we don't call this with other virtqueue operations at the same time (except where noted).h]hnCaller must ensure we don’t call this with other virtqueue operations at the same time (except where noted).}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjOubh)}(h[Returns NULL if there are no used buffers, or the "data" token handed to virtqueue_add_*().h]h_Returns NULL if there are no used buffers, or the “data” token handed to virtqueue_add_*().}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:172: ./drivers/virtio/virtio_ring.chM hjOubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hjhhhNhNubh)}(hThe virtqueue callbacks can be disabled and re-enabled using the virtqueue_disable_cb() and the family of virtqueue_enable_cb() functions respectively. See drivers/virtio/virtio_ring.c for more details:h]hThe virtqueue callbacks can be disabled and re-enabled using the virtqueue_disable_cb() and the family of virtqueue_enable_cb() functions respectively. See drivers/virtio/virtio_ring.c for more details:}(hj}hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj)}(hhh]h}(h]h ]h"]h$]h&]entries](j!virtqueue_disable_cb (C function)c.virtqueue_disable_cbhNtauh1jhjhhhNhNubj)}(hhh](j )}(h1void virtqueue_disable_cb (struct virtqueue *_vq)h]j)}(h0void virtqueue_disable_cb(struct virtqueue *_vq)h](j)}(hvoidh]hvoid}(hjhhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhjhhhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjhhhjhM ubj8)}(hvirtqueue_disable_cbh]j>)}(hvirtqueue_disable_cbh]hvirtqueue_disable_cb}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjhhhjhM ubjW)}(h(struct virtqueue *_vq)h]j])}(hstruct virtqueue *_vqh](jc)}(hjfh]hstruct}(hjhhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubh)}(hhh]j>)}(h virtqueueh]h virtqueue}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetjmodnameN classnameNjj)}j]j)}jjsbc.virtqueue_disable_cbasbuh1hhjubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjubj)}(hjh]h*}(hj-hhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjubj>)}(h_vqh]h_vq}(hj:hhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjubah}(h]h ]h"]h$]h&]hhuh1jVhjhhhjhM ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhjhhhjhM ubah}(h]jah ](jjeh"]h$]h&]jj)jhuh1jhjhM hjhhubj)}(hhh]h)}(hdisable callbacksh]hdisable callbacks}(hjdhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM hjahhubah}(h]h ]h"]h$]h&]uh1jhjhhhjhM ubeh}(h]h ](jfunctioneh"]h$]h&]jjjj|jj|jj j!uh1jhhhjhNhNubj#)}(hX**Parameters** ``struct virtqueue *_vq`` the struct virtqueue we're talking about. **Description** Note that this is not necessarily synchronous, hence unreliable and only useful as an optimization. Unlike other operations, this need not be serialized.h](h)}(h**Parameters**h]j-)}(hjh]h Parameters}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM hjubjC)}(hhh]jH)}(hD``struct virtqueue *_vq`` the struct virtqueue we're talking about. h](jN)}(h``struct virtqueue *_vq``h]ju)}(hjh]hstruct virtqueue *_vq}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jthjubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM hjubjh)}(hhh]h)}(h)the struct virtqueue we're talking about.h]h+the struct virtqueue we’re talking about.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM hjubah}(h]h ]h"]h$]h&]uh1jBhjubh)}(h**Description**h]j-)}(hjh]h Description}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM hjubh)}(hcNote that this is not necessarily synchronous, hence unreliable and only useful as an optimization.h]hcNote that this is not necessarily synchronous, hence unreliable and only useful as an optimization.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM hjubh)}(h5Unlike other operations, this need not be serialized.h]h5Unlike other operations, this need not be serialized.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:179: ./drivers/virtio/virtio_ring.chM hjubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hjhhhNhNubj)}(hhh]h}(h]h ]h"]h$]h&]entries](j virtqueue_enable_cb (C function)c.virtqueue_enable_cbhNtauh1jhjhhhNhNubj)}(hhh](j )}(h0bool virtqueue_enable_cb (struct virtqueue *_vq)h]j)}(h/bool virtqueue_enable_cb(struct virtqueue *_vq)h](j)}(hboolh]hbool}(hj4hhhNhNubah}(h]h ]j!ah"]h$]h&]uh1jhj0hhhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chMV ubj')}(h h]h }(hjChhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj0hhhjBhMV ubj8)}(hvirtqueue_enable_cbh]j>)}(hvirtqueue_enable_cbh]hvirtqueue_enable_cb}(hjUhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjQubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hj0hhhjBhMV ubjW)}(h(struct virtqueue *_vq)h]j])}(hstruct virtqueue *_vqh](jc)}(hjfh]hstruct}(hjqhhhNhNubah}(h]h ]joah"]h$]h&]uh1jbhjmubj')}(h h]h }(hj~hhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjmubh)}(hhh]j>)}(h virtqueueh]h virtqueue}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ]h"]h$]h&] refdomainjreftypej reftargetjmodnameN classnameNjj)}j]j)}jjWsbc.virtqueue_enable_cbasbuh1hhjmubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjmubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjmubj>)}(h_vqh]h_vq}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjmubeh}(h]h ]h"]h$]h&]noemphhhuh1j\hjiubah}(h]h ]h"]h$]h&]hhuh1jVhj0hhhjBhMV ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhj,hhhjBhMV ubah}(h]j'ah ](jjeh"]h$]h&]jj)jhuh1jhjBhMV hj)hhubj)}(hhh]h)}(h#restart callbacks after disable_cb.h]h#restart callbacks after disable_cb.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chMV hjhhubah}(h]h ]h"]h$]h&]uh1jhj)hhhjBhMV ubeh}(h]h ](jfunctioneh"]h$]h&]jjjj jj jj j!uh1jhhhjhNhNubj#)}(hX**Parameters** ``struct virtqueue *_vq`` the struct virtqueue we're talking about. **Description** This re-enables callbacks; it returns "false" if there are pending buffers in the queue, to detect a possible race between the driver checking for more work, and enabling callbacks. Caller must ensure we don't call this with other virtqueue operations at the same time (except where noted).h](h)}(h**Parameters**h]j-)}(hjh]h Parameters}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chMZ hjubjC)}(hhh]jH)}(hD``struct virtqueue *_vq`` the struct virtqueue we're talking about. h](jN)}(h``struct virtqueue *_vq``h]ju)}(hj5h]hstruct virtqueue *_vq}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1jthj3ubah}(h]h ]h"]h$]h&]uh1jMhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chMW hj/ubjh)}(hhh]h)}(h)the struct virtqueue we're talking about.h]h+the struct virtqueue we’re talking about.}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjJhMW hjKubah}(h]h ]h"]h$]h&]uh1jghj/ubeh}(h]h ]h"]h$]h&]uh1jGhjJhMW hj,ubah}(h]h ]h"]h$]h&]uh1jBhjubh)}(h**Description**h]j-)}(hjph]h Description}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjnubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chMY hjubh)}(hThis re-enables callbacks; it returns "false" if there are pending buffers in the queue, to detect a possible race between the driver checking for more work, and enabling callbacks.h]hThis re-enables callbacks; it returns “false” if there are pending buffers in the queue, to detect a possible race between the driver checking for more work, and enabling callbacks.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chMX hjubh)}(hlCaller must ensure we don't call this with other virtqueue operations at the same time (except where noted).h]hnCaller must ensure we don’t call this with other virtqueue operations at the same time (except where noted).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:182: ./drivers/virtio/virtio_ring.chM\ hjubeh}(h]h ] kernelindentah"]h$]h&]uh1j"hjhhhNhNubh)}(hBut note that some spurious callbacks can still be triggered under certain scenarios. The way to disable callbacks reliably is to reset the device or the virtqueue (virtio_reset_device()).h]hBut note that some spurious callbacks can still be triggered under certain scenarios. The way to disable callbacks reliably is to reset the device or the virtqueue (virtio_reset_device()).}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]sending-and-receiving-dataah ]h"]sending and receiving dataah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(h Referencesh]h References}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hX_`[1]` Virtio Spec v1.2: https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.htmlh](h)}(h_`[1]`h]h[1]}(hjhhhNhNubah}(h]id2ah ]h"][1]ah$]h&]uh1hhjubh Virtio Spec v1.2: }(hjhhhNhNubh reference)}(h?https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.htmlh]h?https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html}(hjhhhNhNubah}(h]h ]h"]h$]h&]refurijuh1jhjubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(h-Check for later versions of the spec as well.h]h-Check for later versions of the spec as well.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h] referencesah ]h"] referencesah$]h&]uh1hhhhhhhhKubeh}(h](hՌid1eh ]h"](writing virtio driverswriting_virtio_driverseh$]h&]uh1hhhhhhhhKexpect_referenced_by_name}jhsexpect_referenced_by_id}hhsubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjGerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehnj _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}h]hasnameids}(jhjjj:j7jjjjjjjju nametypes}(jjj:jjjjuh}(hhjhj7hjj=jj jjjjjYj^j* j/ jjjjj'j,jjjju footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jUKsRparse_messages]transform_messages](hsystem_message)}(hhh]h)}(hhh]h