}
static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
- unsigned long page)
+ unsigned long page,
+ pgprot_t prot)
{
struct page *d = ttm_tt_get_page(ttm, page);
void *dst;
return -ENOMEM;
src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
- dst = kmap(d);
+
+#ifdef CONFIG_X86
+ dst = kmap_atomic_prot(d, KM_USER0, prot);
+#else
+ if (prot != PAGE_KERNEL)
+ dst = vmap(&d, 1, 0, prot);
+ else
+ dst = kmap(d);
+#endif
if (!dst)
return -ENOMEM;
memcpy_fromio(dst, src, PAGE_SIZE);
- kunmap(d);
+
+#ifdef CONFIG_X86
+ kunmap_atomic(dst, KM_USER0);
+#else
+ if (prot != PAGE_KERNEL)
+ vunmap(dst);
+ else
+ kunmap(d);
+#endif
+
return 0;
}
static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
- unsigned long page)
+ unsigned long page,
+ pgprot_t prot)
{
struct page *s = ttm_tt_get_page(ttm, page);
void *src;
return -ENOMEM;
dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
- src = kmap(s);
+#ifdef CONFIG_X86
+ src = kmap_atomic_prot(s, KM_USER0, prot);
+#else
+ if (prot != PAGE_KERNEL)
+ src = vmap(&s, 1, 0, prot);
+ else
+ src = kmap(s);
+#endif
if (!src)
return -ENOMEM;
memcpy_toio(dst, src, PAGE_SIZE);
- kunmap(s);
+
+#ifdef CONFIG_X86
+ kunmap_atomic(src, KM_USER0);
+#else
+ if (prot != PAGE_KERNEL)
+ vunmap(src);
+ else
+ kunmap(s);
+#endif
+
return 0;
}
for (i = 0; i < new_mem->num_pages; ++i) {
page = i * dir + add;
- if (old_iomap == NULL)
- ret = ttm_copy_ttm_io_page(ttm, new_iomap, page);
- else if (new_iomap == NULL)
- ret = ttm_copy_io_ttm_page(ttm, old_iomap, page);
- else
+ if (old_iomap == NULL) {
+ pgprot_t prot = ttm_io_prot(old_mem->placement,
+ PAGE_KERNEL);
+ ret = ttm_copy_ttm_io_page(ttm, new_iomap, page,
+ prot);
+ } else if (new_iomap == NULL) {
+ pgprot_t prot = ttm_io_prot(new_mem->placement,
+ PAGE_KERNEL);
+ ret = ttm_copy_io_ttm_page(ttm, old_iomap, page,
+ prot);
+ } else
ret = ttm_copy_io_page(new_iomap, old_iomap, page);
if (ret)
goto out1;