Propper use of pci_map_sg
Malte Vesper
malte.vesper at postgrad.manchester.ac.uk
Thu Jan 29 14:50:52 EST 2015
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;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.kernelnewbies.org/pipermail/kernelnewbies/attachments/20150129/ab36b03d/attachment.html
More information about the Kernelnewbies
mailing list