v2: drm/msm/gpu updates for 4.21
Subsystems (4)
cover v2: drm/msm/gpu updates for 4.21
Resend of [1] with the order rearranged to put a6xx gpu state at the end and attach an add-on patch to better manage a6xx state memory.
I think everything here is good to go for 4.21 (maybe even some 4.20 fixes) but I can understand if we want to let the gpu state soak for another cycle. Sharat has been doing an excellent job of finding the bugs in it.
Jordan Crouse (10):
drm/msm: Update generated headers
drm/msm/gpu: Allocate the correct size for the GPU memptrs drm/msm: Gracefully handle failure in _msm_gem_kernel_new drm/msm/gpu: Add per-submission statistics
drm/msm/gpu: Add trace events for tracking GPU submissions drm/msm/gpu: Only store local command buffers in the GPU state drm/msm/gpu: Move gpu_poll_timeout() to adreno_gpu.h drm/msm/adreno: Don't capture register values if target doesn't define
them
drm/msm/a6xx: Add a6xx gpu state
drm/msm/a6xx: Track and manage a6xx state memory
drivers/gpu/drm/msm/Makefile | 4 +- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 5 - drivers/gpu/drm/msm/adreno/a6xx.xml.h | 54 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 45 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 3 + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 80 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 8 + drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 1171 +++++++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h | 430 +++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 19 +- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 6 + drivers/gpu/drm/msm/msm_gem.c | 18 +- drivers/gpu/drm/msm/msm_gem.h | 1 + drivers/gpu/drm/msm/msm_gem_submit.c | 15 +- drivers/gpu/drm/msm/msm_gpu.c | 49 +- drivers/gpu/drm/msm/msm_gpu_trace.h | 90 ++ drivers/gpu/drm/msm/msm_gpu_tracepoints.c | 6 + drivers/gpu/drm/msm/msm_ringbuffer.h | 16 + 18 files changed, 1921 insertions(+), 99 deletions(-) create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h create mode 100644 drivers/gpu/drm/msm/msm_gpu_trace.h create mode 100644 drivers/gpu/drm/msm/msm_gpu_tracepoints.c
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
A message that is not in the archive (sent off-list or not yet received): 20181102152526.23854-1-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
PATCH 1/10 drm/msm: Update generated headers
Resync the a6xx generated headers from the database.
--- drivers/gpu/drm/msm/adreno/a6xx.xml.h | 54 +++++++++++++++++++++------ 1 file changed, 42 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/adreno/a6xx.xml.h +42 -12
@@ -8,17 +8,17 @@ This file was generated by the rules-ng-ng headergen tool in this git repository git clone https://github.com/freedreno/envytools.git The rules-ng-ng source files this header was generated from are: -- /home/robclark/src/envytools/rnndb/adreno.xml ( 501 bytes, from 2018-07-03 19:37:13) -- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13) -- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13) -- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13) -- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37) -- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13) -- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13) -- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37) -- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42) -- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07) -- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13) +- ./adreno.xml ( 501 bytes, from 2018-10-10 15:35:49) +- ./freedreno_copyright.xml ( 1572 bytes, from 2016-10-24 21:12:27) +- ./adreno/a2xx.xml ( 37936 bytes, from 2018-10-10 15:35:49) +- ./adreno/adreno_common.xml ( 14201 bytes, from 2018-10-10 15:35:49) +- ./adreno/adreno_pm4.xml ( 42864 bytes, from 2018-10-10 15:35:49) +- ./adreno/a3xx.xml ( 83840 bytes, from 2017-12-05 18:20:27) +- ./adreno/a4xx.xml ( 112086 bytes, from 2018-10-10 15:35:49) +- ./adreno/a5xx.xml ( 147240 bytes, from 2018-10-10 15:35:49) +- ./adreno/a6xx.xml ( 140514 bytes, from 2018-10-10 15:35:49) +- ./adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-10-10 15:35:49) +- ./adreno/ocmem.xml ( 1773 bytes, from 2016-10-24 21:12:27) Copyright (C) 2013-2018 by the following authors: - Rob Clark <[email protected]> (robclark)
@@ -501,7 +501,7 @@ enum a6xx_vfd_perfcounter_select { PERF_VFDP_VS_STAGE_WAVES = 22, }; -enum a6xx_hslq_perfcounter_select { +enum a6xx_hlsq_perfcounter_select {PERF_HLSQ_BUSY_CYCLES =0 ,PERF_HLSQ_STALL_CYCLES_UCHE =1 ,PERF_HLSQ_STALL_CYCLES_SP_STATE =2 ,
@@ -2959,6 +2959,8 @@ static inline uint32_t A6XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)#define A6XX_GRAS_LRZ_CNTL_ENABLE 0x00000001#define A6XX_GRAS_LRZ_CNTL_LRZ_WRITE 0x00000002#define A6XX_GRAS_LRZ_CNTL_GREATER 0x00000004 +#define A6XX_GRAS_LRZ_CNTL_UNK3 0x00000008 +#define A6XX_GRAS_LRZ_CNTL_UNK4 0x00000010#define REG_A6XX_GRAS_UNKNOWN_8101 0x00008101
@@ -2997,6 +2999,13 @@ static inline uint32_t A6XX_GRAS_LRZ_BUFFER_PITCH_ARRAY_PITCH(uint32_t val)#define REG_A6XX_GRAS_UNKNOWN_8110 0x00008110#define REG_A6XX_GRAS_2D_BLIT_CNTL 0x00008400 +#define A6XX_GRAS_2D_BLIT_CNTL_COLOR_FORMAT__MASK 0x0000ff00 +#define A6XX_GRAS_2D_BLIT_CNTL_COLOR_FORMAT__SHIFT 8 +static inline uint32_t A6XX_GRAS_2D_BLIT_CNTL_COLOR_FORMAT (enum a6xx_color_fmt val) +{ +return ((val) <<A6XX_GRAS_2D_BLIT_CNTL_COLOR_FORMAT__SHIFT ) &A6XX_GRAS_2D_BLIT_CNTL_COLOR_FORMAT__MASK ; +} +#define A6XX_GRAS_2D_BLIT_CNTL_SCISSOR 0x00010000#define REG_A6XX_GRAS_2D_SRC_TL_X 0x00008401#define A6XX_GRAS_2D_SRC_TL_X_X__MASK 0x00ffff00
@@ -3642,6 +3651,9 @@ static inline uint32_t A6XX_RB_WINDOW_OFFSET_Y(uint32_t val)#define REG_A6XX_RB_SAMPLE_COUNT_CONTROL 0x00008891#define A6XX_RB_SAMPLE_COUNT_CONTROL_COPY 0x00000002 +#define REG_A6XX_RB_LRZ_CNTL 0x00008898 +#define A6XX_RB_LRZ_CNTL_ENABLE 0x00000001 +#define REG_A6XX_RB_UNKNOWN_88D0 0x000088d0#define REG_A6XX_RB_BLIT_SCISSOR_TL 0x000088d1
@@ -3780,6 +3792,9 @@ static inline uint32_t A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT(enum a6xx_color_fmt val {return ((val) <<A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT__SHIFT ) &A6XX_RB_2D_BLIT_CNTL_COLOR_FORMAT__MASK ; } +#define A6XX_RB_2D_BLIT_CNTL_SCISSOR 0x00010000 + +#define REG_A6XX_RB_UNKNOWN_8C01 0x00008c01#define REG_A6XX_RB_2D_DST_INFO 0x00008c17#define A6XX_RB_2D_DST_INFO_COLOR_FORMAT__MASK 0x000000ff
@@ -4643,6 +4658,8 @@ static inline uint32_t A6XX_SP_FS_CONFIG_NSAMP(uint32_t val)#define REG_A6XX_SP_UNKNOWN_AB20 0x0000ab20 +#define REG_A6XX_SP_UNKNOWN_ACC0 0x0000acc0 +#define REG_A6XX_SP_UNKNOWN_AE00 0x0000ae00#define REG_A6XX_SP_UNKNOWN_AE03 0x0000ae03
@@ -4700,11 +4717,20 @@ static inline uint32_t A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP(enum a3xx_color_swap vareturn ((val) <<A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP__SHIFT ) &A6XX_SP_PS_2D_SRC_INFO_COLOR_SWAP__MASK ; }#define A6XX_SP_PS_2D_SRC_INFO_FLAGS 0x00001000 +#define A6XX_SP_PS_2D_SRC_INFO_FILTER 0x00010000#define REG_A6XX_SP_PS_2D_SRC_LO 0x0000b4c2#define REG_A6XX_SP_PS_2D_SRC_HI 0x0000b4c3 +#define REG_A6XX_SP_PS_2D_SRC_SIZE 0x0000b4c4 +#define A6XX_SP_PS_2D_SRC_SIZE_PITCH__MASK 0x01fffe00 +#define A6XX_SP_PS_2D_SRC_SIZE_PITCH__SHIFT 9 +static inline uint32_t A6XX_SP_PS_2D_SRC_SIZE_PITCH (uint32_t val) +{ +return ((val >>6 ) <<A6XX_SP_PS_2D_SRC_SIZE_PITCH__SHIFT ) &A6XX_SP_PS_2D_SRC_SIZE_PITCH__MASK ; +} +#define REG_A6XX_SP_PS_2D_SRC_FLAGS_LO 0x0000b4ca#define REG_A6XX_SP_PS_2D_SRC_FLAGS_HI 0x0000b4cb
@@ -5365,5 +5391,9 @@ static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15(uint32_t val)#define REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2 0x00000030 +#define REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_0 0x00000001 + +#define REG_A6XX_CX_MISC_SYSTEM_CACHE_CNTL_1 0x00000002 +#endif /* A6XX_XML */
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 2/10 drm/msm/gpu: Allocate the correct size for the GPU memptrs
In reply to a message not in the archiveAllocate the correct buffer size for the GPU memptrs. The incorrect size hasn't affected us thus far since the incorrect size was larger than the intended size and we're still stuck on page sized granularity anyway but technically correct is the best kind of correct.
--- drivers/gpu/drm/msm/msm_gpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_gpu.c +2 -1
@@ -920,7 +920,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, goto fail; } - memptrs =msm_gem_kernel_new (drm,sizeof (*gpu->memptrs_bo), + memptrs =msm_gem_kernel_new (drm, +sizeof (struct msm_rbmemptrs ) * nr_rings,MSM_BO_UNCACHED , gpu->aspace, &gpu->memptrs_bo, &memptrs_iova);
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 3/10 drm/msm: Gracefully handle failure in _msm_gem_kernel_new
In reply to a message not in the archiveIf any of the function calls in _msm_gem_kernel_new fail we need to make sure to dereference the GEM object with the appropriate function for the current locking state.
--- drivers/gpu/drm/msm/msm_gem.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/msm_gem.c +12 -6
@@ -1041,23 +1041,29 @@ static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size,if (iova) { ret =msm_gem_get_iova (obj, aspace, iova); -if (ret) { -drm_gem_object_put (obj); -return ERR_PTR (ret); - } +if (ret) + goto err; } vaddr =msm_gem_get_vaddr (obj);if (IS_ERR (vaddr)) {msm_gem_put_iova (obj, aspace); -drm_gem_object_put (obj); -return ERR_CAST (vaddr); + ret =PTR_ERR (vaddr); + goto err; }if (bo) *bo = obj;return vaddr; +err: +if (locked) +drm_gem_object_put (obj); +else +drm_gem_object_put_unlocked (obj); + +return ERR_PTR (ret); + } void *msm_gem_kernel_new(struct drm_device *dev, uint32_t size,
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 4/10 drm/msm/gpu: Add per-submission statistics
In reply to a message not in the archiveAdd infrastructure to track statistics for GPU submissions by sampling certain perfcounters before and after a submission.
To store the statistics, the per-ring memptrs region is expanded to include room for up to 64 entries - this should cover a reasonable amount of inflight submissions without worrying about losing data. The target specific code inserts PM4 commands to sample the counters before and after submission and store them in the data region. The CPU can access the data after the submission retires to make sense of the statistics and communicate them to the user.
--- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 20 +++++++++------- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 34 ++++++++++++++++++++------- drivers/gpu/drm/msm/msm_ringbuffer.h | 16 +++++++++++++ 3 files changed, 54 insertions(+), 16 deletions(-)
drivers/gpu/drm/msm/adreno/a6xx_gmu.c +12 -8
@@ -346,16 +346,20 @@ static int a6xx_rpmh_start(struct a6xx_gmu *gmu) ret =gmu_poll_timeout (gmu,REG_A6XX_RSCC_SEQ_BUSY_DRV0 , val, !val,100 ,10000 ); -if (!ret) { -gmu_write (gmu,REG_A6XX_GMU_RSCC_CONTROL_REQ ,0 ); - -/* Re-enable the power counter */ -gmu_write (gmu,REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE ,1 ); -return 0 ; +if (ret) { +DRM_DEV_ERROR (gmu->dev,"GPU RSC sequence stuck while waking up the GPU\n" ); +return ret; } -DRM_DEV_ERROR (gmu->dev,"GPU RSC sequence stuck while waking up the GPU\n" ); -return ret; +gmu_write (gmu,REG_A6XX_GMU_RSCC_CONTROL_REQ ,0 ); + +/* Set up CX GMU counter 0 to count busy ticks */ +gmu_write (gmu,REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK ,0xff000000 ); +gmu_rmw (gmu,REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0 ,0xff ,0x20 ); + +/* Enable the power counter */ +gmu_write (gmu,REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE ,1 ); +return 0 ; }static void a6xx_rpmh_stop (struct a6xx_gmu *gmu)
drivers/gpu/drm/msm/adreno/a6xx_gpu.c +26 -8
@@ -67,13 +67,34 @@ static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)gpu_write (gpu,REG_A6XX_CP_RB_WPTR , wptr); } +static void get_stats_counter (struct msm_ringbuffer *ring,u32 counter, +u64 iova) +{ +OUT_PKT7 (ring,CP_REG_TO_MEM ,3 ); +OUT_RING (ring, counter | (1 <<30 ) | (2 <<18 )); +OUT_RING (ring,lower_32_bits (iova)); +OUT_RING (ring,upper_32_bits (iova)); +} +static void a6xx_submit (struct msm_gpu *gpu,struct msm_gem_submit *submit,struct msm_file_private *ctx) { +unsigned int index = submit->seqno %MSM_GPU_SUBMIT_STATS_COUNT ;struct msm_drm_private *priv = gpu->dev->dev_private;struct msm_ringbuffer *ring = submit->ring;unsigned int i; +get_stats_counter (ring,REG_A6XX_RBBM_PERFCTR_CP_0_LO , +rbmemptr_stats (ring, index, cpcycles_start)); + +/* +* For PM4 the GMU register offsets are calculated from the base of the +* GPU registers so we need to add 0x1a800 to the register value on A630 +* to get the right value from PM4. +*/ +get_stats_counter (ring,REG_A6XX_GMU_ALWAYS_ON_COUNTER_L +0x1a800 , +rbmemptr_stats (ring, index, alwayson_start)); +/* Invalidate CCU depth and color */ OUT_PKT7 (ring,CP_EVENT_WRITE ,1 );OUT_RING (ring,PC_CCU_INVALIDATE_DEPTH );
@@ -98,6 +119,11 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, } } +get_stats_counter (ring,REG_A6XX_RBBM_PERFCTR_CP_0_LO , +rbmemptr_stats (ring, index, cpcycles_end)); +get_stats_counter (ring,REG_A6XX_GMU_ALWAYS_ON_COUNTER_L +0x1a800 , +rbmemptr_stats (ring, index, alwayson_end)); +/* Write the fence to the scratch register */ OUT_PKT4 (ring,REG_A6XX_CP_SCRATCH_REG (2 ),1 );OUT_RING (ring, submit->seqno);
@@ -387,14 +413,6 @@ static int a6xx_hw_init(struct msm_gpu *gpu)/* Select CP0 to always count cycles */ gpu_write (gpu,REG_A6XX_CP_PERFCTR_CP_SEL_0 ,PERF_CP_ALWAYS_COUNT ); -/* FIXME: not sure if this should live here or in a6xx_gmu.c */ -gmu_write (&a6xx_gpu->gmu,REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK , -0xff000000 ); -gmu_rmw (&a6xx_gpu->gmu,REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0 , -0xff ,0x20 ); -gmu_write (&a6xx_gpu->gmu,REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE , -0x01 ); -gpu_write (gpu,REG_A6XX_RB_NC_MODE_CNTL ,2 <<1 );gpu_write (gpu,REG_A6XX_TPL1_NC_MODE_CNTL ,2 <<1 );gpu_write (gpu,REG_A6XX_SP_NC_MODE_CNTL ,2 <<1 );
drivers/gpu/drm/msm/msm_ringbuffer.h +16 -0
@@ -23,9 +23,25 @@#define rbmemptr (ring, member) \ ((ring)->memptrs_iova + offsetof(struct msm_rbmemptrs, member)) +#define rbmemptr_stats (ring, index, member) \ + (rbmemptr((ring), stats) + \ + ((index) * sizeof(struct msm_gpu_submit_stats)) + \ + offsetof(struct msm_gpu_submit_stats, member)) + +struct msm_gpu_submit_stats { +u64 cpcycles_start; +u64 cpcycles_end; +u64 alwayson_start; +u64 alwayson_end; +}; + +#define MSM_GPU_SUBMIT_STATS_COUNT 64 +struct msm_rbmemptrs {volatile uint32_t rptr;volatile uint32_t fence; + +volatile struct msm_gpu_submit_stats stats[MSM_GPU_SUBMIT_STATS_COUNT ]; };struct msm_ringbuffer {
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 5/10 drm/msm/gpu: Add trace events for tracking GPU submissions
In reply to a message not in the archiveAdd trace events to track the progress of a GPU submission msm_gpu_submit occurs at the beginning of the submissions, msm_gpu_submit_flush happens when the submission is put on the ringbuffer and msm_submit_flush_retired is sent when the operation is retired.
To make it easier to track the operations a unique sequence number is assigned to each submission and displayed in each event output so a human or a script can easily associate the events related to a specific submission.
--- drivers/gpu/drm/msm/Makefile | 3 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 ++ drivers/gpu/drm/msm/msm_gem.h | 1 + drivers/gpu/drm/msm/msm_gem_submit.c | 15 +++- drivers/gpu/drm/msm/msm_gpu.c | 23 +++++- drivers/gpu/drm/msm/msm_gpu_trace.h | 90 +++++++++++++++++++++++ drivers/gpu/drm/msm/msm_gpu_tracepoints.c | 6 ++ 7 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/msm/msm_gpu_trace.h create mode 100644 drivers/gpu/drm/msm/msm_gpu_tracepoints.c
drivers/gpu/drm/msm/Makefile +2 -1
@@ -90,7 +90,8 @@ msm-y := \ msm_perf.o \ msm_rd.o \ msm_ringbuffer.o \ - msm_submitqueue.o + msm_submitqueue.o \ + msm_gpu_tracepoints.o msm-$(CONFIG_DEBUG_FS) += adreno/a5xx_debugfs.o \ disp/dpu1/dpu_dbg.o
drivers/gpu/drm/msm/adreno/a6xx_gpu.c +7 -0
@@ -4,6 +4,7 @@#include "msm_gem.h" #include "msm_mmu.h" +#include "msm_gpu_trace.h" #include "a6xx_gpu.h" #include "a6xx_gmu.xml.h"
@@ -81,6 +82,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, {unsigned int index = submit->seqno %MSM_GPU_SUBMIT_STATS_COUNT ;struct msm_drm_private *priv = gpu->dev->dev_private; +struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu); +struct a6xx_gpu *a6xx_gpu =to_a6xx_gpu (adreno_gpu);struct msm_ringbuffer *ring = submit->ring;unsigned int i;
@@ -138,6 +141,10 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,OUT_RING (ring,upper_32_bits (rbmemptr (ring, fence)));OUT_RING (ring, submit->seqno); +trace_msm_gpu_submit_flush (submit, +gmu_read64 (&a6xx_gpu->gmu,REG_A6XX_GMU_ALWAYS_ON_COUNTER_L , +REG_A6XX_GMU_ALWAYS_ON_COUNTER_H )); +a6xx_flush (gpu, ring); }
drivers/gpu/drm/msm/msm_gem.h +1 -0
@@ -150,6 +150,7 @@ struct msm_gem_submit {struct msm_ringbuffer *ring;unsigned int nr_cmds;unsigned int nr_bos; +u32 ident;/* A "identifier" for the submit for logging */ struct {uint32_t type;uint32_t size;/* in dwords */
drivers/gpu/drm/msm/msm_gem_submit.c +12 -3
@@ -20,6 +20,7 @@#include "msm_drv.h" #include "msm_gpu.h" #include "msm_gem.h" +#include "msm_gpu_trace.h" /* * Cmdstream submission:
@@ -48,7 +49,6 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, submit->dev = dev; submit->gpu = gpu; submit->fence =NULL ; - submit->pid =get_pid (task_pid (current)); submit->cmd = (void *)&submit->bos[nr_bos]; submit->queue = queue; submit->ring = gpu->rb[queue->prio];
@@ -408,6 +408,7 @@ static void submit_cleanup(struct msm_gem_submit *submit)int msm_ioctl_gem_submit (struct drm_device *dev,void *data,struct drm_file *file) { +static atomic_t ident =ATOMIC_INIT (0 );struct msm_drm_private *priv = dev->dev_private;struct drm_msm_gem_submit *args = data;struct msm_file_private *ctx = file->driver_priv;
@@ -418,9 +419,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,struct msm_gpu_submitqueue *queue;struct msm_ringbuffer *ring;int out_fence_fd =-1 ; +struct pid *pid =get_pid (task_pid (current));unsigned i; -int ret; - +int ret, submitid;if (!gpu)return -ENXIO ;
@@ -443,7 +444,12 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,if (!queue)return -ENOENT ; +/* Get a unique identifier for the submission for logging purposes */ + submitid =atomic_inc_return (&ident) -1 ; + ring = gpu->rb[queue->prio]; +trace_msm_gpu_submit (pid_nr (pid), ring->id, submitid, + args->nr_bos, args->nr_cmds);if (args->flags &MSM_SUBMIT_FENCE_FD_IN ) { in_fence =sync_file_get_fence (args->fence_fd);
@@ -480,6 +486,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, goto out_unlock; } + submit->pid = pid; + submit->ident = submitid; +if (args->flags &MSM_SUBMIT_SUDO ) submit->in_rb = true;
drivers/gpu/drm/msm/msm_gpu.c +21 -2
@@ -19,6 +19,7 @@#include "msm_gem.h" #include "msm_mmu.h" #include "msm_fence.h" +#include "msm_gpu_trace.h" #include <generated/utsrelease.h> #include <linux/string_helpers.h>
@@ -662,10 +663,28 @@ int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime,* Cmdstream submission/retirement: */ -static void retire_submit (struct msm_gpu *gpu,struct msm_gem_submit *submit) +static void retire_submit (struct msm_gpu *gpu,struct msm_ringbuffer *ring, +struct msm_gem_submit *submit) { +int index = submit->seqno %MSM_GPU_SUBMIT_STATS_COUNT ; +volatile struct msm_gpu_submit_stats *stats; +u64 elapsed, clock =0 ;int i; + stats = &ring->memptrs->stats[index]; +/* Convert 19.2Mhz alwayson ticks to nanoseconds for elapsed time */ + elapsed = (stats->alwayson_end - stats->alwayson_start) *10000 ; +do_div (elapsed,192 ); + +/* Calculate the clock frequency from the number of CP cycles */ +if (elapsed) { + clock = (stats->cpcycles_end - stats->cpcycles_start) *1000 ; +do_div (clock, elapsed); + } + +trace_msm_gpu_submit_retired (submit, elapsed, clock, + stats->alwayson_start, stats->alwayson_end); +for (i =0 ; i < submit->nr_bos; i++) {struct msm_gem_object *msm_obj = submit->bos[i].obj;/* move to inactive: */
@@ -693,7 +712,7 @@ static void retire_submits(struct msm_gpu *gpu)list_for_each_entry_safe (submit, tmp, &ring->submits, node) {if (dma_fence_is_signaled (submit->fence)) -retire_submit (gpu, submit); +retire_submit (gpu, ring, submit); } } }
drivers/gpu/drm/msm/msm_gpu_trace.h new file +90 -0
90 lines not on this page · raw message
drivers/gpu/drm/msm/msm_gpu_tracepoints.c new file +6 -0
@@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "msm_gem.h" +#include "msm_ringbuffer.h" + +#define CREATE_TRACE_POINTS +#include "msm_gpu_trace.h"
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 6/10 drm/msm/gpu: Only store local command buffers in the GPU state
In reply to a message not in the archiveInstead of trying to store all the tagged buffers from a hanging submit only store the command buffers that were not imported. This cuts down on the amount of data stored in the GPU state to the base minimum of useful information.
The downside is that this will make it more difficult to successfully replay a hang with just the GPU state but there isn't any reason why that functionality can't be added back in later once we've figured out how to better communicate such massive amounts of data.
--- drivers/gpu/drm/msm/msm_gpu.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
drivers/gpu/drm/msm/msm_gpu.c +13 -10
@@ -316,28 +316,28 @@ static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state,struct msm_gpu_state_bo *state_bo = &state->bos[state->nr_bos];/* Don't record write only objects */ - state_bo->size = obj->base.size; state_bo->iova = iova; -/* Only store the data for buffer objects marked for read */ -if ((flags &MSM_SUBMIT_BO_READ )) { +/* Only store data for non imported buffer objects marked for read */ +if ((flags &MSM_SUBMIT_BO_READ ) && !obj->base.import_attach) {void *ptr; state_bo->data =kvmalloc (obj->base.size,GFP_KERNEL );if (!state_bo->data) -return ; + goto out; ptr =msm_gem_get_vaddr_active (&obj->base);if (IS_ERR (ptr)) {kvfree (state_bo->data); -return ; + state_bo->data =NULL ; + goto out; }memcpy (state_bo->data, ptr, obj->base.size);msm_gem_put_vaddr (&obj->base); } - +out: state->nr_bos++; }
@@ -365,12 +365,15 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,if (submit) {int i; - state->bos =kcalloc (submit->nr_bos, + state->bos =kcalloc (submit->nr_cmds,sizeof (struct msm_gpu_state_bo ),GFP_KERNEL ); -for (i =0 ; state->bos && i < submit->nr_bos; i++) -msm_gpu_crashstate_get_bo (state, submit->bos[i].obj, - submit->bos[i].iova, submit->bos[i].flags); +for (i =0 ; state->bos && i < submit->nr_cmds; i++) { +int idx = submit->cmd[i].idx; + +msm_gpu_crashstate_get_bo (state, submit->bos[idx].obj, + submit->bos[idx].iova, submit->bos[idx].flags); + } }/* Set the active crash state to be dumped on failure */
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 7/10 drm/msm/gpu: Move gpu_poll_timeout() to adreno_gpu.h
In reply to a message not in the archiveThe gpu_poll_timeout() function can be useful to multiple targets so mvoe it into adreno_gpu.h from the a5xx code.
--- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 5 ----- drivers/gpu/drm/msm/adreno/adreno_gpu.h | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-)
drivers/gpu/drm/msm/adreno/a5xx_gpu.c +0 -5
@@ -20,7 +20,6 @@#include <linux/soc/qcom/mdt_loader.h> #include <linux/pm_opp.h> #include <linux/nvmem-consumer.h> -#include <linux/iopoll.h> #include <linux/slab.h> #include "msm_gem.h" #include "msm_mmu.h"
@@ -1211,10 +1210,6 @@ struct a5xx_gpu_state {u32 *hlsqregs; }; -#define gpu_poll_timeout (gpu, addr, val, cond, interval, timeout) \ - readl_poll_timeout((gpu)->mmio + ((addr) << 2), val, cond, \ - interval, timeout) -static int a5xx_crashdumper_init (struct msm_gpu *gpu,struct a5xx_crashdumper *dumper) {
drivers/gpu/drm/msm/adreno/adreno_gpu.h +6 -0
@@ -21,6 +21,7 @@#define __ADRENO_GPU_H__#include <linux/firmware.h> +#include <linux/iopoll.h> #include "msm_gpu.h"
@@ -375,4 +376,9 @@ static inline uint32_t get_wptr(struct msm_ringbuffer *ring) ((1 <<29 ) \ ((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF)) + +#define gpu_poll_timeout (gpu, addr, val, cond, interval, timeout) \ + readl_poll_timeout((gpu)->mmio + ((addr) << 2), val, cond, \ + interval, timeout) +#endif /* __ADRENO_GPU_H__ */
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 8/10 drm/msm/adreno: Don't capture register values if target doesn't define them
In reply to a message not in the archiveIf the GPU target doesn't define a list of registers then gracefully skip capturing and/or printing them. This is used by more complex targets like 6xx that have other means of capturing register values.
--- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
drivers/gpu/drm/msm/adreno/adreno_gpu.c +14 -5
@@ -414,6 +414,10 @@ int adreno_gpu_state_get(struct msm_gpu *gpu, struct msm_gpu_state *state) } } +/* Some targets prefer to collect their own registers */ +if (!adreno_gpu->registers) +return 0 ; +/* Count the number of registers */ for (i =0 ; adreno_gpu->registers[i] != ~0 ; i +=2 ) count += adreno_gpu->registers[i + 1] -
@@ -551,12 +555,14 @@ void adreno_show(struct msm_gpu *gpu, struct msm_gpu_state *state, } } -drm_puts (p,"registers:\n" ); +if (state->nr_registers) { +drm_puts (p,"registers:\n" ); -for (i =0 ; i < state->nr_registers; i++) { -drm_printf (p," - { offset: 0x%04x, value: 0x%08x }\n" , - state->registers[i *2 ] <<2 , - state->registers[(i *2 ) +1 ]); +for (i =0 ; i < state->nr_registers; i++) { +drm_printf (p," - { offset: 0x%04x, value: 0x%08x }\n" , + state->registers[i *2 ] <<2 , + state->registers[(i *2 ) +1 ]); + } } }#endif
@@ -595,6 +601,9 @@ void adreno_dump(struct msm_gpu *gpu)struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu);int i; +if (!adreno_gpu->registers) +return ; +/* dump these out in a form that can be parsed by demsm: */ printk ("IO:region %s 00000000 00020000\n" , gpu->name);for (i =0 ; adreno_gpu->registers[i] != ~0 ; i +=2 ) {
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 10/10 drm/msm/a6xx: Track and manage a6xx state memory
In reply to a message not in the archiveThe a6xx GPU state allocates a LOT of memory. Add a bit of infrastructure to track the memory allocations in the GPU structure and delete them when the state is destroyed much the same way that devm works with the device model as a whole. This protects against the developer accidentally forgetting to add a kfree() to an ever growing list.
--- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 192 +++++++++++--------- 1 file changed, 102 insertions(+), 90 deletions(-)
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +102 -90
@@ -41,6 +41,8 @@ struct a6xx_gpu_state {struct a6xx_gpu_state_obj *cx_debugbus;int nr_cx_debugbus; + +struct list_head objs; };static inline int CRASHDUMP_WRITE (u64 *in,u32 reg,u32 val)
@@ -73,6 +75,33 @@ struct a6xx_crashdumper {u64 iova; }; +struct a6xx_state_memobj { +struct list_head node; +unsigned long long data[]; +}; + +void *state_kcalloc (struct a6xx_gpu_state *a6xx_state,int nr,size_t objsize) +{ +struct a6xx_state_memobj *obj = +kzalloc ((nr * objsize) +sizeof (*obj),GFP_KERNEL ); + +if (!obj) +return NULL ; + +list_add_tail (&obj->node, &a6xx_state->objs); +return &obj->data; +} + +void *state_kmemdup (struct a6xx_gpu_state *a6xx_state,void *src, +size_t size) +{ +void *dst =state_kcalloc (a6xx_state,1 , size); + +if (dst) +memcpy (dst, src, size); +return dst; +} +/* * Allocate 1MB for the crashdumper scratch region - 8k for the script and * the rest for the data
@@ -203,12 +232,17 @@ static int vbif_debugbus_read(struct msm_gpu *gpu, u32 ctrl0, u32 ctrl1, (12 * XIN_CORE_BLOCKS))static void a6xx_get_vbif_debugbus_block (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,struct a6xx_gpu_state_obj *obj) {u32 clk, *ptr;int i; - obj->data =kcalloc (VBIF_DEBUGBUS_BLOCK_SIZE ,sizeof (u32),GFP_KERNEL ); + obj->data =state_kcalloc (a6xx_state,VBIF_DEBUGBUS_BLOCK_SIZE , +sizeof (u32)); +if (!obj->data) +return ; + obj->handle =NULL ;/* Get the current clock setting */
@@ -252,13 +286,14 @@ static void a6xx_get_vbif_debugbus_block(struct msm_gpu *gpu, }static void a6xx_get_debugbus_block (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_debugbus_block *block,struct a6xx_gpu_state_obj *obj) {int i;u32 *ptr; - obj->data =kcalloc (block->count,sizeof (u64),GFP_KERNEL ); + obj->data =state_kcalloc (a6xx_state, block->count,sizeof (u64));if (!obj->data)return ;
@@ -269,13 +304,14 @@ static void a6xx_get_debugbus_block(struct msm_gpu *gpu, }static void a6xx_get_cx_debugbus_block (void __iomem *cxdbg, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_debugbus_block *block,struct a6xx_gpu_state_obj *obj) {int i;u32 *ptr; - obj->data =kcalloc (block->count,sizeof (u64),GFP_KERNEL ); + obj->data =state_kcalloc (a6xx_state, block->count,sizeof (u64));if (!obj->data)return ;
@@ -344,36 +380,42 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu,cxdbg_write (cxdbg,REG_A6XX_DBGC_CFG_DBGBUS_MASKL_3 ,0 ); } - a6xx_state->debugbus =kcalloc (ARRAY_SIZE (a6xx_debugbus_blocks), -sizeof (*a6xx_state->debugbus),GFP_KERNEL ); + a6xx_state->debugbus =state_kcalloc (a6xx_state, +ARRAY_SIZE (a6xx_debugbus_blocks), +sizeof (*a6xx_state->debugbus));if (a6xx_state->debugbus) {int i;for (i =0 ; i <ARRAY_SIZE (a6xx_debugbus_blocks); i++)a6xx_get_debugbus_block (gpu, + a6xx_state, &a6xx_debugbus_blocks[i], &a6xx_state->debugbus[i]); a6xx_state->nr_debugbus =ARRAY_SIZE (a6xx_debugbus_blocks); } - a6xx_state->vbif_debugbus =kzalloc (sizeof (*a6xx_state->vbif_debugbus), -GFP_KERNEL ); + a6xx_state->vbif_debugbus = +state_kcalloc (a6xx_state,1 , +sizeof (*a6xx_state->vbif_debugbus));if (a6xx_state->vbif_debugbus) -a6xx_get_vbif_debugbus_block (gpu, a6xx_state->vbif_debugbus); +a6xx_get_vbif_debugbus_block (gpu, a6xx_state, + a6xx_state->vbif_debugbus);if (cxdbg) { a6xx_state->cx_debugbus = -kcalloc (ARRAY_SIZE (a6xx_cx_debugbus_blocks), -sizeof (*a6xx_state->cx_debugbus),GFP_KERNEL ); +state_kcalloc (a6xx_state, +ARRAY_SIZE (a6xx_cx_debugbus_blocks), +sizeof (*a6xx_state->cx_debugbus));if (a6xx_state->cx_debugbus) {int i;for (i =0 ; i <ARRAY_SIZE (a6xx_cx_debugbus_blocks); i++)a6xx_get_cx_debugbus_block (cxdbg, + a6xx_state, &a6xx_cx_debugbus_blocks[i], &a6xx_state->cx_debugbus[i]);
@@ -389,6 +431,7 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu,/* Read a data cluster from behind the AHB aperture */ static void a6xx_get_dbgahb_cluster (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_dbgahb_cluster *dbgahb,struct a6xx_gpu_state_obj *obj,struct a6xx_crashdumper *dumper)
@@ -429,8 +472,8 @@ static void a6xx_get_dbgahb_cluster(struct msm_gpu *gpu,return ; obj->handle = dbgahb; - obj->data =kmemdup (dumper->ptr +A6XX_CD_DATA_OFFSET , - datasize,GFP_KERNEL ); + obj->data =state_kmemdup (a6xx_state, dumper->ptr +A6XX_CD_DATA_OFFSET , + datasize); } static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu,
@@ -439,8 +482,9 @@ static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu, {int i; - a6xx_state->dbgahb_clusters =kcalloc (ARRAY_SIZE (a6xx_dbgahb_clusters), -sizeof (*a6xx_state->dbgahb_clusters),GFP_KERNEL ); + a6xx_state->dbgahb_clusters =state_kcalloc (a6xx_state, +ARRAY_SIZE (a6xx_dbgahb_clusters), +sizeof (*a6xx_state->dbgahb_clusters));if (!a6xx_state->dbgahb_clusters)return ;
@@ -448,12 +492,14 @@ static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu, a6xx_state->nr_dbgahb_clusters =ARRAY_SIZE (a6xx_dbgahb_clusters);for (i =0 ; i <ARRAY_SIZE (a6xx_dbgahb_clusters); i++) -a6xx_get_dbgahb_cluster (gpu, &a6xx_dbgahb_clusters[i], +a6xx_get_dbgahb_cluster (gpu, a6xx_state, + &a6xx_dbgahb_clusters[i], &a6xx_state->dbgahb_clusters[i], dumper); }/* Read a data cluster from the CP aperture with the crashdumper */ static void a6xx_get_cluster (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_cluster *cluster,struct a6xx_gpu_state_obj *obj,struct a6xx_crashdumper *dumper)
@@ -497,8 +543,8 @@ static void a6xx_get_cluster(struct msm_gpu *gpu,return ; obj->handle = cluster; - obj->data =kmemdup (dumper->ptr +A6XX_CD_DATA_OFFSET , - datasize,GFP_KERNEL ); + obj->data =state_kmemdup (a6xx_state, dumper->ptr +A6XX_CD_DATA_OFFSET , + datasize); } static void a6xx_get_clusters(struct msm_gpu *gpu,
@@ -507,8 +553,8 @@ static void a6xx_get_clusters(struct msm_gpu *gpu, {int i; - a6xx_state->clusters =kcalloc (ARRAY_SIZE (a6xx_clusters), -sizeof (*a6xx_state->clusters),GFP_KERNEL ); + a6xx_state->clusters =state_kcalloc (a6xx_state, +ARRAY_SIZE (a6xx_clusters),sizeof (*a6xx_state->clusters));if (!a6xx_state->clusters)return ;
@@ -516,12 +562,13 @@ static void a6xx_get_clusters(struct msm_gpu *gpu, a6xx_state->nr_clusters =ARRAY_SIZE (a6xx_clusters);for (i =0 ; i <ARRAY_SIZE (a6xx_clusters); i++) -a6xx_get_cluster (gpu, &a6xx_clusters[i], +a6xx_get_cluster (gpu, a6xx_state, &a6xx_clusters[i], &a6xx_state->clusters[i], dumper); }/* Read a shader / debug block from the HLSQ aperture with the crashdumper */ static void a6xx_get_shader_block (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_shader_block *block,struct a6xx_gpu_state_obj *obj,struct a6xx_crashdumper *dumper)
@@ -547,8 +594,8 @@ static void a6xx_get_shader_block(struct msm_gpu *gpu,return ; obj->handle = block; - obj->data =kmemdup (dumper->ptr +A6XX_CD_DATA_OFFSET , - datasize,GFP_KERNEL ); + obj->data =state_kmemdup (a6xx_state, dumper->ptr +A6XX_CD_DATA_OFFSET , + datasize); } static void a6xx_get_shaders(struct msm_gpu *gpu,
@@ -557,8 +604,8 @@ static void a6xx_get_shaders(struct msm_gpu *gpu, {int i; - a6xx_state->shaders =kcalloc (ARRAY_SIZE (a6xx_shader_blocks), -sizeof (*a6xx_state->shaders),GFP_KERNEL ); + a6xx_state->shaders =state_kcalloc (a6xx_state, +ARRAY_SIZE (a6xx_shader_blocks),sizeof (*a6xx_state->shaders));if (!a6xx_state->shaders)return ;
@@ -566,12 +613,13 @@ static void a6xx_get_shaders(struct msm_gpu *gpu, a6xx_state->nr_shaders =ARRAY_SIZE (a6xx_shader_blocks);for (i =0 ; i <ARRAY_SIZE (a6xx_shader_blocks); i++) -a6xx_get_shader_block (gpu, &a6xx_shader_blocks[i], +a6xx_get_shader_block (gpu, a6xx_state, &a6xx_shader_blocks[i], &a6xx_state->shaders[i], dumper); }/* Read registers from behind the HLSQ aperture with the crashdumper */ static void a6xx_get_crashdumper_hlsq_registers (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_registers *regs,struct a6xx_gpu_state_obj *obj,struct a6xx_crashdumper *dumper)
@@ -603,12 +651,13 @@ static void a6xx_get_crashdumper_hlsq_registers(struct msm_gpu *gpu,return ; obj->handle = regs; - obj->data =kmemdup (dumper->ptr +A6XX_CD_DATA_OFFSET , - regcount *sizeof (u32),GFP_KERNEL ); + obj->data =state_kmemdup (a6xx_state, dumper->ptr +A6XX_CD_DATA_OFFSET , + regcount *sizeof (u32)); }/* Read a block of registers using the crashdumper */ static void a6xx_get_crashdumper_registers (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_registers *regs,struct a6xx_gpu_state_obj *obj,struct a6xx_crashdumper *dumper)
@@ -640,12 +689,13 @@ static void a6xx_get_crashdumper_registers(struct msm_gpu *gpu,return ; obj->handle = regs; - obj->data =kmemdup (dumper->ptr +A6XX_CD_DATA_OFFSET , - regcount *sizeof (u32),GFP_KERNEL ); + obj->data =state_kmemdup (a6xx_state, dumper->ptr +A6XX_CD_DATA_OFFSET , + regcount *sizeof (u32)); }/* Read a block of registers via AHB */ static void a6xx_get_ahb_gpu_registers (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_registers *regs,struct a6xx_gpu_state_obj *obj) {
@@ -655,7 +705,7 @@ static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu, regcount +=RANGE (regs->registers, i); obj->handle = (const void *) regs; - obj->data =kcalloc (regcount,sizeof (u32),GFP_KERNEL ); + obj->data =state_kcalloc (a6xx_state, regcount,sizeof (u32));if (!obj->data)return ;
@@ -671,6 +721,7 @@ static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu,/* Read a block of GMU registers */ static void _a6xx_get_gmu_registers (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_registers *regs,struct a6xx_gpu_state_obj *obj) {
@@ -683,7 +734,7 @@ static void _a6xx_get_gmu_registers(struct msm_gpu *gpu, regcount +=RANGE (regs->registers, i); obj->handle = (const void *) regs; - obj->data =kcalloc (regcount,sizeof (u32),GFP_KERNEL ); + obj->data =state_kcalloc (a6xx_state, regcount,sizeof (u32));if (!obj->data)return ;
@@ -703,8 +754,8 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu,struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu);struct a6xx_gpu *a6xx_gpu =to_a6xx_gpu (adreno_gpu); - a6xx_state->gmu_registers =kcalloc (2 , -sizeof (*a6xx_state->gmu_registers),GFP_KERNEL ); + a6xx_state->gmu_registers =state_kcalloc (a6xx_state, +2 ,sizeof (*a6xx_state->gmu_registers));if (!a6xx_state->gmu_registers)return ;
@@ -712,7 +763,7 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, a6xx_state->nr_gmu_registers =2 ;/* Get the CX GMU registers from AHB */ -_a6xx_get_gmu_registers (gpu, &a6xx_gmu_reglist[0 ], +_a6xx_get_gmu_registers (gpu, a6xx_state, &a6xx_gmu_reglist[0 ], &a6xx_state->gmu_registers[0 ]);if (!a6xx_gmu_gx_is_on (&a6xx_gpu->gmu))
@@ -721,7 +772,7 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu,/* Set the fence to ALLOW mode so we can access the registers */ gpu_write (gpu,REG_A6XX_GMU_AO_AHB_FENCE_CTRL ,0 ); -_a6xx_get_gmu_registers (gpu, &a6xx_gmu_reglist[1 ], +_a6xx_get_gmu_registers (gpu, a6xx_state, &a6xx_gmu_reglist[1 ], &a6xx_state->gmu_registers[1 ]); }
@@ -734,8 +785,8 @@ static void a6xx_get_registers(struct msm_gpu *gpu,ARRAY_SIZE (a6xx_hlsq_reglist);int index =0 ; - a6xx_state->registers =kcalloc (count,sizeof (*a6xx_state->registers), -GFP_KERNEL ); + a6xx_state->registers =state_kcalloc (a6xx_state, + count,sizeof (*a6xx_state->registers));if (!a6xx_state->registers)return ;
@@ -744,31 +795,32 @@ static void a6xx_get_registers(struct msm_gpu *gpu,for (i =0 ; i <ARRAY_SIZE (a6xx_ahb_reglist); i++)a6xx_get_ahb_gpu_registers (gpu, - &a6xx_ahb_reglist[i], + a6xx_state, &a6xx_ahb_reglist[i], &a6xx_state->registers[index++]);for (i =0 ; i <ARRAY_SIZE (a6xx_reglist); i++)a6xx_get_crashdumper_registers (gpu, - &a6xx_reglist[i], + a6xx_state, &a6xx_reglist[i], &a6xx_state->registers[index++], dumper);for (i =0 ; i <ARRAY_SIZE (a6xx_hlsq_reglist); i++)a6xx_get_crashdumper_hlsq_registers (gpu, - &a6xx_hlsq_reglist[i], + a6xx_state, &a6xx_hlsq_reglist[i], &a6xx_state->registers[index++], dumper); }/* Read a block of data from an indexed register pair */ static void a6xx_get_indexed_regs (struct msm_gpu *gpu, +struct a6xx_gpu_state *a6xx_state,const struct a6xx_indexed_registers *indexed,struct a6xx_gpu_state_obj *obj) {int i; obj->handle = (const void *) indexed; - obj->data =kcalloc (indexed->count,sizeof (u32),GFP_KERNEL ); + obj->data =state_kcalloc (a6xx_state, indexed->count,sizeof (u32));if (!obj->data)return ;
@@ -787,13 +839,13 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu,int count =ARRAY_SIZE (a6xx_indexed_reglist) +1 ;int i; - a6xx_state->indexed_regs =kcalloc (count, -sizeof (a6xx_state->indexed_regs),GFP_KERNEL ); + a6xx_state->indexed_regs =state_kcalloc (a6xx_state, count, +sizeof (a6xx_state->indexed_regs));if (!a6xx_state->indexed_regs)return ;for (i =0 ; i <ARRAY_SIZE (a6xx_indexed_reglist); i++) -a6xx_get_indexed_regs (gpu, &a6xx_indexed_reglist[i], +a6xx_get_indexed_regs (gpu, a6xx_state, &a6xx_indexed_reglist[i], &a6xx_state->indexed_regs[i]);/* Set the CP mempool size to 0 to stabilize it while dumping */
@@ -801,7 +853,7 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu,gpu_write (gpu,REG_A6XX_CP_MEM_POOL_SIZE ,0 );/* Get the contents of the CP mempool */ -a6xx_get_indexed_regs (gpu, &a6xx_cp_mempool_indexed, +a6xx_get_indexed_regs (gpu, a6xx_state, &a6xx_cp_mempool_indexed, &a6xx_state->indexed_regs[i]);/*
@@ -827,6 +879,8 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)if (!a6xx_state)return ERR_PTR (-ENOMEM ); +INIT_LIST_HEAD (&a6xx_state->objs); +/* Get the generic state from the adreno core */ adreno_gpu_state_get (gpu, &a6xx_state->base);
@@ -856,56 +910,14 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu)void a6xx_gpu_state_destroy (struct kref *kref) { +struct a6xx_state_memobj *obj, *tmp;struct msm_gpu_state *state =container_of (kref, struct msm_gpu_state, ref);struct a6xx_gpu_state *a6xx_state =container_of (state, struct a6xx_gpu_state, base); -int i; - -for (i =0 ; i < a6xx_state->nr_gmu_registers; i++) -kfree (a6xx_state->gmu_registers[i].data); - -kfree (a6xx_state->gmu_registers); - -for (i =0 ; i < a6xx_state->nr_registers; i++) -kfree (a6xx_state->registers[i].data); - -kfree (a6xx_state->registers); - -for (i =0 ; i < a6xx_state->nr_shaders; i++) -kfree (a6xx_state->shaders[i].data); - -kfree (a6xx_state->shaders); - -for (i =0 ; i < a6xx_state->nr_clusters; i++) -kfree (a6xx_state->clusters[i].data); - -kfree (a6xx_state->clusters); - -for (i =0 ; i < a6xx_state->nr_dbgahb_clusters; i++) -kfree (a6xx_state->dbgahb_clusters[i].data); - -kfree (a6xx_state->dbgahb_clusters); - -for (i =0 ; i < a6xx_state->nr_indexed_regs; i++) -kfree (a6xx_state->indexed_regs[i].data); - -kfree (a6xx_state->indexed_regs); - -for (i =0 ; i < a6xx_state->nr_debugbus; i++) -kfree (a6xx_state->debugbus[i].data); - -kfree (a6xx_state->debugbus); - -if (a6xx_state->vbif_debugbus) -kfree (a6xx_state->vbif_debugbus->data); - -kfree (a6xx_state->vbif_debugbus); - -for (i =0 ; i < a6xx_state->nr_cx_debugbus; i++) -kfree (a6xx_state->cx_debugbus[i].data); -kfree (a6xx_state->cx_debugbus); +list_for_each_entry_safe (obj, tmp, &a6xx_state->objs, node) +kfree (obj);adreno_gpu_state_destroy (state);kfree (a6xx_state);
Signature · 6 lines
2.18.0 _______________________________________________ Freedreno mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/freedreno
PATCH 9/10 drm/msm/a6xx: Add a6xx gpu state
In reply to Jordan CrouseAdd support for gathering and dumping the a6xx GPU state including registers, GMU registers, indexed registers, shader blocks, context clusters and debugbus.
v2: Fix bugs discovered by Sharat Masetty
--- drivers/gpu/drm/msm/Makefile | 1 + drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 3 + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 39 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 8 + drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 1159 +++++++++++++++++++ drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h | 430 +++++++ 7 files changed, 1627 insertions(+), 38 deletions(-) create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c create mode 100644 drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
drivers/gpu/drm/msm/Makefile +1 -0
@@ -14,6 +14,7 @@ msm-y := \ adreno/a6xx_gpu.o \ adreno/a6xx_gmu.o \ adreno/a6xx_hfi.o \ + adreno/a6xx_gpu_state.o \ hdmi/hdmi.o \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \
drivers/gpu/drm/msm/adreno/a6xx_gmu.c +23 -2
@@ -51,10 +51,31 @@ static irqreturn_t a6xx_hfi_irq(int irq, void *data)return IRQ_HANDLED ; } +bool a6xx_gmu_sptprac_is_on (struct a6xx_gmu *gmu) +{ +u32 val; + +/* This can be called from gpu state code so make sure GMU is valid */ +if (IS_ERR_OR_NULL (gmu->mmio)) +return false; + + val =gmu_read (gmu,REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS ); + +return !(val & + (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_OFF | +A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SP_CLOCK_OFF )); +} +/* Check to see if the GX rail is still powered */ -static bool a6xx_gmu_gx_is_on (struct a6xx_gmu *gmu) +bool a6xx_gmu_gx_is_on (struct a6xx_gmu *gmu) { -u32 val =gmu_read (gmu,REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS ); +u32 val; + +/* This can be called from gpu state code so make sure GMU is valid */ +if (IS_ERR_OR_NULL (gmu->mmio)) +return false; + + val =gmu_read (gmu,REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS ); return !(val & (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
drivers/gpu/drm/msm/adreno/a6xx_gmu.h +3 -0
@@ -164,4 +164,7 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu);int a6xx_hfi_start (struct a6xx_gmu *gmu,int boot_state);void a6xx_hfi_stop (struct a6xx_gmu *gmu); +bool a6xx_gmu_gx_is_on (struct a6xx_gmu *gmu); +bool a6xx_gmu_sptprac_is_on (struct a6xx_gmu *gmu); +#endif
drivers/gpu/drm/msm/adreno/a6xx_gpu.c +3 -36
@@ -670,33 +670,6 @@ static const u32 a6xx_register_offsets[REG_ADRENO_REGISTER_MAX] = { REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A6XX_CP_RB_CNTL), }; -static const u32 a6xx_registers[] = { -0x0000 ,0x0002 ,0x0010 ,0x0010 ,0x0012 ,0x0012 ,0x0018 ,0x001b , -0x001e ,0x0032 ,0x0038 ,0x003c ,0x0042 ,0x0042 ,0x0044 ,0x0044 , -0x0047 ,0x0047 ,0x0056 ,0x0056 ,0x00ad ,0x00ae ,0x00b0 ,0x00fb , -0x0100 ,0x011d ,0x0200 ,0x020d ,0x0210 ,0x0213 ,0x0218 ,0x023d , -0x0400 ,0x04f9 ,0x0500 ,0x0500 ,0x0505 ,0x050b ,0x050e ,0x0511 , -0x0533 ,0x0533 ,0x0540 ,0x0555 ,0x0800 ,0x0808 ,0x0810 ,0x0813 , -0x0820 ,0x0821 ,0x0823 ,0x0827 ,0x0830 ,0x0833 ,0x0840 ,0x0843 , -0x084f ,0x086f ,0x0880 ,0x088a ,0x08a0 ,0x08ab ,0x08c0 ,0x08c4 , -0x08d0 ,0x08dd ,0x08f0 ,0x08f3 ,0x0900 ,0x0903 ,0x0908 ,0x0911 , -0x0928 ,0x093e ,0x0942 ,0x094d ,0x0980 ,0x0984 ,0x098d ,0x0996 , -0x0998 ,0x099e ,0x09a0 ,0x09a6 ,0x09a8 ,0x09ae ,0x09b0 ,0x09b1 , -0x09c2 ,0x09c8 ,0x0a00 ,0x0a03 ,0x0c00 ,0x0c04 ,0x0c06 ,0x0c06 , -0x0c10 ,0x0cd9 ,0x0e00 ,0x0e0e ,0x0e10 ,0x0e13 ,0x0e17 ,0x0e19 , -0x0e1c ,0x0e2b ,0x0e30 ,0x0e32 ,0x0e38 ,0x0e39 ,0x8600 ,0x8601 , -0x8610 ,0x861b ,0x8620 ,0x8620 ,0x8628 ,0x862b ,0x8630 ,0x8637 , -0x8e01 ,0x8e01 ,0x8e04 ,0x8e05 ,0x8e07 ,0x8e08 ,0x8e0c ,0x8e0c , -0x8e10 ,0x8e1c ,0x8e20 ,0x8e25 ,0x8e28 ,0x8e28 ,0x8e2c ,0x8e2f , -0x8e3b ,0x8e3e ,0x8e40 ,0x8e43 ,0x8e50 ,0x8e5e ,0x8e70 ,0x8e77 , -0x9600 ,0x9604 ,0x9624 ,0x9637 ,0x9e00 ,0x9e01 ,0x9e03 ,0x9e0e , -0x9e11 ,0x9e16 ,0x9e19 ,0x9e19 ,0x9e1c ,0x9e1c ,0x9e20 ,0x9e23 , -0x9e30 ,0x9e31 ,0x9e34 ,0x9e34 ,0x9e70 ,0x9e72 ,0x9e78 ,0x9e79 , -0x9e80 ,0x9fff ,0xa600 ,0xa601 ,0xa603 ,0xa603 ,0xa60a ,0xa60a , -0xa610 ,0xa617 ,0xa630 ,0xa630 , - ~0 -}; -static int a6xx_pm_resume (struct msm_gpu *gpu) {struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu);
@@ -749,14 +722,6 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)return 0 ; } -#if defined(CONFIG_DEBUG_FS ) || defined(CONFIG_DEV_COREDUMP ) -static void a6xx_show (struct msm_gpu *gpu,struct msm_gpu_state *state, -struct drm_printer *p) -{ -adreno_show (gpu, state, p); -} -#endif -static struct msm_ringbuffer *a6xx_active_ring (struct msm_gpu *gpu) {struct adreno_gpu *adreno_gpu =to_adreno_gpu (gpu);
@@ -821,6 +786,8 @@ static const struct adreno_gpu_funcs funcs = { .gpu_busy = a6xx_gpu_busy, .gpu_get_freq = a6xx_gmu_get_freq, .gpu_set_freq = a6xx_gmu_set_freq, + .gpu_state_get = a6xx_gpu_state_get, + .gpu_state_put = a6xx_gpu_state_put, }, .get_timestamp = a6xx_get_timestamp, };
@@ -842,7 +809,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) adreno_gpu = &a6xx_gpu->base; gpu = &adreno_gpu->base; - adreno_gpu->registers = a6xx_registers; + adreno_gpu->registers =NULL ; adreno_gpu->reg_offsets = a6xx_register_offsets; ret =adreno_gpu_init (dev, pdev, adreno_gpu, &funcs,1 );
drivers/gpu/drm/msm/adreno/a6xx_gpu.h +8 -0
@@ -56,6 +56,14 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);int a6xx_gmu_probe (struct a6xx_gpu *a6xx_gpu,struct device_node *node);void a6xx_gmu_remove (struct a6xx_gpu *a6xx_gpu); +void a6xx_gmu_set_freq (struct msm_gpu *gpu,unsigned long freq);unsigned long a6xx_gmu_get_freq (struct msm_gpu *gpu); + +void a6xx_show (struct msm_gpu *gpu,struct msm_gpu_state *state, +struct drm_printer *p); + +struct msm_gpu_state *a6xx_gpu_state_get (struct msm_gpu *gpu); +int a6xx_gpu_state_put (struct msm_gpu_state *state); +#endif /* __A6XX_GPU_H__ */
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c new file +1159 -0
1,159 lines not on this page · raw message
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h new file +430 -0
430 lines not on this page · raw message
Signature · 6 lines
2.18.0 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel