@@ -51,9 +51,20 @@ bool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
5151
5252static void a6xx_flush (struct msm_gpu * gpu , struct msm_ringbuffer * ring )
5353{
54+ struct adreno_gpu * adreno_gpu = to_adreno_gpu (gpu );
55+ struct a6xx_gpu * a6xx_gpu = to_a6xx_gpu (adreno_gpu );
5456 uint32_t wptr ;
5557 unsigned long flags ;
5658
59+ /* Expanded APRIV doesn't need to issue the WHERE_AM_I opcode */
60+ if (a6xx_gpu -> has_whereami && !adreno_gpu -> base .hw_apriv ) {
61+ struct a6xx_gpu * a6xx_gpu = to_a6xx_gpu (adreno_gpu );
62+
63+ OUT_PKT7 (ring , CP_WHERE_AM_I , 2 );
64+ OUT_RING (ring , lower_32_bits (shadowptr (a6xx_gpu , ring )));
65+ OUT_RING (ring , upper_32_bits (shadowptr (a6xx_gpu , ring )));
66+ }
67+
5768 spin_lock_irqsave (& ring -> lock , flags );
5869
5970 /* Copy the shadow to the actual register */
@@ -508,6 +519,30 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
508519 return a6xx_idle (gpu , ring ) ? 0 : - EINVAL ;
509520}
510521
522+ static void a6xx_ucode_check_version (struct a6xx_gpu * a6xx_gpu ,
523+ struct drm_gem_object * obj )
524+ {
525+ u32 * buf = msm_gem_get_vaddr_active (obj );
526+
527+ if (IS_ERR (buf ))
528+ return ;
529+
530+ /*
531+ * If the lowest nibble is 0xa that is an indication that this microcode
532+ * has been patched. The actual version is in dword [3] but we only care
533+ * about the patchlevel which is the lowest nibble of dword [3]
534+ *
535+ * Otherwise check that the firmware is greater than or equal to 1.90
536+ * which was the first version that had this fix built in
537+ */
538+ if (((buf [0 ] & 0xf ) == 0xa ) && (buf [2 ] & 0xf ) >= 1 )
539+ a6xx_gpu -> has_whereami = true;
540+ else if ((buf [0 ] & 0xfff ) > 0x190 )
541+ a6xx_gpu -> has_whereami = true;
542+
543+ msm_gem_put_vaddr (obj );
544+ }
545+
511546static int a6xx_ucode_init (struct msm_gpu * gpu )
512547{
513548 struct adreno_gpu * adreno_gpu = to_adreno_gpu (gpu );
@@ -528,6 +563,7 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
528563 }
529564
530565 msm_gem_object_set_name (a6xx_gpu -> sqe_bo , "sqefw" );
566+ a6xx_ucode_check_version (a6xx_gpu , a6xx_gpu -> sqe_bo );
531567 }
532568
533569 gpu_write64 (gpu , REG_A6XX_CP_SQE_INSTR_BASE_LO ,
@@ -743,8 +779,37 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
743779 gpu_write64 (gpu , REG_A6XX_CP_RB_BASE , REG_A6XX_CP_RB_BASE_HI ,
744780 gpu -> rb [0 ]-> iova );
745781
746- gpu_write (gpu , REG_A6XX_CP_RB_CNTL ,
747- MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE );
782+ /* Targets that support extended APRIV can use the RPTR shadow from
783+ * hardware but all the other ones need to disable the feature. Targets
784+ * that support the WHERE_AM_I opcode can use that instead
785+ */
786+ if (adreno_gpu -> base .hw_apriv )
787+ gpu_write (gpu , REG_A6XX_CP_RB_CNTL , MSM_GPU_RB_CNTL_DEFAULT );
788+ else
789+ gpu_write (gpu , REG_A6XX_CP_RB_CNTL ,
790+ MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE );
791+
792+ /*
793+ * Expanded APRIV and targets that support WHERE_AM_I both need a
794+ * privileged buffer to store the RPTR shadow
795+ */
796+
797+ if (adreno_gpu -> base .hw_apriv || a6xx_gpu -> has_whereami ) {
798+ if (!a6xx_gpu -> shadow_bo ) {
799+ a6xx_gpu -> shadow = msm_gem_kernel_new_locked (gpu -> dev ,
800+ sizeof (u32 ) * gpu -> nr_rings ,
801+ MSM_BO_UNCACHED | MSM_BO_MAP_PRIV ,
802+ gpu -> aspace , & a6xx_gpu -> shadow_bo ,
803+ & a6xx_gpu -> shadow_iova );
804+
805+ if (IS_ERR (a6xx_gpu -> shadow ))
806+ return PTR_ERR (a6xx_gpu -> shadow );
807+ }
808+
809+ gpu_write64 (gpu , REG_A6XX_CP_RB_RPTR_ADDR_LO ,
810+ REG_A6XX_CP_RB_RPTR_ADDR_HI ,
811+ shadowptr (a6xx_gpu , gpu -> rb [0 ]));
812+ }
748813
749814 /* Always come up on rb 0 */
750815 a6xx_gpu -> cur_ring = gpu -> rb [0 ];
@@ -1033,6 +1098,11 @@ static void a6xx_destroy(struct msm_gpu *gpu)
10331098 drm_gem_object_put (a6xx_gpu -> sqe_bo );
10341099 }
10351100
1101+ if (a6xx_gpu -> shadow_bo ) {
1102+ msm_gem_unpin_iova (a6xx_gpu -> shadow_bo , gpu -> aspace );
1103+ drm_gem_object_put (a6xx_gpu -> shadow_bo );
1104+ }
1105+
10361106 a6xx_gmu_remove (a6xx_gpu );
10371107
10381108 adreno_gpu_cleanup (adreno_gpu );
@@ -1081,6 +1151,17 @@ a6xx_create_private_address_space(struct msm_gpu *gpu)
10811151 "gpu" , 0x100000000ULL , 0x1ffffffffULL );
10821152}
10831153
1154+ static uint32_t a6xx_get_rptr (struct msm_gpu * gpu , struct msm_ringbuffer * ring )
1155+ {
1156+ struct adreno_gpu * adreno_gpu = to_adreno_gpu (gpu );
1157+ struct a6xx_gpu * a6xx_gpu = to_a6xx_gpu (adreno_gpu );
1158+
1159+ if (adreno_gpu -> base .hw_apriv || a6xx_gpu -> has_whereami )
1160+ return a6xx_gpu -> shadow [ring -> id ];
1161+
1162+ return ring -> memptrs -> rptr = gpu_read (gpu , REG_A6XX_CP_RB_RPTR );
1163+ }
1164+
10841165static const struct adreno_gpu_funcs funcs = {
10851166 .base = {
10861167 .get_param = adreno_get_param ,
@@ -1089,7 +1170,6 @@ static const struct adreno_gpu_funcs funcs = {
10891170 .pm_resume = a6xx_pm_resume ,
10901171 .recover = a6xx_recover ,
10911172 .submit = a6xx_submit ,
1092- .flush = a6xx_flush ,
10931173 .active_ring = a6xx_active_ring ,
10941174 .irq = a6xx_irq ,
10951175 .destroy = a6xx_destroy ,
@@ -1105,6 +1185,7 @@ static const struct adreno_gpu_funcs funcs = {
11051185#endif
11061186 .create_address_space = adreno_iommu_create_address_space ,
11071187 .create_private_address_space = a6xx_create_private_address_space ,
1188+ .get_rptr = a6xx_get_rptr ,
11081189 },
11091190 .get_timestamp = a6xx_get_timestamp ,
11101191};
0 commit comments