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

Merge remote-tracking branch 'airlied/drm-next' into drm-misc-next

Yet another backmerge to get at latest etnaviv code, which is need for
Chris' drm_mm patch.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

+329 -123
+1
drivers/gpu/drm/etnaviv/Makefile
··· 1 1 etnaviv-y := \ 2 2 etnaviv_buffer.o \ 3 3 etnaviv_cmd_parser.o \ 4 + etnaviv_cmdbuf.o \ 4 5 etnaviv_drv.o \ 5 6 etnaviv_dump.o \ 6 7 etnaviv_gem_prime.o \
+8 -6
drivers/gpu/drm/etnaviv/etnaviv_buffer.c
··· 15 15 * this program. If not, see <http://www.gnu.org/licenses/>. 16 16 */ 17 17 18 + #include "etnaviv_cmdbuf.h" 18 19 #include "etnaviv_gpu.h" 19 20 #include "etnaviv_gem.h" 20 21 #include "etnaviv_mmu.h" ··· 126 125 u32 *ptr = buf->vaddr + off; 127 126 128 127 dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n", 129 - ptr, etnaviv_iommu_get_cmdbuf_va(gpu, buf) + off, size - len * 4 - off); 128 + ptr, etnaviv_cmdbuf_get_va(buf) + off, size - len * 4 - off); 130 129 131 130 print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, 132 131 ptr, len * 4, 0); ··· 159 158 if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size) 160 159 buffer->user_size = 0; 161 160 162 - return etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + buffer->user_size; 161 + return etnaviv_cmdbuf_get_va(buffer) + buffer->user_size; 163 162 } 164 163 165 164 u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu) ··· 170 169 buffer->user_size = 0; 171 170 172 171 CMD_WAIT(buffer); 173 - CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + 172 + CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) + 174 173 buffer->user_size - 4); 175 174 176 175 return buffer->user_size / 8; ··· 262 261 if (drm_debug & DRM_UT_DRIVER) 263 262 etnaviv_buffer_dump(gpu, buffer, 0, 0x50); 264 263 265 - link_target = etnaviv_iommu_get_cmdbuf_va(gpu, cmdbuf); 264 + link_target = etnaviv_cmdbuf_get_va(cmdbuf); 266 265 link_dwords = cmdbuf->size / 8; 267 266 268 267 /* ··· 356 355 CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | 357 356 VIVS_GL_EVENT_FROM_PE); 358 357 CMD_WAIT(buffer); 359 - CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + 358 + CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) + 360 359 buffer->user_size - 4); 361 360 362 361 if (drm_debug & DRM_UT_DRIVER) 363 362 pr_info("stream link to 0x%08x @ 0x%08x %p\n", 364 - return_target, etnaviv_iommu_get_cmdbuf_va(gpu, cmdbuf), cmdbuf->vaddr); 363 + return_target, etnaviv_cmdbuf_get_va(cmdbuf), 364 + cmdbuf->vaddr); 365 365 366 366 if (drm_debug & DRM_UT_DRIVER) { 367 367 print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
+6
drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
··· 56 56 ST(0x0644, 1), 57 57 ST(0x064c, 1), 58 58 ST(0x0680, 8), 59 + ST(0x086c, 1), 60 + ST(0x1028, 1), 59 61 ST(0x1410, 1), 60 62 ST(0x1430, 1), 61 63 ST(0x1458, 1), ··· 75 73 ST(0x16c0, 8), 76 74 ST(0x16e0, 8), 77 75 ST(0x1740, 8), 76 + ST(0x17c0, 8), 77 + ST(0x17e0, 8), 78 78 ST(0x2400, 14 * 16), 79 79 ST(0x10800, 32 * 16), 80 + ST(0x14600, 16), 81 + ST(0x14800, 8 * 8), 80 82 #undef ST 81 83 }; 82 84
+153
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c
··· 1 + /* 2 + * Copyright (C) 2017 Etnaviv Project 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + 17 + #include <drm/drm_mm.h> 18 + 19 + #include "etnaviv_cmdbuf.h" 20 + #include "etnaviv_gpu.h" 21 + #include "etnaviv_mmu.h" 22 + 23 + #define SUBALLOC_SIZE SZ_256K 24 + #define SUBALLOC_GRANULE SZ_4K 25 + #define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE) 26 + 27 + struct etnaviv_cmdbuf_suballoc { 28 + /* suballocated dma buffer properties */ 29 + struct etnaviv_gpu *gpu; 30 + void *vaddr; 31 + dma_addr_t paddr; 32 + 33 + /* GPU mapping */ 34 + u32 iova; 35 + struct drm_mm_node vram_node; /* only used on MMUv2 */ 36 + 37 + /* allocation management */ 38 + struct mutex lock; 39 + DECLARE_BITMAP(granule_map, SUBALLOC_GRANULES); 40 + int free_space; 41 + wait_queue_head_t free_event; 42 + }; 43 + 44 + struct etnaviv_cmdbuf_suballoc * 45 + etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu) 46 + { 47 + struct etnaviv_cmdbuf_suballoc *suballoc; 48 + int ret; 49 + 50 + suballoc = kzalloc(sizeof(*suballoc), GFP_KERNEL); 51 + if (!suballoc) 52 + return ERR_PTR(-ENOMEM); 53 + 54 + suballoc->gpu = gpu; 55 + mutex_init(&suballoc->lock); 56 + init_waitqueue_head(&suballoc->free_event); 57 + 58 + suballoc->vaddr = dma_alloc_wc(gpu->dev, SUBALLOC_SIZE, 59 + &suballoc->paddr, GFP_KERNEL); 60 + if (!suballoc->vaddr) 61 + goto free_suballoc; 62 + 63 + ret = etnaviv_iommu_get_suballoc_va(gpu, suballoc->paddr, 64 + &suballoc->vram_node, SUBALLOC_SIZE, 65 + &suballoc->iova); 66 + if (ret) 67 + goto free_dma; 68 + 69 + return suballoc; 70 + 71 + free_dma: 72 + dma_free_wc(gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, suballoc->paddr); 73 + free_suballoc: 74 + kfree(suballoc); 75 + 76 + return NULL; 77 + } 78 + 79 + void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc) 80 + { 81 + etnaviv_iommu_put_suballoc_va(suballoc->gpu, &suballoc->vram_node, 82 + SUBALLOC_SIZE, suballoc->iova); 83 + dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, 84 + suballoc->paddr); 85 + kfree(suballoc); 86 + } 87 + 88 + struct etnaviv_cmdbuf * 89 + etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size, 90 + size_t nr_bos) 91 + { 92 + struct etnaviv_cmdbuf *cmdbuf; 93 + size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]), 94 + sizeof(*cmdbuf)); 95 + int granule_offs, order, ret; 96 + 97 + cmdbuf = kzalloc(sz, GFP_KERNEL); 98 + if (!cmdbuf) 99 + return NULL; 100 + 101 + cmdbuf->suballoc = suballoc; 102 + cmdbuf->size = size; 103 + 104 + order = order_base_2(ALIGN(size, SUBALLOC_GRANULE) / SUBALLOC_GRANULE); 105 + retry: 106 + mutex_lock(&suballoc->lock); 107 + granule_offs = bitmap_find_free_region(suballoc->granule_map, 108 + SUBALLOC_GRANULES, order); 109 + if (granule_offs < 0) { 110 + suballoc->free_space = 0; 111 + mutex_unlock(&suballoc->lock); 112 + ret = wait_event_interruptible_timeout(suballoc->free_event, 113 + suballoc->free_space, 114 + msecs_to_jiffies(10 * 1000)); 115 + if (!ret) { 116 + dev_err(suballoc->gpu->dev, 117 + "Timeout waiting for cmdbuf space\n"); 118 + return NULL; 119 + } 120 + goto retry; 121 + } 122 + mutex_unlock(&suballoc->lock); 123 + cmdbuf->suballoc_offset = granule_offs * SUBALLOC_GRANULE; 124 + cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset; 125 + 126 + return cmdbuf; 127 + } 128 + 129 + void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf) 130 + { 131 + struct etnaviv_cmdbuf_suballoc *suballoc = cmdbuf->suballoc; 132 + int order = order_base_2(ALIGN(cmdbuf->size, SUBALLOC_GRANULE) / 133 + SUBALLOC_GRANULE); 134 + 135 + mutex_lock(&suballoc->lock); 136 + bitmap_release_region(suballoc->granule_map, 137 + cmdbuf->suballoc_offset / SUBALLOC_GRANULE, 138 + order); 139 + suballoc->free_space = 1; 140 + mutex_unlock(&suballoc->lock); 141 + wake_up_all(&suballoc->free_event); 142 + kfree(cmdbuf); 143 + } 144 + 145 + u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf) 146 + { 147 + return buf->suballoc->iova + buf->suballoc_offset; 148 + } 149 + 150 + dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf) 151 + { 152 + return buf->suballoc->paddr + buf->suballoc_offset; 153 + }
+58
drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h
··· 1 + /* 2 + * Copyright (C) 2017 Etnaviv Project 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License version 2 as published by 6 + * the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + 17 + #ifndef __ETNAVIV_CMDBUF_H__ 18 + #define __ETNAVIV_CMDBUF_H__ 19 + 20 + #include <linux/types.h> 21 + 22 + struct etnaviv_gpu; 23 + struct etnaviv_cmdbuf_suballoc; 24 + 25 + struct etnaviv_cmdbuf { 26 + /* suballocator this cmdbuf is allocated from */ 27 + struct etnaviv_cmdbuf_suballoc *suballoc; 28 + /* user context key, must be unique between all active users */ 29 + struct etnaviv_file_private *ctx; 30 + /* cmdbuf properties */ 31 + int suballoc_offset; 32 + void *vaddr; 33 + u32 size; 34 + u32 user_size; 35 + /* fence after which this buffer is to be disposed */ 36 + struct dma_fence *fence; 37 + /* target exec state */ 38 + u32 exec_state; 39 + /* per GPU in-flight list */ 40 + struct list_head node; 41 + /* BOs attached to this command buffer */ 42 + unsigned int nr_bos; 43 + struct etnaviv_vram_mapping *bo_map[0]; 44 + }; 45 + 46 + struct etnaviv_cmdbuf_suballoc * 47 + etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu); 48 + void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc); 49 + 50 + struct etnaviv_cmdbuf * 51 + etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size, 52 + size_t nr_bos); 53 + void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf); 54 + 55 + u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf); 56 + dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf); 57 + 58 + #endif /* __ETNAVIV_CMDBUF_H__ */
+3 -2
drivers/gpu/drm/etnaviv/etnaviv_drv.c
··· 18 18 #include <linux/of_platform.h> 19 19 #include <drm/drm_of.h> 20 20 21 + #include "etnaviv_cmdbuf.h" 21 22 #include "etnaviv_drv.h" 22 23 #include "etnaviv_gpu.h" 23 24 #include "etnaviv_gem.h" 24 25 #include "etnaviv_mmu.h" 25 - #include "etnaviv_gem.h" 26 26 27 27 #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING 28 28 static bool reglog; ··· 177 177 u32 i; 178 178 179 179 seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n", 180 - buf->vaddr, (u64)buf->paddr, size - buf->user_size); 180 + buf->vaddr, (u64)etnaviv_cmdbuf_get_pa(buf), 181 + size - buf->user_size); 181 182 182 183 for (i = 0; i < size / 4; i++) { 183 184 if (i && !(i % 4))
+3 -3
drivers/gpu/drm/etnaviv/etnaviv_dump.c
··· 15 15 */ 16 16 17 17 #include <linux/devcoredump.h> 18 + #include "etnaviv_cmdbuf.h" 18 19 #include "etnaviv_dump.h" 19 20 #include "etnaviv_gem.h" 20 21 #include "etnaviv_gpu.h" ··· 178 177 etnaviv_core_dump_mmu(&iter, gpu, mmu_size); 179 178 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr, 180 179 gpu->buffer->size, 181 - etnaviv_iommu_get_cmdbuf_va(gpu, gpu->buffer)); 180 + etnaviv_cmdbuf_get_va(gpu->buffer)); 182 181 183 182 list_for_each_entry(cmd, &gpu->active_cmd_list, node) 184 183 etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr, 185 - cmd->size, 186 - etnaviv_iommu_get_cmdbuf_va(gpu, cmd)); 184 + cmd->size, etnaviv_cmdbuf_get_va(cmd)); 187 185 188 186 /* Reserve space for the bomap */ 189 187 if (n_bomap_pages) {
+5 -3
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
··· 15 15 */ 16 16 17 17 #include <linux/reservation.h> 18 + #include "etnaviv_cmdbuf.h" 18 19 #include "etnaviv_drv.h" 19 20 #include "etnaviv_gpu.h" 20 21 #include "etnaviv_gem.h" ··· 333 332 bos = drm_malloc_ab(args->nr_bos, sizeof(*bos)); 334 333 relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs)); 335 334 stream = drm_malloc_ab(1, args->stream_size); 336 - cmdbuf = etnaviv_gpu_cmdbuf_new(gpu, ALIGN(args->stream_size, 8) + 8, 337 - args->nr_bos); 335 + cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, 336 + ALIGN(args->stream_size, 8) + 8, 337 + args->nr_bos); 338 338 if (!bos || !relocs || !stream || !cmdbuf) { 339 339 ret = -ENOMEM; 340 340 goto err_submit_cmds; ··· 424 422 err_submit_cmds: 425 423 /* if we still own the cmdbuf */ 426 424 if (cmdbuf) 427 - etnaviv_gpu_cmdbuf_free(cmdbuf); 425 + etnaviv_cmdbuf_free(cmdbuf); 428 426 if (stream) 429 427 drm_free_large(stream); 430 428 if (bos)
+54 -41
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
··· 18 18 #include <linux/dma-fence.h> 19 19 #include <linux/moduleparam.h> 20 20 #include <linux/of_device.h> 21 + 22 + #include "etnaviv_cmdbuf.h" 21 23 #include "etnaviv_dump.h" 22 24 #include "etnaviv_gpu.h" 23 25 #include "etnaviv_gem.h" ··· 548 546 VIVS_FE_COMMAND_CONTROL_PREFETCH(prefetch)); 549 547 } 550 548 549 + static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu) 550 + { 551 + /* 552 + * Base value for VIVS_PM_PULSE_EATER register on models where it 553 + * cannot be read, extracted from vivante kernel driver. 554 + */ 555 + u32 pulse_eater = 0x01590880; 556 + 557 + if (etnaviv_is_model_rev(gpu, GC4000, 0x5208) || 558 + etnaviv_is_model_rev(gpu, GC4000, 0x5222)) { 559 + pulse_eater |= BIT(23); 560 + 561 + } 562 + 563 + if (etnaviv_is_model_rev(gpu, GC1000, 0x5039) || 564 + etnaviv_is_model_rev(gpu, GC1000, 0x5040)) { 565 + pulse_eater &= ~BIT(16); 566 + pulse_eater |= BIT(17); 567 + } 568 + 569 + if ((gpu->identity.revision > 0x5420) && 570 + (gpu->identity.features & chipFeatures_PIPE_3D)) 571 + { 572 + /* Performance fix: disable internal DFS */ 573 + pulse_eater = gpu_read(gpu, VIVS_PM_PULSE_EATER); 574 + pulse_eater |= BIT(18); 575 + } 576 + 577 + gpu_write(gpu, VIVS_PM_PULSE_EATER, pulse_eater); 578 + } 579 + 551 580 static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu) 552 581 { 553 582 u16 prefetch; ··· 619 586 gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config); 620 587 } 621 588 589 + /* setup the pulse eater */ 590 + etnaviv_gpu_setup_pulse_eater(gpu); 591 + 622 592 /* setup the MMU */ 623 593 etnaviv_iommu_restore(gpu); 624 594 ··· 629 593 prefetch = etnaviv_buffer_init(gpu); 630 594 631 595 gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U); 632 - etnaviv_gpu_start_fe(gpu, etnaviv_iommu_get_cmdbuf_va(gpu, gpu->buffer), 596 + etnaviv_gpu_start_fe(gpu, etnaviv_cmdbuf_get_va(gpu->buffer), 633 597 prefetch); 634 598 } 635 599 ··· 694 658 goto fail; 695 659 } 696 660 661 + gpu->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(gpu); 662 + if (IS_ERR(gpu->cmdbuf_suballoc)) { 663 + dev_err(gpu->dev, "Failed to create cmdbuf suballocator\n"); 664 + ret = PTR_ERR(gpu->cmdbuf_suballoc); 665 + goto fail; 666 + } 667 + 697 668 /* Create buffer: */ 698 - gpu->buffer = etnaviv_gpu_cmdbuf_new(gpu, PAGE_SIZE, 0); 669 + gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0); 699 670 if (!gpu->buffer) { 700 671 ret = -ENOMEM; 701 672 dev_err(gpu->dev, "could not create command buffer\n"); ··· 710 667 } 711 668 712 669 if (gpu->mmu->version == ETNAVIV_IOMMU_V1 && 713 - gpu->buffer->paddr - gpu->memory_base > 0x80000000) { 670 + etnaviv_cmdbuf_get_va(gpu->buffer) > 0x80000000) { 714 671 ret = -EINVAL; 715 672 dev_err(gpu->dev, 716 673 "command buffer outside valid memory window\n"); ··· 737 694 return 0; 738 695 739 696 free_buffer: 740 - etnaviv_gpu_cmdbuf_free(gpu->buffer); 697 + etnaviv_cmdbuf_free(gpu->buffer); 741 698 gpu->buffer = NULL; 742 699 destroy_iommu: 743 700 etnaviv_iommu_destroy(gpu->mmu); ··· 1160 1117 * Cmdstream submission/retirement: 1161 1118 */ 1162 1119 1163 - struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, u32 size, 1164 - size_t nr_bos) 1165 - { 1166 - struct etnaviv_cmdbuf *cmdbuf; 1167 - size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]), 1168 - sizeof(*cmdbuf)); 1169 - 1170 - cmdbuf = kzalloc(sz, GFP_KERNEL); 1171 - if (!cmdbuf) 1172 - return NULL; 1173 - 1174 - if (gpu->mmu->version == ETNAVIV_IOMMU_V2) 1175 - size = ALIGN(size, SZ_4K); 1176 - 1177 - cmdbuf->vaddr = dma_alloc_wc(gpu->dev, size, &cmdbuf->paddr, 1178 - GFP_KERNEL); 1179 - if (!cmdbuf->vaddr) { 1180 - kfree(cmdbuf); 1181 - return NULL; 1182 - } 1183 - 1184 - cmdbuf->gpu = gpu; 1185 - cmdbuf->size = size; 1186 - 1187 - return cmdbuf; 1188 - } 1189 - 1190 - void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf) 1191 - { 1192 - etnaviv_iommu_put_cmdbuf_va(cmdbuf->gpu, cmdbuf); 1193 - dma_free_wc(cmdbuf->gpu->dev, cmdbuf->size, cmdbuf->vaddr, 1194 - cmdbuf->paddr); 1195 - kfree(cmdbuf); 1196 - } 1197 - 1198 1120 static void retire_worker(struct work_struct *work) 1199 1121 { 1200 1122 struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, ··· 1185 1177 etnaviv_gem_mapping_unreference(mapping); 1186 1178 } 1187 1179 1188 - etnaviv_gpu_cmdbuf_free(cmdbuf); 1180 + etnaviv_cmdbuf_free(cmdbuf); 1189 1181 /* 1190 1182 * We need to balance the runtime PM count caused by 1191 1183 * each submission. Upon submission, we increment ··· 1601 1593 #endif 1602 1594 1603 1595 if (gpu->buffer) { 1604 - etnaviv_gpu_cmdbuf_free(gpu->buffer); 1596 + etnaviv_cmdbuf_free(gpu->buffer); 1605 1597 gpu->buffer = NULL; 1598 + } 1599 + 1600 + if (gpu->cmdbuf_suballoc) { 1601 + etnaviv_cmdbuf_suballoc_destroy(gpu->cmdbuf_suballoc); 1602 + gpu->cmdbuf_suballoc = NULL; 1606 1603 } 1607 1604 1608 1605 if (gpu->mmu) {
+2 -26
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
··· 92 92 struct dma_fence *fence; 93 93 }; 94 94 95 + struct etnaviv_cmdbuf_suballoc; 95 96 struct etnaviv_cmdbuf; 96 97 97 98 struct etnaviv_gpu { ··· 136 135 int irq; 137 136 138 137 struct etnaviv_iommu *mmu; 138 + struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc; 139 139 140 140 /* Power Control: */ 141 141 struct clk *clk_bus; ··· 150 148 u32 hangcheck_fence; 151 149 u32 hangcheck_dma_addr; 152 150 struct work_struct recover_work; 153 - }; 154 - 155 - struct etnaviv_cmdbuf { 156 - /* device this cmdbuf is allocated for */ 157 - struct etnaviv_gpu *gpu; 158 - /* user context key, must be unique between all active users */ 159 - struct etnaviv_file_private *ctx; 160 - /* cmdbuf properties */ 161 - void *vaddr; 162 - dma_addr_t paddr; 163 - u32 size; 164 - u32 user_size; 165 - /* vram node used if the cmdbuf is mapped through the MMUv2 */ 166 - struct drm_mm_node vram_node; 167 - /* fence after which this buffer is to be disposed */ 168 - struct dma_fence *fence; 169 - /* target exec state */ 170 - u32 exec_state; 171 - /* per GPU in-flight list */ 172 - struct list_head node; 173 - /* BOs attached to this command buffer */ 174 - unsigned int nr_bos; 175 - struct etnaviv_vram_mapping *bo_map[0]; 176 151 }; 177 152 178 153 static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data) ··· 190 211 struct etnaviv_gem_object *etnaviv_obj, struct timespec *timeout); 191 212 int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, 192 213 struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf); 193 - struct etnaviv_cmdbuf *etnaviv_gpu_cmdbuf_new(struct etnaviv_gpu *gpu, 194 - u32 size, size_t nr_bos); 195 - void etnaviv_gpu_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf); 196 214 int etnaviv_gpu_pm_get_sync(struct etnaviv_gpu *gpu); 197 215 void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu); 198 216 int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms);
+1 -1
drivers/gpu/drm/etnaviv/etnaviv_iommu.c
··· 184 184 memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE); 185 185 } 186 186 187 - static struct etnaviv_iommu_ops etnaviv_iommu_ops = { 187 + static const struct etnaviv_iommu_ops etnaviv_iommu_ops = { 188 188 .ops = { 189 189 .domain_free = etnaviv_domain_free, 190 190 .map = etnaviv_iommuv1_map,
+4 -2
drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
··· 21 21 #include <linux/dma-mapping.h> 22 22 #include <linux/bitops.h> 23 23 24 + #include "etnaviv_cmdbuf.h" 24 25 #include "etnaviv_gpu.h" 25 26 #include "etnaviv_mmu.h" 26 27 #include "etnaviv_iommu.h" ··· 230 229 memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K); 231 230 } 232 231 233 - static struct etnaviv_iommu_ops etnaviv_iommu_ops = { 232 + static const struct etnaviv_iommu_ops etnaviv_iommu_ops = { 234 233 .ops = { 235 234 .domain_free = etnaviv_iommuv2_domain_free, 236 235 .map = etnaviv_iommuv2_map, ··· 255 254 prefetch = etnaviv_buffer_config_mmuv2(gpu, 256 255 (u32)etnaviv_domain->mtlb_dma, 257 256 (u32)etnaviv_domain->bad_page_dma); 258 - etnaviv_gpu_start_fe(gpu, gpu->buffer->paddr, prefetch); 257 + etnaviv_gpu_start_fe(gpu, (u32)etnaviv_cmdbuf_get_pa(gpu->buffer), 258 + prefetch); 259 259 etnaviv_gpu_wait_idle(gpu, 100); 260 260 261 261 gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);
+25 -35
drivers/gpu/drm/etnaviv/etnaviv_mmu.c
··· 15 15 */ 16 16 17 17 #include "common.xml.h" 18 + #include "etnaviv_cmdbuf.h" 18 19 #include "etnaviv_drv.h" 19 20 #include "etnaviv_gem.h" 20 21 #include "etnaviv_gpu.h" ··· 118 117 struct list_head list; 119 118 bool found; 120 119 121 - /* 122 - * XXX: The DRM_MM_SEARCH_BELOW is really a hack to trick 123 - * drm_mm into giving out a low IOVA after address space 124 - * rollover. This needs a proper fix. 125 - */ 126 120 ret = drm_mm_insert_node_in_range(&mmu->mm, node, 127 121 size, 0, mmu->last_iova, ~0UL, 128 - mmu->last_iova ? DRM_MM_SEARCH_DEFAULT : DRM_MM_SEARCH_BELOW); 122 + DRM_MM_SEARCH_DEFAULT); 129 123 130 124 if (ret != -ENOSPC) 131 125 break; ··· 190 194 191 195 /* 192 196 * We removed enough mappings so that the new allocation will 193 - * succeed. Ensure that the MMU will be flushed before the 194 - * associated commit requesting this mapping, and retry the 195 - * allocation one more time. 197 + * succeed, retry the allocation one more time. 196 198 */ 197 - mmu->need_flush = true; 198 199 } 199 200 200 201 return ret; ··· 243 250 } 244 251 245 252 list_add_tail(&mapping->mmu_node, &mmu->mappings); 253 + mmu->need_flush = true; 246 254 mutex_unlock(&mmu->lock); 247 255 248 256 return ret; ··· 261 267 etnaviv_iommu_remove_mapping(mmu, mapping); 262 268 263 269 list_del(&mapping->mmu_node); 270 + mmu->need_flush = true; 264 271 mutex_unlock(&mmu->lock); 265 272 } 266 273 ··· 317 322 etnaviv_iommuv2_restore(gpu); 318 323 } 319 324 320 - u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, 321 - struct etnaviv_cmdbuf *buf) 325 + int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr, 326 + struct drm_mm_node *vram_node, size_t size, 327 + u32 *iova) 322 328 { 323 329 struct etnaviv_iommu *mmu = gpu->mmu; 324 330 325 331 if (mmu->version == ETNAVIV_IOMMU_V1) { 326 - return buf->paddr - gpu->memory_base; 332 + *iova = paddr - gpu->memory_base; 333 + return 0; 327 334 } else { 328 335 int ret; 329 336 330 - if (buf->vram_node.allocated) 331 - return (u32)buf->vram_node.start; 332 - 333 337 mutex_lock(&mmu->lock); 334 - ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, 335 - buf->size + SZ_64K); 338 + ret = etnaviv_iommu_find_iova(mmu, vram_node, size); 336 339 if (ret < 0) { 337 340 mutex_unlock(&mmu->lock); 338 - return 0; 341 + return ret; 339 342 } 340 - ret = iommu_map(mmu->domain, buf->vram_node.start, buf->paddr, 341 - buf->size, IOMMU_READ); 343 + ret = iommu_map(mmu->domain, vram_node->start, paddr, size, 344 + IOMMU_READ); 342 345 if (ret < 0) { 343 - drm_mm_remove_node(&buf->vram_node); 346 + drm_mm_remove_node(vram_node); 344 347 mutex_unlock(&mmu->lock); 345 - return 0; 348 + return ret; 346 349 } 347 - /* 348 - * At least on GC3000 the FE MMU doesn't properly flush old TLB 349 - * entries. Make sure to space the command buffers out in a way 350 - * that the FE MMU prefetch won't load invalid entries. 351 - */ 352 - mmu->last_iova = buf->vram_node.start + buf->size + SZ_64K; 350 + mmu->last_iova = vram_node->start + size; 353 351 gpu->mmu->need_flush = true; 354 352 mutex_unlock(&mmu->lock); 355 353 356 - return (u32)buf->vram_node.start; 354 + *iova = (u32)vram_node->start; 355 + return 0; 357 356 } 358 357 } 359 358 360 - void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu, 361 - struct etnaviv_cmdbuf *buf) 359 + void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu, 360 + struct drm_mm_node *vram_node, size_t size, 361 + u32 iova) 362 362 { 363 363 struct etnaviv_iommu *mmu = gpu->mmu; 364 364 365 - if (mmu->version == ETNAVIV_IOMMU_V2 && buf->vram_node.allocated) { 365 + if (mmu->version == ETNAVIV_IOMMU_V2) { 366 366 mutex_lock(&mmu->lock); 367 - iommu_unmap(mmu->domain, buf->vram_node.start, buf->size); 368 - drm_mm_remove_node(&buf->vram_node); 367 + iommu_unmap(mmu->domain,iova, size); 368 + drm_mm_remove_node(vram_node); 369 369 mutex_unlock(&mmu->lock); 370 370 } 371 371 }
+6 -4
drivers/gpu/drm/etnaviv/etnaviv_mmu.h
··· 62 62 struct etnaviv_vram_mapping *mapping); 63 63 void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu); 64 64 65 - u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, 66 - struct etnaviv_cmdbuf *buf); 67 - void etnaviv_iommu_put_cmdbuf_va(struct etnaviv_gpu *gpu, 68 - struct etnaviv_cmdbuf *buf); 65 + int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr, 66 + struct drm_mm_node *vram_node, size_t size, 67 + u32 *iova); 68 + void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu, 69 + struct drm_mm_node *vram_node, size_t size, 70 + u32 iova); 69 71 70 72 size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu); 71 73 void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf);