Merge remote-tracking branches 'asoc/fix/atmel', 'asoc/fix/compress', 'asoc/fix/da721...
[cascardo/linux.git] / drivers / iommu / dma-iommu.c
index ea5a9eb..00c8a08 100644 (file)
@@ -68,7 +68,8 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
        if (!iovad)
                return;
 
-       put_iova_domain(iovad);
+       if (iovad->granule)
+               put_iova_domain(iovad);
        kfree(iovad);
        domain->iova_cookie = NULL;
 }
@@ -151,12 +152,15 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent)
        }
 }
 
-static struct iova *__alloc_iova(struct iova_domain *iovad, size_t size,
+static struct iova *__alloc_iova(struct iommu_domain *domain, size_t size,
                dma_addr_t dma_limit)
 {
+       struct iova_domain *iovad = domain->iova_cookie;
        unsigned long shift = iova_shift(iovad);
        unsigned long length = iova_align(iovad, size) >> shift;
 
+       if (domain->geometry.force_aperture)
+               dma_limit = min(dma_limit, domain->geometry.aperture_end);
        /*
         * Enforce size-alignment to be safe - there could perhaps be an
         * attribute to control this per-device, or at least per-domain...
@@ -286,7 +290,7 @@ void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
  *        or NULL on failure.
  */
 struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
-               struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+               unsigned long attrs, int prot, dma_addr_t *handle,
                void (*flush_page)(struct device *, const void *, phys_addr_t))
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
@@ -306,7 +310,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
        } else {
                size = ALIGN(size, min_size);
        }
-       if (dma_get_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, attrs))
+       if (attrs & DMA_ATTR_ALLOC_SINGLE_PAGES)
                alloc_sizes = min_size;
 
        count = PAGE_ALIGN(size) >> PAGE_SHIFT;
@@ -314,7 +318,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
        if (!pages)
                return NULL;
 
-       iova = __alloc_iova(iovad, size, dev->coherent_dma_mask);
+       iova = __alloc_iova(domain, size, dev->coherent_dma_mask);
        if (!iova)
                goto out_free_pages;
 
@@ -386,7 +390,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
        phys_addr_t phys = page_to_phys(page) + offset;
        size_t iova_off = iova_offset(iovad, phys);
        size_t len = iova_align(iovad, size + iova_off);
-       struct iova *iova = __alloc_iova(iovad, len, dma_get_mask(dev));
+       struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
 
        if (!iova)
                return DMA_ERROR_CODE;
@@ -400,7 +404,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
 }
 
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
-               enum dma_data_direction dir, struct dma_attrs *attrs)
+               enum dma_data_direction dir, unsigned long attrs)
 {
        __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
 }
@@ -538,7 +542,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
                prev = s;
        }
 
-       iova = __alloc_iova(iovad, iova_len, dma_get_mask(dev));
+       iova = __alloc_iova(domain, iova_len, dma_get_mask(dev));
        if (!iova)
                goto out_restore_sg;
 
@@ -560,7 +564,7 @@ out_restore_sg:
 }
 
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-               enum dma_data_direction dir, struct dma_attrs *attrs)
+               enum dma_data_direction dir, unsigned long attrs)
 {
        /*
         * The scatterlist segments are mapped into a single