|
@@ -945,52 +945,56 @@ int _set_memory_uc(unsigned long addr, int numpages)
|
|
|
|
|
|
int set_memory_uc(unsigned long addr, int numpages)
|
|
|
{
|
|
|
+ int ret;
|
|
|
+
|
|
|
/*
|
|
|
* for now UC MINUS. see comments in ioremap_nocache()
|
|
|
*/
|
|
|
- if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
|
|
|
- _PAGE_CACHE_UC_MINUS, NULL))
|
|
|
- return -EINVAL;
|
|
|
+ ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
|
|
|
+ _PAGE_CACHE_UC_MINUS, NULL);
|
|
|
+ if (ret)
|
|
|
+ goto out_err;
|
|
|
+
|
|
|
+ ret = _set_memory_uc(addr, numpages);
|
|
|
+ if (ret)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ return 0;
|
|
|
|
|
|
- return _set_memory_uc(addr, numpages);
|
|
|
+out_free:
|
|
|
+ free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
|
|
|
+out_err:
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(set_memory_uc);
|
|
|
|
|
|
int set_memory_array_uc(unsigned long *addr, int addrinarray)
|
|
|
{
|
|
|
- unsigned long start;
|
|
|
- unsigned long end;
|
|
|
- int i;
|
|
|
+ int i, j;
|
|
|
+ int ret;
|
|
|
+
|
|
|
/*
|
|
|
* for now UC MINUS. see comments in ioremap_nocache()
|
|
|
*/
|
|
|
for (i = 0; i < addrinarray; i++) {
|
|
|
- start = __pa(addr[i]);
|
|
|
- for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
|
|
|
- if (end != __pa(addr[i + 1]))
|
|
|
- break;
|
|
|
- i++;
|
|
|
- }
|
|
|
- if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
|
|
|
- goto out;
|
|
|
+ ret = reserve_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE,
|
|
|
+ _PAGE_CACHE_UC_MINUS, NULL);
|
|
|
+ if (ret)
|
|
|
+ goto out_free;
|
|
|
}
|
|
|
|
|
|
- return change_page_attr_set(addr, addrinarray,
|
|
|
+ ret = change_page_attr_set(addr, addrinarray,
|
|
|
__pgprot(_PAGE_CACHE_UC_MINUS), 1);
|
|
|
-out:
|
|
|
- for (i = 0; i < addrinarray; i++) {
|
|
|
- unsigned long tmp = __pa(addr[i]);
|
|
|
-
|
|
|
- if (tmp == start)
|
|
|
- break;
|
|
|
- for (end = tmp + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
|
|
|
- if (end != __pa(addr[i + 1]))
|
|
|
- break;
|
|
|
- i++;
|
|
|
- }
|
|
|
- free_memtype(tmp, end);
|
|
|
- }
|
|
|
- return -EINVAL;
|
|
|
+ if (ret)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+out_free:
|
|
|
+ for (j = 0; j < i; j++)
|
|
|
+ free_memtype(__pa(addr[j]), __pa(addr[j]) + PAGE_SIZE);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(set_memory_array_uc);
|
|
|
|
|
@@ -1002,14 +1006,26 @@ int _set_memory_wc(unsigned long addr, int numpages)
|
|
|
|
|
|
int set_memory_wc(unsigned long addr, int numpages)
|
|
|
{
|
|
|
+ int ret;
|
|
|
+
|
|
|
if (!pat_enabled)
|
|
|
return set_memory_uc(addr, numpages);
|
|
|
|
|
|
- if (reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
|
|
|
- _PAGE_CACHE_WC, NULL))
|
|
|
- return -EINVAL;
|
|
|
+ ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
|
|
|
+ _PAGE_CACHE_WC, NULL);
|
|
|
+ if (ret)
|
|
|
+ goto out_err;
|
|
|
|
|
|
- return _set_memory_wc(addr, numpages);
|
|
|
+ ret = _set_memory_wc(addr, numpages);
|
|
|
+ if (ret)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+out_free:
|
|
|
+ free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
|
|
|
+out_err:
|
|
|
+ return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(set_memory_wc);
|
|
|
|
|
@@ -1021,9 +1037,14 @@ int _set_memory_wb(unsigned long addr, int numpages)
|
|
|
|
|
|
int set_memory_wb(unsigned long addr, int numpages)
|
|
|
{
|
|
|
- int ret = _set_memory_wb(addr, numpages);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = _set_memory_wb(addr, numpages);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
free_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE);
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL(set_memory_wb);
|
|
|
|
|
@@ -1034,19 +1055,13 @@ int set_memory_array_wb(unsigned long *addr, int addrinarray)
|
|
|
|
|
|
ret = change_page_attr_clear(addr, addrinarray,
|
|
|
__pgprot(_PAGE_CACHE_MASK), 1);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
- for (i = 0; i < addrinarray; i++) {
|
|
|
- unsigned long start = __pa(addr[i]);
|
|
|
- unsigned long end;
|
|
|
+ for (i = 0; i < addrinarray; i++)
|
|
|
+ free_memtype(__pa(addr[i]), __pa(addr[i]) + PAGE_SIZE);
|
|
|
|
|
|
- for (end = start + PAGE_SIZE; i < addrinarray - 1; end += PAGE_SIZE) {
|
|
|
- if (end != __pa(addr[i + 1]))
|
|
|
- break;
|
|
|
- i++;
|
|
|
- }
|
|
|
- free_memtype(start, end);
|
|
|
- }
|
|
|
- return ret;
|
|
|
+ return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL(set_memory_array_wb);
|
|
|
|
|
@@ -1139,6 +1154,8 @@ int set_pages_array_wb(struct page **pages, int addrinarray)
|
|
|
|
|
|
retval = cpa_clear_pages_array(pages, addrinarray,
|
|
|
__pgprot(_PAGE_CACHE_MASK));
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
|
|
|
for (i = 0; i < addrinarray; i++) {
|
|
|
start = (unsigned long)page_address(pages[i]);
|
|
@@ -1146,7 +1163,7 @@ int set_pages_array_wb(struct page **pages, int addrinarray)
|
|
|
free_memtype(start, end);
|
|
|
}
|
|
|
|
|
|
- return retval;
|
|
|
+ return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL(set_pages_array_wb);
|
|
|
|