Hi Robin I now see your patch and it does seem to be fix the problem. On Thu, Sep 28, 2017 at 08:43:46AM -0700, Ashok Raj wrote: > Hi Robin > > > On Thu, Sep 28, 2017 at 05:59:11PM +0100, Robin Murphy wrote: > > I hope our email server hasn't got blacklisted again... Said patch is > > the top of this very thread we're replying on[1] - you were definitely > > on cc :( > > (sg->dma_address + sg->dma_len) ----+ > sg->dma_address ---------+ | > iov_pfn------+ | | > | | | > v v v > iova: a b c d e f > |--------|--------|--------|--------|--------| > <...calculated....> > [_____mapped______] > pfn: 0 1 2 3 4 5 > |--------|--------|--------|--------|--------| > ^ ^ ^ > | | | > sg->page ----+ | | > sg->offset --------------+ | > (sg->offset + sg->length) ----------+ > > The picture seems right. Looking at the code i'm not sure if i understand > it correctly. > > pgoff = sg->offset & ~PAGE_MASK; > > this gets the offset past the start of page. > > sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff; > > this would set dma_address at b+off instead of starting at c+off correct? I assumed align_nrpages() would allocate 2 pages when the offset is over PAGE_SIZE, but it seems economical and only allocates 1 page to cover just the sg->length bytes. the pteval also seems correct now, since you changed to sg_phys() that already accounts for sg->offset, so you subtract pgoff. - pteval = page_to_phys(sg_page(sg)) | prot; + pteval = (sg_phys(sg) - pgoff) | prot; Cheers, Ashok