Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6344437 authored by Sudeep Dutt's avatar Sudeep Dutt Committed by Greg Kroah-Hartman
Browse files

misc: mic: scif bug fix for vmalloc_to_page crash

v4.2-rc1 enabled huge page support for ioremap(..).
Calling vmalloc_to_page after v4.2-rc1 results in the
crash shown below on the host upon booting X100 coprocessors:

BUG: unable to handle kernel paging request at ffffc47c00000000
IP: [<ffffffff811a2c0c>] vmalloc_to_page+0x6c/0xb0

This patch fixes this crash by obtaining the fake struct page
pointer which is required to be passed into dma_map_sg(..)
by calling pfn_to_page(..) instead of vmalloc_to_page(..).

Link: https://lkml.org/lkml/2015/7/18/110


Reviewed-by: default avatarNikhil Rao <nikhil.rao@intel.com>
Suggested-by: default avatarToshi Kani <toshi.kani@hp.com>
Signed-off-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarSudeep Dutt <sudeep.dutt@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 68d35c7b
Loading
Loading
Loading
Loading
+5 −10
Original line number Original line Diff line number Diff line
@@ -357,7 +357,7 @@ static void scif_p2p_freesg(struct scatterlist *sg)
}
}


static struct scatterlist *
static struct scatterlist *
scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt)
scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt)
{
{
	struct scatterlist *sg;
	struct scatterlist *sg;
	struct page *page;
	struct page *page;
@@ -368,16 +368,11 @@ scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt)
		return NULL;
		return NULL;
	sg_init_table(sg, page_cnt);
	sg_init_table(sg, page_cnt);
	for (i = 0; i < page_cnt; i++) {
	for (i = 0; i < page_cnt; i++) {
		page = vmalloc_to_page((void __force *)va);
		page = pfn_to_page(pa >> PAGE_SHIFT);
		if (!page)
			goto p2p_sg_err;
		sg_set_page(&sg[i], page, page_size, 0);
		sg_set_page(&sg[i], page, page_size, 0);
		va += page_size;
		pa += page_size;
	}
	}
	return sg;
	return sg;
p2p_sg_err:
	kfree(sg);
	return NULL;
}
}


/* Init p2p mappings required to access peerdev from scifdev */
/* Init p2p mappings required to access peerdev from scifdev */
@@ -395,14 +390,14 @@ scif_init_p2p_info(struct scif_dev *scifdev, struct scif_dev *peerdev)
	p2p = kzalloc(sizeof(*p2p), GFP_KERNEL);
	p2p = kzalloc(sizeof(*p2p), GFP_KERNEL);
	if (!p2p)
	if (!p2p)
		return NULL;
		return NULL;
	p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->va,
	p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa,
						    PAGE_SIZE, num_mmio_pages);
						    PAGE_SIZE, num_mmio_pages);
	if (!p2p->ppi_sg[SCIF_PPI_MMIO])
	if (!p2p->ppi_sg[SCIF_PPI_MMIO])
		goto free_p2p;
		goto free_p2p;
	p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages;
	p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages;
	sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30)));
	sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30)));
	num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT);
	num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT);
	p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->va,
	p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa,
						    1 << sg_page_shift,
						    1 << sg_page_shift,
						    num_aper_chunks);
						    num_aper_chunks);
	p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks;
	p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks;