Skip to content

Commit 8daafe9

Browse files
fengidrimstsirkin
authored andcommitted
virtio_ring: introduce virtqueue_set_dma_premapped()
This helper allows the driver change the dma mode to premapped mode. Under the premapped mode, the virtio core do not do dma mapping internally. This just work when the use_dma_api is true. If the use_dma_api is false, the dma options is not through the DMA APIs, that is not the standard way of the linux kernel. Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Message-Id: <20230810123057.43407-4-xuanzhuo@linux.alibaba.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
1 parent 0e27fa6 commit 8daafe9

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

drivers/virtio/virtio_ring.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ struct vring_virtqueue {
172172
/* Host publishes avail event idx */
173173
bool event;
174174

175+
/* Do DMA mapping by driver */
176+
bool premapped;
177+
175178
/* Head of free buffer list. */
176179
unsigned int free_head;
177180
/* Number we've added since last sync. */
@@ -2061,6 +2064,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
20612064
vq->packed_ring = true;
20622065
vq->dma_dev = dma_dev;
20632066
vq->use_dma_api = vring_use_dma_api(vdev);
2067+
vq->premapped = false;
20642068

20652069
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
20662070
!context;
@@ -2550,6 +2554,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
25502554
#endif
25512555
vq->dma_dev = dma_dev;
25522556
vq->use_dma_api = vring_use_dma_api(vdev);
2557+
vq->premapped = false;
25532558

25542559
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
25552560
!context;
@@ -2693,6 +2698,54 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
26932698
}
26942699
EXPORT_SYMBOL_GPL(virtqueue_resize);
26952700

2701+
/**
2702+
* virtqueue_set_dma_premapped - set the vring premapped mode
2703+
* @_vq: the struct virtqueue we're talking about.
2704+
*
2705+
* Enable the premapped mode of the vq.
2706+
*
2707+
* The vring in premapped mode does not do dma internally, so the driver must
2708+
* do dma mapping in advance. The driver must pass the dma_address through
2709+
* dma_address of scatterlist. When the driver got a used buffer from
2710+
* the vring, it has to unmap the dma address.
2711+
*
2712+
* This function must be called immediately after creating the vq, or after vq
2713+
* reset, and before adding any buffers to it.
2714+
*
2715+
* Caller must ensure we don't call this with other virtqueue operations
2716+
* at the same time (except where noted).
2717+
*
2718+
* Returns zero or a negative error.
2719+
* 0: success.
2720+
* -EINVAL: vring does not use the dma api, so we can not enable premapped mode.
2721+
*/
2722+
int virtqueue_set_dma_premapped(struct virtqueue *_vq)
2723+
{
2724+
struct vring_virtqueue *vq = to_vvq(_vq);
2725+
u32 num;
2726+
2727+
START_USE(vq);
2728+
2729+
num = vq->packed_ring ? vq->packed.vring.num : vq->split.vring.num;
2730+
2731+
if (num != vq->vq.num_free) {
2732+
END_USE(vq);
2733+
return -EINVAL;
2734+
}
2735+
2736+
if (!vq->use_dma_api) {
2737+
END_USE(vq);
2738+
return -EINVAL;
2739+
}
2740+
2741+
vq->premapped = true;
2742+
2743+
END_USE(vq);
2744+
2745+
return 0;
2746+
}
2747+
EXPORT_SYMBOL_GPL(virtqueue_set_dma_premapped);
2748+
26962749
/* Only available for split ring */
26972750
struct virtqueue *vring_new_virtqueue(unsigned int index,
26982751
unsigned int num,

include/linux/virtio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ bool virtqueue_enable_cb(struct virtqueue *vq);
7878

7979
unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq);
8080

81+
int virtqueue_set_dma_premapped(struct virtqueue *_vq);
82+
8183
bool virtqueue_poll(struct virtqueue *vq, unsigned);
8284

8385
bool virtqueue_enable_cb_delayed(struct virtqueue *vq);

0 commit comments

Comments
 (0)