aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorvenkatesh.pallipadi@intel.com <venkatesh.pallipadi@intel.com>2009-04-09 17:26:49 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-10 07:55:47 -0400
commit9fa3ab390abfc8b49fc0dd7c845b0ad224ec429f (patch)
tree5357d961200ba3852098254fef8fce4ea84d8733 /arch/x86/mm
parenta5593e0b329a14dea41ea173380dbf1533de2bd2 (diff)
x86, PAT: Handle faults cleanly in set_memory_ APIs
Handle faults and do proper cleanups in set_memory_*() functions. In some cases, these functions were not doing proper free on failure paths. With the changes to tracking memtype of RAM pages in struct page instead of pat list, we do not need the changes in commits c5e147. This patch reverts that change. Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> LKML-Reference: <20090409212708.653222000@intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
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