diff options
author | Robin Murphy <robin.murphy@arm.com> | 2017-01-10 12:51:17 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-01 02:33:13 -0500 |
commit | 776050a9b55e17b72b5684794b9580d72e920e17 (patch) | |
tree | d59368fb4c8390177a238be8cab07a8829c9fab7 | |
parent | 143a9ad4e68cc5c210e6e99e910d6b77cc8a9ec5 (diff) |
virtio_mmio: Set DMA masks appropriately
commit f7f6634d23830ff74335734fbdb28ea109c1f349 upstream.
Once DMA API usage is enabled, it becomes apparent that virtio-mmio is
inadvertently relying on the default 32-bit DMA mask, which leads to
problems like rapidly exhausting SWIOTLB bounce buffers.
Ensure that we set the appropriate 64-bit DMA mask whenever possible,
with the coherent mask suitably limited for the legacy vring as per
a0be1db4304f ("virtio_pci: Limit DMA mask to 44 bits for legacy virtio
devices").
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Michael S. Tsirkin <mst@redhat.com>
Reported-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Fixes: b42111382f0e ("virtio_mmio: Use the DMA API if enabled")
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/virtio/virtio_mmio.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 48bfea91dbca..50840984fbfa 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #define pr_fmt(fmt) "virtio-mmio: " fmt | 59 | #define pr_fmt(fmt) "virtio-mmio: " fmt |
60 | 60 | ||
61 | #include <linux/acpi.h> | 61 | #include <linux/acpi.h> |
62 | #include <linux/dma-mapping.h> | ||
62 | #include <linux/highmem.h> | 63 | #include <linux/highmem.h> |
63 | #include <linux/interrupt.h> | 64 | #include <linux/interrupt.h> |
64 | #include <linux/io.h> | 65 | #include <linux/io.h> |
@@ -497,6 +498,7 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
497 | struct virtio_mmio_device *vm_dev; | 498 | struct virtio_mmio_device *vm_dev; |
498 | struct resource *mem; | 499 | struct resource *mem; |
499 | unsigned long magic; | 500 | unsigned long magic; |
501 | int rc; | ||
500 | 502 | ||
501 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 503 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
502 | if (!mem) | 504 | if (!mem) |
@@ -545,9 +547,25 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
545 | } | 547 | } |
546 | vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); | 548 | vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); |
547 | 549 | ||
548 | if (vm_dev->version == 1) | 550 | if (vm_dev->version == 1) { |
549 | writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); | 551 | writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); |
550 | 552 | ||
553 | rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); | ||
554 | /* | ||
555 | * In the legacy case, ensure our coherently-allocated virtio | ||
556 | * ring will be at an address expressable as a 32-bit PFN. | ||
557 | */ | ||
558 | if (!rc) | ||
559 | dma_set_coherent_mask(&pdev->dev, | ||
560 | DMA_BIT_MASK(32 + PAGE_SHIFT)); | ||
561 | } else { | ||
562 | rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); | ||
563 | } | ||
564 | if (rc) | ||
565 | rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); | ||
566 | if (rc) | ||
567 | dev_warn(&pdev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); | ||
568 | |||
551 | platform_set_drvdata(pdev, vm_dev); | 569 | platform_set_drvdata(pdev, vm_dev); |
552 | 570 | ||
553 | return register_virtio_device(&vm_dev->vdev); | 571 | return register_virtio_device(&vm_dev->vdev); |