Merge tag 'smack-for-5.4-rc1' of git://github.com/cschaufler/smack-next
[linux-2.6-microblaze.git] / kernel / dma / mapping.c
index b0038ca..d9334f3 100644 (file)
@@ -136,17 +136,29 @@ int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
        return ret;
 }
 
+/*
+ * The whole dma_get_sgtable() idea is fundamentally unsafe - it seems
+ * that the intention is to allow exporting memory allocated via the
+ * coherent DMA APIs through the dma_buf API, which only accepts a
+ * scattertable.  This presents a couple of problems:
+ * 1. Not all memory allocated via the coherent DMA APIs is backed by
+ *    a struct page
+ * 2. Passing coherent DMA memory into the streaming APIs is not allowed
+ *    as we will try to flush the memory through a different alias to that
+ *    actually being used (and the flushes are redundant.)
+ */
 int dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt,
                void *cpu_addr, dma_addr_t dma_addr, size_t size,
                unsigned long attrs)
 {
        const struct dma_map_ops *ops = get_dma_ops(dev);
 
-       if (!dma_is_direct(ops) && ops->get_sgtable)
-               return ops->get_sgtable(dev, sgt, cpu_addr, dma_addr, size,
-                                       attrs);
-       return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr, size,
-                       attrs);
+       if (dma_is_direct(ops))
+               return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr,
+                               size, attrs);
+       if (!ops->get_sgtable)
+               return -ENXIO;
+       return ops->get_sgtable(dev, sgt, cpu_addr, dma_addr, size, attrs);
 }
 EXPORT_SYMBOL(dma_get_sgtable_attrs);
 
@@ -161,9 +173,11 @@ pgprot_t dma_pgprot(struct device *dev, pgprot_t prot, unsigned long attrs)
            (IS_ENABLED(CONFIG_DMA_NONCOHERENT_CACHE_SYNC) &&
              (attrs & DMA_ATTR_NON_CONSISTENT)))
                return prot;
-       if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_MMAP_PGPROT))
-               return arch_dma_mmap_pgprot(dev, prot, attrs);
-       return pgprot_noncached(prot);
+#ifdef CONFIG_ARCH_HAS_DMA_WRITE_COMBINE
+       if (attrs & DMA_ATTR_WRITE_COMBINE)
+               return pgprot_writecombine(prot);
+#endif
+       return pgprot_dmacoherent(prot);
 }
 #endif /* CONFIG_MMU */
 
@@ -174,7 +188,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
                void *cpu_addr, dma_addr_t dma_addr, size_t size,
                unsigned long attrs)
 {
-#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
+#ifdef CONFIG_MMU
        unsigned long user_count = vma_pages(vma);
        unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        unsigned long off = vma->vm_pgoff;
@@ -205,8 +219,29 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
                        user_count << PAGE_SHIFT, vma->vm_page_prot);
 #else
        return -ENXIO;
-#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
+#endif /* CONFIG_MMU */
+}
+
+/**
+ * dma_can_mmap - check if a given device supports dma_mmap_*
+ * @dev: device to check
+ *
+ * Returns %true if @dev supports dma_mmap_coherent() and dma_mmap_attrs() to
+ * map DMA allocations to userspace.
+ */
+bool dma_can_mmap(struct device *dev)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev);
+
+       if (dma_is_direct(ops)) {
+               return IS_ENABLED(CONFIG_MMU) &&
+                      (dev_is_dma_coherent(dev) ||
+                       IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN));
+       }
+
+       return ops->mmap != NULL;
 }
+EXPORT_SYMBOL_GPL(dma_can_mmap);
 
 /**
  * dma_mmap_attrs - map a coherent DMA allocation into user space
@@ -227,31 +262,15 @@ int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 {
        const struct dma_map_ops *ops = get_dma_ops(dev);
 
-       if (!dma_is_direct(ops) && ops->mmap)
-               return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
-       return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
+       if (dma_is_direct(ops))
+               return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size,
+                               attrs);
+       if (!ops->mmap)
+               return -ENXIO;
+       return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
 }
 EXPORT_SYMBOL(dma_mmap_attrs);
 
-static u64 dma_default_get_required_mask(struct device *dev)
-{
-       u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
-       u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
-       u64 mask;
-
-       if (!high_totalram) {
-               /* convert to mask just covering totalram */
-               low_totalram = (1 << (fls(low_totalram) - 1));
-               low_totalram += low_totalram - 1;
-               mask = low_totalram;
-       } else {
-               high_totalram = (1 << (fls(high_totalram) - 1));
-               high_totalram += high_totalram - 1;
-               mask = (((u64)high_totalram) << 32) + 0xffffffff;
-       }
-       return mask;
-}
-
 u64 dma_get_required_mask(struct device *dev)
 {
        const struct dma_map_ops *ops = get_dma_ops(dev);
@@ -260,7 +279,16 @@ u64 dma_get_required_mask(struct device *dev)
                return dma_direct_get_required_mask(dev);
        if (ops->get_required_mask)
                return ops->get_required_mask(dev);
-       return dma_default_get_required_mask(dev);
+
+       /*
+        * We require every DMA ops implementation to at least support a 32-bit
+        * DMA mask (and use bounce buffering if that isn't supported in
+        * hardware).  As the direct mapping code has its own routine to
+        * actually report an optimal mask we default to 32-bit here as that
+        * is the right thing for most IOMMUs, and at least not actively
+        * harmful in general.
+        */
+       return DMA_BIT_MASK(32);
 }
 EXPORT_SYMBOL_GPL(dma_get_required_mask);
 
@@ -317,12 +345,6 @@ void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 }
 EXPORT_SYMBOL(dma_free_attrs);
 
-static inline void dma_check_mask(struct device *dev, u64 mask)
-{
-       if (sme_active() && (mask < (((u64)sme_get_me_mask() << 1) - 1)))
-               dev_warn(dev, "SME is active, device will require DMA bounce buffers\n");
-}
-
 int dma_supported(struct device *dev, u64 mask)
 {
        const struct dma_map_ops *ops = get_dma_ops(dev);
@@ -353,7 +375,6 @@ int dma_set_mask(struct device *dev, u64 mask)
                return -EIO;
 
        arch_dma_set_mask(dev, mask);
-       dma_check_mask(dev, mask);
        *dev->dma_mask = mask;
        return 0;
 }
@@ -371,7 +392,6 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
        if (!dma_supported(dev, mask))
                return -EIO;
 
-       dma_check_mask(dev, mask);
        dev->coherent_dma_mask = mask;
        return 0;
 }
@@ -405,3 +425,14 @@ size_t dma_max_mapping_size(struct device *dev)
        return size;
 }
 EXPORT_SYMBOL_GPL(dma_max_mapping_size);
+
+unsigned long dma_get_merge_boundary(struct device *dev)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev);
+
+       if (!ops || !ops->get_merge_boundary)
+               return 0;       /* can't merge */
+
+       return ops->get_merge_boundary(dev);
+}
+EXPORT_SYMBOL_GPL(dma_get_merge_boundary);