diff options
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_bo_util.c')
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo_util.c | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 1f730b3f18e5..2ebbae6067ab 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -255,6 +255,54 @@ static int ttm_copy_io_page(void *dst, void *src, unsigned long page) | |||
255 | return 0; | 255 | return 0; |
256 | } | 256 | } |
257 | 257 | ||
258 | #ifdef CONFIG_X86 | ||
259 | #define __ttm_kmap_atomic_prot(__page, __prot) kmap_atomic_prot(__page, __prot) | ||
260 | #define __ttm_kunmap_atomic(__addr) kunmap_atomic(__addr) | ||
261 | #else | ||
262 | #define __ttm_kmap_atomic_prot(__page, __prot) vmap(&__page, 1, 0, __prot) | ||
263 | #define __ttm_kunmap_atomic(__addr) vunmap(__addr) | ||
264 | #endif | ||
265 | |||
266 | |||
267 | /** | ||
268 | * ttm_kmap_atomic_prot - Efficient kernel map of a single page with | ||
269 | * specified page protection. | ||
270 | * | ||
271 | * @page: The page to map. | ||
272 | * @prot: The page protection. | ||
273 | * | ||
274 | * This function maps a TTM page using the kmap_atomic api if available, | ||
275 | * otherwise falls back to vmap. The user must make sure that the | ||
276 | * specified page does not have an aliased mapping with a different caching | ||
277 | * policy unless the architecture explicitly allows it. Also mapping and | ||
278 | * unmapping using this api must be correctly nested. Unmapping should | ||
279 | * occur in the reverse order of mapping. | ||
280 | */ | ||
281 | void *ttm_kmap_atomic_prot(struct page *page, pgprot_t prot) | ||
282 | { | ||
283 | if (pgprot_val(prot) == pgprot_val(PAGE_KERNEL)) | ||
284 | return kmap_atomic(page); | ||
285 | else | ||
286 | return __ttm_kmap_atomic_prot(page, prot); | ||
287 | } | ||
288 | EXPORT_SYMBOL(ttm_kmap_atomic_prot); | ||
289 | |||
290 | /** | ||
291 | * ttm_kunmap_atomic_prot - Unmap a page that was mapped using | ||
292 | * ttm_kmap_atomic_prot. | ||
293 | * | ||
294 | * @addr: The virtual address from the map. | ||
295 | * @prot: The page protection. | ||
296 | */ | ||
297 | void ttm_kunmap_atomic_prot(void *addr, pgprot_t prot) | ||
298 | { | ||
299 | if (pgprot_val(prot) == pgprot_val(PAGE_KERNEL)) | ||
300 | kunmap_atomic(addr); | ||
301 | else | ||
302 | __ttm_kunmap_atomic(addr); | ||
303 | } | ||
304 | EXPORT_SYMBOL(ttm_kunmap_atomic_prot); | ||
305 | |||
258 | static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, | 306 | static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, |
259 | unsigned long page, | 307 | unsigned long page, |
260 | pgprot_t prot) | 308 | pgprot_t prot) |
@@ -266,28 +314,13 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, | |||
266 | return -ENOMEM; | 314 | return -ENOMEM; |
267 | 315 | ||
268 | src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); | 316 | src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); |
269 | 317 | dst = ttm_kmap_atomic_prot(d, prot); | |
270 | #ifdef CONFIG_X86 | ||
271 | dst = kmap_atomic_prot(d, prot); | ||
272 | #else | ||
273 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | ||
274 | dst = vmap(&d, 1, 0, prot); | ||
275 | else | ||
276 | dst = kmap(d); | ||
277 | #endif | ||
278 | if (!dst) | 318 | if (!dst) |
279 | return -ENOMEM; | 319 | return -ENOMEM; |
280 | 320 | ||
281 | memcpy_fromio(dst, src, PAGE_SIZE); | 321 | memcpy_fromio(dst, src, PAGE_SIZE); |
282 | 322 | ||
283 | #ifdef CONFIG_X86 | 323 | ttm_kunmap_atomic_prot(dst, prot); |
284 | kunmap_atomic(dst); | ||
285 | #else | ||
286 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | ||
287 | vunmap(dst); | ||
288 | else | ||
289 | kunmap(d); | ||
290 | #endif | ||
291 | 324 | ||
292 | return 0; | 325 | return 0; |
293 | } | 326 | } |
@@ -303,27 +336,13 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, | |||
303 | return -ENOMEM; | 336 | return -ENOMEM; |
304 | 337 | ||
305 | dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); | 338 | dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); |
306 | #ifdef CONFIG_X86 | 339 | src = ttm_kmap_atomic_prot(s, prot); |
307 | src = kmap_atomic_prot(s, prot); | ||
308 | #else | ||
309 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | ||
310 | src = vmap(&s, 1, 0, prot); | ||
311 | else | ||
312 | src = kmap(s); | ||
313 | #endif | ||
314 | if (!src) | 340 | if (!src) |
315 | return -ENOMEM; | 341 | return -ENOMEM; |
316 | 342 | ||
317 | memcpy_toio(dst, src, PAGE_SIZE); | 343 | memcpy_toio(dst, src, PAGE_SIZE); |
318 | 344 | ||
319 | #ifdef CONFIG_X86 | 345 | ttm_kunmap_atomic_prot(src, prot); |
320 | kunmap_atomic(src); | ||
321 | #else | ||
322 | if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) | ||
323 | vunmap(src); | ||
324 | else | ||
325 | kunmap(s); | ||
326 | #endif | ||
327 | 346 | ||
328 | return 0; | 347 | return 0; |
329 | } | 348 | } |