Hi,
I am trying to use pci_map_sg in combination with
get_user_pages_fast for a driver. However my code screws the
processes memory map over. For easier testing I bundled the
piinin/unpinning and mapping unmapping into one ioctl call. The
following code misses all the checks on return values, since it is
only inteneded as a MWE.
When I run my code I get a "BUG: Bad page map in process ...",
after "Done" is printed.
I tried following DMA-API-howto.txt and looking at other code, but I
fail to see where I go wrong.
Regards, Ted
Code from the IOCTL handler:
case IOCTL_FPGA_PIN_PAGE:
{
struct pageInfo pageInfo;
dev_dbg(&pcidev->dev, pr_fmt("IOCTL:
IOCTL_FPGA_PIN_PAGE\n"));
if(!copy_from_user(&pageInfo, (void*)arg,
sizeof(struct pageInfo))) {
//horrible test
const int noPages = pageInfo.size/PAGE_SIZE;
int pinned;
int mapped = 0;
struct scatterlist* scatterlist;
printk("Test start\n");
//userspacestartpointer, nopages, write?, page*
array
struct page** pages=kmalloc(sizeof(struct
page*)*noPages, GFP_KERNEL);
pinned=get_user_pages_fast((unsigned
long)pageInfo.start, noPages, 1, pages);
scatterlist = kmalloc(sizeof(struct
scatterlist)*pinned, GFP_KERNEL);
for(int i=0; i<pinned; ++i) {
sg_set_page(&scatterlist[i], pages[i],
PAGE_SIZE, 0);
}
mapped = pci_map_sg(pcidev, scatterlist,
pinned, DMA_BIDIRECTIONAL);
pci_unmap_sg(pcidev, scatterlist, pinned,
DMA_BIDIRECTIONAL);
for(int i=0; i<pinned; ++i) {
put_page(pages[i]); //I did place a
print here and got two pages unpinned as I expected
}
kfree(scatterlist);
kfree(pages);
printk("Done\n");
/*pageInfo.pageId =
getPageId(getArea(&pageInfo));
copy_to_user((void*)arg, &pageInfo,
sizeof(struct pageInfo));*/
return pageInfo.pageId;
} else {
return -EFAULT;
}
}
break;
P.S.: I used the following code to allocate the memory in userspace,
and I use chunk and chunksize to fill pageInfo.start and
pageInfo.size respectivly:
const int pagesize = sysconf(_SC_PAGESIZE);
const int chunksize = 2*pagesize;
void* chunk;
if(int error = posix_memalign(&chunk, pagesize, chunksize))
{
std::cout << "Could not get a page." <<
std::endl;
return error;
}