@@ -2792,6 +2792,7 @@ EXPORT_SYMBOL_GPL(virtqueue_resize);
/**
* virtqueue_set_dma_premapped - set the vring premapped mode
* @_vq: the struct virtqueue we're talking about.
+ * @premapped: enable/disable the premapped mode.
*
* Enable the premapped mode of the vq.
*
@@ -2808,11 +2809,15 @@ EXPORT_SYMBOL_GPL(virtqueue_resize);
*
* Returns zero or a negative error.
* 0: success.
- * -EINVAL: vring does not use the dma api, so we can not enable premapped mode.
+ * -EINVAL:
+ * vring does not use the dma api, so we can not enable premapped mode.
+ * Or some descs are used, this is not called immediately after creating
+ * the vq, or after vq reset.
*/
-int virtqueue_set_dma_premapped(struct virtqueue *_vq)
+int virtqueue_set_dma_premapped(struct virtqueue *_vq, bool premapped)
{
struct vring_virtqueue *vq = to_vvq(_vq);
+ int err = 0;
u32 num;
START_USE(vq);
@@ -2824,24 +2829,40 @@ int virtqueue_set_dma_premapped(struct virtqueue *_vq)
return -EINVAL;
}
+ if (vq->vq.premapped == premapped) {
+ END_USE(vq);
+ return 0;
+ }
+
if (!vq->use_dma_api) {
END_USE(vq);
return -EINVAL;
}
- vq->vq.premapped = true;
+ if (premapped) {
+ vq->vq.premapped = true;
+
+ if (vq->packed_ring) {
+ kfree(vq->packed.desc_dma);
+ vq->packed.desc_dma = NULL;
+ } else {
+ kfree(vq->split.desc_dma);
+ vq->split.desc_dma = NULL;
+ }
- if (vq->packed_ring) {
- kfree(vq->packed.desc_dma);
- vq->packed.desc_dma = NULL;
} else {
- kfree(vq->split.desc_dma);
- vq->split.desc_dma = NULL;
+ if (vq->packed_ring)
+ err = vring_alloc_dma_split(&vq->split, false);
+ else
+ err = vring_alloc_dma_packed(&vq->packed, false);
+
+ if (!err)
+ vq->vq.premapped = false;
}
END_USE(vq);
- return 0;
+ return err;
}
EXPORT_SYMBOL_GPL(virtqueue_set_dma_premapped);
@@ -82,7 +82,7 @@ bool virtqueue_enable_cb(struct virtqueue *vq);
unsigned virtqueue_enable_cb_prepare(struct virtqueue *vq);
-int virtqueue_set_dma_premapped(struct virtqueue *_vq);
+int virtqueue_set_dma_premapped(struct virtqueue *_vq, bool premapped);
bool virtqueue_poll(struct virtqueue *vq, unsigned);
Now, the API virtqueue_set_dma_premapped just support to enable premapped mode. If we allow enabling the premapped dynamically, we should make this API to support disable the premapped mode. Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> --- drivers/virtio/virtio_ring.c | 39 +++++++++++++++++++++++++++--------- include/linux/virtio.h | 2 +- 2 files changed, 31 insertions(+), 10 deletions(-)