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; } |
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@xxxxxxxxxxxxxxxxx http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies