diff options
author | Rob Clark <rob@ti.com> | 2011-12-20 16:54:28 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-22 13:46:15 -0800 |
commit | f3bc9d24cb4a221bd3530c445fa08e33775e7707 (patch) | |
tree | b0d1d06cf43e518856614502c9c0d75059c9e161 /drivers/staging/omapdrm | |
parent | c25b3c9a43ced0affb77be68d2ddcb89ddd17917 (diff) | |
download | linux-f3bc9d24cb4a221bd3530c445fa08e33775e7707.tar.gz linux-f3bc9d24cb4a221bd3530c445fa08e33775e7707.tar.bz2 linux-f3bc9d24cb4a221bd3530c445fa08e33775e7707.zip |
drm/omap: GEM, deal with cache
Uncached/writecombine buffers need to be clean before creating uc/wc
userspace mappings, lest dirty cache lines fall down and corrupt the
contents of the buffer.
Signed-off-by: Rob Clark <rob@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/omapdrm')
-rw-r--r-- | drivers/staging/omapdrm/omap_gem.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c index 63490f75350a..e0ebd1d139f6 100644 --- a/drivers/staging/omapdrm/omap_gem.c +++ b/drivers/staging/omapdrm/omap_gem.c @@ -84,6 +84,9 @@ struct omap_gem_object { */ struct page **pages; + /** addresses corresponding to pages in above array */ + dma_addr_t *addrs; + /** * Virtual address, if mapped. */ @@ -208,6 +211,19 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) 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; + } + omap_obj->pages = pages; return 0; } @@ -216,6 +232,20 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj) 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); + } + kfree(omap_obj->addrs); + omap_obj->addrs = NULL; + } + _drm_gem_put_pages(obj, omap_obj->pages, true, false); omap_obj->pages = NULL; } |