On Fri, Jul 31, 2015 at 06:18:27PM +0100, Robin Murphy wrote:
> +int iommu_get_dma_cookie(struct iommu_domain *domain)
> +{
> +     struct iova_domain *iovad;
> +
> +     if (domain->dma_api_cookie)
> +             return -EEXIST;

Why do you call that dma_api_cookie? It is just a pointer to an iova
allocator, you can just name it as such, like domain->iova.

> +static struct iova *__alloc_iova(struct iova_domain *iovad, size_t size,
> +             dma_addr_t dma_limit)

I think you also need a struct device here to take segment boundary and
dma_mask into account.

> +/* The IOVA allocator knows what we mapped, so just unmap whatever that was 
> */
> +static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t 
> dma_addr)
> +{
> +     struct iova_domain *iovad = domain->dma_api_cookie;
> +     unsigned long shift = iova_shift(iovad);
> +     unsigned long pfn = dma_addr >> shift;
> +     struct iova *iova = find_iova(iovad, pfn);
> +     size_t size = iova_size(iova) << shift;
> +
> +     /* ...and if we can't, then something is horribly, horribly wrong */
> +     BUG_ON(iommu_unmap(domain, pfn << shift, size) < size);

This is a WARN_ON at most, not a BUG_ON condition, especially since this
type of bug is also catched with the dma-api debugging code.

> +static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp)
> +{
> +     struct page **pages;
> +     unsigned int i = 0, array_size = count * sizeof(*pages);
> +
> +     if (array_size <= PAGE_SIZE)
> +             pages = kzalloc(array_size, GFP_KERNEL);
> +     else
> +             pages = vzalloc(array_size);
> +     if (!pages)
> +             return NULL;
> +
> +     /* IOMMU can map any pages, so himem can also be used here */
> +     gfp |= __GFP_NOWARN | __GFP_HIGHMEM;
> +
> +     while (count) {
> +             struct page *page = NULL;
> +             int j, order = __fls(count);
> +
> +             /*
> +              * Higher-order allocations are a convenience rather
> +              * than a necessity, hence using __GFP_NORETRY until
> +              * falling back to single-page allocations.
> +              */
> +             for (order = min(order, MAX_ORDER); order > 0; order--) {
> +                     page = alloc_pages(gfp | __GFP_NORETRY, order);
> +                     if (!page)
> +                             continue;
> +                     if (PageCompound(page)) {
> +                             if (!split_huge_page(page))
> +                                     break;
> +                             __free_pages(page, order);
> +                     } else {
> +                             split_page(page, order);
> +                             break;
> +                     }
> +             }
> +             if (!page)
> +                     page = alloc_page(gfp);
> +             if (!page) {
> +                     __iommu_dma_free_pages(pages, i);
> +                     return NULL;
> +             }
> +             j = 1 << order;
> +             count -= j;
> +             while (j--)
> +                     pages[i++] = page++;
> +     }
> +     return pages;
> +}

Hmm, most dma-api implementation just try to allocate a big enough
region from the page-alloctor. Is it implemented different here to avoid
the use of CMA?


        Joerg

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to