lkml.org 
[lkml]   [2006]   [Mar]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 10 of 20] ipath - support for userspace apps using core driver


    On Thu, 16 Mar 2006, Bryan O'Sullivan wrote:
    >
    > This is precisely our case, btw. The pages in question are allocated
    > during fops->open (some during dev->probe). mmap and nopage never
    > allocate anything.

    If the mapping isn't actually dynamic, then you really should use either:

    - remap_pfn_range() (for when you have a physically consecutive page
    mapping)
    - vm_insert_page() (for when you have individual pages).

    at mmap time. Either of those will then do the right thing at unmap.

    The rules are:

    - remap_pfn_range() doesn't muck around with "struct page" AT ALL, so you
    can pass it damn well anything you want these days. It doesn't care,
    the VM doesn't care, there's no ref-counting or page flag checking
    either on the mmap or the munmap parh.

    So with remap_pfn_range(), you can literally do just

    remap_pfn_range(vma,
    vma->vm_start,
    device->phys_dma_address >> PAGE_SHIFT,
    device->phys_dma_size,
    vma->vm_page_prot);

    and the VM will not care what that DMA region is (it might, for
    example, be actual device memory, not real RAM at all). But this should
    only be used on memory that will be guaranteed to be around for as long
    as the mapping exists (which you can guarantee by doing refcounting of
    your own "struct file"s, of course).

    Normally, you'd use remap_pfn_range() only for special allocations.
    Most commonly, it's not RAM at all, but the PCI MMIO memory window to
    the hardware itself.

    - vm_insert_page() wants _individual_ pages that have been allocated as
    such by the page allocator. You can't pass it a kmalloc'ed area or
    anything like that, but you _can_ pass it anything that works with the
    page allocator. It will increment the page count appropriately for the
    mapping, so you should think of it as a no-op: you can do

    ...
    page = get_free_page(..);
    if (!page)
    return -ENOMEM;
    vm_insert_page(mm, addr, page, prot);
    ...

    .. and then in your close/module_exit routine ..
    free_page(page);

    ie you should do the freeing of _your_ references (you got one when you
    allocated the page, so you should free it), and the VM layer will track
    _its_ references (ie vm_insert_page() will do whatever is correct so
    that when the VM gets unmapped, the page really gets freed)

    As a special case (it's not actually a special case in the VM, but as
    far as _usage_ is concerned, it's different from the "allocate
    individual pages" case), if you allocate a single large _compound_ page
    with __GFP_COMP, you can then use vm_insert_page() to insert the
    sub-pages individually in the mapping. IOW, you can do

    /* Get a compound page of order 4 (16 pages) */
    bigpage = __get_free_pages(GFP_USER | __GFP_COMP, 4);
    for (i = 0; i < 15; i++)
    vm_insert_page(mm, addr + (i << PAGE_SHIFT), bigpage + i, prot);


    .. in close/module-exit ..
    free_page(bigpage);

    Hope this clarifies.

    Linus
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2009-11-18 23:46    [W:4.444 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site