Index: sys/compat/linuxkpi/common/include/linux/scatterlist.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/scatterlist.h +++ sys/compat/linuxkpi/common/include/linux/scatterlist.h @@ -66,6 +66,10 @@ } internal; }; +struct sg_dma_page_iter { + struct sg_page_iter base; +}; + #define SCATTERLIST_MAX_SEGMENT (-1U & ~(PAGE_SIZE - 1)) #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) @@ -86,6 +90,9 @@ for (_sg_iter_init(sgl, iter, nents, pgoffset); \ (iter)->sg; _sg_iter_next(iter)) +#define for_each_sg_dma_page(sgl, iter, nents, pgoffset) \ + for_each_sg_page(sgl, &(iter)->base, nents, pgoffset) + #define for_each_sg(sglist, sg, sgmax, iter) \ for (iter = 0, sg = (sglist); iter < (sgmax); iter++, sg = sg_next(sg)) @@ -427,6 +434,37 @@ return (1); } +static int +sg_dma_page_count(struct scatterlist *sg) +{ + return PAGE_ALIGN(sg->offset + sg_dma_len(sg)) >> PAGE_SHIFT; +} + +static inline bool +__sg_page_iter_dma_next(struct sg_dma_page_iter *dma_iter) +{ + struct sg_page_iter *piter = &dma_iter->base; + + if (piter->internal.nents == 0) + return (0); + if (piter->sg == NULL) + return (0); + + piter->sg_pgoffset += piter->internal.pg_advance; + piter->internal.pg_advance = 1; + + while (piter->sg_pgoffset >= sg_dma_page_count(piter->sg)) { + piter->sg_pgoffset -= sg_dma_page_count(piter->sg); + piter->sg = sg_next(piter->sg); + if (--piter->internal.nents == 0) + return (0); + if (piter->sg == NULL) + return (0); + } + + return (true); +} + static inline void _sg_iter_init(struct scatterlist *sgl, struct sg_page_iter *iter, unsigned int nents, unsigned long pgoffset) @@ -443,8 +481,17 @@ } } +/* + * Prevent api breakage by casting the itr + * argument to sg_page_iter. Newer drm code uses + * sg_dma_page_iter. This works because sg_dma_page_itr + * just wraps sg_page_iter. + */ +#define sg_page_iter_dma_address(itr) \ + _sg_page_iter_dma_address((struct sg_page_iter *)itr) + static inline dma_addr_t -sg_page_iter_dma_address(struct sg_page_iter *spi) +_sg_page_iter_dma_address(struct sg_page_iter *spi) { return (spi->sg->dma_address + (spi->sg_pgoffset << PAGE_SHIFT)); }