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.chM ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjhhhjhM ubj8)}(hvirtqueue_add_inbufh]j>)}(hvirtqueue_add_inbufh]hvirtqueue_add_inbuf}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjhhhjhM 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&]hhuh1jVhjhhhjhM ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhjhhhjhM ubah}(h]jah ](jjeh"]h$]h&]jj)jhuh1jhjhM 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.chM hjhhubah}(h]h ]h"]h$]h&]uh1jhjhhhjhM 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.chM 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.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 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.chM 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/hM hj0ubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhj/hM 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.chM 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&]uh1hhjhhM hjiubah}(h]h ]h"]h$]h&]uh1jghjMubeh}(h]h ]h"]h$]h&]uh1jGhjhhM 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.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)}(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.chM 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&]uh1hhjhM hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhM 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.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:157: ./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).}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1hhv/var/lib/git/docbuild/linux/Documentation/driver-api/virtio/writing_virtio_drivers:157: ./drivers/virtio/virtio_ring.chM 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.chMb ubj')}(h h]h }(hjuhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjbhhhjthMb ubj8)}(hvirtqueue_add_outbufh]j>)}(hvirtqueue_add_outbufh]hvirtqueue_add_outbuf}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjbhhhjthMb 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&]hhuh1jVhjbhhhjthMb ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhj^hhhjthMb ubah}(h]jYah ](jjeh"]h$]h&]jj)jhuh1jhjthMb 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.chMb hjn hhubah}(h]h ]h"]h$]h&]uh1jhj[hhhjthMb 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.chMf 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.chMc 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 hMc hj ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj hMc 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.chMd 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 hMd hj ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj hMd 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.chMe 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 hMe hj: ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj9 hMe 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.chMf 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 hMf hj ubah}(h]h ]h"]h$]h&]uh1jghji ubeh}(h]h ]h"]h$]h&]uh1jGhj hMf 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.chMg 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 hMg hj ubah}(h]h ]h"]h$]h&]uh1jghj ubeh}(h]h ]h"]h$]h&]uh1jGhj hMg 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.chMi 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.chMh 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.chMk 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.chMA 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"hMA hj#ubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhj"hMA 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.chMC 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.chMB 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.chME 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.chMG 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.chMB ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjhhhjhMB ubj)}(hjh]h*}(hjhhhNhNubah}(h]h ]jah"]h$]h&]uh1jhjhhhjhMB 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&]hhuh1j7hjhhhjhMB 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&]hhuh1jVhjhhhjhMB ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhjhhhjhMB ubah}(h]jah ](jjeh"]h$]h&]jj)jhuh1jhjhMB 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.chMB hj0hhubah}(h]h ]h"]h$]h&]uh1jhjhhhjhMB 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.chMF 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.chMC 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&]uh1hhjhMC hjubah}(h]h ]h"]h$]h&]uh1jghjnubeh}(h]h ]h"]h$]h&]uh1jGhjhMC 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.chMD hjubjh)}(hhh]h)}(h"the length written into the bufferh]h"the length written into the buffer}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhMD hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhMD 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.chME hjubjh)}(hhh]h)}(hextra context for the tokenh]hextra context for the token}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhME hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhME 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.chMG 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.chMF 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.chMK 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.chMN 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.chMa ubj')}(h h]h }(hjhhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hjhhhjhMa ubj8)}(hvirtqueue_disable_cbh]j>)}(hvirtqueue_disable_cbh]hvirtqueue_disable_cb}(hjhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hjhhhjhMa 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&]hhuh1jVhjhhhjhMa ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhjhhhjhMa ubah}(h]jah ](jjeh"]h$]h&]jj)jhuh1jhjhMa 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.chMa hjahhubah}(h]h ]h"]h$]h&]uh1jhjhhhjhMa 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.chMe 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.chMb 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&]uh1hhjhMb hjubah}(h]h ]h"]h$]h&]uh1jghjubeh}(h]h ]h"]h$]h&]uh1jGhjhMb 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.chMd 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.chMc 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.chMf 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.chM ubj')}(h h]h }(hjChhhNhNubah}(h]h ]j3ah"]h$]h&]uh1j&hj0hhhjBhM ubj8)}(hvirtqueue_enable_cbh]j>)}(hvirtqueue_enable_cbh]hvirtqueue_enable_cb}(hjUhhhNhNubah}(h]h ]jJah"]h$]h&]uh1j=hjQubah}(h]h ](jQjReh"]h$]h&]hhuh1j7hj0hhhjBhM 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&]hhuh1jVhj0hhhjBhM ubeh}(h]h ]h"]h$]h&]hhjuh1jjjhj,hhhjBhM ubah}(h]j'ah ](jjeh"]h$]h&]jj)jhuh1jhjBhM 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.chM hjhhubah}(h]h ]h"]h$]h&]uh1jhj)hhhjBhM 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.chM 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.chM 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&]uh1hhjJhM hjKubah}(h]h ]h"]h$]h&]uh1jghj/ubeh}(h]h ]h"]h$]h&]uh1jGhjJhM 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.chM 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.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).}(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