Convenience function to add chains that mixes out and in buffers. Signed-off-by: Eugenio Pérez <eperezma@xxxxxxxxxx> --- drivers/virtio/virtio_ring.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/virtio.h | 7 +++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 05729bc5cbb1..e49912fa77c5 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -2385,6 +2385,41 @@ static inline int virtqueue_add(struct virtqueue *_vq, out_sgs, in_sgs, data, ctx, premapped, gfp); } +/** + * virtqueue_add_sgs_premapped - expose buffers to other end + * @_vq: the struct virtqueue we're talking about. + * @sgs: array of terminated scatterlists. + * @out_sgs: the number of scatterlists readable by other side + * @in_sgs: the number of scatterlists which are writable (after readable ones) + * @data: the token identifying the buffer. + * @gfp: how to do memory allocations (if necessary). + * + * 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). + */ +int virtqueue_add_sgs_premapped(struct virtqueue *_vq, + struct scatterlist *sgs[], + unsigned int out_sgs, + unsigned int in_sgs, + void *data, + gfp_t gfp) +{ + unsigned int i, total_sg = 0; + + /* Count them first. */ + for (i = 0; i < out_sgs + in_sgs; i++) { + struct scatterlist *sg; + + for (sg = sgs[i]; sg; sg = sg_next(sg)) + total_sg++; + } + return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, + data, NULL, true, gfp); +} +EXPORT_SYMBOL_GPL(virtqueue_add_sgs_premapped); + /** * virtqueue_add_sgs - expose buffers to other end * @_vq: the struct virtqueue we're talking about. diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 28db998d691e..de52a0f6f734 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -84,6 +84,13 @@ int virtqueue_add_sgs(struct virtqueue *vq, void *data, gfp_t gfp); +int virtqueue_add_sgs_premapped(struct virtqueue *vq, + struct scatterlist *sgs[], + unsigned int out_sgs, + unsigned int in_sgs, + void *data, + gfp_t gfp); + struct device *virtqueue_dma_dev(struct virtqueue *vq); bool virtqueue_kick(struct virtqueue *vq); -- 2.48.1