]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - lib/swiotlb.c
lib/genalloc.c: use vzalloc_node() to allocate the bitmap
[mirror_ubuntu-bionic-kernel.git] / lib / swiotlb.c
index cea19aaf303c9f3c558dd8246205ed39f38dcc46..2fab4208728f95ad4506bf5015744718fca19882 100644 (file)
@@ -17,6 +17,8 @@
  * 08/12/11 beckyb     Add highmem support
  */
 
+#define pr_fmt(fmt) "software IO TLB: " fmt
+
 #include <linux/cache.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
@@ -177,20 +179,16 @@ static bool no_iotlb_memory;
 void swiotlb_print_info(void)
 {
        unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
-       unsigned char *vstart, *vend;
 
        if (no_iotlb_memory) {
-               pr_warn("software IO TLB: No low mem\n");
+               pr_warn("No low mem\n");
                return;
        }
 
-       vstart = phys_to_virt(io_tlb_start);
-       vend = phys_to_virt(io_tlb_end);
-
-       printk(KERN_INFO "software IO TLB [mem %#010llx-%#010llx] (%luMB) mapped at [%p-%p]\n",
+       pr_info("mapped [mem %#010llx-%#010llx] (%luMB)\n",
               (unsigned long long)io_tlb_start,
               (unsigned long long)io_tlb_end,
-              bytes >> 20, vstart, vend - 1);
+              bytes >> 20);
 }
 
 /*
@@ -290,7 +288,7 @@ swiotlb_init(int verbose)
        if (io_tlb_start)
                memblock_free_early(io_tlb_start,
                                    PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
-       pr_warn("Cannot allocate SWIOTLB buffer");
+       pr_warn("Cannot allocate buffer");
        no_iotlb_memory = true;
 }
 
@@ -332,8 +330,8 @@ swiotlb_late_init_with_default_size(size_t default_size)
                return -ENOMEM;
        }
        if (order != get_order(bytes)) {
-               printk(KERN_WARNING "Warning: only able to allocate %ld MB "
-                      "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
+               pr_warn("only able to allocate %ld MB\n",
+                       (PAGE_SIZE << order) >> 20);
                io_tlb_nslabs = SLABS_PER_PAGE << order;
        }
        rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
@@ -586,7 +584,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
 
 not_found:
        spin_unlock_irqrestore(&io_tlb_lock, flags);
-       if (printk_ratelimit())
+       if (!(attrs & DMA_ATTR_NO_WARN) && printk_ratelimit())
                dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", size);
        return SWIOTLB_MAP_ERROR;
 found:
@@ -713,6 +711,7 @@ void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                       dma_addr_t *dma_handle, gfp_t flags)
 {
+       bool warn = !(flags & __GFP_NOWARN);
        dma_addr_t dev_addr;
        void *ret;
        int order = get_order(size);
@@ -738,8 +737,8 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                 * GFP_DMA memory; fall back on map_single(), which
                 * will grab memory from the lowest available address range.
                 */
-               phys_addr_t paddr = map_single(hwdev, 0, size,
-                                              DMA_FROM_DEVICE, 0);
+               phys_addr_t paddr = map_single(hwdev, 0, size, DMA_FROM_DEVICE,
+                                              warn ? 0 : DMA_ATTR_NO_WARN);
                if (paddr == SWIOTLB_MAP_ERROR)
                        goto err_warn;
 
@@ -769,9 +768,11 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
        return ret;
 
 err_warn:
-       pr_warn("swiotlb: coherent allocation failed for device %s size=%zu\n",
-               dev_name(hwdev), size);
-       dump_stack();
+       if (warn && printk_ratelimit()) {
+               pr_warn("coherent allocation failed for device %s size=%zu\n",
+                       dev_name(hwdev), size);
+               dump_stack();
+       }
 
        return NULL;
 }
@@ -796,34 +797,6 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
 }
 EXPORT_SYMBOL(swiotlb_free_coherent);
 
-static void
-swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
-            int do_panic)
-{
-       if (swiotlb_force == SWIOTLB_NO_FORCE)
-               return;
-
-       /*
-        * Ran out of IOMMU space for this operation. This is very bad.
-        * Unfortunately the drivers cannot handle this operation properly.
-        * unless they check for dma_mapping_error (most don't)
-        * When the mapping is small enough return a static buffer to limit
-        * the damage, or panic when the transfer is too big.
-        */
-       dev_err_ratelimited(dev, "DMA: Out of SW-IOMMU space for %zu bytes\n",
-                           size);
-
-       if (size <= io_tlb_overflow || !do_panic)
-               return;
-
-       if (dir == DMA_BIDIRECTIONAL)
-               panic("DMA: Random memory could be DMA accessed\n");
-       if (dir == DMA_FROM_DEVICE)
-               panic("DMA: Random memory could be DMA written\n");
-       if (dir == DMA_TO_DEVICE)
-               panic("DMA: Random memory could be DMA read\n");
-}
-
 /*
  * Map a single buffer of the indicated size for DMA in streaming mode.  The
  * physical address to use is returned.
@@ -852,10 +825,8 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
 
        /* Oh well, have to allocate and map a bounce buffer. */
        map = map_single(dev, phys, size, dir, attrs);
-       if (map == SWIOTLB_MAP_ERROR) {
-               swiotlb_full(dev, size, dir, 1);
+       if (map == SWIOTLB_MAP_ERROR)
                return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
-       }
 
        dev_addr = swiotlb_phys_to_dma(dev, map);
 
@@ -993,7 +964,6 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
                        if (map == SWIOTLB_MAP_ERROR) {
                                /* Don't panic here, we expect map_sg users
                                   to do proper error handling. */
-                               swiotlb_full(hwdev, sg->length, dir, 0);
                                attrs |= DMA_ATTR_SKIP_CPU_SYNC;
                                swiotlb_unmap_sg_attrs(hwdev, sgl, i, dir,
                                                       attrs);