From: Alan Mikhak <alan.mik...@sifive.com> Modify sg_miter_stop() to validate the page pointer before calling PageSlab(). This check prevents a crash that will occur if PageSlab() gets called with a page pointer that is not backed by page struct.
A virtual address obtained from ioremap() for a physical address in PCI address space can be assigned to a scatterlist segment using the public scatterlist API as in the following example: my_sg_set_page(struct scatterlist *sg, const void __iomem *ioaddr, size_t iosize) { sg_set_page(sg, virt_to_page(ioaddr), (unsigned int)iosize, offset_in_page(ioaddr)); sg_init_marker(sg, 1); } If the virtual address obtained from ioremap() is not backed by a page struct, virt_to_page() returns an invalid page pointer. However, sg_copy_buffer() can correctly recover the original virtual address. Such addresses can successfully be assigned to scatterlist segments to transfer data across the PCI bus with sg_copy_buffer() if it were not for the crash in PageSlab() when called by sg_miter_stop(). Signed-off-by: Alan Mikhak <alan.mik...@sifive.com> --- lib/scatterlist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/scatterlist.c b/lib/scatterlist.c index c2cf2c311b7d..f5c61cad40ba 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -807,6 +807,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter) miter->__remaining -= miter->consumed; if ((miter->__flags & SG_MITER_TO_SG) && + pfn_valid(page_to_pfn(miter->page)) && !PageSlab(miter->page)) flush_kernel_dcache_page(miter->page); -- 2.7.4