Messages in this thread Patch in this message | | | Date | Thu, 19 Mar 2009 14:51:15 -0700 | From | venkatesh.pallipadi@intel ... | Subject | [patch 3/3] x86, CPA: Add set_pages_arrayuc and set_pages_array_wb |
| |
Add new interfaces set_pages_array_uc() set_pages_array_wb() that can be used change the page attribute for a bunch of pages with flush etc done once at the end of all the changes. These interfaces are similar to existing set_memory_array_uc() and set_memory_array_wc().
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
--- arch/x86/include/asm/cacheflush.h | 3 + arch/x86/mm/pageattr.c | 63 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+)
Index: tip/arch/x86/mm/pageattr.c =================================================================== --- tip.orig/arch/x86/mm/pageattr.c 2009-03-17 11:03:51.000000000 -0700 +++ tip/arch/x86/mm/pageattr.c 2009-03-17 11:04:08.000000000 -0700 @@ -919,6 +919,20 @@ static inline int change_page_attr_clear (array ? CPA_ARRAY : 0), NULL); } +static inline int cpa_set_pages_array(struct page **pages, int numpages, + pgprot_t mask) +{ + return change_page_attr_set_clr(NULL, numpages, mask, __pgprot(0), 0, + CPA_PAGES_ARRAY, pages); +} + +static inline int cpa_clear_pages_array(struct page **pages, int numpages, + pgprot_t mask) +{ + return change_page_attr_set_clr(NULL, numpages, __pgprot(0), mask, 0, + CPA_PAGES_ARRAY, pages); +} + int _set_memory_uc(unsigned long addr, int numpages) { /* @@ -1075,6 +1089,35 @@ int set_pages_uc(struct page *page, int } EXPORT_SYMBOL(set_pages_uc); +int set_pages_array_uc(struct page **pages, int addrinarray) +{ + unsigned long start; + unsigned long end; + int i; + int free_idx; + + for (i = 0; i < addrinarray; i++) { + start = (unsigned long)page_address(pages[i]); + end = start + PAGE_SIZE; + if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) + goto err_out; + } + + if (cpa_set_pages_array(pages, addrinarray, + __pgprot(_PAGE_CACHE_UC_MINUS)) == 0) { + return 0; /* Success */ + } +err_out: + free_idx = i; + for (i = 0; i < free_idx; i++) { + start = (unsigned long)page_address(pages[i]); + end = start + PAGE_SIZE; + free_memtype(start, end); + } + return -EINVAL; +} +EXPORT_SYMBOL(set_pages_array_uc); + int set_pages_wb(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); @@ -1083,6 +1126,26 @@ int set_pages_wb(struct page *page, int } EXPORT_SYMBOL(set_pages_wb); +int set_pages_array_wb(struct page **pages, int addrinarray) +{ + int retval; + unsigned long start; + unsigned long end; + int i; + + retval = cpa_clear_pages_array(pages, addrinarray, + __pgprot(_PAGE_CACHE_MASK)); + + for (i = 0; i < addrinarray; i++) { + start = (unsigned long)page_address(pages[i]); + end = start + PAGE_SIZE; + free_memtype(start, end); + } + + return retval; +} +EXPORT_SYMBOL(set_pages_array_wb); + int set_pages_x(struct page *page, int numpages) { unsigned long addr = (unsigned long)page_address(page); Index: tip/arch/x86/include/asm/cacheflush.h =================================================================== --- tip.orig/arch/x86/include/asm/cacheflush.h 2009-03-13 11:51:31.000000000 -0700 +++ tip/arch/x86/include/asm/cacheflush.h 2009-03-17 11:04:08.000000000 -0700 @@ -90,6 +90,9 @@ int set_memory_4k(unsigned long addr, in int set_memory_array_uc(unsigned long *addr, int addrinarray); int set_memory_array_wb(unsigned long *addr, int addrinarray); +int set_pages_array_uc(struct page **pages, int addrinarray); +int set_pages_array_wb(struct page **pages, int addrinarray); + /* * For legacy compatibility with the old APIs, a few functions * are provided that work on a "struct page". --
| |