<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
Hi,<br>
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.<br>
<br>
When I run my code I get a "<b>BUG: Bad page map in process ...</b>",
after "Done" is printed.<br>
<br>
I tried following DMA-API-howto.txt and looking at other code, but I
fail to see where I go wrong.<br>
<br>
Regards, Ted<br>
<br>
<br>
Code from the IOCTL handler:<br>
<br>
case IOCTL_FPGA_PIN_PAGE:<br>
{<br>
struct pageInfo pageInfo;<br>
<br>
dev_dbg(&pcidev->dev, pr_fmt("IOCTL:
IOCTL_FPGA_PIN_PAGE\n"));<br>
<br>
if(!copy_from_user(&pageInfo, (void*)arg,
sizeof(struct pageInfo))) {<br>
//horrible test<br>
const int noPages = pageInfo.size/PAGE_SIZE;<br>
int pinned;<br>
int mapped = 0;<br>
struct scatterlist* scatterlist;<br>
printk("Test start\n");<br>
//userspacestartpointer, nopages, write?, page*
array<br>
struct page** pages=kmalloc(sizeof(struct
page*)*noPages, GFP_KERNEL);<br>
pinned=<b>get_user_pages_fast</b>((unsigned
long)pageInfo.start, noPages, 1, pages);<br>
<br>
scatterlist = kmalloc(sizeof(struct
scatterlist)*pinned, GFP_KERNEL);<br>
<br>
for(int i=0; i<pinned; ++i) {<br>
sg_set_page(&scatterlist[i], pages[i],
PAGE_SIZE, 0);<br>
}<br>
<br>
mapped =<b> pci_map_sg</b>(pcidev, scatterlist,
pinned, DMA_BIDIRECTIONAL);<br>
<b>pci_unmap_sg</b>(pcidev, scatterlist, pinned,
DMA_BIDIRECTIONAL);<br>
<br>
for(int i=0; i<pinned; ++i) {<br>
<b>put_page</b>(pages[i]); //I did place a
print here and got two pages unpinned as I expected<br>
}<br>
kfree(scatterlist);<br>
kfree(pages);<br>
printk("Done\n");<br>
/*pageInfo.pageId =
getPageId(getArea(&pageInfo));<br>
copy_to_user((void*)arg, &pageInfo,
sizeof(struct pageInfo));*/<br>
return pageInfo.pageId;<br>
} else {<br>
return -EFAULT;<br>
}<br>
}<br>
break;<br>
<br>
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:<br>
<br>
const int pagesize = sysconf(_SC_PAGESIZE);<br>
const int chunksize = 2*pagesize;<br>
void* chunk;<br>
<br>
if(int error = posix_memalign(&chunk, pagesize, chunksize))
{<br>
std::cout << "Could not get a page." <<
std::endl;<br>
return error;<br>
}<br>
</body>
</html>