1cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* 2cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * drivers/staging/omapdrm/omap_gem.c 3cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 4cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Copyright (C) 2011 Texas Instruments 5cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Author: Rob Clark <rob.clark@linaro.org> 6cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 7cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * This program is free software; you can redistribute it and/or modify it 8cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * under the terms of the GNU General Public License version 2 as published by 9cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * the Free Software Foundation. 10cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 11cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 12cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * more details. 15cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 16cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * You should have received a copy of the GNU General Public License along with 17cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 18cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 19cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 20cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 21cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#include <linux/spinlock.h> 22cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#include <linux/shmem_fs.h> 23cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 24cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#include "omap_drv.h" 25f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark#include "omap_dmm_tiler.h" 26cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 27cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* remove these once drm core helpers are merged */ 28cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstruct page ** _drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask); 29cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkvoid _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, 30cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark bool dirty, bool accessed); 31f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkint _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size); 32cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 33cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* 34cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * GEM buffer object implementation. 35cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 36cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 37cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#define to_omap_bo(x) container_of(x, struct omap_gem_object, base) 38cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 39cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* note: we use upper 8 bits of flags for driver-internal flags: */ 40cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#define OMAP_BO_DMA 0x01000000 /* actually is physically contiguous */ 41cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#define OMAP_BO_EXT_SYNC 0x02000000 /* externally allocated sync object */ 42cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#define OMAP_BO_EXT_MEM 0x04000000 /* externally allocated memory */ 43cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 44cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 45cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstruct omap_gem_object { 46cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_gem_object base; 47cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 48f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct list_head mm_list; 49f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 50cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t flags; 51cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 52f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /** width/height for tiled formats (rounded up to slot boundaries) */ 53f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark uint16_t width, height; 54f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 55a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark /** roll applied when mapping to DMM */ 56a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark uint32_t roll; 57a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 58cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /** 59cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * If buffer is allocated physically contiguous, the OMAP_BO_DMA flag 60f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * is set and the paddr is valid. Also if the buffer is remapped in 61f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * TILER and paddr_cnt > 0, then paddr is valid. But if you are using 62f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * the physical address and OMAP_BO_DMA is not set, then you should 63f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * be going thru omap_gem_{get,put}_paddr() to ensure the mapping is 64f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * not removed from under your feet. 65cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 66cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Note that OMAP_BO_SCANOUT is a hint from userspace that DMA capable 67cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * buffer is requested, but doesn't mean that it is. Use the 68cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * OMAP_BO_DMA flag to determine if the buffer has a DMA capable 69cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * physical address. 70cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 71cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark dma_addr_t paddr; 72cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 73cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /** 74f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * # of users of paddr 75f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 76f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark uint32_t paddr_cnt; 77f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 78f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /** 79f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * tiler block used when buffer is remapped in DMM/TILER. 80f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 81f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct tiler_block *block; 82f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 83f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /** 84cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Array of backing pages, if allocated. Note that pages are never 85cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * allocated for buffers originally allocated from contiguous memory 86cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 87cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct page **pages; 88cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 89f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark /** addresses corresponding to pages in above array */ 90f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark dma_addr_t *addrs; 91f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark 92cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /** 93cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Virtual address, if mapped. 94cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 95cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark void *vaddr; 96cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 97cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /** 98cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * sync-object allocated on demand (if needed) 99cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 100cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Per-buffer sync-object for tracking pending and completed hw/dma 101cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * read and write operations. The layout in memory is dictated by 102cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * the SGX firmware, which uses this information to stall the command 103cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * stream if a surface is not ready yet. 104cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 105cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Note that when buffer is used by SGX, the sync-object needs to be 106cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * allocated from a special heap of sync-objects. This way many sync 107cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * objects can be packed in a page, and not waste GPU virtual address 108cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * space. Because of this we have to have a omap_gem_set_sync_object() 109cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * API to allow replacement of the syncobj after it has (potentially) 110cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * already been allocated. A bit ugly but I haven't thought of a 111cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * better alternative. 112cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 113cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct { 114cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t write_pending; 115cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t write_complete; 116cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t read_pending; 117cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t read_complete; 118cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } *sync; 119cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark}; 120cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 121c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clarkstatic int get_pages(struct drm_gem_object *obj, struct page ***pages); 122c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clarkstatic uint64_t mmap_offset(struct drm_gem_object *obj); 123c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark 124f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are 125f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * not necessarily pinned in TILER all the time, and (b) when they are 126f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * they are not necessarily page aligned, we reserve one or more small 127f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * regions in each of the 2d containers to use as a user-GART where we 128f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * can create a second page-aligned mapping of parts of the buffer 129f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * being accessed from userspace. 130f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * 131f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * Note that we could optimize slightly when we know that multiple 132f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * tiler containers are backed by the same PAT.. but I'll leave that 133f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * for later.. 134f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 135f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark#define NUM_USERGART_ENTRIES 2 136f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkstruct usergart_entry { 137f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct tiler_block *block; /* the reserved tiler block */ 138f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dma_addr_t paddr; 139f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct drm_gem_object *obj; /* the current pinned obj */ 140f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pgoff_t obj_pgoff; /* page offset of obj currently 141f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark mapped in */ 142f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark}; 143f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkstatic struct { 144f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct usergart_entry entry[NUM_USERGART_ENTRIES]; 145f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int height; /* height in rows */ 146f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int height_shift; /* ilog2(height in rows) */ 147f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int slot_shift; /* ilog2(width per slot) */ 148f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int stride_pfn; /* stride in pages */ 149f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int last; /* index of last used entry */ 150f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} *usergart; 151f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 152f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkstatic void evict_entry(struct drm_gem_object *obj, 153f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark enum tiler_fmt fmt, struct usergart_entry *entry) 154f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 155f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (obj->dev->dev_mapping) { 156e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 157e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark int n = usergart[fmt].height; 158e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark size_t size = PAGE_SIZE * n; 159c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark loff_t off = mmap_offset(obj) + 160f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark (entry->obj_pgoff << PAGE_SHIFT); 161e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE); 162e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark if (m > 1) { 163e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark int i; 164e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* if stride > than PAGE_SIZE then sparse mapping: */ 165e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark for (i = n; i > 0; i--) { 166e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark unmap_mapping_range(obj->dev->dev_mapping, 167e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark off, PAGE_SIZE, 1); 168e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark off += PAGE_SIZE * m; 169e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark } 170e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark } else { 171e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark unmap_mapping_range(obj->dev->dev_mapping, off, size, 1); 172e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark } 173f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 174f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 175f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark entry->obj = NULL; 176f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 177f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 178f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/* Evict a buffer from usergart, if it is mapped there */ 179f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkstatic void evict(struct drm_gem_object *obj) 180f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 181f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 182f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 183f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 184f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark enum tiler_fmt fmt = gem2fmt(omap_obj->flags); 185f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int i; 186f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 187f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (!usergart) 188f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return; 189f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 190f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark for (i = 0; i < NUM_USERGART_ENTRIES; i++) { 191f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct usergart_entry *entry = &usergart[fmt].entry[i]; 192f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (entry->obj == obj) 193f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark evict_entry(obj, fmt, entry); 194f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 195f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 196f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 197f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 198cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* GEM objects can either be allocated from contiguous memory (in which 199cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * case obj->filp==NULL), or w/ shmem backing (obj->filp!=NULL). But non 200cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * contiguous buffers can be remapped in TILER/DMM if they need to be 201cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * contiguous... but we don't do this all the time to reduce pressure 202cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * on TILER/DMM space when we know at allocation time that the buffer 203cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * will need to be scanned out. 204cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 205cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic inline bool is_shmem(struct drm_gem_object *obj) 206cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 207cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return obj->filp != NULL; 208cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 209cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 210cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic DEFINE_SPINLOCK(sync_lock); 211cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 212cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** ensure backing pages are allocated */ 213cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic int omap_gem_attach_pages(struct drm_gem_object *obj) 214cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 215cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 216cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct page **pages; 217cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 218cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark WARN_ON(omap_obj->pages); 219cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 220cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the 221cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably 222cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * we actually want CMA memory for it all anyways.. 223cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 224cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark pages = _drm_gem_get_pages(obj, GFP_KERNEL); 225cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (IS_ERR(pages)) { 226cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages)); 227cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return PTR_ERR(pages); 228cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 229cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 230f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark /* for non-cached buffers, ensure the new pages are clean because 231f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark * DSS, GPU, etc. are not cache coherent: 232f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark */ 233f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { 234f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark int i, npages = obj->size >> PAGE_SHIFT; 235f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark dma_addr_t *addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL); 236f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark for (i = 0; i < npages; i++) { 237f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark addrs[i] = dma_map_page(obj->dev->dev, pages[i], 238f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark 0, PAGE_SIZE, DMA_BIDIRECTIONAL); 239f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark } 240f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark omap_obj->addrs = addrs; 241f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark } 242f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark 243cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->pages = pages; 244cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 245cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 246cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 247cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** release backing pages */ 248cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic void omap_gem_detach_pages(struct drm_gem_object *obj) 249cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 250cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 251f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark 252f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark /* for non-cached buffers, ensure the new pages are clean because 253f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark * DSS, GPU, etc. are not cache coherent: 254f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark */ 255f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) { 256f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark int i, npages = obj->size >> PAGE_SHIFT; 257f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark for (i = 0; i < npages; i++) { 258f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark dma_unmap_page(obj->dev->dev, omap_obj->addrs[i], 259f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark PAGE_SIZE, DMA_BIDIRECTIONAL); 260f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark } 261f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark kfree(omap_obj->addrs); 262f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark omap_obj->addrs = NULL; 263f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark } 264f3bc9d24cb4a221bd3530c445fa08e33775e7707Rob Clark 265cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark _drm_gem_put_pages(obj, omap_obj->pages, true, false); 266cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->pages = NULL; 267cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 268cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 269cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** get mmap offset */ 270c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clarkstatic uint64_t mmap_offset(struct drm_gem_object *obj) 271cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 272f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct drm_device *dev = obj->dev; 273f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 274f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 275f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 276cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!obj->map_list.map) { 277cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* Make it mmapable */ 278f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark size_t size = omap_gem_mmap_size(obj); 279f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int ret = _drm_gem_create_mmap_offset_size(obj, size); 280f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 281cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (ret) { 282f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark dev_err(dev->dev, "could not allocate mmap offset\n"); 283cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 284cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 285cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 286cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 287cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT; 288cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 289cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 290c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clarkuint64_t omap_gem_mmap_offset(struct drm_gem_object *obj) 291c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark{ 292c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark uint64_t offset; 293c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark mutex_lock(&obj->dev->struct_mutex); 294c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark offset = mmap_offset(obj); 295c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark mutex_unlock(&obj->dev->struct_mutex); 296c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark return offset; 297c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark} 298c5b1247bd1c3ab6722acfa95213be9a16bfb664cRob Clark 299f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/** get mmap size */ 300f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarksize_t omap_gem_mmap_size(struct drm_gem_object *obj) 301f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 302f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 303f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark size_t size = obj->size; 304f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 305f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 306f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* for tiled buffers, the virtual size has stride rounded up 307f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * to 4kb.. (to hide the fact that row n+1 might start 16kb or 308f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * 32kb later!). But we don't back the entire buffer with 309f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * pages, only the valid picture part.. so need to adjust for 310f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * this in the size used to mmap and generate mmap offset 311f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 312f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark size = tiler_vsize(gem2fmt(omap_obj->flags), 313f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->width, omap_obj->height); 314f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 315f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 316f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return size; 317f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 318f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 319f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 320f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/* Normal handling for the case of faulting in non-tiled buffers */ 321f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkstatic int fault_1d(struct drm_gem_object *obj, 322f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct vm_area_struct *vma, struct vm_fault *vmf) 323f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 324f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 325f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark unsigned long pfn; 326f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pgoff_t pgoff; 327f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 328f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* We don't use vmf->pgoff since that has the fake offset: */ 329f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pgoff = ((unsigned long)vmf->virtual_address - 330f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark vma->vm_start) >> PAGE_SHIFT; 331f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 332f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->pages) { 333f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pfn = page_to_pfn(omap_obj->pages[pgoff]); 334f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } else { 335f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark BUG_ON(!(omap_obj->flags & OMAP_BO_DMA)); 336f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pfn = (omap_obj->paddr >> PAGE_SHIFT) + pgoff; 337f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 338f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 339f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address, 340f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pfn, pfn << PAGE_SHIFT); 341f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 342f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); 343f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 344f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 345f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/* Special handling for the case of faulting in 2d tiled buffers */ 346f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkstatic int fault_2d(struct drm_gem_object *obj, 347f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct vm_area_struct *vma, struct vm_fault *vmf) 348f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 349f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 350f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct usergart_entry *entry; 351f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark enum tiler_fmt fmt = gem2fmt(omap_obj->flags); 352f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct page *pages[64]; /* XXX is this too much to have on stack? */ 353f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark unsigned long pfn; 354f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pgoff_t pgoff, base_pgoff; 355f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark void __user *vaddr; 356f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int i, ret, slots; 357f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 358e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* 359e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * Note the height of the slot is also equal to the number of pages 360e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * that need to be mapped in to fill 4kb wide CPU page. If the slot 361e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * height is 64, then 64 pages fill a 4kb wide by 64 row region. 362e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark */ 363e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark const int n = usergart[fmt].height; 364e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark const int n_shift = usergart[fmt].height_shift; 365e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark 366e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* 367e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * If buffer width in bytes > PAGE_SIZE then the virtual stride is 368e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * rounded up to next multiple of PAGE_SIZE.. this need to be taken 369e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * into account in some of the math, so figure out virtual stride 370e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * in pages 371f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 372e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE); 373f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 374f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* We don't use vmf->pgoff since that has the fake offset: */ 375f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pgoff = ((unsigned long)vmf->virtual_address - 376f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark vma->vm_start) >> PAGE_SHIFT; 377f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 378e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* 379e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * Actual address we start mapping at is rounded down to previous slot 380f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * boundary in the y direction: 381f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 382e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark base_pgoff = round_down(pgoff, m << n_shift); 383f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 384e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* figure out buffer width in slots */ 385f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark slots = omap_obj->width >> usergart[fmt].slot_shift; 386f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 387e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT); 388e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark 389e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark entry = &usergart[fmt].entry[usergart[fmt].last]; 390e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark 391f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* evict previous buffer using this usergart entry, if any: */ 392f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (entry->obj) 393f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark evict_entry(entry->obj, fmt, entry); 394f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 395f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark entry->obj = obj; 396f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark entry->obj_pgoff = base_pgoff; 397f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 398e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* now convert base_pgoff to phys offset from virt offset: */ 399e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark base_pgoff = (base_pgoff >> n_shift) * slots; 400e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark 401e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* for wider-than 4k.. figure out which part of the slot-row we want: */ 402e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark if (m > 1) { 403e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark int off = pgoff % m; 404e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark entry->obj_pgoff += off; 405e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark base_pgoff /= m; 406e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark slots = min(slots - (off << n_shift), n); 407e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark base_pgoff += off << n_shift; 408e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark vaddr += off << PAGE_SHIFT; 409e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark } 410e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark 411e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark /* 412e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * Map in pages. Beyond the valid pixel part of the buffer, we set 413e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * pages[i] to NULL to get a dummy page mapped in.. if someone 414e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * reads/writes it they will get random/undefined content, but at 415e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * least it won't be corrupting whatever other random page used to 416e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark * be mapped in, or other undefined behavior. 417f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 418f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark memcpy(pages, &omap_obj->pages[base_pgoff], 419f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark sizeof(struct page *) * slots); 420f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark memset(pages + slots, 0, 421e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark sizeof(struct page *) * (n - slots)); 422f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 423a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark ret = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true); 424f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (ret) { 425f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(obj->dev->dev, "failed to pin: %d\n", ret); 426f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return ret; 427f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 428f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 429f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pfn = entry->paddr >> PAGE_SHIFT; 430f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 431f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address, 432f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pfn, pfn << PAGE_SHIFT); 433f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 434e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark for (i = n; i > 0; i--) { 435f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark vm_insert_mixed(vma, (unsigned long)vaddr, pfn); 436f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark pfn += usergart[fmt].stride_pfn; 437e559895ae99fb99ecb91d5ad9e0b742ad881b341Rob Clark vaddr += PAGE_SIZE * m; 438f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 439f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 440f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* simple round-robin: */ 441f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart[fmt].last = (usergart[fmt].last + 1) % NUM_USERGART_ENTRIES; 442f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 443f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return 0; 444f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 445f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 446cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** 447cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * omap_gem_fault - pagefault handler for GEM objects 448cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @vma: the VMA of the GEM object 449cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @vmf: fault detail 450cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 451cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Invoked when a fault occurs on an mmap of a GEM managed area. GEM 452cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * does most of the work for us including the actual map/unmap calls 453cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * but we need to do the actual page work. 454cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 455cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * The VMA was set up by GEM. In doing so it also ensured that the 456cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * vma->vm_private_data points to the GEM object that is backing this 457cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * mapping. 458cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 459cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 460cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 461cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_gem_object *obj = vma->vm_private_data; 462cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 463cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_device *dev = obj->dev; 464cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct page **pages; 465cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret; 466cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 467cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* Make sure we don't parallel update on a fault, nor move or remove 468cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * something from beneath our feet 469cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 470cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark mutex_lock(&dev->struct_mutex); 471cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 472cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* if a shmem backed object, make sure we have pages attached now */ 473cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = get_pages(obj, &pages); 474cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (ret) { 475cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark goto fail; 476cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 477cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 478cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* where should we do corresponding put_pages().. we are mapping 479cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * the original page, rather than thru a GART, so we can't rely 480cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * on eviction to trigger this. But munmap() or all mappings should 481cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * probably trigger put_pages()? 482cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 483cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 484f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->flags & OMAP_BO_TILED) 485f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = fault_2d(obj, vma, vmf); 486f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark else 487f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = fault_1d(obj, vma, vmf); 488cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 489cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 490cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkfail: 491cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark mutex_unlock(&dev->struct_mutex); 492cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark switch (ret) { 493cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark case 0: 494cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark case -ERESTARTSYS: 495cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark case -EINTR: 496cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return VM_FAULT_NOPAGE; 497cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark case -ENOMEM: 498cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return VM_FAULT_OOM; 499cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark default: 500cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return VM_FAULT_SIGBUS; 501cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 502cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 503cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 504cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** We override mainly to fix up some of the vm mapping flags.. */ 505cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_mmap(struct file *filp, struct vm_area_struct *vma) 506cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 507cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj; 508cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret; 509cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 510cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = drm_gem_mmap(filp, vma); 511cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (ret) { 512cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark DBG("mmap failed: %d", ret); 513cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 514cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 515cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 516cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* after drm_gem_mmap(), it is safe to access the obj */ 517cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj = to_omap_bo(vma->vm_private_data); 518cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 519cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark vma->vm_flags &= ~VM_PFNMAP; 520cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark vma->vm_flags |= VM_MIXEDMAP; 521cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 522cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (omap_obj->flags & OMAP_BO_WC) { 523cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags)); 524cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } else if (omap_obj->flags & OMAP_BO_UNCACHED) { 525cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags)); 526cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } else { 527cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 528cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 529cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 530cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 531cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 532cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 533cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** 534cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * omap_gem_dumb_create - create a dumb buffer 535cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @drm_file: our client file 536cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @dev: our device 537cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @args: the requested arguments copied from userspace 538cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 539cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Allocate a buffer suitable for use for a frame buffer of the 540cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * form described by user space. Give userspace a handle by which 541cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * to reference it. 542cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 543cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev, 544cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_mode_create_dumb *args) 545cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 546cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark union omap_gem_size gsize; 547cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 548cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* in case someone tries to feed us a completely bogus stride: */ 549cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark args->pitch = align_pitch(args->pitch, args->width, args->bpp); 550cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark args->size = PAGE_ALIGN(args->pitch * args->height); 551cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 552cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark gsize = (union omap_gem_size){ 553cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark .bytes = args->size, 554cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark }; 555cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 556cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return omap_gem_new_handle(dev, file, gsize, 557cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark OMAP_BO_SCANOUT | OMAP_BO_WC, &args->handle); 558cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 559cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 560cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** 561cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * omap_gem_dumb_destroy - destroy a dumb buffer 562cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @file: client file 563cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @dev: our DRM device 564cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @handle: the object handle 565cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 566cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Destroy a handle that was created via omap_gem_dumb_create. 567cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 568cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, 569cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t handle) 570cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 571cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* No special work needed, drop the reference and see what falls out */ 572cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return drm_gem_handle_delete(file, handle); 573cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 574cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 575cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/** 576cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * omap_gem_dumb_map - buffer mapping for dumb interface 577cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @file: our drm client file 578cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @dev: drm device 579cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * @handle: GEM handle to the object (from dumb_create) 580cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 581cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * Do the necessary setup to allow the mapping of the frame buffer 582cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * into user memory. We don't have to do much here at the moment. 583cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 584cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, 585cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t handle, uint64_t *offset) 586cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 587cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_gem_object *obj; 588cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret = 0; 589cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 590cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* GEM does all our handle to object mapping */ 591cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark obj = drm_gem_object_lookup(dev, file, handle); 592cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (obj == NULL) { 593cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = -ENOENT; 594cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark goto fail; 595cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 596cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 597cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark *offset = omap_gem_mmap_offset(obj); 598cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 599cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark drm_gem_object_unreference_unlocked(obj); 600cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 601cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkfail: 602cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 603cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 604cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 605a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark/* Set scrolling position. This allows us to implement fast scrolling 606a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark * for console. 6079b55b95a8eca1a6bb2d7674e4af1fed003462677Rob Clark * 6089b55b95a8eca1a6bb2d7674e4af1fed003462677Rob Clark * Call only from non-atomic contexts. 609a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark */ 610a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clarkint omap_gem_roll(struct drm_gem_object *obj, uint32_t roll) 611a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark{ 612a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 613a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark uint32_t npages = obj->size >> PAGE_SHIFT; 614a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark int ret = 0; 615a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 616a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark if (roll > npages) { 617a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark dev_err(obj->dev->dev, "invalid roll: %d\n", roll); 618a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark return -EINVAL; 619a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark } 620a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 621a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark omap_obj->roll = roll; 622a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 623af69592aa098ff8cd640e8109ba946db3c1cdb4eRob Clark mutex_lock(&obj->dev->struct_mutex); 624af69592aa098ff8cd640e8109ba946db3c1cdb4eRob Clark 625a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark /* if we aren't mapped yet, we don't need to do anything */ 626a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark if (omap_obj->block) { 627a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark struct page **pages; 628a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark ret = get_pages(obj, &pages); 629a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark if (ret) 630a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark goto fail; 631a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark ret = tiler_pin(omap_obj->block, pages, npages, roll, true); 632a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark if (ret) 633a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark dev_err(obj->dev->dev, "could not repin: %d\n", ret); 634a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark } 635a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 636a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clarkfail: 637a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark mutex_unlock(&obj->dev->struct_mutex); 638a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 639a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark return ret; 640a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark} 641a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 642cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* Get physical address for DMA.. if 'remap' is true, and the buffer is not 643cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * already contiguous, remap it to pin in physically contiguous memory.. (ie. 644cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * map in TILER) 645cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 646cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_get_paddr(struct drm_gem_object *obj, 647cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark dma_addr_t *paddr, bool remap) 648cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 649a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark struct omap_drm_private *priv = obj->dev->dev_private; 650cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 651cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret = 0; 652cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 653f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark mutex_lock(&obj->dev->struct_mutex); 654f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 655a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark if (remap && is_shmem(obj) && priv->has_dmm) { 656f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->paddr_cnt == 0) { 657f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct page **pages; 658a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark uint32_t npages = obj->size >> PAGE_SHIFT; 659f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark enum tiler_fmt fmt = gem2fmt(omap_obj->flags); 660f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct tiler_block *block; 661a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 662f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark BUG_ON(omap_obj->block); 663f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 664f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = get_pages(obj, &pages); 665f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (ret) 666f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark goto fail; 667f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 668f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->flags & OMAP_BO_TILED) { 669f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark block = tiler_reserve_2d(fmt, 670f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->width, 671f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->height, 0); 672f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } else { 673f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark block = tiler_reserve_1d(obj->size); 674f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 675f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 676f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (IS_ERR(block)) { 677f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = PTR_ERR(block); 678f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(obj->dev->dev, 679f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark "could not remap: %d (%d)\n", ret, fmt); 680f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark goto fail; 681f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 682f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 683f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* TODO: enable async refill.. */ 684a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark ret = tiler_pin(block, pages, npages, 685a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark omap_obj->roll, true); 686f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (ret) { 687f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark tiler_release(block); 688f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(obj->dev->dev, 689f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark "could not pin: %d\n", ret); 690f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark goto fail; 691f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 692f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 693f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->paddr = tiler_ssptr(block); 694f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->block = block; 695f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 696f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark DBG("got paddr: %08x", omap_obj->paddr); 697f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 698f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 699f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->paddr_cnt++; 700f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 701f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark *paddr = omap_obj->paddr; 702f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } else if (omap_obj->flags & OMAP_BO_DMA) { 703f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark *paddr = omap_obj->paddr; 704f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } else { 705f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = -EINVAL; 706cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 707cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 708f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkfail: 709f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark mutex_unlock(&obj->dev->struct_mutex); 710cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 711cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 712cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 713cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 714cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* Release physical address, when DMA is no longer being performed.. this 715cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * could potentially unpin and unmap buffers from TILER 716cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 717cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_put_paddr(struct drm_gem_object *obj) 718cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 719f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 720f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int ret = 0; 721f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 722f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark mutex_lock(&obj->dev->struct_mutex); 723f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->paddr_cnt > 0) { 724f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->paddr_cnt--; 725f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (omap_obj->paddr_cnt == 0) { 726f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = tiler_unpin(omap_obj->block); 727f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (ret) { 728f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(obj->dev->dev, 729f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark "could not unpin pages: %d\n", ret); 730f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark goto fail; 731f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 732f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark ret = tiler_release(omap_obj->block); 733f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (ret) { 734f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(obj->dev->dev, 735f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark "could not release unmap: %d\n", ret); 736f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 737f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->block = NULL; 738f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 739f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 740f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkfail: 741f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark mutex_unlock(&obj->dev->struct_mutex); 742f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return ret; 743cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 744cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 745cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* acquire pages when needed (for example, for DMA where physically 746cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * contiguous buffer is not required 747cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 748cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic int get_pages(struct drm_gem_object *obj, struct page ***pages) 749cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 750cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 751cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret = 0; 752cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 753cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (is_shmem(obj) && !omap_obj->pages) { 754cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = omap_gem_attach_pages(obj); 755cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (ret) { 756cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark dev_err(obj->dev->dev, "could not attach pages\n"); 757cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 758cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 759cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 760cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 761cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* TODO: even phys-contig.. we should have a list of pages? */ 762cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark *pages = omap_obj->pages; 763cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 764cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 765cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 766cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 767cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages) 768cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 769cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret; 770cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark mutex_lock(&obj->dev->struct_mutex); 771cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = get_pages(obj, pages); 772cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark mutex_unlock(&obj->dev->struct_mutex); 773cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 774cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 775cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 776cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* release pages when DMA no longer being performed */ 777cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_put_pages(struct drm_gem_object *obj) 778cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 779cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* do something here if we dynamically attach/detach pages.. at 780cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * least they would no longer need to be pinned if everyone has 781cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * released the pages.. 782cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 783cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 784cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 785cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 786f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/* Get kernel virtual address for CPU access.. this more or less only 787f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * exists for omap_fbdev. This should be called with struct_mutex 788f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * held. 789cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 790cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkvoid *omap_gem_vaddr(struct drm_gem_object *obj) 791cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 792cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 793f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark WARN_ON(! mutex_is_locked(&obj->dev->struct_mutex)); 794f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (!omap_obj->vaddr) { 795f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct page **pages; 796f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark int ret = get_pages(obj, &pages); 797f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (ret) 798f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return ERR_PTR(ret); 799f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT, 800f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark VM_MAP, pgprot_writecombine(PAGE_KERNEL)); 801f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 802cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return omap_obj->vaddr; 803cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 804cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 805f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark#ifdef CONFIG_DEBUG_FS 806f6b6036e56ca17378dd0294b684db623abd6a901Rob Clarkvoid omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) 807f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark{ 808f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct drm_device *dev = obj->dev; 809f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 810f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark uint64_t off = 0; 811f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 812f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark WARN_ON(! mutex_is_locked(&dev->struct_mutex)); 813f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 814f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark if (obj->map_list.map) 815f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark off = (uint64_t)obj->map_list.hash.key; 816f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 817f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", 818f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark omap_obj->flags, obj->name, obj->refcount.refcount.counter, 819f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark off, omap_obj->paddr, omap_obj->paddr_cnt, 820f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark omap_obj->vaddr, omap_obj->roll); 821f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 822f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark if (omap_obj->flags & OMAP_BO_TILED) { 823f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height); 824f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark if (omap_obj->block) { 825f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct tcm_area *area = &omap_obj->block->area; 826f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, " (%dx%d, %dx%d)", 827f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark area->p0.x, area->p0.y, 828f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark area->p1.x, area->p1.y); 829f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark } 830f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark } else { 831f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, " %d", obj->size); 832f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark } 833f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 834f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, "\n"); 835f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark} 836f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 837f6b6036e56ca17378dd0294b684db623abd6a901Rob Clarkvoid omap_gem_describe_objects(struct list_head *list, struct seq_file *m) 838f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark{ 839f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct omap_gem_object *omap_obj; 840f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark int count = 0; 841f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark size_t size = 0; 842f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 843f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark list_for_each_entry(omap_obj, list, mm_list) { 844f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark struct drm_gem_object *obj = &omap_obj->base; 845f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, " "); 846f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark omap_gem_describe(obj, m); 847f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark count++; 848f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark size += obj->size; 849f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark } 850f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 851f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark seq_printf(m, "Total %d objects, %zu bytes\n", count, size); 852f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark} 853f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark#endif 854f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 855cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* Buffer Synchronization: 856cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 857cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 858cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstruct omap_gem_sync_waiter { 859cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct list_head list; 860cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj; 861cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark enum omap_gem_op op; 862cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark uint32_t read_target, write_target; 863cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* notify called w/ sync_lock held */ 864cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark void (*notify)(void *arg); 865cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark void *arg; 866cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark}; 867cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 868cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* list of omap_gem_sync_waiter.. the notify fxn gets called back when 869cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * the read and/or write target count is achieved which can call a user 870cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * callback (ex. to kick 3d and/or 2d), wakeup blocked task (prep for 871cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * cpu access), etc. 872cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 873cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic LIST_HEAD(waiters); 874cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 875cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic inline bool is_waiting(struct omap_gem_sync_waiter *waiter) 876cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 877cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = waiter->omap_obj; 878cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if ((waiter->op & OMAP_GEM_READ) && 879cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark (omap_obj->sync->read_complete < waiter->read_target)) 880cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return true; 881cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if ((waiter->op & OMAP_GEM_WRITE) && 882cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark (omap_obj->sync->write_complete < waiter->write_target)) 883cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return true; 884cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return false; 885cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 886cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 887cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* macro for sync debug.. */ 888cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#define SYNCDBG 0 889cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark#define SYNC(fmt, ...) do { if (SYNCDBG) \ 890cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark printk(KERN_ERR "%s:%d: "fmt"\n", \ 891cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark __func__, __LINE__, ##__VA_ARGS__); \ 892cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } while (0) 893cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 894cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 895cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic void sync_op_update(void) 896cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 897cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_sync_waiter *waiter, *n; 898cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark list_for_each_entry_safe(waiter, n, &waiters, list) { 899cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!is_waiting(waiter)) { 900cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark list_del(&waiter->list); 901cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark SYNC("notify: %p", waiter); 902cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->notify(waiter->arg); 903cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kfree(waiter); 904cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 905cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 906cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 907cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 908cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic inline int sync_op(struct drm_gem_object *obj, 909cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark enum omap_gem_op op, bool start) 910cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 911cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 912cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret = 0; 913cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 914cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_lock(&sync_lock); 915cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 916cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!omap_obj->sync) { 917cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync = kzalloc(sizeof(*omap_obj->sync), GFP_ATOMIC); 918cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!omap_obj->sync) { 919cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = -ENOMEM; 920cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark goto unlock; 921cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 922cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 923cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 924cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (start) { 925cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (op & OMAP_GEM_READ) 926cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync->read_pending++; 927cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (op & OMAP_GEM_WRITE) 928cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync->write_pending++; 929cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } else { 930cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (op & OMAP_GEM_READ) 931cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync->read_complete++; 932cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (op & OMAP_GEM_WRITE) 933cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync->write_complete++; 934cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark sync_op_update(); 935cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 936cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 937cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkunlock: 938cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 939cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 940cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 941cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 942cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 943cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* it is a bit lame to handle updates in this sort of polling way, but 944cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * in case of PVR, the GPU can directly update read/write complete 945cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * values, and not really tell us which ones it updated.. this also 946cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * means that sync_lock is not quite sufficient. So we'll need to 947cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * do something a bit better when it comes time to add support for 948cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * separate 2d hw.. 949cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 950cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkvoid omap_gem_op_update(void) 951cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 952cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_lock(&sync_lock); 953cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark sync_op_update(); 954cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 955cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 956cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 957cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* mark the start of read and/or write operation */ 958cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op) 959cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 960cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return sync_op(obj, op, true); 961cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 962cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 963cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op) 964cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 965cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return sync_op(obj, op, false); 966cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 967cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 968cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic DECLARE_WAIT_QUEUE_HEAD(sync_event); 969cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 970cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstatic void sync_notify(void *arg) 971cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 972cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct task_struct **waiter_task = arg; 973cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark *waiter_task = NULL; 974cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark wake_up_all(&sync_event); 975cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 976cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 977cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op) 978cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 979cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 980cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret = 0; 981cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (omap_obj->sync) { 982cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct task_struct *waiter_task = current; 983cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_sync_waiter *waiter = 984cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kzalloc(sizeof(*waiter), GFP_KERNEL); 985cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 986cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!waiter) { 987cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return -ENOMEM; 988cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 989cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 990cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->omap_obj = omap_obj; 991cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->op = op; 992cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->read_target = omap_obj->sync->read_pending; 993cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->write_target = omap_obj->sync->write_pending; 994cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->notify = sync_notify; 995cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->arg = &waiter_task; 996cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 997cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_lock(&sync_lock); 998cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (is_waiting(waiter)) { 999cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark SYNC("waited: %p", waiter); 1000cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark list_add_tail(&waiter->list, &waiters); 1001cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 1002cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = wait_event_interruptible(sync_event, 1003cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark (waiter_task == NULL)); 1004cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_lock(&sync_lock); 1005cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (waiter_task) { 1006cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark SYNC("interrupted: %p", waiter); 1007cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* we were interrupted */ 1008cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark list_del(&waiter->list); 1009cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter_task = NULL; 1010cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } else { 1011cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* freed in sync_op_update() */ 1012cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter = NULL; 1013cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1014cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1015cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 1016cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1017cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (waiter) { 1018cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kfree(waiter); 1019cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1020cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1021cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 1022cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1023cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1024cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* call fxn(arg), either synchronously or asynchronously if the op 1025cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * is currently blocked.. fxn() can be called from any context 1026cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 1027cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * (TODO for now fxn is called back from whichever context calls 1028cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * omap_gem_op_update().. but this could be better defined later 1029cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * if needed) 1030cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * 1031cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * TODO more code in common w/ _sync().. 1032cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 1033cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op, 1034cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark void (*fxn)(void *arg), void *arg) 1035cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 1036cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 1037cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (omap_obj->sync) { 1038cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_sync_waiter *waiter = 1039cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kzalloc(sizeof(*waiter), GFP_ATOMIC); 1040cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1041cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!waiter) { 1042cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return -ENOMEM; 1043cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1044cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1045cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->omap_obj = omap_obj; 1046cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->op = op; 1047cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->read_target = omap_obj->sync->read_pending; 1048cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->write_target = omap_obj->sync->write_pending; 1049cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->notify = fxn; 1050cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark waiter->arg = arg; 1051cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1052cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_lock(&sync_lock); 1053cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (is_waiting(waiter)) { 1054cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark SYNC("waited: %p", waiter); 1055cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark list_add_tail(&waiter->list, &waiters); 1056cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 1057cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 1058cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1059cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1060cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 1061cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1062cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1063cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* no waiting.. */ 1064cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark fxn(arg); 1065cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1066cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 1067cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1068cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1069cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* special API so PVR can update the buffer to use a sync-object allocated 1070cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * from it's sync-obj heap. Only used for a newly allocated (from PVR's 1071cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * perspective) sync-object, so we overwrite the new syncobj w/ values 1072cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * from the already allocated syncobj (if there is one) 1073cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 1074cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_set_sync_object(struct drm_gem_object *obj, void *syncobj) 1075cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 1076cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 1077cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret = 0; 1078cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1079cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_lock(&sync_lock); 1080cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1081cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if ((omap_obj->flags & OMAP_BO_EXT_SYNC) && !syncobj) { 1082cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* clearing a previously set syncobj */ 1083cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark syncobj = kzalloc(sizeof(*omap_obj->sync), GFP_ATOMIC); 1084cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!syncobj) { 1085cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = -ENOMEM; 1086cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark goto unlock; 1087cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1088cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark memcpy(syncobj, omap_obj->sync, sizeof(*omap_obj->sync)); 1089cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->flags &= ~OMAP_BO_EXT_SYNC; 1090cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync = syncobj; 1091cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } else if (syncobj && !(omap_obj->flags & OMAP_BO_EXT_SYNC)) { 1092cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* replacing an existing syncobj */ 1093cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (omap_obj->sync) { 1094cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark memcpy(syncobj, omap_obj->sync, sizeof(*omap_obj->sync)); 1095cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kfree(omap_obj->sync); 1096cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1097cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->flags |= OMAP_BO_EXT_SYNC; 1098cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->sync = syncobj; 1099cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1100cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1101cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkunlock: 1102cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark spin_unlock(&sync_lock); 1103cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 1104cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1105cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1106cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_init_object(struct drm_gem_object *obj) 1107cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 1108cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return -EINVAL; /* unused */ 1109cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1110cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1111cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* don't call directly.. called from GEM core when it is time to actually 1112cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark * free the object.. 1113cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark */ 1114cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkvoid omap_gem_free_object(struct drm_gem_object *obj) 1115cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 1116cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_device *dev = obj->dev; 1117cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj = to_omap_bo(obj); 1118cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1119f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark evict(obj); 1120f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1121f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 1122f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 1123f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark list_del(&omap_obj->mm_list); 1124f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 1125cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (obj->map_list.map) { 1126cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark drm_gem_free_mmap_offset(obj); 1127cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1128cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 11299a0774e0991c82a95ef5e5848b318bd15aba0dcdRob Clark /* this means the object is still pinned.. which really should 11309a0774e0991c82a95ef5e5848b318bd15aba0dcdRob Clark * not happen. I think.. 11319a0774e0991c82a95ef5e5848b318bd15aba0dcdRob Clark */ 11329a0774e0991c82a95ef5e5848b318bd15aba0dcdRob Clark WARN_ON(omap_obj->paddr_cnt > 0); 11339a0774e0991c82a95ef5e5848b318bd15aba0dcdRob Clark 1134cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* don't free externally allocated backing memory */ 1135cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) { 1136cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (omap_obj->pages) { 1137cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_gem_detach_pages(obj); 1138cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1139cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!is_shmem(obj)) { 1140cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark dma_free_writecombine(dev->dev, obj->size, 1141cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->vaddr, omap_obj->paddr); 1142f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } else if (omap_obj->vaddr) { 1143f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark vunmap(omap_obj->vaddr); 1144cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1145cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1146cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1147cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* don't free externally allocated syncobj */ 1148cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!(omap_obj->flags & OMAP_BO_EXT_SYNC)) { 1149cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kfree(omap_obj->sync); 1150cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1151cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1152cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark drm_gem_object_release(obj); 1153cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1154cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kfree(obj); 1155cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1156cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1157cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* convenience method to construct a GEM buffer object, and userspace handle */ 1158cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkint omap_gem_new_handle(struct drm_device *dev, struct drm_file *file, 1159cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark union omap_gem_size gsize, uint32_t flags, uint32_t *handle) 1160cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 1161cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_gem_object *obj; 1162cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret; 1163cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1164cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark obj = omap_gem_new(dev, gsize, flags); 1165cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!obj) 1166cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return -ENOMEM; 1167cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1168cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = drm_gem_handle_create(file, obj, handle); 1169cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (ret) { 1170cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark drm_gem_object_release(obj); 1171cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark kfree(obj); /* TODO isn't there a dtor to call? just copying i915 */ 1172cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return ret; 1173cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1174cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1175cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark /* drop reference from allocate - handle holds it now */ 1176cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark drm_gem_object_unreference_unlocked(obj); 1177cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1178cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return 0; 1179cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1180cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1181cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark/* GEM buffer object constructor */ 1182cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkstruct drm_gem_object *omap_gem_new(struct drm_device *dev, 1183cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark union omap_gem_size gsize, uint32_t flags) 1184cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark{ 1185a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark struct omap_drm_private *priv = dev->dev_private; 1186cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct omap_gem_object *omap_obj; 1187cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark struct drm_gem_object *obj = NULL; 1188cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark size_t size; 1189cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark int ret; 1190cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1191cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (flags & OMAP_BO_TILED) { 1192f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (!usergart) { 1193f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(dev->dev, "Tiled buffers require DMM\n"); 1194f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark goto fail; 1195f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1196f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1197f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* tiled buffers are always shmem paged backed.. when they are 1198f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * scanned out, they are remapped into DMM/TILER 1199f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 1200f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark flags &= ~OMAP_BO_SCANOUT; 1201f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1202f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* currently don't allow cached buffers.. there is some caching 1203f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * stuff that needs to be handled better 1204f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 1205f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark flags &= ~(OMAP_BO_CACHED|OMAP_BO_UNCACHED); 1206f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark flags |= OMAP_BO_WC; 1207cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1208f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* align dimensions to slot boundaries... */ 1209f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark tiler_align(gem2fmt(flags), 1210f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark &gsize.tiled.width, &gsize.tiled.height); 1211f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1212f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* ...and calculate size based on aligned dimensions */ 1213f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark size = tiler_size(gem2fmt(flags), 1214f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark gsize.tiled.width, gsize.tiled.height); 1215f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } else { 1216f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark size = PAGE_ALIGN(gsize.bytes); 1217f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1218cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1219cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL); 1220cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (!omap_obj) { 1221cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark dev_err(dev->dev, "could not allocate GEM object\n"); 1222cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark goto fail; 1223cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1224cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1225f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark list_add(&omap_obj->mm_list, &priv->obj_list); 1226f6b6036e56ca17378dd0294b684db623abd6a901Rob Clark 1227cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark obj = &omap_obj->base; 1228cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1229a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) { 1230a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark /* attempt to allocate contiguous memory if we don't 1231a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark * have DMM for remappign discontiguous buffers 1232a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark */ 1233cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size, 1234cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark &omap_obj->paddr, GFP_KERNEL); 1235cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (omap_obj->vaddr) { 1236cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark flags |= OMAP_BO_DMA; 1237cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1238cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1239cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1240cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_obj->flags = flags; 1241cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1242f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (flags & OMAP_BO_TILED) { 1243f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->width = gsize.tiled.width; 1244f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark omap_obj->height = gsize.tiled.height; 1245f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1246f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1247cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM)) { 1248cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = drm_gem_private_object_init(dev, obj, size); 1249cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } else { 1250cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark ret = drm_gem_object_init(dev, obj, size); 1251cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1252cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1253cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (ret) { 1254cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark goto fail; 1255cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1256cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1257cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return obj; 1258cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark 1259cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clarkfail: 1260cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark if (obj) { 1261cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark omap_gem_free_object(obj); 1262cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark } 1263cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark return NULL; 1264cd5351f4d2b1b884d8c21a7636d5c0ea3b69d123Rob Clark} 1265f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1266f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark/* init/cleanup.. if DMM is used, we need to set some stuff up.. */ 1267f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkvoid omap_gem_init(struct drm_device *dev) 1268f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 1269a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark struct omap_drm_private *priv = dev->dev_private; 1270f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark const enum tiler_fmt fmts[] = { 1271f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT 1272f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark }; 12735c137797377db64d4cfb429ee8e4a420d9743660Andy Gross int i, j; 1274f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 12755c137797377db64d4cfb429ee8e4a420d9743660Andy Gross if (!dmm_is_initialized()) { 1276f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* DMM only supported on OMAP4 and later, so this isn't fatal */ 12775c137797377db64d4cfb429ee8e4a420d9743660Andy Gross dev_warn(dev->dev, "DMM not available, disable DMM support\n"); 1278f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return; 1279f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1280f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1281f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart = kzalloc(3 * sizeof(*usergart), GFP_KERNEL); 1282b369839b88d6ffd9ad5b4f9362d6bb09a0e16c10Rob Clark if (!usergart) { 1283b369839b88d6ffd9ad5b4f9362d6bb09a0e16c10Rob Clark dev_warn(dev->dev, "could not allocate usergart\n"); 1284b369839b88d6ffd9ad5b4f9362d6bb09a0e16c10Rob Clark return; 1285b369839b88d6ffd9ad5b4f9362d6bb09a0e16c10Rob Clark } 1286f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1287f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* reserve 4k aligned/wide regions for userspace mappings: */ 1288f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark for (i = 0; i < ARRAY_SIZE(fmts); i++) { 1289f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark uint16_t h = 1, w = PAGE_SIZE >> i; 1290f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark tiler_align(fmts[i], &w, &h); 1291f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* note: since each region is 1 4kb page wide, and minimum 1292f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * number of rows, the height ends up being the same as the 1293f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * # of pages in the region 1294f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 1295f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart[i].height = h; 1296f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart[i].height_shift = ilog2(h); 1297f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart[i].stride_pfn = tiler_stride(fmts[i]) >> PAGE_SHIFT; 1298f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i); 1299f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark for (j = 0; j < NUM_USERGART_ENTRIES; j++) { 1300f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct usergart_entry *entry = &usergart[i].entry[j]; 1301f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark struct tiler_block *block = 1302f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark tiler_reserve_2d(fmts[i], w, h, 1303f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark PAGE_SIZE); 1304f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark if (IS_ERR(block)) { 1305f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark dev_err(dev->dev, 1306f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark "reserve failed: %d, %d, %ld\n", 1307f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark i, j, PTR_ERR(block)); 1308f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark return; 1309f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1310f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark entry->paddr = tiler_ssptr(block); 1311f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark entry->block = block; 1312f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1313f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h, 1314f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark entry->paddr, 1315f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark usergart[i].stride_pfn << PAGE_SHIFT); 1316f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1317f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark } 1318a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark 1319a6a918274116d8edc25eb20f6097dedf97b108e2Rob Clark priv->has_dmm = true; 1320f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 1321f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark 1322f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clarkvoid omap_gem_deinit(struct drm_device *dev) 1323f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark{ 1324f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark /* I believe we can rely on there being no more outstanding GEM 1325f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark * objects which could depend on usergart/dmm at this point. 1326f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark */ 1327f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark kfree(usergart); 1328f7f9f4536a09f9f73c800663df2e600c9405e1efRob Clark} 1329