Re: [PATCH 10 of 20] ipath - support for userspace apps using core driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux