lkml.org 
[lkml]   [2011]   [Oct]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    SubjectRe: [PATCH v3 1/6] iommu/core: split mapping to page sizes as supported by the hardware
    From
    On Tue, Oct 11, 2011 at 7:49 AM, Ohad Ben-Cohen <ohad@wizery.com> wrote:
    >  int iommu_map(struct iommu_domain *domain, unsigned long iova,
    > -             phys_addr_t paddr, int gfp_order, int prot)
    > +             phys_addr_t paddr, int size, int prot)
    >  {
    Even though it is not realistic that size becomes larger than 1 <<
    ((sizeof(int) * 8) - 1),
    I think the type of size should be size_t.

    > -       size_t size;
    > +       unsigned long orig_iova = iova;
    > +       int ret = 0, orig_size = size;
    >
    >        if (unlikely(domain->ops->map == NULL))
    >                return -ENODEV;
    >
    > -       size         = PAGE_SIZE << gfp_order;
    > +       /*
    > +        * both the virtual address and the physical one, as well as
    > +        * the size of the mapping, must be aligned (at least) to the
    > +        * size of the smallest page supported by the hardware
    > +        */
    > +       if (!IS_ALIGNED(iova | paddr | size, domain->ops->min_pagesz)) {
    > +               pr_err("unaligned: iova 0x%lx pa 0x%lx size 0x%x min_pagesz "
    > +                       "0x%x\n", iova, (unsigned long)paddr,
    > +                       size, domain->ops->min_pagesz);
    > +               return -EINVAL;
    > +       }
    > +
    > +       pr_debug("map: iova 0x%lx pa 0x%lx size 0x%x\n", iova,
    > +                               (unsigned long)paddr, size);
    > +
    > +       while (size) {
    > +               unsigned long pgsize, addr_merge = iova | paddr;
    > +               unsigned int pgsize_idx;
    > +
    > +               /* Max page size that still fits into 'size' */
    > +               pgsize_idx = __fls(size);
    > +
    > +               /* need to consider alignment requirements ? */
    > +               if (likely(addr_merge)) {
    > +                       /* Max page size allowed by both iova and paddr */
    > +                       unsigned int align_pgsize_idx = __ffs(addr_merge);
    > +
    > +                       pgsize_idx = min(pgsize_idx, align_pgsize_idx);
    > +               }
    > +
    > +               /* build a mask of acceptable page sizes */
    > +               pgsize = (1UL << (pgsize_idx + 1)) - 1;
    > +
    > +               /* throw away page sizes not supported by the hardware */
    > +               pgsize &= domain->ops->pgsize_bitmap;
    > +
    > +               /* make sure we're still sane */
    > +               BUG_ON(!pgsize);
    >
    > -       BUG_ON(!IS_ALIGNED(iova | paddr, size));
    > +               /* pick the biggest page */
    > +               pgsize_idx = __fls(pgsize);
    > +               pgsize = 1UL << pgsize_idx;
    >
    > -       return domain->ops->map(domain, iova, paddr, gfp_order, prot);
    > +               /* convert index to page order */
    > +               pgsize_idx -= PAGE_SHIFT;
    > +
    > +               pr_debug("mapping: iova 0x%lx pa 0x%lx order %u\n", iova,
    > +                                       (unsigned long)paddr, pgsize_idx);
    > +
    > +               ret = domain->ops->map(domain, iova, paddr, pgsize_idx, prot);
    > +               if (ret)
    > +                       break;
    > +
    > +               iova += pgsize;
    > +               paddr += pgsize;
    > +               size -= pgsize;
    > +       }
    > +
    > +       /* unroll mapping in case something went wrong */
    > +       if (ret)
    > +               iommu_unmap(domain, orig_iova, orig_size);
    > +
    domain->ops->map() might return error because a mapping already exists
    in the range from iova until iova + size.
    Thus, it should be
    iommu_unmap(domain, orig_iova, orig_size - size)

    Regards,

    KyongHo
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2011-10-11 17:03    [W:3.110 / U:0.552 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site