static int vgem_prime_pin(struct drm_gem_object *obj) { struct drm_vgem_gem_object *bo = to_vgem_bo(obj); long n_pages = obj->size >> PAGE_SHIFT; struct page **pages; pages = vgem_pin_pages(bo); if (IS_ERR(pages)) return PTR_ERR(pages); /* Flush the object from the CPU cache so that importers can rely * on coherent indirect access via the exported dma-address. */ drm_clflush_pages(pages, n_pages); return 0; }
static int ttm_tt_set_caching(struct ttm_tt *ttm, enum ttm_caching_state c_state) { int i, j; struct page *cur_page; int ret; if (ttm->caching_state == c_state) return 0; if (ttm->state == tt_unpopulated) { /* Change caching but don't populate */ ttm->caching_state = c_state; return 0; } if (ttm->caching_state == tt_cached) drm_clflush_pages(ttm->pages, ttm->num_pages); for (i = 0; i < ttm->num_pages; ++i) { cur_page = ttm->pages[i]; if (likely(cur_page != NULL)) { ret = ttm_tt_set_page_caching(cur_page, ttm->caching_state, c_state); if (unlikely(ret != 0)) goto out_err; } } ttm->caching_state = c_state; return 0; out_err: for (j = 0; j < i; ++j) { cur_page = ttm->pages[j]; if (likely(cur_page != NULL)) { (void)ttm_tt_set_page_caching(cur_page, c_state, ttm->caching_state); } } return ret; }
static struct drm_i915_error_object * i915_error_object_create_sized(struct drm_i915_private *dev_priv, struct drm_i915_gem_object *src, const int num_pages) { struct drm_i915_error_object *dst; int i; u32 reloc_offset; if (src == NULL || src->pages == NULL) return NULL; dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC); if (dst == NULL) return NULL; reloc_offset = dst->gtt_offset = i915_gem_obj_ggtt_offset(src); for (i = 0; i < num_pages; i++) { unsigned long flags; void *d; d = kmalloc(PAGE_SIZE, GFP_ATOMIC); if (d == NULL) goto unwind; local_irq_save(flags); if (reloc_offset < dev_priv->gtt.mappable_end && src->has_global_gtt_mapping) { bus_space_handle_t bsh; void __iomem *s; /* Simply ignore tiling or any overlapping fence. * It's part of the error state, and this hopefully * captures what the GPU read. */ #ifdef __linux__ s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, reloc_offset); #else agp_map_atomic(dev_priv->agph, reloc_offset, &bsh); s = bus_space_vaddr(dev_priv->bst, bsh); #endif memcpy_fromio(d, s, PAGE_SIZE); #ifdef __linux__ io_mapping_unmap_atomic(s); #else agp_unmap_atomic(dev_priv->agph, bsh); #endif } else if (src->stolen) { unsigned long offset; offset = dev_priv->mm.stolen_base; offset += src->stolen->start; offset += i << PAGE_SHIFT; memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE); } else { struct vm_page *page; void *s; page = i915_gem_object_get_page(src, i); drm_clflush_pages(&page, 1); s = kmap_atomic(page); memcpy(d, s, PAGE_SIZE); kunmap_atomic(s); drm_clflush_pages(&page, 1); } local_irq_restore(flags); dst->pages[i] = d; reloc_offset += PAGE_SIZE; } dst->page_count = num_pages; return dst; unwind: while (i--) kfree(dst->pages[i]); kfree(dst); return NULL; }