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

Merge branch 'drm-etnaviv-next' of git://git.pengutronix.de/git/lst/linux into drm-next

Notable changes:
- correctness fixes to the GPU cache flushing when switching execution
state and when powering down the GPU
- reduction of time spent in hardirq-off context
- placement improvements to the GPU DMA linear window, allowing the
driver to properly work on i.MX6 systems with more than 2GB of RAM

* 'drm-etnaviv-next' of git://git.pengutronix.de/git/lst/linux:
drm: etnaviv: clean up submit_bo()
drm: etnaviv: clean up vram_mapping submission/retire path
drm: etnaviv: improve readability of command insertion to ring buffer
drm: etnaviv: clean up GPU command submission
drm: etnaviv: use previous GPU pipe state when pipe switching
drm: etnaviv: flush all GPU caches when stopping GPU
drm: etnaviv: track current execution state
drm: etnaviv: extract arming of semaphore
drm: etnaviv: extract replacement of WAIT command
drm: etnaviv: extract command ring reservation
drm/etnaviv: move GPU linear window to end of DMA window
drm/etnaviv: move runtime PM balance into retire worker

+238 -158
+138 -79
drivers/gpu/drm/etnaviv/etnaviv_buffer.c
··· 21 21 22 22 #include "common.xml.h" 23 23 #include "state.xml.h" 24 + #include "state_3d.xml.h" 24 25 #include "cmdstream.xml.h" 25 26 26 27 /* ··· 86 85 OUT(buffer, VIV_FE_STALL_TOKEN_FROM(from) | VIV_FE_STALL_TOKEN_TO(to)); 87 86 } 88 87 89 - static void etnaviv_cmd_select_pipe(struct etnaviv_cmdbuf *buffer, u8 pipe) 88 + static inline void CMD_SEM(struct etnaviv_cmdbuf *buffer, u32 from, u32 to) 90 89 { 91 - u32 flush; 92 - u32 stall; 90 + CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN, 91 + VIVS_GL_SEMAPHORE_TOKEN_FROM(from) | 92 + VIVS_GL_SEMAPHORE_TOKEN_TO(to)); 93 + } 94 + 95 + static void etnaviv_cmd_select_pipe(struct etnaviv_gpu *gpu, 96 + struct etnaviv_cmdbuf *buffer, u8 pipe) 97 + { 98 + u32 flush = 0; 93 99 94 100 /* 95 101 * This assumes that if we're switching to 2D, we're switching ··· 104 96 * the 2D core, we need to flush the 3D depth and color caches, 105 97 * otherwise we need to flush the 2D pixel engine cache. 106 98 */ 107 - if (pipe == ETNA_PIPE_2D) 108 - flush = VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR; 109 - else 99 + if (gpu->exec_state == ETNA_PIPE_2D) 110 100 flush = VIVS_GL_FLUSH_CACHE_PE2D; 111 - 112 - stall = VIVS_GL_SEMAPHORE_TOKEN_FROM(SYNC_RECIPIENT_FE) | 113 - VIVS_GL_SEMAPHORE_TOKEN_TO(SYNC_RECIPIENT_PE); 101 + else if (gpu->exec_state == ETNA_PIPE_3D) 102 + flush = VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR; 114 103 115 104 CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush); 116 - CMD_LOAD_STATE(buffer, VIVS_GL_SEMAPHORE_TOKEN, stall); 117 - 105 + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); 118 106 CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); 119 107 120 108 CMD_LOAD_STATE(buffer, VIVS_GL_PIPE_SELECT, ··· 135 131 ptr, len * 4, 0); 136 132 } 137 133 134 + /* 135 + * Safely replace the WAIT of a waitlink with a new command and argument. 136 + * The GPU may be executing this WAIT while we're modifying it, so we have 137 + * to write it in a specific order to avoid the GPU branching to somewhere 138 + * else. 'wl_offset' is the offset to the first byte of the WAIT command. 139 + */ 140 + static void etnaviv_buffer_replace_wait(struct etnaviv_cmdbuf *buffer, 141 + unsigned int wl_offset, u32 cmd, u32 arg) 142 + { 143 + u32 *lw = buffer->vaddr + wl_offset; 144 + 145 + lw[1] = arg; 146 + mb(); 147 + lw[0] = cmd; 148 + mb(); 149 + } 150 + 151 + /* 152 + * Ensure that there is space in the command buffer to contiguously write 153 + * 'cmd_dwords' 64-bit words into the buffer, wrapping if necessary. 154 + */ 155 + static u32 etnaviv_buffer_reserve(struct etnaviv_gpu *gpu, 156 + struct etnaviv_cmdbuf *buffer, unsigned int cmd_dwords) 157 + { 158 + if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size) 159 + buffer->user_size = 0; 160 + 161 + return gpu_va(gpu, buffer) + buffer->user_size; 162 + } 163 + 138 164 u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu) 139 165 { 140 166 struct etnaviv_cmdbuf *buffer = gpu->buffer; ··· 181 147 void etnaviv_buffer_end(struct etnaviv_gpu *gpu) 182 148 { 183 149 struct etnaviv_cmdbuf *buffer = gpu->buffer; 150 + unsigned int waitlink_offset = buffer->user_size - 16; 151 + u32 link_target, flush = 0; 184 152 185 - /* Replace the last WAIT with an END */ 186 - buffer->user_size -= 16; 153 + if (gpu->exec_state == ETNA_PIPE_2D) 154 + flush = VIVS_GL_FLUSH_CACHE_PE2D; 155 + else if (gpu->exec_state == ETNA_PIPE_3D) 156 + flush = VIVS_GL_FLUSH_CACHE_DEPTH | 157 + VIVS_GL_FLUSH_CACHE_COLOR | 158 + VIVS_GL_FLUSH_CACHE_TEXTURE | 159 + VIVS_GL_FLUSH_CACHE_TEXTUREVS | 160 + VIVS_GL_FLUSH_CACHE_SHADER_L2; 187 161 188 - CMD_END(buffer); 189 - mb(); 162 + if (flush) { 163 + unsigned int dwords = 7; 164 + 165 + link_target = etnaviv_buffer_reserve(gpu, buffer, dwords); 166 + 167 + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); 168 + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); 169 + CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush); 170 + if (gpu->exec_state == ETNA_PIPE_3D) 171 + CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, 172 + VIVS_TS_FLUSH_CACHE_FLUSH); 173 + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); 174 + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); 175 + CMD_END(buffer); 176 + 177 + etnaviv_buffer_replace_wait(buffer, waitlink_offset, 178 + VIV_FE_LINK_HEADER_OP_LINK | 179 + VIV_FE_LINK_HEADER_PREFETCH(dwords), 180 + link_target); 181 + } else { 182 + /* Replace the last link-wait with an "END" command */ 183 + etnaviv_buffer_replace_wait(buffer, waitlink_offset, 184 + VIV_FE_END_HEADER_OP_END, 0); 185 + } 190 186 } 191 187 188 + /* Append a command buffer to the ring buffer. */ 192 189 void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, 193 190 struct etnaviv_cmdbuf *cmdbuf) 194 191 { 195 192 struct etnaviv_cmdbuf *buffer = gpu->buffer; 196 - u32 *lw = buffer->vaddr + buffer->user_size - 16; 197 - u32 back, link_target, link_size, reserve_size, extra_size = 0; 193 + unsigned int waitlink_offset = buffer->user_size - 16; 194 + u32 return_target, return_dwords; 195 + u32 link_target, link_dwords; 198 196 199 197 if (drm_debug & DRM_UT_DRIVER) 200 198 etnaviv_buffer_dump(gpu, buffer, 0, 0x50); 201 199 200 + link_target = gpu_va(gpu, cmdbuf); 201 + link_dwords = cmdbuf->size / 8; 202 + 202 203 /* 203 - * If we need to flush the MMU prior to submitting this buffer, we 204 - * will need to append a mmu flush load state, followed by a new 204 + * If we need maintanence prior to submitting this buffer, we will 205 + * need to append a mmu flush load state, followed by a new 205 206 * link to this buffer - a total of four additional words. 206 207 */ 207 208 if (gpu->mmu->need_flush || gpu->switch_context) { 209 + u32 target, extra_dwords; 210 + 208 211 /* link command */ 209 - extra_size += 2; 212 + extra_dwords = 1; 213 + 210 214 /* flush command */ 211 215 if (gpu->mmu->need_flush) 212 - extra_size += 2; 216 + extra_dwords += 1; 217 + 213 218 /* pipe switch commands */ 214 219 if (gpu->switch_context) 215 - extra_size += 8; 216 - } 220 + extra_dwords += 4; 217 221 218 - reserve_size = (6 + extra_size) * 4; 219 - 220 - /* 221 - * if we are going to completely overflow the buffer, we need to wrap. 222 - */ 223 - if (buffer->user_size + reserve_size > buffer->size) 224 - buffer->user_size = 0; 225 - 226 - /* save offset back into main buffer */ 227 - back = buffer->user_size + reserve_size - 6 * 4; 228 - link_target = gpu_va(gpu, buffer) + buffer->user_size; 229 - link_size = 6; 230 - 231 - /* Skip over any extra instructions */ 232 - link_target += extra_size * sizeof(u32); 233 - 234 - if (drm_debug & DRM_UT_DRIVER) 235 - pr_info("stream link to 0x%08x @ 0x%08x %p\n", 236 - link_target, gpu_va(gpu, cmdbuf), cmdbuf->vaddr); 237 - 238 - /* jump back from cmd to main buffer */ 239 - CMD_LINK(cmdbuf, link_size, link_target); 240 - 241 - link_target = gpu_va(gpu, cmdbuf); 242 - link_size = cmdbuf->size / 8; 243 - 244 - 245 - 246 - if (drm_debug & DRM_UT_DRIVER) { 247 - print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, 248 - cmdbuf->vaddr, cmdbuf->size, 0); 249 - 250 - pr_info("link op: %p\n", lw); 251 - pr_info("link addr: %p\n", lw + 1); 252 - pr_info("addr: 0x%08x\n", link_target); 253 - pr_info("back: 0x%08x\n", gpu_va(gpu, buffer) + back); 254 - pr_info("event: %d\n", event); 255 - } 256 - 257 - if (gpu->mmu->need_flush || gpu->switch_context) { 258 - u32 new_target = gpu_va(gpu, buffer) + buffer->user_size; 222 + target = etnaviv_buffer_reserve(gpu, buffer, extra_dwords); 259 223 260 224 if (gpu->mmu->need_flush) { 261 225 /* Add the MMU flush */ ··· 268 236 } 269 237 270 238 if (gpu->switch_context) { 271 - etnaviv_cmd_select_pipe(buffer, cmdbuf->exec_state); 239 + etnaviv_cmd_select_pipe(gpu, buffer, cmdbuf->exec_state); 240 + gpu->exec_state = cmdbuf->exec_state; 272 241 gpu->switch_context = false; 273 242 } 274 243 275 - /* And the link to the first buffer */ 276 - CMD_LINK(buffer, link_size, link_target); 244 + /* And the link to the submitted buffer */ 245 + CMD_LINK(buffer, link_dwords, link_target); 277 246 278 247 /* Update the link target to point to above instructions */ 279 - link_target = new_target; 280 - link_size = extra_size; 248 + link_target = target; 249 + link_dwords = extra_dwords; 281 250 } 282 251 283 - /* trigger event */ 252 + /* 253 + * Append a LINK to the submitted command buffer to return to 254 + * the ring buffer. return_target is the ring target address. 255 + * We need three dwords: event, wait, link. 256 + */ 257 + return_dwords = 3; 258 + return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords); 259 + CMD_LINK(cmdbuf, return_dwords, return_target); 260 + 261 + /* 262 + * Append event, wait and link pointing back to the wait 263 + * command to the ring buffer. 264 + */ 284 265 CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | 285 266 VIVS_GL_EVENT_FROM_PE); 286 - 287 - /* append WAIT/LINK to main buffer */ 288 267 CMD_WAIT(buffer); 289 - CMD_LINK(buffer, 2, gpu_va(gpu, buffer) + (buffer->user_size - 4)); 268 + CMD_LINK(buffer, 2, return_target + 8); 290 269 291 - /* Change WAIT into a LINK command; write the address first. */ 292 - *(lw + 1) = link_target; 293 - mb(); 294 - *(lw) = VIV_FE_LINK_HEADER_OP_LINK | 295 - VIV_FE_LINK_HEADER_PREFETCH(link_size); 296 - mb(); 270 + if (drm_debug & DRM_UT_DRIVER) 271 + pr_info("stream link to 0x%08x @ 0x%08x %p\n", 272 + return_target, gpu_va(gpu, cmdbuf), cmdbuf->vaddr); 273 + 274 + if (drm_debug & DRM_UT_DRIVER) { 275 + print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, 276 + cmdbuf->vaddr, cmdbuf->size, 0); 277 + 278 + pr_info("link op: %p\n", buffer->vaddr + waitlink_offset); 279 + pr_info("addr: 0x%08x\n", link_target); 280 + pr_info("back: 0x%08x\n", return_target); 281 + pr_info("event: %d\n", event); 282 + } 283 + 284 + /* 285 + * Kick off the submitted command by replacing the previous 286 + * WAIT with a link to the address in the ring buffer. 287 + */ 288 + etnaviv_buffer_replace_wait(buffer, waitlink_offset, 289 + VIV_FE_LINK_HEADER_OP_LINK | 290 + VIV_FE_LINK_HEADER_PREFETCH(link_dwords), 291 + link_target); 297 292 298 293 if (drm_debug & DRM_UT_DRIVER) 299 294 etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
-3
drivers/gpu/drm/etnaviv/etnaviv_drv.h
··· 75 75 int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma); 76 76 int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); 77 77 int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset); 78 - int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu, 79 - struct drm_gem_object *obj, u32 *iova); 80 - void etnaviv_gem_put_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj); 81 78 struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj); 82 79 void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj); 83 80 void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+31 -23
drivers/gpu/drm/etnaviv/etnaviv_gem.c
··· 260 260 return NULL; 261 261 } 262 262 263 - int etnaviv_gem_get_iova(struct etnaviv_gpu *gpu, 264 - struct drm_gem_object *obj, u32 *iova) 263 + void etnaviv_gem_mapping_reference(struct etnaviv_vram_mapping *mapping) 264 + { 265 + struct etnaviv_gem_object *etnaviv_obj = mapping->object; 266 + 267 + drm_gem_object_reference(&etnaviv_obj->base); 268 + 269 + mutex_lock(&etnaviv_obj->lock); 270 + WARN_ON(mapping->use == 0); 271 + mapping->use += 1; 272 + mutex_unlock(&etnaviv_obj->lock); 273 + } 274 + 275 + void etnaviv_gem_mapping_unreference(struct etnaviv_vram_mapping *mapping) 276 + { 277 + struct etnaviv_gem_object *etnaviv_obj = mapping->object; 278 + 279 + mutex_lock(&etnaviv_obj->lock); 280 + WARN_ON(mapping->use == 0); 281 + mapping->use -= 1; 282 + mutex_unlock(&etnaviv_obj->lock); 283 + 284 + drm_gem_object_unreference_unlocked(&etnaviv_obj->base); 285 + } 286 + 287 + struct etnaviv_vram_mapping *etnaviv_gem_mapping_get( 288 + struct drm_gem_object *obj, struct etnaviv_gpu *gpu) 265 289 { 266 290 struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 267 291 struct etnaviv_vram_mapping *mapping; ··· 353 329 out: 354 330 mutex_unlock(&etnaviv_obj->lock); 355 331 356 - if (!ret) { 357 - /* Take a reference on the object */ 358 - drm_gem_object_reference(obj); 359 - *iova = mapping->iova; 360 - } 332 + if (ret) 333 + return ERR_PTR(ret); 361 334 362 - return ret; 363 - } 364 - 365 - void etnaviv_gem_put_iova(struct etnaviv_gpu *gpu, struct drm_gem_object *obj) 366 - { 367 - struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); 368 - struct etnaviv_vram_mapping *mapping; 369 - 370 - mutex_lock(&etnaviv_obj->lock); 371 - mapping = etnaviv_gem_get_vram_mapping(etnaviv_obj, gpu->mmu); 372 - 373 - WARN_ON(mapping->use == 0); 374 - mapping->use -= 1; 375 - mutex_unlock(&etnaviv_obj->lock); 376 - 377 - drm_gem_object_unreference_unlocked(obj); 335 + /* Take a reference on the object */ 336 + drm_gem_object_reference(obj); 337 + return mapping; 378 338 } 379 339 380 340 void *etnaviv_gem_vmap(struct drm_gem_object *obj)
+12 -5
drivers/gpu/drm/etnaviv/etnaviv_gem.h
··· 88 88 89 89 #define MAX_CMDS 4 90 90 91 + struct etnaviv_gem_submit_bo { 92 + u32 flags; 93 + struct etnaviv_gem_object *obj; 94 + struct etnaviv_vram_mapping *mapping; 95 + }; 96 + 91 97 /* Created per submit-ioctl, to track bo's and cmdstream bufs, etc, 92 98 * associated with the cmdstream submission for synchronization (and 93 99 * make it easier to unwind when things go wrong, etc). This only ··· 105 99 struct ww_acquire_ctx ticket; 106 100 u32 fence; 107 101 unsigned int nr_bos; 108 - struct { 109 - u32 flags; 110 - struct etnaviv_gem_object *obj; 111 - u32 iova; 112 - } bos[0]; 102 + struct etnaviv_gem_submit_bo bos[0]; 113 103 }; 114 104 115 105 int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, ··· 116 114 int etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj); 117 115 struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *obj); 118 116 void etnaviv_gem_put_pages(struct etnaviv_gem_object *obj); 117 + 118 + struct etnaviv_vram_mapping *etnaviv_gem_mapping_get( 119 + struct drm_gem_object *obj, struct etnaviv_gpu *gpu); 120 + void etnaviv_gem_mapping_reference(struct etnaviv_vram_mapping *mapping); 121 + void etnaviv_gem_mapping_unreference(struct etnaviv_vram_mapping *mapping); 119 122 120 123 #endif /* __ETNAVIV_GEM_H__ */
+16 -20
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
··· 187 187 int i; 188 188 189 189 for (i = 0; i < submit->nr_bos; i++) { 190 - struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; 191 - 192 190 if (submit->bos[i].flags & BO_PINNED) 193 - etnaviv_gem_put_iova(submit->gpu, &etnaviv_obj->base); 191 + etnaviv_gem_mapping_unreference(submit->bos[i].mapping); 194 192 195 - submit->bos[i].iova = 0; 193 + submit->bos[i].mapping = NULL; 196 194 submit->bos[i].flags &= ~BO_PINNED; 197 195 } 198 196 } ··· 201 203 202 204 for (i = 0; i < submit->nr_bos; i++) { 203 205 struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; 204 - u32 iova; 206 + struct etnaviv_vram_mapping *mapping; 205 207 206 - ret = etnaviv_gem_get_iova(submit->gpu, &etnaviv_obj->base, 207 - &iova); 208 - if (ret) 208 + mapping = etnaviv_gem_mapping_get(&etnaviv_obj->base, 209 + submit->gpu); 210 + if (IS_ERR(mapping)) { 211 + ret = PTR_ERR(mapping); 209 212 break; 213 + } 210 214 211 215 submit->bos[i].flags |= BO_PINNED; 212 - submit->bos[i].iova = iova; 216 + submit->bos[i].mapping = mapping; 213 217 } 214 218 215 219 return ret; 216 220 } 217 221 218 222 static int submit_bo(struct etnaviv_gem_submit *submit, u32 idx, 219 - struct etnaviv_gem_object **obj, u32 *iova) 223 + struct etnaviv_gem_submit_bo **bo) 220 224 { 221 225 if (idx >= submit->nr_bos) { 222 226 DRM_ERROR("invalid buffer index: %u (out of %u)\n", ··· 226 226 return -EINVAL; 227 227 } 228 228 229 - if (obj) 230 - *obj = submit->bos[idx].obj; 231 - if (iova) 232 - *iova = submit->bos[idx].iova; 229 + *bo = &submit->bos[idx]; 233 230 234 231 return 0; 235 232 } ··· 242 245 243 246 for (i = 0; i < nr_relocs; i++) { 244 247 const struct drm_etnaviv_gem_submit_reloc *r = relocs + i; 245 - struct etnaviv_gem_object *bobj; 246 - u32 iova, off; 248 + struct etnaviv_gem_submit_bo *bo; 249 + u32 off; 247 250 248 251 if (unlikely(r->flags)) { 249 252 DRM_ERROR("invalid reloc flags\n"); ··· 265 268 return -EINVAL; 266 269 } 267 270 268 - ret = submit_bo(submit, r->reloc_idx, &bobj, &iova); 271 + ret = submit_bo(submit, r->reloc_idx, &bo); 269 272 if (ret) 270 273 return ret; 271 274 272 - if (r->reloc_offset >= 273 - bobj->base.size - sizeof(*ptr)) { 275 + if (r->reloc_offset >= bo->obj->base.size - sizeof(*ptr)) { 274 276 DRM_ERROR("relocation %u outside object", i); 275 277 return -EINVAL; 276 278 } 277 279 278 - ptr[off] = iova + r->reloc_offset; 280 + ptr[off] = bo->mapping->iova + r->reloc_offset; 279 281 280 282 last_offset = off; 281 283 }
+28 -26
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
··· 628 628 /* Now program the hardware */ 629 629 mutex_lock(&gpu->lock); 630 630 etnaviv_gpu_hw_init(gpu); 631 + gpu->exec_state = -1; 631 632 mutex_unlock(&gpu->lock); 632 633 633 634 pm_runtime_mark_last_busy(gpu->dev); ··· 872 871 gpu->event[i].fence = NULL; 873 872 gpu->event[i].used = false; 874 873 complete(&gpu->event_free); 875 - /* 876 - * Decrement the PM count for each stuck event. This is safe 877 - * even in atomic context as we use ASYNC RPM here. 878 - */ 879 - pm_runtime_put_autosuspend(gpu->dev); 880 874 } 881 875 spin_unlock_irqrestore(&gpu->event_spinlock, flags); 882 876 gpu->completed_fence = gpu->active_fence; 883 877 884 878 etnaviv_gpu_hw_init(gpu); 885 879 gpu->switch_context = true; 880 + gpu->exec_state = -1; 886 881 887 882 mutex_unlock(&gpu->lock); 888 883 pm_runtime_mark_last_busy(gpu->dev); ··· 1103 1106 size_t nr_bos) 1104 1107 { 1105 1108 struct etnaviv_cmdbuf *cmdbuf; 1106 - size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo[0]), 1109 + size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]), 1107 1110 sizeof(*cmdbuf)); 1108 1111 1109 1112 cmdbuf = kzalloc(sz, GFP_KERNEL); ··· 1147 1150 fence_put(cmdbuf->fence); 1148 1151 1149 1152 for (i = 0; i < cmdbuf->nr_bos; i++) { 1150 - struct etnaviv_gem_object *etnaviv_obj = cmdbuf->bo[i]; 1153 + struct etnaviv_vram_mapping *mapping = cmdbuf->bo_map[i]; 1154 + struct etnaviv_gem_object *etnaviv_obj = mapping->object; 1151 1155 1152 1156 atomic_dec(&etnaviv_obj->gpu_active); 1153 1157 /* drop the refcount taken in etnaviv_gpu_submit */ 1154 - etnaviv_gem_put_iova(gpu, &etnaviv_obj->base); 1158 + etnaviv_gem_mapping_unreference(mapping); 1155 1159 } 1156 1160 1157 1161 etnaviv_gpu_cmdbuf_free(cmdbuf); 1162 + /* 1163 + * We need to balance the runtime PM count caused by 1164 + * each submission. Upon submission, we increment 1165 + * the runtime PM counter, and allocate one event. 1166 + * So here, we put the runtime PM count for each 1167 + * completed event. 1168 + */ 1169 + pm_runtime_put_autosuspend(gpu->dev); 1158 1170 } 1159 1171 1160 1172 gpu->retired_fence = fence; ··· 1310 1304 1311 1305 for (i = 0; i < submit->nr_bos; i++) { 1312 1306 struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj; 1313 - u32 iova; 1314 1307 1315 - /* Each cmdbuf takes a refcount on the iova */ 1316 - etnaviv_gem_get_iova(gpu, &etnaviv_obj->base, &iova); 1317 - cmdbuf->bo[i] = etnaviv_obj; 1308 + /* Each cmdbuf takes a refcount on the mapping */ 1309 + etnaviv_gem_mapping_reference(submit->bos[i].mapping); 1310 + cmdbuf->bo_map[i] = submit->bos[i].mapping; 1318 1311 atomic_inc(&etnaviv_obj->gpu_active); 1319 1312 1320 1313 if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE) ··· 1383 1378 gpu->completed_fence = fence->seqno; 1384 1379 1385 1380 event_free(gpu, event); 1386 - 1387 - /* 1388 - * We need to balance the runtime PM count caused by 1389 - * each submission. Upon submission, we increment 1390 - * the runtime PM counter, and allocate one event. 1391 - * So here, we put the runtime PM count for each 1392 - * completed event. 1393 - */ 1394 - pm_runtime_put_autosuspend(gpu->dev); 1395 1381 } 1396 1382 1397 1383 /* Retire the buffer objects in a work */ ··· 1477 1481 etnaviv_gpu_hw_init(gpu); 1478 1482 1479 1483 gpu->switch_context = true; 1484 + gpu->exec_state = -1; 1480 1485 1481 1486 mutex_unlock(&gpu->lock); 1482 1487 ··· 1566 1569 { 1567 1570 struct device *dev = &pdev->dev; 1568 1571 struct etnaviv_gpu *gpu; 1572 + u32 dma_mask; 1569 1573 int err = 0; 1570 1574 1571 1575 gpu = devm_kzalloc(dev, sizeof(*gpu), GFP_KERNEL); ··· 1577 1579 mutex_init(&gpu->lock); 1578 1580 1579 1581 /* 1580 - * Set the GPU base address to the start of physical memory. This 1581 - * ensures that if we have up to 2GB, the v1 MMU can address the 1582 - * highest memory. This is important as command buffers may be 1583 - * allocated outside of this limit. 1582 + * Set the GPU linear window to be at the end of the DMA window, where 1583 + * the CMA area is likely to reside. This ensures that we are able to 1584 + * map the command buffers while having the linear window overlap as 1585 + * much RAM as possible, so we can optimize mappings for other buffers. 1584 1586 */ 1585 - gpu->memory_base = PHYS_OFFSET; 1587 + dma_mask = (u32)dma_get_required_mask(dev); 1588 + if (dma_mask < PHYS_OFFSET + SZ_2G) 1589 + gpu->memory_base = PHYS_OFFSET; 1590 + else 1591 + gpu->memory_base = dma_mask - SZ_2G + 1; 1586 1592 1587 1593 /* Map registers: */ 1588 1594 gpu->mmio = etnaviv_ioremap(pdev, NULL, dev_name(gpu->dev));
+3 -1
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
··· 23 23 #include "etnaviv_drv.h" 24 24 25 25 struct etnaviv_gem_submit; 26 + struct etnaviv_vram_mapping; 26 27 27 28 struct etnaviv_chip_identity { 28 29 /* Chip model. */ ··· 104 103 105 104 /* 'ring'-buffer: */ 106 105 struct etnaviv_cmdbuf *buffer; 106 + int exec_state; 107 107 108 108 /* bus base address of memory */ 109 109 u32 memory_base; ··· 168 166 struct list_head node; 169 167 /* BOs attached to this command buffer */ 170 168 unsigned int nr_bos; 171 - struct etnaviv_gem_object *bo[0]; 169 + struct etnaviv_vram_mapping *bo_map[0]; 172 170 }; 173 171 174 172 static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data)
+1 -1
drivers/gpu/drm/etnaviv/etnaviv_mmu.c
··· 193 193 194 194 /* 195 195 * Unmap the blocks which need to be reaped from the MMU. 196 - * Clear the mmu pointer to prevent the get_iova finding 196 + * Clear the mmu pointer to prevent the mapping_get finding 197 197 * this mapping. 198 198 */ 199 199 list_for_each_entry_safe(m, n, &list, scan_node) {
+9
drivers/gpu/drm/etnaviv/state_3d.xml.h
··· 1 + #ifndef STATE_3D_XML 2 + #define STATE_3D_XML 3 + 4 + /* This is a cut-down version of the state_3d.xml.h file */ 5 + 6 + #define VIVS_TS_FLUSH_CACHE 0x00001650 7 + #define VIVS_TS_FLUSH_CACHE_FLUSH 0x00000001 8 + 9 + #endif /* STATE_3D_XML */