diff options
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r-- | arch/x86/mm/pageattr.c | 127 |
1 files changed, 77 insertions, 50 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index d71e1b636ce6..797f9f107cb6 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -945,71 +945,94 @@ 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; | ||
954 | 961 | ||
955 | return _set_memory_uc(addr, numpages); | 962 | return 0; |
963 | |||
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 | ||
997 | int _set_memory_wc(unsigned long addr, int numpages) | 1001 | int _set_memory_wc(unsigned long addr, int numpages) |
998 | { | 1002 | { |
999 | return change_page_attr_set(&addr, numpages, | 1003 | int ret; |
1004 | ret = change_page_attr_set(&addr, numpages, | ||
1005 | __pgprot(_PAGE_CACHE_UC_MINUS), 0); | ||
1006 | |||
1007 | if (!ret) { | ||
1008 | ret = change_page_attr_set(&addr, numpages, | ||
1000 | __pgprot(_PAGE_CACHE_WC), 0); | 1009 | __pgprot(_PAGE_CACHE_WC), 0); |
1010 | } | ||
1011 | return ret; | ||
1001 | } | 1012 | } |
1002 | 1013 | ||
1003 | int set_memory_wc(unsigned long addr, int numpages) | 1014 | int set_memory_wc(unsigned long addr, int numpages) |
1004 | { | 1015 | { |
1016 | int ret; | ||
1017 | |||
1005 | if (!pat_enabled) | 1018 | if (!pat_enabled) |
1006 | return set_memory_uc(addr, numpages); | 1019 | return set_memory_uc(addr, numpages); |
1007 | 1020 | ||
1008 | if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE, | 1021 | ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE, |
1009 | _PAGE_CACHE_WC, NULL)) | 1022 | _PAGE_CACHE_WC, NULL); |
1010 | return -EINVAL; | 1023 | if (ret) |
1024 | goto out_err; | ||
1025 | |||
1026 | ret = _set_memory_wc(addr, numpages); | ||
1027 | if (ret) | ||
1028 | goto out_free; | ||
1029 | |||
1030 | return 0; | ||
1011 | 1031 | ||
1012 | return _set_memory_wc(addr, numpages); | 1032 | out_free: |
1033 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); | ||
1034 | out_err: | ||
1035 | return ret; | ||
1013 | } | 1036 | } |
1014 | EXPORT_SYMBOL(set_memory_wc); | 1037 | EXPORT_SYMBOL(set_memory_wc); |
1015 | 1038 | ||
@@ -1021,29 +1044,31 @@ int _set_memory_wb(unsigned long addr, int numpages) | |||
1021 | 1044 | ||
1022 | int set_memory_wb(unsigned long addr, int numpages) | 1045 | int set_memory_wb(unsigned long addr, int numpages) |
1023 | { | 1046 | { |
1024 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); | 1047 | int ret; |
1048 | |||
1049 | ret = _set_memory_wb(addr, numpages); | ||
1050 | if (ret) | ||
1051 | return ret; | ||
1025 | 1052 | ||
1026 | return _set_memory_wb(addr, numpages); | 1053 | free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE); |
1054 | return 0; | ||
1027 | } | 1055 | } |
1028 | EXPORT_SYMBOL(set_memory_wb); | 1056 | EXPORT_SYMBOL(set_memory_wb); |
1029 | 1057 | ||
1030 | int set_memory_array_wb(unsigned long *addr, int addrinarray) | 1058 | int set_memory_array_wb(unsigned long *addr, int addrinarray) |
1031 | { | 1059 | { |
1032 | int i; | 1060 | int i; |
1061 | int ret; | ||
1033 | 1062 | ||
1034 | for (i = 0; i < addrinarray; i++) { | 1063 | ret = change_page_attr_clear(addr, addrinarray, |
1035 | unsigned long start = __pa(addr[i]); | ||
1036 | unsigned long end; | ||
1037 | |||
1038 | for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) { | ||
1039 | if (end != __pa(addr[i + 1])) | ||
1040 | break; | ||
1041 | i++; | ||
1042 | } | ||
1043 | free_memtype(start, end); | ||
1044 | } | ||
1045 | return change_page_attr_clear(addr, addrinarray, | ||
1046 | __pgprot(_PAGE_CACHE_MASK), 1); | 1064 | __pgprot(_PAGE_CACHE_MASK), 1); |
1065 | if (ret) | ||
1066 | return ret; | ||
1067 | |||
1068 | for (i = 0; i < addrinarray; i++) | ||
1069 | free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE); | ||
1070 | |||
1071 | return 0; | ||
1047 | } | 1072 | } |
1048 | EXPORT_SYMBOL(set_memory_array_wb); | 1073 | EXPORT_SYMBOL(set_memory_array_wb); |
1049 | 1074 | ||
@@ -1136,6 +1161,8 @@ int set_pages_array_wb(struct page **pages, int addrinarray) | |||
1136 | 1161 | ||
1137 | retval = cpa_clear_pages_array(pages, addrinarray, | 1162 | retval = cpa_clear_pages_array(pages, addrinarray, |
1138 | __pgprot(_PAGE_CACHE_MASK)); | 1163 | __pgprot(_PAGE_CACHE_MASK)); |
1164 | if (retval) | ||
1165 | return retval; | ||
1139 | 1166 | ||
1140 | for (i = 0; i < addrinarray; i++) { | 1167 | for (i = 0; i < addrinarray; i++) { |
1141 | start = (unsigned long)page_address(pages[i]); | 1168 | start = (unsigned long)page_address(pages[i]); |
@@ -1143,7 +1170,7 @@ int set_pages_array_wb(struct page **pages, int addrinarray) | |||
1143 | free_memtype(start, end); | 1170 | free_memtype(start, end); |
1144 | } | 1171 | } |
1145 | 1172 | ||
1146 | return retval; | 1173 | return 0; |
1147 | } | 1174 | } |
1148 | EXPORT_SYMBOL(set_pages_array_wb); | 1175 | EXPORT_SYMBOL(set_pages_array_wb); |
1149 | 1176 | ||