Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Rob Clark and committed by
Greg Kroah-Hartman
f3bc9d24 c25b3c9a

+30
+30
drivers/staging/omapdrm/omap_gem.c
··· 84 84 */ 85 85 struct page **pages; 86 86 87 + /** addresses corresponding to pages in above array */ 88 + dma_addr_t *addrs; 89 + 87 90 /** 88 91 * Virtual address, if mapped. 89 92 */ ··· 211 208 return PTR_ERR(pages); 212 209 } 213 210 211 + /* for non-cached buffers, ensure the new pages are clean because 212 + * DSS, GPU, etc. are not cache coherent: 213 + */ 214 + if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { 215 + int i, npages = obj->size >> PAGE_SHIFT; 216 + dma_addr_t *addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); 217 + for (i = 0; i < npages; i++) { 218 + addrs[i] = dma_map_page(obj->dev->dev, pages[i], 219 + 0, PAGE_SIZE, DMA_BIDIRECTIONAL); 220 + } 221 + omap_obj->addrs = addrs; 222 + } 223 + 214 224 omap_obj->pages = pages; 215 225 return 0; 216 226 } ··· 232 216 static void omap_gem_detach_pages(struct drm_gem_object *obj) 233 217 { 234 218 struct omap_gem_object *omap_obj = to_omap_bo(obj); 219 + 220 + /* for non-cached buffers, ensure the new pages are clean because 221 + * DSS, GPU, etc. are not cache coherent: 222 + */ 223 + if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { 224 + int i, npages = obj->size >> PAGE_SHIFT; 225 + for (i = 0; i < npages; i++) { 226 + dma_unmap_page(obj->dev->dev, omap_obj->addrs[i], 227 + PAGE_SIZE, DMA_BIDIRECTIONAL); 228 + } 229 + kfree(omap_obj->addrs); 230 + omap_obj->addrs = NULL; 231 + } 232 + 235 233 _drm_gem_put_pages(obj, omap_obj->pages, true, false); 236 234 omap_obj->pages = NULL; 237 235 }