diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2009-08-03 03:25:45 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-03 13:36:09 -0400 |
commit | 8523acfe40efc1a8d3da8f473ca67cb195b06f0c (patch) | |
tree | 718817f1db5e19edf9c8d3df7d24581c11d27b60 | |
parent | bdc6340f4eb68295b1e7c0ade2356b56dca93d93 (diff) |
x86: Fix CPA memtype reserving in the set_pages_array*() cases
The code was incorrectly reserving memtypes using the page
virtual address instead of the physical address. Furthermore,
the code was not ignoring highmem pages as it ought to.
( upstream does not pass in highmem pages yet - but upcoming
graphics code will do it and there's no reason to not handle
this properly in the CPA APIs.)
Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=13884
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: <stable@kernel.org>
Cc: dri-devel@lists.sourceforge.net
Cc: venkatesh.pallipadi@intel.com
LKML-Reference: <1249284345-7654-1-git-send-email-thellstrom@vmware.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/mm/pageattr.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 895d90e1a81b..7e600c1962db 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -591,9 +591,12 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) | |||
591 | unsigned int level; | 591 | unsigned int level; |
592 | pte_t *kpte, old_pte; | 592 | pte_t *kpte, old_pte; |
593 | 593 | ||
594 | if (cpa->flags & CPA_PAGES_ARRAY) | 594 | if (cpa->flags & CPA_PAGES_ARRAY) { |
595 | address = (unsigned long)page_address(cpa->pages[cpa->curpage]); | 595 | struct page *page = cpa->pages[cpa->curpage]; |
596 | else if (cpa->flags & CPA_ARRAY) | 596 | if (unlikely(PageHighMem(page))) |
597 | return 0; | ||
598 | address = (unsigned long)page_address(page); | ||
599 | } else if (cpa->flags & CPA_ARRAY) | ||
597 | address = cpa->vaddr[cpa->curpage]; | 600 | address = cpa->vaddr[cpa->curpage]; |
598 | else | 601 | else |
599 | address = *cpa->vaddr; | 602 | address = *cpa->vaddr; |
@@ -697,9 +700,12 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
697 | * No need to redo, when the primary call touched the direct | 700 | * No need to redo, when the primary call touched the direct |
698 | * mapping already: | 701 | * mapping already: |
699 | */ | 702 | */ |
700 | if (cpa->flags & CPA_PAGES_ARRAY) | 703 | if (cpa->flags & CPA_PAGES_ARRAY) { |
701 | vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]); | 704 | struct page *page = cpa->pages[cpa->curpage]; |
702 | else if (cpa->flags & CPA_ARRAY) | 705 | if (unlikely(PageHighMem(page))) |
706 | return 0; | ||
707 | vaddr = (unsigned long)page_address(page); | ||
708 | } else if (cpa->flags & CPA_ARRAY) | ||
703 | vaddr = cpa->vaddr[cpa->curpage]; | 709 | vaddr = cpa->vaddr[cpa->curpage]; |
704 | else | 710 | else |
705 | vaddr = *cpa->vaddr; | 711 | vaddr = *cpa->vaddr; |
@@ -1122,7 +1128,9 @@ int set_pages_array_uc(struct page **pages, int addrinarray) | |||
1122 | int free_idx; | 1128 | int free_idx; |
1123 | 1129 | ||
1124 | for (i = 0; i < addrinarray; i++) { | 1130 | for (i = 0; i < addrinarray; i++) { |
1125 | start = (unsigned long)page_address(pages[i]); | 1131 | if (PageHighMem(pages[i])) |
1132 | continue; | ||
1133 | start = page_to_pfn(pages[i]) << PAGE_SHIFT; | ||
1126 | end = start + PAGE_SIZE; | 1134 | end = start + PAGE_SIZE; |
1127 | if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) | 1135 | if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) |
1128 | goto err_out; | 1136 | goto err_out; |
@@ -1135,7 +1143,9 @@ int set_pages_array_uc(struct page **pages, int addrinarray) | |||
1135 | err_out: | 1143 | err_out: |
1136 | free_idx = i; | 1144 | free_idx = i; |
1137 | for (i = 0; i < free_idx; i++) { | 1145 | for (i = 0; i < free_idx; i++) { |
1138 | start = (unsigned long)page_address(pages[i]); | 1146 | if (PageHighMem(pages[i])) |
1147 | continue; | ||
1148 | start = page_to_pfn(pages[i]) << PAGE_SHIFT; | ||
1139 | end = start + PAGE_SIZE; | 1149 | end = start + PAGE_SIZE; |
1140 | free_memtype(start, end); | 1150 | free_memtype(start, end); |
1141 | } | 1151 | } |
@@ -1164,7 +1174,9 @@ int set_pages_array_wb(struct page **pages, int addrinarray) | |||
1164 | return retval; | 1174 | return retval; |
1165 | 1175 | ||
1166 | for (i = 0; i < addrinarray; i++) { | 1176 | for (i = 0; i < addrinarray; i++) { |
1167 | start = (unsigned long)page_address(pages[i]); | 1177 | if (PageHighMem(pages[i])) |
1178 | continue; | ||
1179 | start = page_to_pfn(pages[i]) << PAGE_SHIFT; | ||
1168 | end = start + PAGE_SIZE; | 1180 | end = start + PAGE_SIZE; |
1169 | free_memtype(start, end); | 1181 | free_memtype(start, end); |
1170 | } | 1182 | } |