diff options
author | Tom St Denis <tom.stdenis@amd.com> | 2016-12-05 11:39:19 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-12-08 14:12:17 -0500 |
commit | c5a60ce81b4962d35a6bbb328fb234d33254cfb7 (patch) | |
tree | 4fdb880c0467c68e9aee75febc93a066928ecd19 /drivers/gpu/drm | |
parent | 40ee5888faecf4ea5423dbe94c862d03c3e7e12c (diff) |
drm/amd/amdgpu: Add debugfs support for reading GPRs (v2)
Implemented for SGPRs for GFX v8 initially.
(v2) cleanup minor whitespace and remove sanity check and
addressing is in dwords not bytes
Signed-off-by: Tom St Denis <tom.stdenis@amd.com>
Acked-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 67 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 25 |
3 files changed, 94 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index f31936b65a58..54ac8a845e9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
@@ -842,6 +842,8 @@ struct amdgpu_gfx_funcs { | |||
842 | uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev); | 842 | uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev); |
843 | void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance); | 843 | void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance); |
844 | void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields); | 844 | void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields); |
845 | void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t thread, uint32_t start, uint32_t size, uint32_t *dst); | ||
846 | void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t start, uint32_t size, uint32_t *dst); | ||
845 | }; | 847 | }; |
846 | 848 | ||
847 | struct amdgpu_gfx { | 849 | struct amdgpu_gfx { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d9074117fb04..53ea782c2c47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -2985,6 +2985,66 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, | |||
2985 | return result; | 2985 | return result; |
2986 | } | 2986 | } |
2987 | 2987 | ||
2988 | static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, | ||
2989 | size_t size, loff_t *pos) | ||
2990 | { | ||
2991 | struct amdgpu_device *adev = f->f_inode->i_private; | ||
2992 | int r; | ||
2993 | ssize_t result = 0; | ||
2994 | uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data; | ||
2995 | |||
2996 | if (size & 3 || *pos & 3) | ||
2997 | return -EINVAL; | ||
2998 | |||
2999 | /* decode offset */ | ||
3000 | offset = (*pos & 0xFFF); /* in dwords */ | ||
3001 | se = ((*pos >> 12) & 0xFF); | ||
3002 | sh = ((*pos >> 20) & 0xFF); | ||
3003 | cu = ((*pos >> 28) & 0xFF); | ||
3004 | wave = ((*pos >> 36) & 0xFF); | ||
3005 | simd = ((*pos >> 44) & 0xFF); | ||
3006 | thread = ((*pos >> 52) & 0xFF); | ||
3007 | bank = ((*pos >> 60) & 1); | ||
3008 | |||
3009 | data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL); | ||
3010 | if (!data) | ||
3011 | return -ENOMEM; | ||
3012 | |||
3013 | /* switch to the specific se/sh/cu */ | ||
3014 | mutex_lock(&adev->grbm_idx_mutex); | ||
3015 | amdgpu_gfx_select_se_sh(adev, se, sh, cu); | ||
3016 | |||
3017 | if (bank == 0) { | ||
3018 | if (adev->gfx.funcs->read_wave_vgprs) | ||
3019 | adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data); | ||
3020 | } else { | ||
3021 | if (adev->gfx.funcs->read_wave_sgprs) | ||
3022 | adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data); | ||
3023 | } | ||
3024 | |||
3025 | amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); | ||
3026 | mutex_unlock(&adev->grbm_idx_mutex); | ||
3027 | |||
3028 | while (size) { | ||
3029 | uint32_t value; | ||
3030 | |||
3031 | value = data[offset++]; | ||
3032 | r = put_user(value, (uint32_t *)buf); | ||
3033 | if (r) { | ||
3034 | result = r; | ||
3035 | goto err; | ||
3036 | } | ||
3037 | |||
3038 | result += 4; | ||
3039 | buf += 4; | ||
3040 | size -= 4; | ||
3041 | } | ||
3042 | |||
3043 | err: | ||
3044 | kfree(data); | ||
3045 | return result; | ||
3046 | } | ||
3047 | |||
2988 | static const struct file_operations amdgpu_debugfs_regs_fops = { | 3048 | static const struct file_operations amdgpu_debugfs_regs_fops = { |
2989 | .owner = THIS_MODULE, | 3049 | .owner = THIS_MODULE, |
2990 | .read = amdgpu_debugfs_regs_read, | 3050 | .read = amdgpu_debugfs_regs_read, |
@@ -3027,6 +3087,11 @@ static const struct file_operations amdgpu_debugfs_wave_fops = { | |||
3027 | .read = amdgpu_debugfs_wave_read, | 3087 | .read = amdgpu_debugfs_wave_read, |
3028 | .llseek = default_llseek | 3088 | .llseek = default_llseek |
3029 | }; | 3089 | }; |
3090 | static const struct file_operations amdgpu_debugfs_gpr_fops = { | ||
3091 | .owner = THIS_MODULE, | ||
3092 | .read = amdgpu_debugfs_gpr_read, | ||
3093 | .llseek = default_llseek | ||
3094 | }; | ||
3030 | 3095 | ||
3031 | static const struct file_operations *debugfs_regs[] = { | 3096 | static const struct file_operations *debugfs_regs[] = { |
3032 | &amdgpu_debugfs_regs_fops, | 3097 | &amdgpu_debugfs_regs_fops, |
@@ -3036,6 +3101,7 @@ static const struct file_operations *debugfs_regs[] = { | |||
3036 | &amdgpu_debugfs_gca_config_fops, | 3101 | &amdgpu_debugfs_gca_config_fops, |
3037 | &amdgpu_debugfs_sensors_fops, | 3102 | &amdgpu_debugfs_sensors_fops, |
3038 | &amdgpu_debugfs_wave_fops, | 3103 | &amdgpu_debugfs_wave_fops, |
3104 | &amdgpu_debugfs_gpr_fops, | ||
3039 | }; | 3105 | }; |
3040 | 3106 | ||
3041 | static const char *debugfs_regs_names[] = { | 3107 | static const char *debugfs_regs_names[] = { |
@@ -3046,6 +3112,7 @@ static const char *debugfs_regs_names[] = { | |||
3046 | "amdgpu_gca_config", | 3112 | "amdgpu_gca_config", |
3047 | "amdgpu_sensors", | 3113 | "amdgpu_sensors", |
3048 | "amdgpu_wave", | 3114 | "amdgpu_wave", |
3115 | "amdgpu_gpr", | ||
3049 | }; | 3116 | }; |
3050 | 3117 | ||
3051 | static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) | 3118 | static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index e90e541581e2..6324f67bdb1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | |||
@@ -5184,6 +5184,21 @@ static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_ | |||
5184 | return RREG32(mmSQ_IND_DATA); | 5184 | return RREG32(mmSQ_IND_DATA); |
5185 | } | 5185 | } |
5186 | 5186 | ||
5187 | static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd, | ||
5188 | uint32_t wave, uint32_t thread, | ||
5189 | uint32_t regno, uint32_t num, uint32_t *out) | ||
5190 | { | ||
5191 | WREG32(mmSQ_IND_INDEX, | ||
5192 | (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) | | ||
5193 | (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) | | ||
5194 | (regno << SQ_IND_INDEX__INDEX__SHIFT) | | ||
5195 | (thread << SQ_IND_INDEX__THREAD_ID__SHIFT) | | ||
5196 | (SQ_IND_INDEX__FORCE_READ_MASK) | | ||
5197 | (SQ_IND_INDEX__AUTO_INCR_MASK)); | ||
5198 | while (num--) | ||
5199 | *(out++) = RREG32(mmSQ_IND_DATA); | ||
5200 | } | ||
5201 | |||
5187 | static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) | 5202 | static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) |
5188 | { | 5203 | { |
5189 | /* type 0 wave data */ | 5204 | /* type 0 wave data */ |
@@ -5208,11 +5223,21 @@ static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, u | |||
5208 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); | 5223 | dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0); |
5209 | } | 5224 | } |
5210 | 5225 | ||
5226 | static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd, | ||
5227 | uint32_t wave, uint32_t start, | ||
5228 | uint32_t size, uint32_t *dst) | ||
5229 | { | ||
5230 | wave_read_regs( | ||
5231 | adev, simd, wave, 0, | ||
5232 | start + SQIND_WAVE_SGPRS_OFFSET, size, dst); | ||
5233 | } | ||
5234 | |||
5211 | 5235 | ||
5212 | static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = { | 5236 | static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = { |
5213 | .get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter, | 5237 | .get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter, |
5214 | .select_se_sh = &gfx_v8_0_select_se_sh, | 5238 | .select_se_sh = &gfx_v8_0_select_se_sh, |
5215 | .read_wave_data = &gfx_v8_0_read_wave_data, | 5239 | .read_wave_data = &gfx_v8_0_read_wave_data, |
5240 | .read_wave_sgprs = &gfx_v8_0_read_wave_sgprs, | ||
5216 | }; | 5241 | }; |
5217 | 5242 | ||
5218 | static int gfx_v8_0_early_init(void *handle) | 5243 | static int gfx_v8_0_early_init(void *handle) |