/** ensure backing pages are allocated */ static int omap_gem_attach_pages(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); struct page **pages; WARN_ON(omap_obj->pages); /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably * we actually want CMA memory for it all anyways.. */ pages = _drm_gem_get_pages(obj, GFP_KERNEL); if (IS_ERR(pages)) { dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages)); return PTR_ERR(pages); } /* for non-cached buffers, ensure the new pages are clean because * DSS, GPU, etc. are not cache coherent: */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { int i, npages = obj->size >> PAGE_SHIFT; dma_addr_t *addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); for (i = 0; i < npages; i++) { addrs[i] = dma_map_page(obj->dev->dev, pages[i], 0, PAGE_SIZE, DMA_BIDIRECTIONAL); } omap_obj->addrs = addrs; }
static void evict_entry(struct drm_gem_object *obj, enum tiler_fmt fmt, struct usergart_entry *entry) { if (obj->dev->dev_mapping) { struct omap_gem_object *omap_obj = to_omap_bo(obj); int n = usergart[fmt].height; size_t size = PAGE_SIZE * n; loff_t off = mmap_offset(obj) + (entry->obj_pgoff << PAGE_SHIFT); const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE); if (m > 1) { int i; /* if stride > than PAGE_SIZE then sparse mapping: */ for (i = n; i > 0; i--) { unmap_mapping_range(obj->dev->dev_mapping, off, PAGE_SIZE, 1); off += PAGE_SIZE * m; } } else { unmap_mapping_range(obj->dev->dev_mapping, off, size, 1); } } entry->obj = NULL; }
/** release backing pages */ static void omap_gem_detach_pages(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); /* for non-cached buffers, ensure the new pages are clean because * DSS, GPU, etc. are not cache coherent: */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { int i, npages = obj->size >> PAGE_SHIFT; for (i = 0; i < npages; i++) { dma_unmap_page(obj->dev->dev, omap_obj->addrs[i], PAGE_SIZE, DMA_BIDIRECTIONAL); } }
/** ensure backing pages are allocated */ static int omap_gem_attach_pages(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; struct omap_gem_object *omap_obj = to_omap_bo(obj); struct page **pages; int npages = obj->size >> PAGE_SHIFT; int i, ret; dma_addr_t *addrs; WARN_ON(omap_obj->pages); pages = drm_gem_get_pages(obj); if (IS_ERR(pages)) { dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages)); return PTR_ERR(pages); } /* for non-cached buffers, ensure the new pages are clean because * DSS, GPU, etc. are not cache coherent: */ if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; } for (i = 0; i < npages; i++) { addrs[i] = dma_map_page(dev->dev, pages[i], 0, PAGE_SIZE, DMA_BIDIRECTIONAL); } } else { addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL); if (!addrs) { ret = -ENOMEM; goto free_pages; } } omap_obj->addrs = addrs; omap_obj->pages = pages; return 0; free_pages: drm_gem_put_pages(obj, pages, true, false); return ret; }
/* Evict a buffer from usergart, if it is mapped there */ static void evict(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); if (omap_obj->flags & OMAP_BO_TILED) { enum tiler_fmt fmt = gem2fmt(omap_obj->flags); int i; if (!usergart) return; for (i = 0; i < NUM_USERGART_ENTRIES; i++) { struct usergart_entry *entry = &usergart[fmt].entry[i]; if (entry->obj == obj) evict_entry(obj, fmt, entry); } } }
/** * shmem buffers that are mapped cached can simulate coherency via using * page faulting to keep track of dirty pages */ static inline bool is_cached_coherent(struct drm_gem_object *obj) { struct omap_gem_object *omap_obj = to_omap_bo(obj); return is_shmem(obj) && ((omap_obj->flags & OMAP_BO_CACHE_MASK) == OMAP_BO_CACHED); }