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

Merge tag 'drm-msm-fixes-2020-09-04' of https://gitlab.freedesktop.org/drm/msm into drm-fixes

A few fixes for a potential RPTR corruption issue.

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ <CAF6AEGvnr6Nhz2J0sjv2G+j7iceVtaDiJDT8T88uW6jiBfOGKQ@mail.gmail.com

+85 -37
+5
drivers/gpu/drm/msm/adreno/a2xx_gpu.c
··· 164 164 if (ret) 165 165 return ret; 166 166 167 + gpu_write(gpu, REG_AXXX_CP_RB_CNTL, 168 + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 169 + 170 + gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); 171 + 167 172 /* NOTE: PM4/micro-engine firmware registers look to be the same 168 173 * for a2xx and a3xx.. we could possibly push that part down to 169 174 * adreno_gpu base class. Or push both PM4 and PFP but
+10
drivers/gpu/drm/msm/adreno/a3xx_gpu.c
··· 211 211 if (ret) 212 212 return ret; 213 213 214 + /* 215 + * Use the default ringbuffer size and block size but disable the RPTR 216 + * shadow 217 + */ 218 + gpu_write(gpu, REG_AXXX_CP_RB_CNTL, 219 + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 220 + 221 + /* Set the ringbuffer address */ 222 + gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); 223 + 214 224 /* setup access protection: */ 215 225 gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007); 216 226
+10
drivers/gpu/drm/msm/adreno/a4xx_gpu.c
··· 267 267 if (ret) 268 268 return ret; 269 269 270 + /* 271 + * Use the default ringbuffer size and block size but disable the RPTR 272 + * shadow 273 + */ 274 + gpu_write(gpu, REG_A4XX_CP_RB_CNTL, 275 + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 276 + 277 + /* Set the ringbuffer address */ 278 + gpu_write(gpu, REG_A4XX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); 279 + 270 280 /* Load PM4: */ 271 281 ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data); 272 282 len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
+11 -3
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
··· 703 703 if (ret) 704 704 return ret; 705 705 706 - a5xx_preempt_hw_init(gpu); 707 - 708 706 if (!adreno_is_a510(adreno_gpu)) 709 707 a5xx_gpmu_ucode_init(gpu); 710 708 711 709 ret = a5xx_ucode_init(gpu); 712 710 if (ret) 713 711 return ret; 712 + 713 + /* Set the ringbuffer address */ 714 + gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI, 715 + gpu->rb[0]->iova); 716 + 717 + gpu_write(gpu, REG_A5XX_CP_RB_CNTL, 718 + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 719 + 720 + a5xx_preempt_hw_init(gpu); 714 721 715 722 /* Disable the interrupts through the initial bringup stage */ 716 723 gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK); ··· 1518 1511 1519 1512 check_speed_bin(&pdev->dev); 1520 1513 1521 - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4); 1514 + /* Restricting nr_rings to 1 to temporarily disable preemption */ 1515 + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 1522 1516 if (ret) { 1523 1517 a5xx_destroy(&(a5xx_gpu->base.base)); 1524 1518 return ERR_PTR(ret);
+1
drivers/gpu/drm/msm/adreno/a5xx_gpu.h
··· 31 31 struct msm_ringbuffer *next_ring; 32 32 33 33 struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS]; 34 + struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS]; 34 35 struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS]; 35 36 uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; 36 37
+20 -5
drivers/gpu/drm/msm/adreno/a5xx_preempt.c
··· 226 226 struct adreno_gpu *adreno_gpu = &a5xx_gpu->base; 227 227 struct msm_gpu *gpu = &adreno_gpu->base; 228 228 struct a5xx_preempt_record *ptr; 229 - struct drm_gem_object *bo = NULL; 230 - u64 iova = 0; 229 + void *counters; 230 + struct drm_gem_object *bo = NULL, *counters_bo = NULL; 231 + u64 iova = 0, counters_iova = 0; 231 232 232 233 ptr = msm_gem_kernel_new(gpu->dev, 233 234 A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE, 234 - MSM_BO_UNCACHED, gpu->aspace, &bo, &iova); 235 + MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova); 235 236 236 237 if (IS_ERR(ptr)) 237 238 return PTR_ERR(ptr); 238 239 240 + /* The buffer to store counters needs to be unprivileged */ 241 + counters = msm_gem_kernel_new(gpu->dev, 242 + A5XX_PREEMPT_COUNTER_SIZE, 243 + MSM_BO_UNCACHED, gpu->aspace, &counters_bo, &counters_iova); 244 + if (IS_ERR(counters)) { 245 + msm_gem_kernel_put(bo, gpu->aspace, true); 246 + return PTR_ERR(counters); 247 + } 248 + 239 249 msm_gem_object_set_name(bo, "preempt"); 250 + msm_gem_object_set_name(counters_bo, "preempt_counters"); 240 251 241 252 a5xx_gpu->preempt_bo[ring->id] = bo; 253 + a5xx_gpu->preempt_counters_bo[ring->id] = counters_bo; 242 254 a5xx_gpu->preempt_iova[ring->id] = iova; 243 255 a5xx_gpu->preempt[ring->id] = ptr; 244 256 ··· 261 249 ptr->data = 0; 262 250 ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT; 263 251 ptr->rptr_addr = rbmemptr(ring, rptr); 264 - ptr->counter = iova + A5XX_PREEMPT_RECORD_SIZE; 252 + ptr->counter = counters_iova; 265 253 266 254 return 0; 267 255 } ··· 272 260 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); 273 261 int i; 274 262 275 - for (i = 0; i < gpu->nr_rings; i++) 263 + for (i = 0; i < gpu->nr_rings; i++) { 276 264 msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace, true); 265 + msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i], 266 + gpu->aspace, true); 267 + } 277 268 } 278 269 279 270 void a5xx_preempt_init(struct msm_gpu *gpu)
+12 -1
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
··· 678 678 A6XX_PROTECT_RDONLY(0x980, 0x4)); 679 679 gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0)); 680 680 681 - if (adreno_is_a650(adreno_gpu)) { 681 + /* Enable expanded apriv for targets that support it */ 682 + if (gpu->hw_apriv) { 682 683 gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, 683 684 (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1)); 684 685 } ··· 694 693 ret = a6xx_ucode_init(gpu); 695 694 if (ret) 696 695 goto out; 696 + 697 + /* Set the ringbuffer address */ 698 + gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI, 699 + gpu->rb[0]->iova); 700 + 701 + gpu_write(gpu, REG_A6XX_CP_RB_CNTL, 702 + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); 697 703 698 704 /* Always come up on rb 0 */ 699 705 a6xx_gpu->cur_ring = gpu->rb[0]; ··· 1063 1055 1064 1056 adreno_gpu->registers = NULL; 1065 1057 adreno_gpu->reg_offsets = a6xx_register_offsets; 1058 + 1059 + if (adreno_is_a650(adreno_gpu)) 1060 + adreno_gpu->base.hw_apriv = true; 1066 1061 1067 1062 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); 1068 1063 if (ret) {
+2 -25
drivers/gpu/drm/msm/adreno/adreno_gpu.c
··· 400 400 ring->memptrs->rptr = 0; 401 401 } 402 402 403 - /* 404 - * Setup REG_CP_RB_CNTL. The same value is used across targets (with 405 - * the excpetion of A430 that disables the RPTR shadow) - the cacluation 406 - * for the ringbuffer size and block size is moved to msm_gpu.h for the 407 - * pre-processor to deal with and the A430 variant is ORed in here 408 - */ 409 - adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_CNTL, 410 - MSM_GPU_RB_CNTL_DEFAULT | 411 - (adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0)); 412 - 413 - /* Setup ringbuffer address - use ringbuffer[0] for GPU init */ 414 - adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE, 415 - REG_ADRENO_CP_RB_BASE_HI, gpu->rb[0]->iova); 416 - 417 - if (!adreno_is_a430(adreno_gpu)) { 418 - adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR, 419 - REG_ADRENO_CP_RB_RPTR_ADDR_HI, 420 - rbmemptr(gpu->rb[0], rptr)); 421 - } 422 - 423 403 return 0; 424 404 } 425 405 ··· 407 427 static uint32_t get_rptr(struct adreno_gpu *adreno_gpu, 408 428 struct msm_ringbuffer *ring) 409 429 { 410 - if (adreno_is_a430(adreno_gpu)) 411 - return ring->memptrs->rptr = adreno_gpu_read( 412 - adreno_gpu, REG_ADRENO_CP_RB_RPTR); 413 - else 414 - return ring->memptrs->rptr; 430 + return ring->memptrs->rptr = adreno_gpu_read( 431 + adreno_gpu, REG_ADRENO_CP_RB_RPTR); 415 432 } 416 433 417 434 struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu)
+1 -1
drivers/gpu/drm/msm/msm_gpu.c
··· 908 908 909 909 memptrs = msm_gem_kernel_new(drm, 910 910 sizeof(struct msm_rbmemptrs) * nr_rings, 911 - MSM_BO_UNCACHED, gpu->aspace, &gpu->memptrs_bo, 911 + check_apriv(gpu, MSM_BO_UNCACHED), gpu->aspace, &gpu->memptrs_bo, 912 912 &memptrs_iova); 913 913 914 914 if (IS_ERR(memptrs)) {
+11
drivers/gpu/drm/msm/msm_gpu.h
··· 15 15 #include "msm_drv.h" 16 16 #include "msm_fence.h" 17 17 #include "msm_ringbuffer.h" 18 + #include "msm_gem.h" 18 19 19 20 struct msm_gem_submit; 20 21 struct msm_gpu_perfcntr; ··· 140 139 } devfreq; 141 140 142 141 struct msm_gpu_state *crashstate; 142 + /* True if the hardware supports expanded apriv (a650 and newer) */ 143 + bool hw_apriv; 143 144 }; 144 145 145 146 /* It turns out that all targets use the same ringbuffer size */ ··· 329 326 330 327 mutex_unlock(&gpu->dev->struct_mutex); 331 328 } 329 + 330 + /* 331 + * Simple macro to semi-cleanly add the MAP_PRIV flag for targets that can 332 + * support expanded privileges 333 + */ 334 + #define check_apriv(gpu, flags) \ 335 + (((gpu)->hw_apriv ? MSM_BO_MAP_PRIV : 0) | (flags)) 336 + 332 337 333 338 #endif /* __MSM_GPU_H__ */
+2 -2
drivers/gpu/drm/msm/msm_ringbuffer.c
··· 27 27 ring->id = id; 28 28 29 29 ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ, 30 - MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &ring->bo, 31 - &ring->iova); 30 + check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY), 31 + gpu->aspace, &ring->bo, &ring->iova); 32 32 33 33 if (IS_ERR(ring->start)) { 34 34 ret = PTR_ERR(ring->start);