18bb0daffSRob Clark /* 28bb0daffSRob Clark * drivers/gpu/drm/omapdrm/omap_gem.c 38bb0daffSRob Clark * 48bb0daffSRob Clark * Copyright (C) 2011 Texas Instruments 58bb0daffSRob Clark * Author: Rob Clark <rob.clark@linaro.org> 68bb0daffSRob Clark * 78bb0daffSRob Clark * This program is free software; you can redistribute it and/or modify it 88bb0daffSRob Clark * under the terms of the GNU General Public License version 2 as published by 98bb0daffSRob Clark * the Free Software Foundation. 108bb0daffSRob Clark * 118bb0daffSRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 128bb0daffSRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 138bb0daffSRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 148bb0daffSRob Clark * more details. 158bb0daffSRob Clark * 168bb0daffSRob Clark * You should have received a copy of the GNU General Public License along with 178bb0daffSRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 188bb0daffSRob Clark */ 198bb0daffSRob Clark 208bb0daffSRob Clark #include <linux/shmem_fs.h> 212d278f54SLaurent Pinchart #include <linux/spinlock.h> 2201c8f1c4SDan Williams #include <linux/pfn_t.h> 232d278f54SLaurent Pinchart 240de23977SDavid Herrmann #include <drm/drm_vma_manager.h> 258bb0daffSRob Clark 268bb0daffSRob Clark #include "omap_drv.h" 278bb0daffSRob Clark #include "omap_dmm_tiler.h" 288bb0daffSRob Clark 298bb0daffSRob Clark /* remove these once drm core helpers are merged */ 308bb0daffSRob Clark struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); 318bb0daffSRob Clark void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, 328bb0daffSRob Clark bool dirty, bool accessed); 338bb0daffSRob Clark int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size); 348bb0daffSRob Clark 358bb0daffSRob Clark /* 368bb0daffSRob Clark * GEM buffer object implementation. 378bb0daffSRob Clark */ 388bb0daffSRob Clark 398bb0daffSRob Clark #define to_omap_bo(x) container_of(x, struct omap_gem_object, base) 408bb0daffSRob Clark 418bb0daffSRob Clark /* note: we use upper 8 bits of flags for driver-internal flags: */ 428bb0daffSRob Clark #define OMAP_BO_DMA 0x01000000 /* actually is physically contiguous */ 438bb0daffSRob Clark #define OMAP_BO_EXT_SYNC 0x02000000 /* externally allocated sync object */ 448bb0daffSRob Clark #define OMAP_BO_EXT_MEM 0x04000000 /* externally allocated memory */ 458bb0daffSRob Clark 468bb0daffSRob Clark 478bb0daffSRob Clark struct omap_gem_object { 488bb0daffSRob Clark struct drm_gem_object base; 498bb0daffSRob Clark 508bb0daffSRob Clark struct list_head mm_list; 518bb0daffSRob Clark 528bb0daffSRob Clark uint32_t flags; 538bb0daffSRob Clark 548bb0daffSRob Clark /** width/height for tiled formats (rounded up to slot boundaries) */ 558bb0daffSRob Clark uint16_t width, height; 568bb0daffSRob Clark 578bb0daffSRob Clark /** roll applied when mapping to DMM */ 588bb0daffSRob Clark uint32_t roll; 598bb0daffSRob Clark 608bb0daffSRob Clark /** 618bb0daffSRob Clark * If buffer is allocated physically contiguous, the OMAP_BO_DMA flag 628bb0daffSRob Clark * is set and the paddr is valid. Also if the buffer is remapped in 638bb0daffSRob Clark * TILER and paddr_cnt > 0, then paddr is valid. But if you are using 648bb0daffSRob Clark * the physical address and OMAP_BO_DMA is not set, then you should 658bb0daffSRob Clark * be going thru omap_gem_{get,put}_paddr() to ensure the mapping is 668bb0daffSRob Clark * not removed from under your feet. 678bb0daffSRob Clark * 688bb0daffSRob Clark * Note that OMAP_BO_SCANOUT is a hint from userspace that DMA capable 698bb0daffSRob Clark * buffer is requested, but doesn't mean that it is. Use the 708bb0daffSRob Clark * OMAP_BO_DMA flag to determine if the buffer has a DMA capable 718bb0daffSRob Clark * physical address. 728bb0daffSRob Clark */ 738bb0daffSRob Clark dma_addr_t paddr; 748bb0daffSRob Clark 758bb0daffSRob Clark /** 768bb0daffSRob Clark * # of users of paddr 778bb0daffSRob Clark */ 788bb0daffSRob Clark uint32_t paddr_cnt; 798bb0daffSRob Clark 808bb0daffSRob Clark /** 818bb0daffSRob Clark * tiler block used when buffer is remapped in DMM/TILER. 828bb0daffSRob Clark */ 838bb0daffSRob Clark struct tiler_block *block; 848bb0daffSRob Clark 858bb0daffSRob Clark /** 868bb0daffSRob Clark * Array of backing pages, if allocated. Note that pages are never 878bb0daffSRob Clark * allocated for buffers originally allocated from contiguous memory 888bb0daffSRob Clark */ 898bb0daffSRob Clark struct page **pages; 908bb0daffSRob Clark 918bb0daffSRob Clark /** addresses corresponding to pages in above array */ 928bb0daffSRob Clark dma_addr_t *addrs; 938bb0daffSRob Clark 948bb0daffSRob Clark /** 958bb0daffSRob Clark * Virtual address, if mapped. 968bb0daffSRob Clark */ 978bb0daffSRob Clark void *vaddr; 988bb0daffSRob Clark 998bb0daffSRob Clark /** 1008bb0daffSRob Clark * sync-object allocated on demand (if needed) 1018bb0daffSRob Clark * 1028bb0daffSRob Clark * Per-buffer sync-object for tracking pending and completed hw/dma 1038bb0daffSRob Clark * read and write operations. The layout in memory is dictated by 1048bb0daffSRob Clark * the SGX firmware, which uses this information to stall the command 1058bb0daffSRob Clark * stream if a surface is not ready yet. 1068bb0daffSRob Clark * 1078bb0daffSRob Clark * Note that when buffer is used by SGX, the sync-object needs to be 1088bb0daffSRob Clark * allocated from a special heap of sync-objects. This way many sync 1098bb0daffSRob Clark * objects can be packed in a page, and not waste GPU virtual address 1108bb0daffSRob Clark * space. Because of this we have to have a omap_gem_set_sync_object() 1118bb0daffSRob Clark * API to allow replacement of the syncobj after it has (potentially) 1128bb0daffSRob Clark * already been allocated. A bit ugly but I haven't thought of a 1138bb0daffSRob Clark * better alternative. 1148bb0daffSRob Clark */ 1158bb0daffSRob Clark struct { 1168bb0daffSRob Clark uint32_t write_pending; 1178bb0daffSRob Clark uint32_t write_complete; 1188bb0daffSRob Clark uint32_t read_pending; 1198bb0daffSRob Clark uint32_t read_complete; 1208bb0daffSRob Clark } *sync; 1218bb0daffSRob Clark }; 1228bb0daffSRob Clark 1238bb0daffSRob Clark static int get_pages(struct drm_gem_object *obj, struct page ***pages); 1248bb0daffSRob Clark static uint64_t mmap_offset(struct drm_gem_object *obj); 1258bb0daffSRob Clark 1268bb0daffSRob Clark /* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are 1278bb0daffSRob Clark * not necessarily pinned in TILER all the time, and (b) when they are 1288bb0daffSRob Clark * they are not necessarily page aligned, we reserve one or more small 1298bb0daffSRob Clark * regions in each of the 2d containers to use as a user-GART where we 1308bb0daffSRob Clark * can create a second page-aligned mapping of parts of the buffer 1318bb0daffSRob Clark * being accessed from userspace. 1328bb0daffSRob Clark * 1338bb0daffSRob Clark * Note that we could optimize slightly when we know that multiple 1348bb0daffSRob Clark * tiler containers are backed by the same PAT.. but I'll leave that 1358bb0daffSRob Clark * for later.. 1368bb0daffSRob Clark */ 1378bb0daffSRob Clark #define NUM_USERGART_ENTRIES 2 1388bb0daffSRob Clark struct usergart_entry { 1398bb0daffSRob Clark struct tiler_block *block; /* the reserved tiler block */ 1408bb0daffSRob Clark dma_addr_t paddr; 1418bb0daffSRob Clark struct drm_gem_object *obj; /* the current pinned obj */ 1428bb0daffSRob Clark pgoff_t obj_pgoff; /* page offset of obj currently 1438bb0daffSRob Clark mapped in */ 1448bb0daffSRob Clark }; 1458bb0daffSRob Clark static struct { 1468bb0daffSRob Clark struct usergart_entry entry[NUM_USERGART_ENTRIES]; 1478bb0daffSRob Clark int height; /* height in rows */ 1488bb0daffSRob Clark int height_shift; /* ilog2(height in rows) */ 1498bb0daffSRob Clark int slot_shift; /* ilog2(width per slot) */ 1508bb0daffSRob Clark int stride_pfn; /* stride in pages */ 1518bb0daffSRob Clark int last; /* index of last used entry */ 1528bb0daffSRob Clark } *usergart; 1538bb0daffSRob Clark 1548bb0daffSRob Clark static void evict_entry(struct drm_gem_object *obj, 1558bb0daffSRob Clark enum tiler_fmt fmt, struct usergart_entry *entry) 1568bb0daffSRob Clark { 1578bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 1588bb0daffSRob Clark int n = usergart[fmt].height; 1598bb0daffSRob Clark size_t size = PAGE_SIZE * n; 1608bb0daffSRob Clark loff_t off = mmap_offset(obj) + 1618bb0daffSRob Clark (entry->obj_pgoff << PAGE_SHIFT); 1628bb0daffSRob Clark const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE); 1636796cb16SDavid Herrmann 1648bb0daffSRob Clark if (m > 1) { 1658bb0daffSRob Clark int i; 1668bb0daffSRob Clark /* if stride > than PAGE_SIZE then sparse mapping: */ 1678bb0daffSRob Clark for (i = n; i > 0; i--) { 1686796cb16SDavid Herrmann unmap_mapping_range(obj->dev->anon_inode->i_mapping, 1698bb0daffSRob Clark off, PAGE_SIZE, 1); 1708bb0daffSRob Clark off += PAGE_SIZE * m; 1718bb0daffSRob Clark } 1728bb0daffSRob Clark } else { 1736796cb16SDavid Herrmann unmap_mapping_range(obj->dev->anon_inode->i_mapping, 1746796cb16SDavid Herrmann off, size, 1); 1758bb0daffSRob Clark } 1768bb0daffSRob Clark 1778bb0daffSRob Clark entry->obj = NULL; 1788bb0daffSRob Clark } 1798bb0daffSRob Clark 1808bb0daffSRob Clark /* Evict a buffer from usergart, if it is mapped there */ 1818bb0daffSRob Clark static void evict(struct drm_gem_object *obj) 1828bb0daffSRob Clark { 1838bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 1848bb0daffSRob Clark 1858bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 1868bb0daffSRob Clark enum tiler_fmt fmt = gem2fmt(omap_obj->flags); 1878bb0daffSRob Clark int i; 1888bb0daffSRob Clark 1898bb0daffSRob Clark if (!usergart) 1908bb0daffSRob Clark return; 1918bb0daffSRob Clark 1928bb0daffSRob Clark for (i = 0; i < NUM_USERGART_ENTRIES; i++) { 1938bb0daffSRob Clark struct usergart_entry *entry = &usergart[fmt].entry[i]; 1948bb0daffSRob Clark if (entry->obj == obj) 1958bb0daffSRob Clark evict_entry(obj, fmt, entry); 1968bb0daffSRob Clark } 1978bb0daffSRob Clark } 1988bb0daffSRob Clark } 1998bb0daffSRob Clark 2008bb0daffSRob Clark /* GEM objects can either be allocated from contiguous memory (in which 2018bb0daffSRob Clark * case obj->filp==NULL), or w/ shmem backing (obj->filp!=NULL). But non 2028bb0daffSRob Clark * contiguous buffers can be remapped in TILER/DMM if they need to be 2038bb0daffSRob Clark * contiguous... but we don't do this all the time to reduce pressure 2048bb0daffSRob Clark * on TILER/DMM space when we know at allocation time that the buffer 2058bb0daffSRob Clark * will need to be scanned out. 2068bb0daffSRob Clark */ 2078bb0daffSRob Clark static inline bool is_shmem(struct drm_gem_object *obj) 2088bb0daffSRob Clark { 2098bb0daffSRob Clark return obj->filp != NULL; 2108bb0daffSRob Clark } 2118bb0daffSRob Clark 2128bb0daffSRob Clark /** 2138bb0daffSRob Clark * shmem buffers that are mapped cached can simulate coherency via using 2148bb0daffSRob Clark * page faulting to keep track of dirty pages 2158bb0daffSRob Clark */ 2168bb0daffSRob Clark static inline bool is_cached_coherent(struct drm_gem_object *obj) 2178bb0daffSRob Clark { 2188bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 2198bb0daffSRob Clark return is_shmem(obj) && 2208bb0daffSRob Clark ((omap_obj->flags & OMAP_BO_CACHE_MASK) == OMAP_BO_CACHED); 2218bb0daffSRob Clark } 2228bb0daffSRob Clark 2238bb0daffSRob Clark static DEFINE_SPINLOCK(sync_lock); 2248bb0daffSRob Clark 2258bb0daffSRob Clark /** ensure backing pages are allocated */ 2268bb0daffSRob Clark static int omap_gem_attach_pages(struct drm_gem_object *obj) 2278bb0daffSRob Clark { 2288bb0daffSRob Clark struct drm_device *dev = obj->dev; 2298bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 2308bb0daffSRob Clark struct page **pages; 2318bb0daffSRob Clark int npages = obj->size >> PAGE_SHIFT; 2328bb0daffSRob Clark int i, ret; 2338bb0daffSRob Clark dma_addr_t *addrs; 2348bb0daffSRob Clark 2358bb0daffSRob Clark WARN_ON(omap_obj->pages); 2368bb0daffSRob Clark 2370cdbe8acSDavid Herrmann pages = drm_gem_get_pages(obj); 2388bb0daffSRob Clark if (IS_ERR(pages)) { 2398bb0daffSRob Clark dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages)); 2408bb0daffSRob Clark return PTR_ERR(pages); 2418bb0daffSRob Clark } 2428bb0daffSRob Clark 2438bb0daffSRob Clark /* for non-cached buffers, ensure the new pages are clean because 2448bb0daffSRob Clark * DSS, GPU, etc. are not cache coherent: 2458bb0daffSRob Clark */ 2468bb0daffSRob Clark if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { 2478bb0daffSRob Clark addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL); 2488bb0daffSRob Clark if (!addrs) { 2498bb0daffSRob Clark ret = -ENOMEM; 2508bb0daffSRob Clark goto free_pages; 2518bb0daffSRob Clark } 2528bb0daffSRob Clark 2538bb0daffSRob Clark for (i = 0; i < npages; i++) { 2548bb0daffSRob Clark addrs[i] = dma_map_page(dev->dev, pages[i], 2558bb0daffSRob Clark 0, PAGE_SIZE, DMA_BIDIRECTIONAL); 2568bb0daffSRob Clark } 2578bb0daffSRob Clark } else { 2588bb0daffSRob Clark addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL); 2598bb0daffSRob Clark if (!addrs) { 2608bb0daffSRob Clark ret = -ENOMEM; 2618bb0daffSRob Clark goto free_pages; 2628bb0daffSRob Clark } 2638bb0daffSRob Clark } 2648bb0daffSRob Clark 2658bb0daffSRob Clark omap_obj->addrs = addrs; 2668bb0daffSRob Clark omap_obj->pages = pages; 2678bb0daffSRob Clark 2688bb0daffSRob Clark return 0; 2698bb0daffSRob Clark 2708bb0daffSRob Clark free_pages: 271ddcd09d6SRob Clark drm_gem_put_pages(obj, pages, true, false); 2728bb0daffSRob Clark 2738bb0daffSRob Clark return ret; 2748bb0daffSRob Clark } 2758bb0daffSRob Clark 2768bb0daffSRob Clark /** release backing pages */ 2778bb0daffSRob Clark static void omap_gem_detach_pages(struct drm_gem_object *obj) 2788bb0daffSRob Clark { 2798bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 2808bb0daffSRob Clark 2818bb0daffSRob Clark /* for non-cached buffers, ensure the new pages are clean because 2828bb0daffSRob Clark * DSS, GPU, etc. are not cache coherent: 2838bb0daffSRob Clark */ 2848bb0daffSRob Clark if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { 2858bb0daffSRob Clark int i, npages = obj->size >> PAGE_SHIFT; 2868bb0daffSRob Clark for (i = 0; i < npages; i++) { 2878bb0daffSRob Clark dma_unmap_page(obj->dev->dev, omap_obj->addrs[i], 2888bb0daffSRob Clark PAGE_SIZE, DMA_BIDIRECTIONAL); 2898bb0daffSRob Clark } 2908bb0daffSRob Clark } 2918bb0daffSRob Clark 2928bb0daffSRob Clark kfree(omap_obj->addrs); 2938bb0daffSRob Clark omap_obj->addrs = NULL; 2948bb0daffSRob Clark 295ddcd09d6SRob Clark drm_gem_put_pages(obj, omap_obj->pages, true, false); 2968bb0daffSRob Clark omap_obj->pages = NULL; 2978bb0daffSRob Clark } 2988bb0daffSRob Clark 2998bb0daffSRob Clark /* get buffer flags */ 3008bb0daffSRob Clark uint32_t omap_gem_flags(struct drm_gem_object *obj) 3018bb0daffSRob Clark { 3028bb0daffSRob Clark return to_omap_bo(obj)->flags; 3038bb0daffSRob Clark } 3048bb0daffSRob Clark 3058bb0daffSRob Clark /** get mmap offset */ 3068bb0daffSRob Clark static uint64_t mmap_offset(struct drm_gem_object *obj) 3078bb0daffSRob Clark { 3088bb0daffSRob Clark struct drm_device *dev = obj->dev; 3090de23977SDavid Herrmann int ret; 3100de23977SDavid Herrmann size_t size; 3118bb0daffSRob Clark 3128bb0daffSRob Clark WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 3138bb0daffSRob Clark 3148bb0daffSRob Clark /* Make it mmapable */ 3150de23977SDavid Herrmann size = omap_gem_mmap_size(obj); 316ddcd09d6SRob Clark ret = drm_gem_create_mmap_offset_size(obj, size); 3178bb0daffSRob Clark if (ret) { 3188bb0daffSRob Clark dev_err(dev->dev, "could not allocate mmap offset\n"); 3198bb0daffSRob Clark return 0; 3208bb0daffSRob Clark } 3218bb0daffSRob Clark 3220de23977SDavid Herrmann return drm_vma_node_offset_addr(&obj->vma_node); 3238bb0daffSRob Clark } 3248bb0daffSRob Clark 3258bb0daffSRob Clark uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj) 3268bb0daffSRob Clark { 3278bb0daffSRob Clark uint64_t offset; 3288bb0daffSRob Clark mutex_lock(&obj->dev->struct_mutex); 3298bb0daffSRob Clark offset = mmap_offset(obj); 3308bb0daffSRob Clark mutex_unlock(&obj->dev->struct_mutex); 3318bb0daffSRob Clark return offset; 3328bb0daffSRob Clark } 3338bb0daffSRob Clark 3348bb0daffSRob Clark /** get mmap size */ 3358bb0daffSRob Clark size_t omap_gem_mmap_size(struct drm_gem_object *obj) 3368bb0daffSRob Clark { 3378bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 3388bb0daffSRob Clark size_t size = obj->size; 3398bb0daffSRob Clark 3408bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 3418bb0daffSRob Clark /* for tiled buffers, the virtual size has stride rounded up 3428bb0daffSRob Clark * to 4kb.. (to hide the fact that row n+1 might start 16kb or 3438bb0daffSRob Clark * 32kb later!). But we don't back the entire buffer with 3448bb0daffSRob Clark * pages, only the valid picture part.. so need to adjust for 3458bb0daffSRob Clark * this in the size used to mmap and generate mmap offset 3468bb0daffSRob Clark */ 3478bb0daffSRob Clark size = tiler_vsize(gem2fmt(omap_obj->flags), 3488bb0daffSRob Clark omap_obj->width, omap_obj->height); 3498bb0daffSRob Clark } 3508bb0daffSRob Clark 3518bb0daffSRob Clark return size; 3528bb0daffSRob Clark } 3538bb0daffSRob Clark 3548bb0daffSRob Clark /* get tiled size, returns -EINVAL if not tiled buffer */ 3558bb0daffSRob Clark int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h) 3568bb0daffSRob Clark { 3578bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 3588bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 3598bb0daffSRob Clark *w = omap_obj->width; 3608bb0daffSRob Clark *h = omap_obj->height; 3618bb0daffSRob Clark return 0; 3628bb0daffSRob Clark } 3638bb0daffSRob Clark return -EINVAL; 3648bb0daffSRob Clark } 3658bb0daffSRob Clark 3668bb0daffSRob Clark /* Normal handling for the case of faulting in non-tiled buffers */ 3678bb0daffSRob Clark static int fault_1d(struct drm_gem_object *obj, 3688bb0daffSRob Clark struct vm_area_struct *vma, struct vm_fault *vmf) 3698bb0daffSRob Clark { 3708bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 3718bb0daffSRob Clark unsigned long pfn; 3728bb0daffSRob Clark pgoff_t pgoff; 3738bb0daffSRob Clark 3748bb0daffSRob Clark /* We don't use vmf->pgoff since that has the fake offset: */ 3758bb0daffSRob Clark pgoff = ((unsigned long)vmf->virtual_address - 3768bb0daffSRob Clark vma->vm_start) >> PAGE_SHIFT; 3778bb0daffSRob Clark 3788bb0daffSRob Clark if (omap_obj->pages) { 3798bb0daffSRob Clark omap_gem_cpu_sync(obj, pgoff); 3808bb0daffSRob Clark pfn = page_to_pfn(omap_obj->pages[pgoff]); 3818bb0daffSRob Clark } else { 3828bb0daffSRob Clark BUG_ON(!(omap_obj->flags & OMAP_BO_DMA)); 3838bb0daffSRob Clark pfn = (omap_obj->paddr >> PAGE_SHIFT) + pgoff; 3848bb0daffSRob Clark } 3858bb0daffSRob Clark 3868bb0daffSRob Clark VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address, 3878bb0daffSRob Clark pfn, pfn << PAGE_SHIFT); 3888bb0daffSRob Clark 38901c8f1c4SDan Williams return vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, 39001c8f1c4SDan Williams __pfn_to_pfn_t(pfn, PFN_DEV)); 3918bb0daffSRob Clark } 3928bb0daffSRob Clark 3938bb0daffSRob Clark /* Special handling for the case of faulting in 2d tiled buffers */ 3948bb0daffSRob Clark static int fault_2d(struct drm_gem_object *obj, 3958bb0daffSRob Clark struct vm_area_struct *vma, struct vm_fault *vmf) 3968bb0daffSRob Clark { 3978bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 3988bb0daffSRob Clark struct usergart_entry *entry; 3998bb0daffSRob Clark enum tiler_fmt fmt = gem2fmt(omap_obj->flags); 4008bb0daffSRob Clark struct page *pages[64]; /* XXX is this too much to have on stack? */ 4018bb0daffSRob Clark unsigned long pfn; 4028bb0daffSRob Clark pgoff_t pgoff, base_pgoff; 4038bb0daffSRob Clark void __user *vaddr; 4048bb0daffSRob Clark int i, ret, slots; 4058bb0daffSRob Clark 4068bb0daffSRob Clark /* 4078bb0daffSRob Clark * Note the height of the slot is also equal to the number of pages 4088bb0daffSRob Clark * that need to be mapped in to fill 4kb wide CPU page. If the slot 4098bb0daffSRob Clark * height is 64, then 64 pages fill a 4kb wide by 64 row region. 4108bb0daffSRob Clark */ 4118bb0daffSRob Clark const int n = usergart[fmt].height; 4128bb0daffSRob Clark const int n_shift = usergart[fmt].height_shift; 4138bb0daffSRob Clark 4148bb0daffSRob Clark /* 4158bb0daffSRob Clark * If buffer width in bytes > PAGE_SIZE then the virtual stride is 4168bb0daffSRob Clark * rounded up to next multiple of PAGE_SIZE.. this need to be taken 4178bb0daffSRob Clark * into account in some of the math, so figure out virtual stride 4188bb0daffSRob Clark * in pages 4198bb0daffSRob Clark */ 4208bb0daffSRob Clark const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE); 4218bb0daffSRob Clark 4228bb0daffSRob Clark /* We don't use vmf->pgoff since that has the fake offset: */ 4238bb0daffSRob Clark pgoff = ((unsigned long)vmf->virtual_address - 4248bb0daffSRob Clark vma->vm_start) >> PAGE_SHIFT; 4258bb0daffSRob Clark 4268bb0daffSRob Clark /* 4278bb0daffSRob Clark * Actual address we start mapping at is rounded down to previous slot 4288bb0daffSRob Clark * boundary in the y direction: 4298bb0daffSRob Clark */ 4308bb0daffSRob Clark base_pgoff = round_down(pgoff, m << n_shift); 4318bb0daffSRob Clark 4328bb0daffSRob Clark /* figure out buffer width in slots */ 4338bb0daffSRob Clark slots = omap_obj->width >> usergart[fmt].slot_shift; 4348bb0daffSRob Clark 4358bb0daffSRob Clark vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT); 4368bb0daffSRob Clark 4378bb0daffSRob Clark entry = &usergart[fmt].entry[usergart[fmt].last]; 4388bb0daffSRob Clark 4398bb0daffSRob Clark /* evict previous buffer using this usergart entry, if any: */ 4408bb0daffSRob Clark if (entry->obj) 4418bb0daffSRob Clark evict_entry(entry->obj, fmt, entry); 4428bb0daffSRob Clark 4438bb0daffSRob Clark entry->obj = obj; 4448bb0daffSRob Clark entry->obj_pgoff = base_pgoff; 4458bb0daffSRob Clark 4468bb0daffSRob Clark /* now convert base_pgoff to phys offset from virt offset: */ 4478bb0daffSRob Clark base_pgoff = (base_pgoff >> n_shift) * slots; 4488bb0daffSRob Clark 4498bb0daffSRob Clark /* for wider-than 4k.. figure out which part of the slot-row we want: */ 4508bb0daffSRob Clark if (m > 1) { 4518bb0daffSRob Clark int off = pgoff % m; 4528bb0daffSRob Clark entry->obj_pgoff += off; 4538bb0daffSRob Clark base_pgoff /= m; 4548bb0daffSRob Clark slots = min(slots - (off << n_shift), n); 4558bb0daffSRob Clark base_pgoff += off << n_shift; 4568bb0daffSRob Clark vaddr += off << PAGE_SHIFT; 4578bb0daffSRob Clark } 4588bb0daffSRob Clark 4598bb0daffSRob Clark /* 4608bb0daffSRob Clark * Map in pages. Beyond the valid pixel part of the buffer, we set 4618bb0daffSRob Clark * pages[i] to NULL to get a dummy page mapped in.. if someone 4628bb0daffSRob Clark * reads/writes it they will get random/undefined content, but at 4638bb0daffSRob Clark * least it won't be corrupting whatever other random page used to 4648bb0daffSRob Clark * be mapped in, or other undefined behavior. 4658bb0daffSRob Clark */ 4668bb0daffSRob Clark memcpy(pages, &omap_obj->pages[base_pgoff], 4678bb0daffSRob Clark sizeof(struct page *) * slots); 4688bb0daffSRob Clark memset(pages + slots, 0, 4698bb0daffSRob Clark sizeof(struct page *) * (n - slots)); 4708bb0daffSRob Clark 4718bb0daffSRob Clark ret = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true); 4728bb0daffSRob Clark if (ret) { 4738bb0daffSRob Clark dev_err(obj->dev->dev, "failed to pin: %d\n", ret); 4748bb0daffSRob Clark return ret; 4758bb0daffSRob Clark } 4768bb0daffSRob Clark 4778bb0daffSRob Clark pfn = entry->paddr >> PAGE_SHIFT; 4788bb0daffSRob Clark 4798bb0daffSRob Clark VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address, 4808bb0daffSRob Clark pfn, pfn << PAGE_SHIFT); 4818bb0daffSRob Clark 4828bb0daffSRob Clark for (i = n; i > 0; i--) { 48301c8f1c4SDan Williams vm_insert_mixed(vma, (unsigned long)vaddr, 48401c8f1c4SDan Williams __pfn_to_pfn_t(pfn, PFN_DEV)); 4858bb0daffSRob Clark pfn += usergart[fmt].stride_pfn; 4868bb0daffSRob Clark vaddr += PAGE_SIZE * m; 4878bb0daffSRob Clark } 4888bb0daffSRob Clark 4898bb0daffSRob Clark /* simple round-robin: */ 4908bb0daffSRob Clark usergart[fmt].last = (usergart[fmt].last + 1) % NUM_USERGART_ENTRIES; 4918bb0daffSRob Clark 4928bb0daffSRob Clark return 0; 4938bb0daffSRob Clark } 4948bb0daffSRob Clark 4958bb0daffSRob Clark /** 4968bb0daffSRob Clark * omap_gem_fault - pagefault handler for GEM objects 4978bb0daffSRob Clark * @vma: the VMA of the GEM object 4988bb0daffSRob Clark * @vmf: fault detail 4998bb0daffSRob Clark * 5008bb0daffSRob Clark * Invoked when a fault occurs on an mmap of a GEM managed area. GEM 5018bb0daffSRob Clark * does most of the work for us including the actual map/unmap calls 5028bb0daffSRob Clark * but we need to do the actual page work. 5038bb0daffSRob Clark * 5048bb0daffSRob Clark * The VMA was set up by GEM. In doing so it also ensured that the 5058bb0daffSRob Clark * vma->vm_private_data points to the GEM object that is backing this 5068bb0daffSRob Clark * mapping. 5078bb0daffSRob Clark */ 5088bb0daffSRob Clark int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 5098bb0daffSRob Clark { 5108bb0daffSRob Clark struct drm_gem_object *obj = vma->vm_private_data; 5118bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 5128bb0daffSRob Clark struct drm_device *dev = obj->dev; 5138bb0daffSRob Clark struct page **pages; 5148bb0daffSRob Clark int ret; 5158bb0daffSRob Clark 5168bb0daffSRob Clark /* Make sure we don't parallel update on a fault, nor move or remove 5178bb0daffSRob Clark * something from beneath our feet 5188bb0daffSRob Clark */ 5198bb0daffSRob Clark mutex_lock(&dev->struct_mutex); 5208bb0daffSRob Clark 5218bb0daffSRob Clark /* if a shmem backed object, make sure we have pages attached now */ 5228bb0daffSRob Clark ret = get_pages(obj, &pages); 5238bb0daffSRob Clark if (ret) 5248bb0daffSRob Clark goto fail; 5258bb0daffSRob Clark 5268bb0daffSRob Clark /* where should we do corresponding put_pages().. we are mapping 5278bb0daffSRob Clark * the original page, rather than thru a GART, so we can't rely 5288bb0daffSRob Clark * on eviction to trigger this. But munmap() or all mappings should 5298bb0daffSRob Clark * probably trigger put_pages()? 5308bb0daffSRob Clark */ 5318bb0daffSRob Clark 5328bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) 5338bb0daffSRob Clark ret = fault_2d(obj, vma, vmf); 5348bb0daffSRob Clark else 5358bb0daffSRob Clark ret = fault_1d(obj, vma, vmf); 5368bb0daffSRob Clark 5378bb0daffSRob Clark 5388bb0daffSRob Clark fail: 5398bb0daffSRob Clark mutex_unlock(&dev->struct_mutex); 5408bb0daffSRob Clark switch (ret) { 5418bb0daffSRob Clark case 0: 5428bb0daffSRob Clark case -ERESTARTSYS: 5438bb0daffSRob Clark case -EINTR: 5448bb0daffSRob Clark return VM_FAULT_NOPAGE; 5458bb0daffSRob Clark case -ENOMEM: 5468bb0daffSRob Clark return VM_FAULT_OOM; 5478bb0daffSRob Clark default: 5488bb0daffSRob Clark return VM_FAULT_SIGBUS; 5498bb0daffSRob Clark } 5508bb0daffSRob Clark } 5518bb0daffSRob Clark 5528bb0daffSRob Clark /** We override mainly to fix up some of the vm mapping flags.. */ 5538bb0daffSRob Clark int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma) 5548bb0daffSRob Clark { 5558bb0daffSRob Clark int ret; 5568bb0daffSRob Clark 5578bb0daffSRob Clark ret = drm_gem_mmap(filp, vma); 5588bb0daffSRob Clark if (ret) { 5598bb0daffSRob Clark DBG("mmap failed: %d", ret); 5608bb0daffSRob Clark return ret; 5618bb0daffSRob Clark } 5628bb0daffSRob Clark 5638bb0daffSRob Clark return omap_gem_mmap_obj(vma->vm_private_data, vma); 5648bb0daffSRob Clark } 5658bb0daffSRob Clark 5668bb0daffSRob Clark int omap_gem_mmap_obj(struct drm_gem_object *obj, 5678bb0daffSRob Clark struct vm_area_struct *vma) 5688bb0daffSRob Clark { 5698bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 5708bb0daffSRob Clark 5718bb0daffSRob Clark vma->vm_flags &= ~VM_PFNMAP; 5728bb0daffSRob Clark vma->vm_flags |= VM_MIXEDMAP; 5738bb0daffSRob Clark 5748bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_WC) { 5758bb0daffSRob Clark vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); 5768bb0daffSRob Clark } else if (omap_obj->flags & OMAP_BO_UNCACHED) { 5778bb0daffSRob Clark vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags)); 5788bb0daffSRob Clark } else { 5798bb0daffSRob Clark /* 5808bb0daffSRob Clark * We do have some private objects, at least for scanout buffers 5818bb0daffSRob Clark * on hardware without DMM/TILER. But these are allocated write- 5828bb0daffSRob Clark * combine 5838bb0daffSRob Clark */ 5848bb0daffSRob Clark if (WARN_ON(!obj->filp)) 5858bb0daffSRob Clark return -EINVAL; 5868bb0daffSRob Clark 5878bb0daffSRob Clark /* 5888bb0daffSRob Clark * Shunt off cached objs to shmem file so they have their own 5898bb0daffSRob Clark * address_space (so unmap_mapping_range does what we want, 5908bb0daffSRob Clark * in particular in the case of mmap'd dmabufs) 5918bb0daffSRob Clark */ 5928bb0daffSRob Clark fput(vma->vm_file); 5938bb0daffSRob Clark vma->vm_pgoff = 0; 5948bb0daffSRob Clark vma->vm_file = get_file(obj->filp); 5958bb0daffSRob Clark 5968bb0daffSRob Clark vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 5978bb0daffSRob Clark } 5988bb0daffSRob Clark 5998bb0daffSRob Clark return 0; 6008bb0daffSRob Clark } 6018bb0daffSRob Clark 6028bb0daffSRob Clark 6038bb0daffSRob Clark /** 6048bb0daffSRob Clark * omap_gem_dumb_create - create a dumb buffer 6058bb0daffSRob Clark * @drm_file: our client file 6068bb0daffSRob Clark * @dev: our device 6078bb0daffSRob Clark * @args: the requested arguments copied from userspace 6088bb0daffSRob Clark * 6098bb0daffSRob Clark * Allocate a buffer suitable for use for a frame buffer of the 6108bb0daffSRob Clark * form described by user space. Give userspace a handle by which 6118bb0daffSRob Clark * to reference it. 6128bb0daffSRob Clark */ 6138bb0daffSRob Clark int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev, 6148bb0daffSRob Clark struct drm_mode_create_dumb *args) 6158bb0daffSRob Clark { 6168bb0daffSRob Clark union omap_gem_size gsize; 6178bb0daffSRob Clark 618bdb2b933SThierry Reding args->pitch = align_pitch(0, args->width, args->bpp); 6198bb0daffSRob Clark args->size = PAGE_ALIGN(args->pitch * args->height); 6208bb0daffSRob Clark 6218bb0daffSRob Clark gsize = (union omap_gem_size){ 6228bb0daffSRob Clark .bytes = args->size, 6238bb0daffSRob Clark }; 6248bb0daffSRob Clark 6258bb0daffSRob Clark return omap_gem_new_handle(dev, file, gsize, 6268bb0daffSRob Clark OMAP_BO_SCANOUT | OMAP_BO_WC, &args->handle); 6278bb0daffSRob Clark } 6288bb0daffSRob Clark 6298bb0daffSRob Clark /** 6308bb0daffSRob Clark * omap_gem_dumb_map - buffer mapping for dumb interface 6318bb0daffSRob Clark * @file: our drm client file 6328bb0daffSRob Clark * @dev: drm device 6338bb0daffSRob Clark * @handle: GEM handle to the object (from dumb_create) 6348bb0daffSRob Clark * 6358bb0daffSRob Clark * Do the necessary setup to allow the mapping of the frame buffer 6368bb0daffSRob Clark * into user memory. We don't have to do much here at the moment. 6378bb0daffSRob Clark */ 6388bb0daffSRob Clark int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, 6398bb0daffSRob Clark uint32_t handle, uint64_t *offset) 6408bb0daffSRob Clark { 6418bb0daffSRob Clark struct drm_gem_object *obj; 6428bb0daffSRob Clark int ret = 0; 6438bb0daffSRob Clark 6448bb0daffSRob Clark /* GEM does all our handle to object mapping */ 6458bb0daffSRob Clark obj = drm_gem_object_lookup(dev, file, handle); 6468bb0daffSRob Clark if (obj == NULL) { 6478bb0daffSRob Clark ret = -ENOENT; 6488bb0daffSRob Clark goto fail; 6498bb0daffSRob Clark } 6508bb0daffSRob Clark 6518bb0daffSRob Clark *offset = omap_gem_mmap_offset(obj); 6528bb0daffSRob Clark 6538bb0daffSRob Clark drm_gem_object_unreference_unlocked(obj); 6548bb0daffSRob Clark 6558bb0daffSRob Clark fail: 6568bb0daffSRob Clark return ret; 6578bb0daffSRob Clark } 6588bb0daffSRob Clark 6598bb0daffSRob Clark /* Set scrolling position. This allows us to implement fast scrolling 6608bb0daffSRob Clark * for console. 6618bb0daffSRob Clark * 6628bb0daffSRob Clark * Call only from non-atomic contexts. 6638bb0daffSRob Clark */ 6648bb0daffSRob Clark int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll) 6658bb0daffSRob Clark { 6668bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 6678bb0daffSRob Clark uint32_t npages = obj->size >> PAGE_SHIFT; 6688bb0daffSRob Clark int ret = 0; 6698bb0daffSRob Clark 6708bb0daffSRob Clark if (roll > npages) { 6718bb0daffSRob Clark dev_err(obj->dev->dev, "invalid roll: %d\n", roll); 6728bb0daffSRob Clark return -EINVAL; 6738bb0daffSRob Clark } 6748bb0daffSRob Clark 6758bb0daffSRob Clark omap_obj->roll = roll; 6768bb0daffSRob Clark 6778bb0daffSRob Clark mutex_lock(&obj->dev->struct_mutex); 6788bb0daffSRob Clark 6798bb0daffSRob Clark /* if we aren't mapped yet, we don't need to do anything */ 6808bb0daffSRob Clark if (omap_obj->block) { 6818bb0daffSRob Clark struct page **pages; 6828bb0daffSRob Clark ret = get_pages(obj, &pages); 6838bb0daffSRob Clark if (ret) 6848bb0daffSRob Clark goto fail; 6858bb0daffSRob Clark ret = tiler_pin(omap_obj->block, pages, npages, roll, true); 6868bb0daffSRob Clark if (ret) 6878bb0daffSRob Clark dev_err(obj->dev->dev, "could not repin: %d\n", ret); 6888bb0daffSRob Clark } 6898bb0daffSRob Clark 6908bb0daffSRob Clark fail: 6918bb0daffSRob Clark mutex_unlock(&obj->dev->struct_mutex); 6928bb0daffSRob Clark 6938bb0daffSRob Clark return ret; 6948bb0daffSRob Clark } 6958bb0daffSRob Clark 6968bb0daffSRob Clark /* Sync the buffer for CPU access.. note pages should already be 6978bb0daffSRob Clark * attached, ie. omap_gem_get_pages() 6988bb0daffSRob Clark */ 6998bb0daffSRob Clark void omap_gem_cpu_sync(struct drm_gem_object *obj, int pgoff) 7008bb0daffSRob Clark { 7018bb0daffSRob Clark struct drm_device *dev = obj->dev; 7028bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 7038bb0daffSRob Clark 7048bb0daffSRob Clark if (is_cached_coherent(obj) && omap_obj->addrs[pgoff]) { 7058bb0daffSRob Clark dma_unmap_page(dev->dev, omap_obj->addrs[pgoff], 7068bb0daffSRob Clark PAGE_SIZE, DMA_BIDIRECTIONAL); 7078bb0daffSRob Clark omap_obj->addrs[pgoff] = 0; 7088bb0daffSRob Clark } 7098bb0daffSRob Clark } 7108bb0daffSRob Clark 7118bb0daffSRob Clark /* sync the buffer for DMA access */ 7128bb0daffSRob Clark void omap_gem_dma_sync(struct drm_gem_object *obj, 7138bb0daffSRob Clark enum dma_data_direction dir) 7148bb0daffSRob Clark { 7158bb0daffSRob Clark struct drm_device *dev = obj->dev; 7168bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 7178bb0daffSRob Clark 7188bb0daffSRob Clark if (is_cached_coherent(obj)) { 7198bb0daffSRob Clark int i, npages = obj->size >> PAGE_SHIFT; 7208bb0daffSRob Clark struct page **pages = omap_obj->pages; 7218bb0daffSRob Clark bool dirty = false; 7228bb0daffSRob Clark 7238bb0daffSRob Clark for (i = 0; i < npages; i++) { 7248bb0daffSRob Clark if (!omap_obj->addrs[i]) { 7258bb0daffSRob Clark omap_obj->addrs[i] = dma_map_page(dev->dev, pages[i], 0, 7268bb0daffSRob Clark PAGE_SIZE, DMA_BIDIRECTIONAL); 7278bb0daffSRob Clark dirty = true; 7288bb0daffSRob Clark } 7298bb0daffSRob Clark } 7308bb0daffSRob Clark 7318bb0daffSRob Clark if (dirty) { 7328bb0daffSRob Clark unmap_mapping_range(obj->filp->f_mapping, 0, 7338bb0daffSRob Clark omap_gem_mmap_size(obj), 1); 7348bb0daffSRob Clark } 7358bb0daffSRob Clark } 7368bb0daffSRob Clark } 7378bb0daffSRob Clark 7388bb0daffSRob Clark /* Get physical address for DMA.. if 'remap' is true, and the buffer is not 7398bb0daffSRob Clark * already contiguous, remap it to pin in physically contiguous memory.. (ie. 7408bb0daffSRob Clark * map in TILER) 7418bb0daffSRob Clark */ 7428bb0daffSRob Clark int omap_gem_get_paddr(struct drm_gem_object *obj, 7438bb0daffSRob Clark dma_addr_t *paddr, bool remap) 7448bb0daffSRob Clark { 7458bb0daffSRob Clark struct omap_drm_private *priv = obj->dev->dev_private; 7468bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 7478bb0daffSRob Clark int ret = 0; 7488bb0daffSRob Clark 7498bb0daffSRob Clark mutex_lock(&obj->dev->struct_mutex); 7508bb0daffSRob Clark 7518bb0daffSRob Clark if (remap && is_shmem(obj) && priv->has_dmm) { 7528bb0daffSRob Clark if (omap_obj->paddr_cnt == 0) { 7538bb0daffSRob Clark struct page **pages; 7548bb0daffSRob Clark uint32_t npages = obj->size >> PAGE_SHIFT; 7558bb0daffSRob Clark enum tiler_fmt fmt = gem2fmt(omap_obj->flags); 7568bb0daffSRob Clark struct tiler_block *block; 7578bb0daffSRob Clark 7588bb0daffSRob Clark BUG_ON(omap_obj->block); 7598bb0daffSRob Clark 7608bb0daffSRob Clark ret = get_pages(obj, &pages); 7618bb0daffSRob Clark if (ret) 7628bb0daffSRob Clark goto fail; 7638bb0daffSRob Clark 7648bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 7658bb0daffSRob Clark block = tiler_reserve_2d(fmt, 7668bb0daffSRob Clark omap_obj->width, 7678bb0daffSRob Clark omap_obj->height, 0); 7688bb0daffSRob Clark } else { 7698bb0daffSRob Clark block = tiler_reserve_1d(obj->size); 7708bb0daffSRob Clark } 7718bb0daffSRob Clark 7728bb0daffSRob Clark if (IS_ERR(block)) { 7738bb0daffSRob Clark ret = PTR_ERR(block); 7748bb0daffSRob Clark dev_err(obj->dev->dev, 7758bb0daffSRob Clark "could not remap: %d (%d)\n", ret, fmt); 7768bb0daffSRob Clark goto fail; 7778bb0daffSRob Clark } 7788bb0daffSRob Clark 7798bb0daffSRob Clark /* TODO: enable async refill.. */ 7808bb0daffSRob Clark ret = tiler_pin(block, pages, npages, 7818bb0daffSRob Clark omap_obj->roll, true); 7828bb0daffSRob Clark if (ret) { 7838bb0daffSRob Clark tiler_release(block); 7848bb0daffSRob Clark dev_err(obj->dev->dev, 7858bb0daffSRob Clark "could not pin: %d\n", ret); 7868bb0daffSRob Clark goto fail; 7878bb0daffSRob Clark } 7888bb0daffSRob Clark 7898bb0daffSRob Clark omap_obj->paddr = tiler_ssptr(block); 7908bb0daffSRob Clark omap_obj->block = block; 7918bb0daffSRob Clark 7922d31ca3aSRussell King DBG("got paddr: %pad", &omap_obj->paddr); 7938bb0daffSRob Clark } 7948bb0daffSRob Clark 7958bb0daffSRob Clark omap_obj->paddr_cnt++; 7968bb0daffSRob Clark 7978bb0daffSRob Clark *paddr = omap_obj->paddr; 7988bb0daffSRob Clark } else if (omap_obj->flags & OMAP_BO_DMA) { 7998bb0daffSRob Clark *paddr = omap_obj->paddr; 8008bb0daffSRob Clark } else { 8018bb0daffSRob Clark ret = -EINVAL; 8028bb0daffSRob Clark goto fail; 8038bb0daffSRob Clark } 8048bb0daffSRob Clark 8058bb0daffSRob Clark fail: 8068bb0daffSRob Clark mutex_unlock(&obj->dev->struct_mutex); 8078bb0daffSRob Clark 8088bb0daffSRob Clark return ret; 8098bb0daffSRob Clark } 8108bb0daffSRob Clark 8118bb0daffSRob Clark /* Release physical address, when DMA is no longer being performed.. this 8128bb0daffSRob Clark * could potentially unpin and unmap buffers from TILER 8138bb0daffSRob Clark */ 814393a949fSTomi Valkeinen void omap_gem_put_paddr(struct drm_gem_object *obj) 8158bb0daffSRob Clark { 8168bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 817393a949fSTomi Valkeinen int ret; 8188bb0daffSRob Clark 8198bb0daffSRob Clark mutex_lock(&obj->dev->struct_mutex); 8208bb0daffSRob Clark if (omap_obj->paddr_cnt > 0) { 8218bb0daffSRob Clark omap_obj->paddr_cnt--; 8228bb0daffSRob Clark if (omap_obj->paddr_cnt == 0) { 8238bb0daffSRob Clark ret = tiler_unpin(omap_obj->block); 8248bb0daffSRob Clark if (ret) { 8258bb0daffSRob Clark dev_err(obj->dev->dev, 8268bb0daffSRob Clark "could not unpin pages: %d\n", ret); 8278bb0daffSRob Clark } 8288bb0daffSRob Clark ret = tiler_release(omap_obj->block); 8298bb0daffSRob Clark if (ret) { 8308bb0daffSRob Clark dev_err(obj->dev->dev, 8318bb0daffSRob Clark "could not release unmap: %d\n", ret); 8328bb0daffSRob Clark } 8333f4d17c4STomi Valkeinen omap_obj->paddr = 0; 8348bb0daffSRob Clark omap_obj->block = NULL; 8358bb0daffSRob Clark } 8368bb0daffSRob Clark } 837393a949fSTomi Valkeinen 8388bb0daffSRob Clark mutex_unlock(&obj->dev->struct_mutex); 8398bb0daffSRob Clark } 8408bb0daffSRob Clark 8418bb0daffSRob Clark /* Get rotated scanout address (only valid if already pinned), at the 8428bb0daffSRob Clark * specified orientation and x,y offset from top-left corner of buffer 8438bb0daffSRob Clark * (only valid for tiled 2d buffers) 8448bb0daffSRob Clark */ 8458bb0daffSRob Clark int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient, 8468bb0daffSRob Clark int x, int y, dma_addr_t *paddr) 8478bb0daffSRob Clark { 8488bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 8498bb0daffSRob Clark int ret = -EINVAL; 8508bb0daffSRob Clark 8518bb0daffSRob Clark mutex_lock(&obj->dev->struct_mutex); 8528bb0daffSRob Clark if ((omap_obj->paddr_cnt > 0) && omap_obj->block && 8538bb0daffSRob Clark (omap_obj->flags & OMAP_BO_TILED)) { 8548bb0daffSRob Clark *paddr = tiler_tsptr(omap_obj->block, orient, x, y); 8558bb0daffSRob Clark ret = 0; 8568bb0daffSRob Clark } 8578bb0daffSRob Clark mutex_unlock(&obj->dev->struct_mutex); 8588bb0daffSRob Clark return ret; 8598bb0daffSRob Clark } 8608bb0daffSRob Clark 8618bb0daffSRob Clark /* Get tiler stride for the buffer (only valid for 2d tiled buffers) */ 8628bb0daffSRob Clark int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient) 8638bb0daffSRob Clark { 8648bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 8658bb0daffSRob Clark int ret = -EINVAL; 8668bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) 8678bb0daffSRob Clark ret = tiler_stride(gem2fmt(omap_obj->flags), orient); 8688bb0daffSRob Clark return ret; 8698bb0daffSRob Clark } 8708bb0daffSRob Clark 8718bb0daffSRob Clark /* acquire pages when needed (for example, for DMA where physically 8728bb0daffSRob Clark * contiguous buffer is not required 8738bb0daffSRob Clark */ 8748bb0daffSRob Clark static int get_pages(struct drm_gem_object *obj, struct page ***pages) 8758bb0daffSRob Clark { 8768bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 8778bb0daffSRob Clark int ret = 0; 8788bb0daffSRob Clark 8798bb0daffSRob Clark if (is_shmem(obj) && !omap_obj->pages) { 8808bb0daffSRob Clark ret = omap_gem_attach_pages(obj); 8818bb0daffSRob Clark if (ret) { 8828bb0daffSRob Clark dev_err(obj->dev->dev, "could not attach pages\n"); 8838bb0daffSRob Clark return ret; 8848bb0daffSRob Clark } 8858bb0daffSRob Clark } 8868bb0daffSRob Clark 8878bb0daffSRob Clark /* TODO: even phys-contig.. we should have a list of pages? */ 8888bb0daffSRob Clark *pages = omap_obj->pages; 8898bb0daffSRob Clark 8908bb0daffSRob Clark return 0; 8918bb0daffSRob Clark } 8928bb0daffSRob Clark 8938bb0daffSRob Clark /* if !remap, and we don't have pages backing, then fail, rather than 8948bb0daffSRob Clark * increasing the pin count (which we don't really do yet anyways, 8958bb0daffSRob Clark * because we don't support swapping pages back out). And 'remap' 8968bb0daffSRob Clark * might not be quite the right name, but I wanted to keep it working 8978bb0daffSRob Clark * similarly to omap_gem_get_paddr(). Note though that mutex is not 8988bb0daffSRob Clark * aquired if !remap (because this can be called in atomic ctxt), 8998bb0daffSRob Clark * but probably omap_gem_get_paddr() should be changed to work in the 9008bb0daffSRob Clark * same way. If !remap, a matching omap_gem_put_pages() call is not 9018bb0daffSRob Clark * required (and should not be made). 9028bb0daffSRob Clark */ 9038bb0daffSRob Clark int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, 9048bb0daffSRob Clark bool remap) 9058bb0daffSRob Clark { 9068bb0daffSRob Clark int ret; 9078bb0daffSRob Clark if (!remap) { 9088bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 9098bb0daffSRob Clark if (!omap_obj->pages) 9108bb0daffSRob Clark return -ENOMEM; 9118bb0daffSRob Clark *pages = omap_obj->pages; 9128bb0daffSRob Clark return 0; 9138bb0daffSRob Clark } 9148bb0daffSRob Clark mutex_lock(&obj->dev->struct_mutex); 9158bb0daffSRob Clark ret = get_pages(obj, pages); 9168bb0daffSRob Clark mutex_unlock(&obj->dev->struct_mutex); 9178bb0daffSRob Clark return ret; 9188bb0daffSRob Clark } 9198bb0daffSRob Clark 9208bb0daffSRob Clark /* release pages when DMA no longer being performed */ 9218bb0daffSRob Clark int omap_gem_put_pages(struct drm_gem_object *obj) 9228bb0daffSRob Clark { 9238bb0daffSRob Clark /* do something here if we dynamically attach/detach pages.. at 9248bb0daffSRob Clark * least they would no longer need to be pinned if everyone has 9258bb0daffSRob Clark * released the pages.. 9268bb0daffSRob Clark */ 9278bb0daffSRob Clark return 0; 9288bb0daffSRob Clark } 9298bb0daffSRob Clark 9308bb0daffSRob Clark /* Get kernel virtual address for CPU access.. this more or less only 9318bb0daffSRob Clark * exists for omap_fbdev. This should be called with struct_mutex 9328bb0daffSRob Clark * held. 9338bb0daffSRob Clark */ 9348bb0daffSRob Clark void *omap_gem_vaddr(struct drm_gem_object *obj) 9358bb0daffSRob Clark { 9368bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 9378bb0daffSRob Clark WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); 9388bb0daffSRob Clark if (!omap_obj->vaddr) { 9398bb0daffSRob Clark struct page **pages; 9408bb0daffSRob Clark int ret = get_pages(obj, &pages); 9418bb0daffSRob Clark if (ret) 9428bb0daffSRob Clark return ERR_PTR(ret); 9438bb0daffSRob Clark omap_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT, 9448bb0daffSRob Clark VM_MAP, pgprot_writecombine(PAGE_KERNEL)); 9458bb0daffSRob Clark } 9468bb0daffSRob Clark return omap_obj->vaddr; 9478bb0daffSRob Clark } 9488bb0daffSRob Clark 9498bb0daffSRob Clark #ifdef CONFIG_PM 9508bb0daffSRob Clark /* re-pin objects in DMM in resume path: */ 9518bb0daffSRob Clark int omap_gem_resume(struct device *dev) 9528bb0daffSRob Clark { 9538bb0daffSRob Clark struct drm_device *drm_dev = dev_get_drvdata(dev); 9548bb0daffSRob Clark struct omap_drm_private *priv = drm_dev->dev_private; 9558bb0daffSRob Clark struct omap_gem_object *omap_obj; 9568bb0daffSRob Clark int ret = 0; 9578bb0daffSRob Clark 9588bb0daffSRob Clark list_for_each_entry(omap_obj, &priv->obj_list, mm_list) { 9598bb0daffSRob Clark if (omap_obj->block) { 9608bb0daffSRob Clark struct drm_gem_object *obj = &omap_obj->base; 9618bb0daffSRob Clark uint32_t npages = obj->size >> PAGE_SHIFT; 9628bb0daffSRob Clark WARN_ON(!omap_obj->pages); /* this can't happen */ 9638bb0daffSRob Clark ret = tiler_pin(omap_obj->block, 9648bb0daffSRob Clark omap_obj->pages, npages, 9658bb0daffSRob Clark omap_obj->roll, true); 9668bb0daffSRob Clark if (ret) { 9678bb0daffSRob Clark dev_err(dev, "could not repin: %d\n", ret); 9688bb0daffSRob Clark return ret; 9698bb0daffSRob Clark } 9708bb0daffSRob Clark } 9718bb0daffSRob Clark } 9728bb0daffSRob Clark 9738bb0daffSRob Clark return 0; 9748bb0daffSRob Clark } 9758bb0daffSRob Clark #endif 9768bb0daffSRob Clark 9778bb0daffSRob Clark #ifdef CONFIG_DEBUG_FS 9788bb0daffSRob Clark void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) 9798bb0daffSRob Clark { 9808bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 9810de23977SDavid Herrmann uint64_t off; 9828bb0daffSRob Clark 9830de23977SDavid Herrmann off = drm_vma_node_start(&obj->vma_node); 9848bb0daffSRob Clark 9852d31ca3aSRussell King seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", 9868bb0daffSRob Clark omap_obj->flags, obj->name, obj->refcount.refcount.counter, 9872d31ca3aSRussell King off, &omap_obj->paddr, omap_obj->paddr_cnt, 9888bb0daffSRob Clark omap_obj->vaddr, omap_obj->roll); 9898bb0daffSRob Clark 9908bb0daffSRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 9918bb0daffSRob Clark seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height); 9928bb0daffSRob Clark if (omap_obj->block) { 9938bb0daffSRob Clark struct tcm_area *area = &omap_obj->block->area; 9948bb0daffSRob Clark seq_printf(m, " (%dx%d, %dx%d)", 9958bb0daffSRob Clark area->p0.x, area->p0.y, 9968bb0daffSRob Clark area->p1.x, area->p1.y); 9978bb0daffSRob Clark } 9988bb0daffSRob Clark } else { 9998bb0daffSRob Clark seq_printf(m, " %d", obj->size); 10008bb0daffSRob Clark } 10018bb0daffSRob Clark 10028bb0daffSRob Clark seq_printf(m, "\n"); 10038bb0daffSRob Clark } 10048bb0daffSRob Clark 10058bb0daffSRob Clark void omap_gem_describe_objects(struct list_head *list, struct seq_file *m) 10068bb0daffSRob Clark { 10078bb0daffSRob Clark struct omap_gem_object *omap_obj; 10088bb0daffSRob Clark int count = 0; 10098bb0daffSRob Clark size_t size = 0; 10108bb0daffSRob Clark 10118bb0daffSRob Clark list_for_each_entry(omap_obj, list, mm_list) { 10128bb0daffSRob Clark struct drm_gem_object *obj = &omap_obj->base; 10138bb0daffSRob Clark seq_printf(m, " "); 10148bb0daffSRob Clark omap_gem_describe(obj, m); 10158bb0daffSRob Clark count++; 10168bb0daffSRob Clark size += obj->size; 10178bb0daffSRob Clark } 10188bb0daffSRob Clark 10198bb0daffSRob Clark seq_printf(m, "Total %d objects, %zu bytes\n", count, size); 10208bb0daffSRob Clark } 10218bb0daffSRob Clark #endif 10228bb0daffSRob Clark 10238bb0daffSRob Clark /* Buffer Synchronization: 10248bb0daffSRob Clark */ 10258bb0daffSRob Clark 10268bb0daffSRob Clark struct omap_gem_sync_waiter { 10278bb0daffSRob Clark struct list_head list; 10288bb0daffSRob Clark struct omap_gem_object *omap_obj; 10298bb0daffSRob Clark enum omap_gem_op op; 10308bb0daffSRob Clark uint32_t read_target, write_target; 10318bb0daffSRob Clark /* notify called w/ sync_lock held */ 10328bb0daffSRob Clark void (*notify)(void *arg); 10338bb0daffSRob Clark void *arg; 10348bb0daffSRob Clark }; 10358bb0daffSRob Clark 10368bb0daffSRob Clark /* list of omap_gem_sync_waiter.. the notify fxn gets called back when 10378bb0daffSRob Clark * the read and/or write target count is achieved which can call a user 10388bb0daffSRob Clark * callback (ex. to kick 3d and/or 2d), wakeup blocked task (prep for 10398bb0daffSRob Clark * cpu access), etc. 10408bb0daffSRob Clark */ 10418bb0daffSRob Clark static LIST_HEAD(waiters); 10428bb0daffSRob Clark 10438bb0daffSRob Clark static inline bool is_waiting(struct omap_gem_sync_waiter *waiter) 10448bb0daffSRob Clark { 10458bb0daffSRob Clark struct omap_gem_object *omap_obj = waiter->omap_obj; 10468bb0daffSRob Clark if ((waiter->op & OMAP_GEM_READ) && 1047f2cff0f3SArchit Taneja (omap_obj->sync->write_complete < waiter->write_target)) 10488bb0daffSRob Clark return true; 10498bb0daffSRob Clark if ((waiter->op & OMAP_GEM_WRITE) && 1050f2cff0f3SArchit Taneja (omap_obj->sync->read_complete < waiter->read_target)) 10518bb0daffSRob Clark return true; 10528bb0daffSRob Clark return false; 10538bb0daffSRob Clark } 10548bb0daffSRob Clark 10558bb0daffSRob Clark /* macro for sync debug.. */ 10568bb0daffSRob Clark #define SYNCDBG 0 10578bb0daffSRob Clark #define SYNC(fmt, ...) do { if (SYNCDBG) \ 10588bb0daffSRob Clark printk(KERN_ERR "%s:%d: "fmt"\n", \ 10598bb0daffSRob Clark __func__, __LINE__, ##__VA_ARGS__); \ 10608bb0daffSRob Clark } while (0) 10618bb0daffSRob Clark 10628bb0daffSRob Clark 10638bb0daffSRob Clark static void sync_op_update(void) 10648bb0daffSRob Clark { 10658bb0daffSRob Clark struct omap_gem_sync_waiter *waiter, *n; 10668bb0daffSRob Clark list_for_each_entry_safe(waiter, n, &waiters, list) { 10678bb0daffSRob Clark if (!is_waiting(waiter)) { 10688bb0daffSRob Clark list_del(&waiter->list); 10698bb0daffSRob Clark SYNC("notify: %p", waiter); 10708bb0daffSRob Clark waiter->notify(waiter->arg); 10718bb0daffSRob Clark kfree(waiter); 10728bb0daffSRob Clark } 10738bb0daffSRob Clark } 10748bb0daffSRob Clark } 10758bb0daffSRob Clark 10768bb0daffSRob Clark static inline int sync_op(struct drm_gem_object *obj, 10778bb0daffSRob Clark enum omap_gem_op op, bool start) 10788bb0daffSRob Clark { 10798bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 10808bb0daffSRob Clark int ret = 0; 10818bb0daffSRob Clark 10828bb0daffSRob Clark spin_lock(&sync_lock); 10838bb0daffSRob Clark 10848bb0daffSRob Clark if (!omap_obj->sync) { 10858bb0daffSRob Clark omap_obj->sync = kzalloc(sizeof(*omap_obj->sync), GFP_ATOMIC); 10868bb0daffSRob Clark if (!omap_obj->sync) { 10878bb0daffSRob Clark ret = -ENOMEM; 10888bb0daffSRob Clark goto unlock; 10898bb0daffSRob Clark } 10908bb0daffSRob Clark } 10918bb0daffSRob Clark 10928bb0daffSRob Clark if (start) { 10938bb0daffSRob Clark if (op & OMAP_GEM_READ) 10948bb0daffSRob Clark omap_obj->sync->read_pending++; 10958bb0daffSRob Clark if (op & OMAP_GEM_WRITE) 10968bb0daffSRob Clark omap_obj->sync->write_pending++; 10978bb0daffSRob Clark } else { 10988bb0daffSRob Clark if (op & OMAP_GEM_READ) 10998bb0daffSRob Clark omap_obj->sync->read_complete++; 11008bb0daffSRob Clark if (op & OMAP_GEM_WRITE) 11018bb0daffSRob Clark omap_obj->sync->write_complete++; 11028bb0daffSRob Clark sync_op_update(); 11038bb0daffSRob Clark } 11048bb0daffSRob Clark 11058bb0daffSRob Clark unlock: 11068bb0daffSRob Clark spin_unlock(&sync_lock); 11078bb0daffSRob Clark 11088bb0daffSRob Clark return ret; 11098bb0daffSRob Clark } 11108bb0daffSRob Clark 11118bb0daffSRob Clark /* it is a bit lame to handle updates in this sort of polling way, but 11128bb0daffSRob Clark * in case of PVR, the GPU can directly update read/write complete 11138bb0daffSRob Clark * values, and not really tell us which ones it updated.. this also 11148bb0daffSRob Clark * means that sync_lock is not quite sufficient. So we'll need to 11158bb0daffSRob Clark * do something a bit better when it comes time to add support for 11168bb0daffSRob Clark * separate 2d hw.. 11178bb0daffSRob Clark */ 11188bb0daffSRob Clark void omap_gem_op_update(void) 11198bb0daffSRob Clark { 11208bb0daffSRob Clark spin_lock(&sync_lock); 11218bb0daffSRob Clark sync_op_update(); 11228bb0daffSRob Clark spin_unlock(&sync_lock); 11238bb0daffSRob Clark } 11248bb0daffSRob Clark 11258bb0daffSRob Clark /* mark the start of read and/or write operation */ 11268bb0daffSRob Clark int omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op) 11278bb0daffSRob Clark { 11288bb0daffSRob Clark return sync_op(obj, op, true); 11298bb0daffSRob Clark } 11308bb0daffSRob Clark 11318bb0daffSRob Clark int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op) 11328bb0daffSRob Clark { 11338bb0daffSRob Clark return sync_op(obj, op, false); 11348bb0daffSRob Clark } 11358bb0daffSRob Clark 11368bb0daffSRob Clark static DECLARE_WAIT_QUEUE_HEAD(sync_event); 11378bb0daffSRob Clark 11388bb0daffSRob Clark static void sync_notify(void *arg) 11398bb0daffSRob Clark { 11408bb0daffSRob Clark struct task_struct **waiter_task = arg; 11418bb0daffSRob Clark *waiter_task = NULL; 11428bb0daffSRob Clark wake_up_all(&sync_event); 11438bb0daffSRob Clark } 11448bb0daffSRob Clark 11458bb0daffSRob Clark int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op) 11468bb0daffSRob Clark { 11478bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 11488bb0daffSRob Clark int ret = 0; 11498bb0daffSRob Clark if (omap_obj->sync) { 11508bb0daffSRob Clark struct task_struct *waiter_task = current; 11518bb0daffSRob Clark struct omap_gem_sync_waiter *waiter = 11528bb0daffSRob Clark kzalloc(sizeof(*waiter), GFP_KERNEL); 11538bb0daffSRob Clark 11548bb0daffSRob Clark if (!waiter) 11558bb0daffSRob Clark return -ENOMEM; 11568bb0daffSRob Clark 11578bb0daffSRob Clark waiter->omap_obj = omap_obj; 11588bb0daffSRob Clark waiter->op = op; 11598bb0daffSRob Clark waiter->read_target = omap_obj->sync->read_pending; 11608bb0daffSRob Clark waiter->write_target = omap_obj->sync->write_pending; 11618bb0daffSRob Clark waiter->notify = sync_notify; 11628bb0daffSRob Clark waiter->arg = &waiter_task; 11638bb0daffSRob Clark 11648bb0daffSRob Clark spin_lock(&sync_lock); 11658bb0daffSRob Clark if (is_waiting(waiter)) { 11668bb0daffSRob Clark SYNC("waited: %p", waiter); 11678bb0daffSRob Clark list_add_tail(&waiter->list, &waiters); 11688bb0daffSRob Clark spin_unlock(&sync_lock); 11698bb0daffSRob Clark ret = wait_event_interruptible(sync_event, 11708bb0daffSRob Clark (waiter_task == NULL)); 11718bb0daffSRob Clark spin_lock(&sync_lock); 11728bb0daffSRob Clark if (waiter_task) { 11738bb0daffSRob Clark SYNC("interrupted: %p", waiter); 11748bb0daffSRob Clark /* we were interrupted */ 11758bb0daffSRob Clark list_del(&waiter->list); 11768bb0daffSRob Clark waiter_task = NULL; 11778bb0daffSRob Clark } else { 11788bb0daffSRob Clark /* freed in sync_op_update() */ 11798bb0daffSRob Clark waiter = NULL; 11808bb0daffSRob Clark } 11818bb0daffSRob Clark } 11828bb0daffSRob Clark spin_unlock(&sync_lock); 11838bb0daffSRob Clark kfree(waiter); 11848bb0daffSRob Clark } 11858bb0daffSRob Clark return ret; 11868bb0daffSRob Clark } 11878bb0daffSRob Clark 11888bb0daffSRob Clark /* call fxn(arg), either synchronously or asynchronously if the op 11898bb0daffSRob Clark * is currently blocked.. fxn() can be called from any context 11908bb0daffSRob Clark * 11918bb0daffSRob Clark * (TODO for now fxn is called back from whichever context calls 11928bb0daffSRob Clark * omap_gem_op_update().. but this could be better defined later 11938bb0daffSRob Clark * if needed) 11948bb0daffSRob Clark * 11958bb0daffSRob Clark * TODO more code in common w/ _sync().. 11968bb0daffSRob Clark */ 11978bb0daffSRob Clark int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op, 11988bb0daffSRob Clark void (*fxn)(void *arg), void *arg) 11998bb0daffSRob Clark { 12008bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 12018bb0daffSRob Clark if (omap_obj->sync) { 12028bb0daffSRob Clark struct omap_gem_sync_waiter *waiter = 12038bb0daffSRob Clark kzalloc(sizeof(*waiter), GFP_ATOMIC); 12048bb0daffSRob Clark 12058bb0daffSRob Clark if (!waiter) 12068bb0daffSRob Clark return -ENOMEM; 12078bb0daffSRob Clark 12088bb0daffSRob Clark waiter->omap_obj = omap_obj; 12098bb0daffSRob Clark waiter->op = op; 12108bb0daffSRob Clark waiter->read_target = omap_obj->sync->read_pending; 12118bb0daffSRob Clark waiter->write_target = omap_obj->sync->write_pending; 12128bb0daffSRob Clark waiter->notify = fxn; 12138bb0daffSRob Clark waiter->arg = arg; 12148bb0daffSRob Clark 12158bb0daffSRob Clark spin_lock(&sync_lock); 12168bb0daffSRob Clark if (is_waiting(waiter)) { 12178bb0daffSRob Clark SYNC("waited: %p", waiter); 12188bb0daffSRob Clark list_add_tail(&waiter->list, &waiters); 12198bb0daffSRob Clark spin_unlock(&sync_lock); 12208bb0daffSRob Clark return 0; 12218bb0daffSRob Clark } 12228bb0daffSRob Clark 12238bb0daffSRob Clark spin_unlock(&sync_lock); 122415ec2ca9SSubhajit Paul 122515ec2ca9SSubhajit Paul kfree(waiter); 12268bb0daffSRob Clark } 12278bb0daffSRob Clark 12288bb0daffSRob Clark /* no waiting.. */ 12298bb0daffSRob Clark fxn(arg); 12308bb0daffSRob Clark 12318bb0daffSRob Clark return 0; 12328bb0daffSRob Clark } 12338bb0daffSRob Clark 12348bb0daffSRob Clark /* special API so PVR can update the buffer to use a sync-object allocated 12358bb0daffSRob Clark * from it's sync-obj heap. Only used for a newly allocated (from PVR's 12368bb0daffSRob Clark * perspective) sync-object, so we overwrite the new syncobj w/ values 12378bb0daffSRob Clark * from the already allocated syncobj (if there is one) 12388bb0daffSRob Clark */ 12398bb0daffSRob Clark int omap_gem_set_sync_object(struct drm_gem_object *obj, void *syncobj) 12408bb0daffSRob Clark { 12418bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 12428bb0daffSRob Clark int ret = 0; 12438bb0daffSRob Clark 12448bb0daffSRob Clark spin_lock(&sync_lock); 12458bb0daffSRob Clark 12468bb0daffSRob Clark if ((omap_obj->flags & OMAP_BO_EXT_SYNC) && !syncobj) { 12478bb0daffSRob Clark /* clearing a previously set syncobj */ 12488bb0daffSRob Clark syncobj = kmemdup(omap_obj->sync, sizeof(*omap_obj->sync), 12498bb0daffSRob Clark GFP_ATOMIC); 12508bb0daffSRob Clark if (!syncobj) { 12518bb0daffSRob Clark ret = -ENOMEM; 12528bb0daffSRob Clark goto unlock; 12538bb0daffSRob Clark } 12548bb0daffSRob Clark omap_obj->flags &= ~OMAP_BO_EXT_SYNC; 12558bb0daffSRob Clark omap_obj->sync = syncobj; 12568bb0daffSRob Clark } else if (syncobj && !(omap_obj->flags & OMAP_BO_EXT_SYNC)) { 12578bb0daffSRob Clark /* replacing an existing syncobj */ 12588bb0daffSRob Clark if (omap_obj->sync) { 12598bb0daffSRob Clark memcpy(syncobj, omap_obj->sync, sizeof(*omap_obj->sync)); 12608bb0daffSRob Clark kfree(omap_obj->sync); 12618bb0daffSRob Clark } 12628bb0daffSRob Clark omap_obj->flags |= OMAP_BO_EXT_SYNC; 12638bb0daffSRob Clark omap_obj->sync = syncobj; 12648bb0daffSRob Clark } 12658bb0daffSRob Clark 12668bb0daffSRob Clark unlock: 12678bb0daffSRob Clark spin_unlock(&sync_lock); 12688bb0daffSRob Clark return ret; 12698bb0daffSRob Clark } 12708bb0daffSRob Clark 12718bb0daffSRob Clark /* don't call directly.. called from GEM core when it is time to actually 12728bb0daffSRob Clark * free the object.. 12738bb0daffSRob Clark */ 12748bb0daffSRob Clark void omap_gem_free_object(struct drm_gem_object *obj) 12758bb0daffSRob Clark { 12768bb0daffSRob Clark struct drm_device *dev = obj->dev; 127776c4055fSTomi Valkeinen struct omap_drm_private *priv = dev->dev_private; 12788bb0daffSRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 12798bb0daffSRob Clark 12808bb0daffSRob Clark evict(obj); 12818bb0daffSRob Clark 12828bb0daffSRob Clark WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 12838bb0daffSRob Clark 128476c4055fSTomi Valkeinen spin_lock(&priv->list_lock); 12858bb0daffSRob Clark list_del(&omap_obj->mm_list); 128676c4055fSTomi Valkeinen spin_unlock(&priv->list_lock); 12878bb0daffSRob Clark 12888bb0daffSRob Clark drm_gem_free_mmap_offset(obj); 12898bb0daffSRob Clark 12908bb0daffSRob Clark /* this means the object is still pinned.. which really should 12918bb0daffSRob Clark * not happen. I think.. 12928bb0daffSRob Clark */ 12938bb0daffSRob Clark WARN_ON(omap_obj->paddr_cnt > 0); 12948bb0daffSRob Clark 12958bb0daffSRob Clark /* don't free externally allocated backing memory */ 12968bb0daffSRob Clark if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) { 12978bb0daffSRob Clark if (omap_obj->pages) 12988bb0daffSRob Clark omap_gem_detach_pages(obj); 12998bb0daffSRob Clark 13008bb0daffSRob Clark if (!is_shmem(obj)) { 13018bb0daffSRob Clark dma_free_writecombine(dev->dev, obj->size, 13028bb0daffSRob Clark omap_obj->vaddr, omap_obj->paddr); 13038bb0daffSRob Clark } else if (omap_obj->vaddr) { 13048bb0daffSRob Clark vunmap(omap_obj->vaddr); 13058bb0daffSRob Clark } 13068bb0daffSRob Clark } 13078bb0daffSRob Clark 13088bb0daffSRob Clark /* don't free externally allocated syncobj */ 13098bb0daffSRob Clark if (!(omap_obj->flags & OMAP_BO_EXT_SYNC)) 13108bb0daffSRob Clark kfree(omap_obj->sync); 13118bb0daffSRob Clark 13128bb0daffSRob Clark drm_gem_object_release(obj); 13138bb0daffSRob Clark 13148bb0daffSRob Clark kfree(obj); 13158bb0daffSRob Clark } 13168bb0daffSRob Clark 13178bb0daffSRob Clark /* convenience method to construct a GEM buffer object, and userspace handle */ 13188bb0daffSRob Clark int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file, 13198bb0daffSRob Clark union omap_gem_size gsize, uint32_t flags, uint32_t *handle) 13208bb0daffSRob Clark { 13218bb0daffSRob Clark struct drm_gem_object *obj; 13228bb0daffSRob Clark int ret; 13238bb0daffSRob Clark 13248bb0daffSRob Clark obj = omap_gem_new(dev, gsize, flags); 13258bb0daffSRob Clark if (!obj) 13268bb0daffSRob Clark return -ENOMEM; 13278bb0daffSRob Clark 13288bb0daffSRob Clark ret = drm_gem_handle_create(file, obj, handle); 13298bb0daffSRob Clark if (ret) { 13308bb0daffSRob Clark drm_gem_object_release(obj); 13318bb0daffSRob Clark kfree(obj); /* TODO isn't there a dtor to call? just copying i915 */ 13328bb0daffSRob Clark return ret; 13338bb0daffSRob Clark } 13348bb0daffSRob Clark 13358bb0daffSRob Clark /* drop reference from allocate - handle holds it now */ 13368bb0daffSRob Clark drm_gem_object_unreference_unlocked(obj); 13378bb0daffSRob Clark 13388bb0daffSRob Clark return 0; 13398bb0daffSRob Clark } 13408bb0daffSRob Clark 13418bb0daffSRob Clark /* GEM buffer object constructor */ 13428bb0daffSRob Clark struct drm_gem_object *omap_gem_new(struct drm_device *dev, 13438bb0daffSRob Clark union omap_gem_size gsize, uint32_t flags) 13448bb0daffSRob Clark { 13458bb0daffSRob Clark struct omap_drm_private *priv = dev->dev_private; 13468bb0daffSRob Clark struct omap_gem_object *omap_obj; 13478bb0daffSRob Clark struct drm_gem_object *obj = NULL; 1348ab5a60c3SDavid Herrmann struct address_space *mapping; 13498bb0daffSRob Clark size_t size; 13508bb0daffSRob Clark int ret; 13518bb0daffSRob Clark 13528bb0daffSRob Clark if (flags & OMAP_BO_TILED) { 13538bb0daffSRob Clark if (!usergart) { 13548bb0daffSRob Clark dev_err(dev->dev, "Tiled buffers require DMM\n"); 13558bb0daffSRob Clark goto fail; 13568bb0daffSRob Clark } 13578bb0daffSRob Clark 13588bb0daffSRob Clark /* tiled buffers are always shmem paged backed.. when they are 13598bb0daffSRob Clark * scanned out, they are remapped into DMM/TILER 13608bb0daffSRob Clark */ 13618bb0daffSRob Clark flags &= ~OMAP_BO_SCANOUT; 13628bb0daffSRob Clark 13638bb0daffSRob Clark /* currently don't allow cached buffers.. there is some caching 13648bb0daffSRob Clark * stuff that needs to be handled better 13658bb0daffSRob Clark */ 13667cb0d6c1STomi Valkeinen flags &= ~(OMAP_BO_CACHED|OMAP_BO_WC|OMAP_BO_UNCACHED); 13677cb0d6c1STomi Valkeinen flags |= tiler_get_cpu_cache_flags(); 13688bb0daffSRob Clark 13698bb0daffSRob Clark /* align dimensions to slot boundaries... */ 13708bb0daffSRob Clark tiler_align(gem2fmt(flags), 13718bb0daffSRob Clark &gsize.tiled.width, &gsize.tiled.height); 13728bb0daffSRob Clark 13738bb0daffSRob Clark /* ...and calculate size based on aligned dimensions */ 13748bb0daffSRob Clark size = tiler_size(gem2fmt(flags), 13758bb0daffSRob Clark gsize.tiled.width, gsize.tiled.height); 13768bb0daffSRob Clark } else { 13778bb0daffSRob Clark size = PAGE_ALIGN(gsize.bytes); 13788bb0daffSRob Clark } 13798bb0daffSRob Clark 13808bb0daffSRob Clark omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL); 1381fffddfd6SLinus Torvalds if (!omap_obj) 1382a903e3b6STomi Valkeinen return NULL; 13838bb0daffSRob Clark 13848bb0daffSRob Clark obj = &omap_obj->base; 13858bb0daffSRob Clark 13868bb0daffSRob Clark if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) { 13878bb0daffSRob Clark /* attempt to allocate contiguous memory if we don't 13888bb0daffSRob Clark * have DMM for remappign discontiguous buffers 13898bb0daffSRob Clark */ 13908bb0daffSRob Clark omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size, 13918bb0daffSRob Clark &omap_obj->paddr, GFP_KERNEL); 1392a903e3b6STomi Valkeinen if (!omap_obj->vaddr) { 1393a903e3b6STomi Valkeinen kfree(omap_obj); 13948bb0daffSRob Clark 1395a903e3b6STomi Valkeinen return NULL; 13968bb0daffSRob Clark } 13978bb0daffSRob Clark 1398a903e3b6STomi Valkeinen flags |= OMAP_BO_DMA; 1399a903e3b6STomi Valkeinen } 1400a903e3b6STomi Valkeinen 1401a903e3b6STomi Valkeinen spin_lock(&priv->list_lock); 1402a903e3b6STomi Valkeinen list_add(&omap_obj->mm_list, &priv->obj_list); 1403a903e3b6STomi Valkeinen spin_unlock(&priv->list_lock); 1404a903e3b6STomi Valkeinen 14058bb0daffSRob Clark omap_obj->flags = flags; 14068bb0daffSRob Clark 14078bb0daffSRob Clark if (flags & OMAP_BO_TILED) { 14088bb0daffSRob Clark omap_obj->width = gsize.tiled.width; 14098bb0daffSRob Clark omap_obj->height = gsize.tiled.height; 14108bb0daffSRob Clark } 14118bb0daffSRob Clark 1412ab5a60c3SDavid Herrmann if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) { 141389c8233fSDavid Herrmann drm_gem_private_object_init(dev, obj, size); 1414ab5a60c3SDavid Herrmann } else { 14158bb0daffSRob Clark ret = drm_gem_object_init(dev, obj, size); 14168bb0daffSRob Clark if (ret) 14178bb0daffSRob Clark goto fail; 14188bb0daffSRob Clark 1419ab5a60c3SDavid Herrmann mapping = file_inode(obj->filp)->i_mapping; 1420ab5a60c3SDavid Herrmann mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32); 1421ab5a60c3SDavid Herrmann } 1422ab5a60c3SDavid Herrmann 14238bb0daffSRob Clark return obj; 14248bb0daffSRob Clark 14258bb0daffSRob Clark fail: 14268bb0daffSRob Clark if (obj) 14278bb0daffSRob Clark omap_gem_free_object(obj); 14288bb0daffSRob Clark 14298bb0daffSRob Clark return NULL; 14308bb0daffSRob Clark } 14318bb0daffSRob Clark 14328bb0daffSRob Clark /* init/cleanup.. if DMM is used, we need to set some stuff up.. */ 14338bb0daffSRob Clark void omap_gem_init(struct drm_device *dev) 14348bb0daffSRob Clark { 14358bb0daffSRob Clark struct omap_drm_private *priv = dev->dev_private; 14368bb0daffSRob Clark const enum tiler_fmt fmts[] = { 14378bb0daffSRob Clark TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT 14388bb0daffSRob Clark }; 14398bb0daffSRob Clark int i, j; 14408bb0daffSRob Clark 14418bb0daffSRob Clark if (!dmm_is_available()) { 14428bb0daffSRob Clark /* DMM only supported on OMAP4 and later, so this isn't fatal */ 14438bb0daffSRob Clark dev_warn(dev->dev, "DMM not available, disable DMM support\n"); 14448bb0daffSRob Clark return; 14458bb0daffSRob Clark } 14468bb0daffSRob Clark 1447fffddfd6SLinus Torvalds usergart = kcalloc(3, sizeof(*usergart), GFP_KERNEL); 1448fffddfd6SLinus Torvalds if (!usergart) 14498bb0daffSRob Clark return; 14508bb0daffSRob Clark 14518bb0daffSRob Clark /* reserve 4k aligned/wide regions for userspace mappings: */ 14528bb0daffSRob Clark for (i = 0; i < ARRAY_SIZE(fmts); i++) { 14538bb0daffSRob Clark uint16_t h = 1, w = PAGE_SIZE >> i; 14548bb0daffSRob Clark tiler_align(fmts[i], &w, &h); 14558bb0daffSRob Clark /* note: since each region is 1 4kb page wide, and minimum 14568bb0daffSRob Clark * number of rows, the height ends up being the same as the 14578bb0daffSRob Clark * # of pages in the region 14588bb0daffSRob Clark */ 14598bb0daffSRob Clark usergart[i].height = h; 14608bb0daffSRob Clark usergart[i].height_shift = ilog2(h); 14618bb0daffSRob Clark usergart[i].stride_pfn = tiler_stride(fmts[i], 0) >> PAGE_SHIFT; 14628bb0daffSRob Clark usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i); 14638bb0daffSRob Clark for (j = 0; j < NUM_USERGART_ENTRIES; j++) { 14648bb0daffSRob Clark struct usergart_entry *entry = &usergart[i].entry[j]; 14658bb0daffSRob Clark struct tiler_block *block = 14668bb0daffSRob Clark tiler_reserve_2d(fmts[i], w, h, 14678bb0daffSRob Clark PAGE_SIZE); 14688bb0daffSRob Clark if (IS_ERR(block)) { 14698bb0daffSRob Clark dev_err(dev->dev, 14708bb0daffSRob Clark "reserve failed: %d, %d, %ld\n", 14718bb0daffSRob Clark i, j, PTR_ERR(block)); 14728bb0daffSRob Clark return; 14738bb0daffSRob Clark } 14748bb0daffSRob Clark entry->paddr = tiler_ssptr(block); 14758bb0daffSRob Clark entry->block = block; 14768bb0daffSRob Clark 14772d31ca3aSRussell King DBG("%d:%d: %dx%d: paddr=%pad stride=%d", i, j, w, h, 14782d31ca3aSRussell King &entry->paddr, 14798bb0daffSRob Clark usergart[i].stride_pfn << PAGE_SHIFT); 14808bb0daffSRob Clark } 14818bb0daffSRob Clark } 14828bb0daffSRob Clark 14838bb0daffSRob Clark priv->has_dmm = true; 14848bb0daffSRob Clark } 14858bb0daffSRob Clark 14868bb0daffSRob Clark void omap_gem_deinit(struct drm_device *dev) 14878bb0daffSRob Clark { 14888bb0daffSRob Clark /* I believe we can rely on there being no more outstanding GEM 14898bb0daffSRob Clark * objects which could depend on usergart/dmm at this point. 14908bb0daffSRob Clark */ 14918bb0daffSRob Clark kfree(usergart); 14928bb0daffSRob Clark } 1493