• Nicolin Chen's avatar
    dma-mapping: introduce dma_get_seg_boundary_nr_pages() · 1e9d90db
    Nicolin Chen authored
    We found that callers of dma_get_seg_boundary mostly do an ALIGN
    with page mask and then do a page shift to get number of pages:
        ALIGN(boundary + 1, 1 << shift) >> shift
    
    However, the boundary might be as large as ULONG_MAX, which means
    that a device has no specific boundary limit. So either "+ 1" or
    passing it to ALIGN() would potentially overflow.
    
    According to kernel defines:
        #define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
        #define ALIGN(x, a)	ALIGN_MASK(x, (typeof(x))(a) - 1)
    
    We can simplify the logic here into a helper function doing:
      ALIGN(boundary + 1, 1 << shift) >> shift
    = ALIGN_MASK(b + 1, (1 << s) - 1) >> s
    = {[b + 1 + (1 << s) - 1] & ~[(1 << s) - 1]} >> s
    = [b + 1 + (1 << s) - 1] >> s
    = [b + (1 << s)] >> s
    = (b >> s) + 1
    
    This patch introduces and applies dma_get_seg_boundary_nr_pages()
    as an overflow-free helper for the dma_get_seg_boundary() callers
    to get numbers of pages. It also takes care of the NULL dev case
    for non-DMA API callers.
    Suggested-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarNicolin Chen <nicoleotsuka@gmail.com>
    Acked-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
    Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
    Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
    1e9d90db
dma-mapping.h 24.2 KB