<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(&amp;pcidev-&gt;dev, pr_fmt("IOCTL:
    IOCTL_FPGA_PIN_PAGE\n"));<br>
    <br>
                if(!copy_from_user(&amp;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&lt;pinned; ++i) {<br>
                        sg_set_page(&amp;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&lt;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(&amp;pageInfo));<br>
                    copy_to_user((void*)arg, &amp;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(&amp;chunk, pagesize, chunksize))
    {<br>
            std::cout &lt;&lt; "Could not get a page." &lt;&lt;
    std::endl;<br>
            return error;<br>
        }<br>
  </body>
</html>