mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
mm: introduce new vm_map_pages() and vm_map_pages_zero() API
Patch series "mm: Use vm_map_pages() and vm_map_pages_zero() API", v5. This patch (of 5): Previouly drivers have their own way of mapping range of kernel pages/memory into user vma and this was done by invoking vm_insert_page() within a loop. As this pattern is common across different drivers, it can be generalized by creating new functions and using them across the drivers. vm_map_pages() is the API which can be used to map kernel memory/pages in drivers which have considered vm_pgoff vm_map_pages_zero() is the API which can be used to map a range of kernel memory/pages in drivers which have not considered vm_pgoff. vm_pgoff is passed as default 0 for those drivers. We _could_ then at a later "fix" these drivers which are using vm_map_pages_zero() to behave according to the normal vm_pgoff offsetting simply by removing the _zero suffix on the function name and if that causes regressions, it gives us an easy way to revert. Tested on Rockchip hardware and display is working, including talking to Lima via prime. Link: http://lkml.kernel.org/r/751cb8a0f4c3e67e95c58a3b072937617f338eea.1552921225.git.jrdr.linux@gmail.com Signed-off-by: Souptick Joarder <[email protected]> Suggested-by: Russell King <[email protected]> Suggested-by: Matthew Wilcox <[email protected]> Reviewed-by: Mike Rapoport <[email protected]> Tested-by: Heiko Stuebner <[email protected]> Cc: Michal Hocko <[email protected]> Cc: "Kirill A. Shutemov" <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Stephen Rothwell <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Robin Murphy <[email protected]> Cc: Joonsoo Kim <[email protected]> Cc: Thierry Reding <[email protected]> Cc: Kees Cook <[email protected]> Cc: Marek Szyprowski <[email protected]> Cc: Stefan Richter <[email protected]> Cc: Sandy Huang <[email protected]> Cc: David Airlie <[email protected]> Cc: Oleksandr Andrushchenko <[email protected]> Cc: Joerg Roedel <[email protected]> Cc: Pawel Osciak <[email protected]> Cc: Kyungmin Park <[email protected]> Cc: Boris Ostrovsky <[email protected]> Cc: Juergen Gross <[email protected]> Cc: Mauro Carvalho Chehab <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
62afcd1cb8
commit
a667d7456f
3 changed files with 99 additions and 0 deletions
81
mm/memory.c
81
mm/memory.c
|
|
@ -1527,6 +1527,87 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
|
|||
}
|
||||
EXPORT_SYMBOL(vm_insert_page);
|
||||
|
||||
/*
|
||||
* __vm_map_pages - maps range of kernel pages into user vma
|
||||
* @vma: user vma to map to
|
||||
* @pages: pointer to array of source kernel pages
|
||||
* @num: number of pages in page array
|
||||
* @offset: user's requested vm_pgoff
|
||||
*
|
||||
* This allows drivers to map range of kernel pages into a user vma.
|
||||
*
|
||||
* Return: 0 on success and error code otherwise.
|
||||
*/
|
||||
static int __vm_map_pages(struct vm_area_struct *vma, struct page **pages,
|
||||
unsigned long num, unsigned long offset)
|
||||
{
|
||||
unsigned long count = vma_pages(vma);
|
||||
unsigned long uaddr = vma->vm_start;
|
||||
int ret, i;
|
||||
|
||||
/* Fail if the user requested offset is beyond the end of the object */
|
||||
if (offset > num)
|
||||
return -ENXIO;
|
||||
|
||||
/* Fail if the user requested size exceeds available object size */
|
||||
if (count > num - offset)
|
||||
return -ENXIO;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = vm_insert_page(vma, uaddr, pages[offset + i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
uaddr += PAGE_SIZE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vm_map_pages - maps range of kernel pages starts with non zero offset
|
||||
* @vma: user vma to map to
|
||||
* @pages: pointer to array of source kernel pages
|
||||
* @num: number of pages in page array
|
||||
*
|
||||
* Maps an object consisting of @num pages, catering for the user's
|
||||
* requested vm_pgoff
|
||||
*
|
||||
* If we fail to insert any page into the vma, the function will return
|
||||
* immediately leaving any previously inserted pages present. Callers
|
||||
* from the mmap handler may immediately return the error as their caller
|
||||
* will destroy the vma, removing any successfully inserted pages. Other
|
||||
* callers should make their own arrangements for calling unmap_region().
|
||||
*
|
||||
* Context: Process context. Called by mmap handlers.
|
||||
* Return: 0 on success and error code otherwise.
|
||||
*/
|
||||
int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
|
||||
unsigned long num)
|
||||
{
|
||||
return __vm_map_pages(vma, pages, num, vma->vm_pgoff);
|
||||
}
|
||||
EXPORT_SYMBOL(vm_map_pages);
|
||||
|
||||
/**
|
||||
* vm_map_pages_zero - map range of kernel pages starts with zero offset
|
||||
* @vma: user vma to map to
|
||||
* @pages: pointer to array of source kernel pages
|
||||
* @num: number of pages in page array
|
||||
*
|
||||
* Similar to vm_map_pages(), except that it explicitly sets the offset
|
||||
* to 0. This function is intended for the drivers that did not consider
|
||||
* vm_pgoff.
|
||||
*
|
||||
* Context: Process context. Called by mmap handlers.
|
||||
* Return: 0 on success and error code otherwise.
|
||||
*/
|
||||
int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
|
||||
unsigned long num)
|
||||
{
|
||||
return __vm_map_pages(vma, pages, num, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(vm_map_pages_zero);
|
||||
|
||||
static vm_fault_t insert_pfn(struct vm_area_struct *vma, unsigned long addr,
|
||||
pfn_t pfn, pgprot_t prot, bool mkwrite)
|
||||
{
|
||||
|
|
|
|||
14
mm/nommu.c
14
mm/nommu.c
|
|
@ -473,6 +473,20 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
|
|||
}
|
||||
EXPORT_SYMBOL(vm_insert_page);
|
||||
|
||||
int vm_map_pages(struct vm_area_struct *vma, struct page **pages,
|
||||
unsigned long num)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(vm_map_pages);
|
||||
|
||||
int vm_map_pages_zero(struct vm_area_struct *vma, struct page **pages,
|
||||
unsigned long num)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(vm_map_pages_zero);
|
||||
|
||||
/*
|
||||
* sys_brk() for the most part doesn't need the global kernel
|
||||
* lock, except when an application is doing something nasty
|
||||
|
|
|
|||
Loading…
Reference in a new issue