From aa2a4936ece6e65e3416d0357ef56fb0aa29a3cc Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 18 Aug 2022 11:20:25 +0000 Subject: [PATCH] ANDROID: virtio_balloon: Do not translate reported pages through DMA API The free-page reporting and hinting queues do not pass arrays of page addresses (like the basic inflate queue) but instead pass the free page ranges as buffers. This does not work well with DMA API: The host wants to know the GPA, not an IOVA. For these two virtqueues, disable DMA API and pass through buffers untranslated. Bug: 240239989 Change-Id: I2d13a8b7e8f6775819de7fe96f4579afa08b1300 Signed-off-by: Keir Fraser [ qperret@: Fixed minor context conflict in virtio.h ] Signed-off-by: Quentin Perret --- drivers/virtio/virtio_balloon.c | 8 ++++++-- drivers/virtio/virtio_ring.c | 10 ++++++++++ include/linux/virtio.h | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 3f78a3a1eb75..4c85349024c1 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -553,11 +553,15 @@ static int init_vqs(struct virtio_balloon *vb) virtqueue_kick(vb->stats_vq); } - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { vb->free_page_vq = vqs[VIRTIO_BALLOON_VQ_FREE_PAGE]; + virtqueue_disable_dma_api_for_buffers(vb->free_page_vq); + } - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) + if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) { vb->reporting_vq = vqs[VIRTIO_BALLOON_VQ_REPORTING]; + virtqueue_disable_dma_api_for_buffers(vb->reporting_vq); + } return 0; } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 2e7689bb933b..3eca7140bd80 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -2863,4 +2863,14 @@ const struct vring *virtqueue_get_vring(struct virtqueue *vq) } EXPORT_SYMBOL_GPL(virtqueue_get_vring); +/* + * Prevents use of DMA API for buffers passed via the specified virtqueue. + * DMA API may still be used for the vrings themselves. + */ +void virtqueue_disable_dma_api_for_buffers(struct virtqueue *vq) +{ + to_vvq(vq)->use_dma_api = false; +} +EXPORT_SYMBOL_GPL(virtqueue_disable_dma_api_for_buffers); + MODULE_LICENSE("GPL"); diff --git a/include/linux/virtio.h b/include/linux/virtio.h index dcab9c7e8784..34e936343ae4 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -96,6 +96,8 @@ dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq); int virtqueue_resize(struct virtqueue *vq, u32 num, void (*recycle)(struct virtqueue *vq, void *buf)); +void virtqueue_disable_dma_api_for_buffers(struct virtqueue *vq); + /** * struct virtio_device - representation of a device using virtio * @index: unique position on the virtio bus