aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/pageattr.c113
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
946int set_memory_uc(unsigned long addr, int numpages) 946int 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); 964out_free:
965 free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
966out_err:
967 return ret;
956} 968}
957EXPORT_SYMBOL(set_memory_uc); 969EXPORT_SYMBOL(set_memory_uc);
958 970
959int set_memory_array_uc(unsigned long *addr, int addrinarray) 971int 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);
980out: 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; 993out_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}
995EXPORT_SYMBOL(set_memory_array_uc); 999EXPORT_SYMBOL(set_memory_array_uc);
996 1000
@@ -1002,14 +1006,26 @@ int _set_memory_wc(unsigned long addr, int numpages)
1002 1006
1003int set_memory_wc(unsigned long addr, int numpages) 1007int 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
1025out_free:
1026 free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
1027out_err:
1028 return ret;
1013} 1029}
1014EXPORT_SYMBOL(set_memory_wc); 1030EXPORT_SYMBOL(set_memory_wc);
1015 1031
@@ -1021,9 +1037,14 @@ int _set_memory_wb(unsigned long addr, int numpages)
1021 1037
1022int set_memory_wb(unsigned long addr, int numpages) 1038int 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}
1028EXPORT_SYMBOL(set_memory_wb); 1049EXPORT_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}
1051EXPORT_SYMBOL(set_memory_array_wb); 1066EXPORT_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}
1151EXPORT_SYMBOL(set_pages_array_wb); 1168EXPORT_SYMBOL(set_pages_array_wb);
1152 1169