diff options
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/pageattr.c | 113 |
1 files changed, 65 insertions, 48 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index d487eaa17bff..985eef80c552 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -945,52 +945,56 @@ int _set_memory_uc(unsigned long addr, int numpages) | |||
945 | 945 | ||
946 | int set_memory_uc(unsigned long addr, int numpages) | 946 | int set_memory_uc(unsigned long addr, int numpages) |
947 | { | 947 | { |
948 | int ret; | ||
949 | |||
948 | /* | 950 | /* |
949 | * for now UC MINUS. see comments in ioremap_nocache() | 951 | * for now UC MINUS. see comments in ioremap_nocache() |
950 | */ | 952 | */ |
951 | if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE, | 953 | ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE, |
952 | _PAGE_CACHE_UC_MINUS, NULL)) | 954 | _PAGE_CACHE_UC_MINUS, NULL); |
953 | return -EINVAL; | 955 | if (ret) |
956 | goto out_err; | ||
957 | |||
958 | ret = _set_memory_uc(addr, numpages); | ||
959 | if (ret) | ||
960 | goto out_free; | ||
961 | |||
962 | return 0; | ||
954 | 963 | ||
955 | return _set_memory_uc(addr, numpages); | 964 | out_free: |
965 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); | ||
966 | out_err: | ||
967 | return ret; | ||
956 | } | 968 | } |
957 | EXPORT_SYMBOL(set_memory_uc); | 969 | EXPORT_SYMBOL(set_memory_uc); |
958 | 970 | ||
959 | int set_memory_array_uc(unsigned long *addr, int addrinarray) | 971 | int set_memory_array_uc(unsigned long *addr, int addrinarray) |
960 | { | 972 | { |
961 | unsigned long start; | 973 | int i, j; |
962 | unsigned long end; | 974 | int ret; |
963 | int i; | 975 | |
964 | /* | 976 | /* |
965 | * for now UC MINUS. see comments in ioremap_nocache() | 977 | * for now UC MINUS. see comments in ioremap_nocache() |
966 | */ | 978 | */ |
967 | for (i = 0; i < addrinarray; i++) { | 979 | for (i = 0; i < addrinarray; i++) { |
968 | start = __pa(addr[i]); | 980 | ret = reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE, |
969 | for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { | 981 | _PAGE_CACHE_UC_MINUS, NULL); |
970 | if (end != __pa(addr[i + 1])) | 982 | if (ret) |
971 | break; | 983 | goto out_free; |
972 | i++; | ||
973 | } | ||
974 | if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) | ||
975 | goto out; | ||
976 | } | 984 | } |
977 | 985 | ||
978 | return change_page_attr_set(addr, addrinarray, | 986 | ret = change_page_attr_set(addr, addrinarray, |
979 | __pgprot(_PAGE_CACHE_UC_MINUS), 1); | 987 | __pgprot(_PAGE_CACHE_UC_MINUS), 1); |
980 | out: | 988 | if (ret) |
981 | for (i = 0; i < addrinarray; i++) { | 989 | goto out_free; |
982 | unsigned long tmp = __pa(addr[i]); | 990 | |
983 | 991 | return 0; | |
984 | if (tmp == start) | 992 | |
985 | break; | 993 | out_free: |
986 | for (end = tmp + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { | 994 | for (j = 0; j < i; j++) |
987 | if (end != __pa(addr[i + 1])) | 995 | free_memtype(__pa(addr[j]), __pa(addr[j]) + PAGE_SIZE); |
988 | break; | 996 | |
989 | i++; | 997 | return ret; |
990 | } | ||
991 | free_memtype(tmp, end); | ||
992 | } | ||
993 | return -EINVAL; | ||
994 | } | 998 | } |
995 | EXPORT_SYMBOL(set_memory_array_uc); | 999 | EXPORT_SYMBOL(set_memory_array_uc); |
996 | 1000 | ||
@@ -1002,14 +1006,26 @@ int _set_memory_wc(unsigned long addr, int numpages) | |||
1002 | 1006 | ||
1003 | int set_memory_wc(unsigned long addr, int numpages) | 1007 | int set_memory_wc(unsigned long addr, int numpages) |
1004 | { | 1008 | { |
1009 | int ret; | ||
1010 | |||
1005 | if (!pat_enabled) | 1011 | if (!pat_enabled) |
1006 | return set_memory_uc(addr, numpages); | 1012 | return set_memory_uc(addr, numpages); |
1007 | 1013 | ||
1008 | if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE, | 1014 | ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE, |
1009 | _PAGE_CACHE_WC, NULL)) | 1015 | _PAGE_CACHE_WC, NULL); |
1010 | return -EINVAL; | 1016 | if (ret) |
1017 | goto out_err; | ||
1011 | 1018 | ||
1012 | return _set_memory_wc(addr, numpages); | 1019 | ret = _set_memory_wc(addr, numpages); |
1020 | if (ret) | ||
1021 | goto out_free; | ||
1022 | |||
1023 | return 0; | ||
1024 | |||
1025 | out_free: | ||
1026 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); | ||
1027 | out_err: | ||
1028 | return ret; | ||
1013 | } | 1029 | } |
1014 | EXPORT_SYMBOL(set_memory_wc); | 1030 | EXPORT_SYMBOL(set_memory_wc); |
1015 | 1031 | ||
@@ -1021,9 +1037,14 @@ int _set_memory_wb(unsigned long addr, int numpages) | |||
1021 | 1037 | ||
1022 | int set_memory_wb(unsigned long addr, int numpages) | 1038 | int set_memory_wb(unsigned long addr, int numpages) |
1023 | { | 1039 | { |
1024 | int ret = _set_memory_wb(addr, numpages); | 1040 | int ret; |
1041 | |||
1042 | ret = _set_memory_wb(addr, numpages); | ||
1043 | if (ret) | ||
1044 | return ret; | ||
1045 | |||
1025 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); | 1046 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); |
1026 | return ret; | 1047 | return 0; |
1027 | } | 1048 | } |
1028 | EXPORT_SYMBOL(set_memory_wb); | 1049 | EXPORT_SYMBOL(set_memory_wb); |
1029 | 1050 | ||
@@ -1034,19 +1055,13 @@ int set_memory_array_wb(unsigned long *addr, int addrinarray) | |||
1034 | 1055 | ||
1035 | ret = change_page_attr_clear(addr, addrinarray, | 1056 | ret = change_page_attr_clear(addr, addrinarray, |
1036 | __pgprot(_PAGE_CACHE_MASK), 1); | 1057 | __pgprot(_PAGE_CACHE_MASK), 1); |
1058 | if (ret) | ||
1059 | return ret; | ||
1037 | 1060 | ||
1038 | for (i = 0; i < addrinarray; i++) { | 1061 | for (i = 0; i < addrinarray; i++) |
1039 | unsigned long start = __pa(addr[i]); | 1062 | free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE); |
1040 | unsigned long end; | ||
1041 | 1063 | ||
1042 | for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { | 1064 | return 0; |
1043 | if (end != __pa(addr[i + 1])) | ||
1044 | break; | ||
1045 | i++; | ||
1046 | } | ||
1047 | free_memtype(start, end); | ||
1048 | } | ||
1049 | return ret; | ||
1050 | } | 1065 | } |
1051 | EXPORT_SYMBOL(set_memory_array_wb); | 1066 | EXPORT_SYMBOL(set_memory_array_wb); |
1052 | 1067 | ||
@@ -1139,6 +1154,8 @@ int set_pages_array_wb(struct page **pages, int addrinarray) | |||
1139 | 1154 | ||
1140 | retval = cpa_clear_pages_array(pages, addrinarray, | 1155 | retval = cpa_clear_pages_array(pages, addrinarray, |
1141 | __pgprot(_PAGE_CACHE_MASK)); | 1156 | __pgprot(_PAGE_CACHE_MASK)); |
1157 | if (retval) | ||
1158 | return retval; | ||
1142 | 1159 | ||
1143 | for (i = 0; i < addrinarray; i++) { | 1160 | for (i = 0; i < addrinarray; i++) { |
1144 | start = (unsigned long)page_address(pages[i]); | 1161 | start = (unsigned long)page_address(pages[i]); |
@@ -1146,7 +1163,7 @@ int set_pages_array_wb(struct page **pages, int addrinarray) | |||
1146 | free_memtype(start, end); | 1163 | free_memtype(start, end); |
1147 | } | 1164 | } |
1148 | 1165 | ||
1149 | return retval; | 1166 | return 0; |
1150 | } | 1167 | } |
1151 | EXPORT_SYMBOL(set_pages_array_wb); | 1168 | EXPORT_SYMBOL(set_pages_array_wb); |
1152 | 1169 | ||