aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c82
1 files changed, 69 insertions, 13 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 1d99a4205958..4201f3dfaece 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -704,6 +704,17 @@ static const u32 stoney_mgcg_cgcg_init[] =
704 mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96940200, 704 mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96940200,
705}; 705};
706 706
707
708static const char * const sq_edc_source_names[] = {
709 "SQ_EDC_INFO_SOURCE_INVALID: No EDC error has occurred",
710 "SQ_EDC_INFO_SOURCE_INST: EDC source is Instruction Fetch",
711 "SQ_EDC_INFO_SOURCE_SGPR: EDC source is SGPR or SQC data return",
712 "SQ_EDC_INFO_SOURCE_VGPR: EDC source is VGPR",
713 "SQ_EDC_INFO_SOURCE_LDS: EDC source is LDS",
714 "SQ_EDC_INFO_SOURCE_GDS: EDC source is GDS",
715 "SQ_EDC_INFO_SOURCE_TA: EDC source is TA",
716};
717
707static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev); 718static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev);
708static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev); 719static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev);
709static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev); 720static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev);
@@ -2006,6 +2017,8 @@ static int gfx_v8_0_compute_ring_init(struct amdgpu_device *adev, int ring_id,
2006 return 0; 2017 return 0;
2007} 2018}
2008 2019
2020static void gfx_v8_0_sq_irq_work_func(struct work_struct *work);
2021
2009static int gfx_v8_0_sw_init(void *handle) 2022static int gfx_v8_0_sw_init(void *handle)
2010{ 2023{
2011 int i, j, k, r, ring_id; 2024 int i, j, k, r, ring_id;
@@ -2069,6 +2082,8 @@ static int gfx_v8_0_sw_init(void *handle)
2069 return r; 2082 return r;
2070 } 2083 }
2071 2084
2085 INIT_WORK(&adev->gfx.sq_work.work, gfx_v8_0_sq_irq_work_func);
2086
2072 adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE; 2087 adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE;
2073 2088
2074 gfx_v8_0_scratch_init(adev); 2089 gfx_v8_0_scratch_init(adev);
@@ -6955,14 +6970,11 @@ static int gfx_v8_0_cp_ecc_error_irq(struct amdgpu_device *adev,
6955 return 0; 6970 return 0;
6956} 6971}
6957 6972
6958static int gfx_v8_0_sq_irq(struct amdgpu_device *adev, 6973static void gfx_v8_0_parse_sq_irq(struct amdgpu_device *adev, unsigned ih_data)
6959 struct amdgpu_irq_src *source,
6960 struct amdgpu_iv_entry *entry)
6961{ 6974{
6962 u8 enc, se_id; 6975 u32 enc, se_id, sh_id, cu_id;
6963 char type[20]; 6976 char type[20];
6964 unsigned ih_data = entry->src_data[0]; 6977 int sq_edc_source = -1;
6965
6966 6978
6967 enc = REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_CMN, ENCODING); 6979 enc = REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_CMN, ENCODING);
6968 se_id = REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_CMN, SE_ID); 6980 se_id = REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_CMN, SE_ID);
@@ -6988,6 +7000,24 @@ static int gfx_v8_0_sq_irq(struct amdgpu_device *adev,
6988 case 1: 7000 case 1:
6989 case 2: 7001 case 2:
6990 7002
7003 cu_id = REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, CU_ID);
7004 sh_id = REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, SH_ID);
7005
7006 /*
7007 * This function can be called either directly from ISR
7008 * or from BH in which case we can access SQ_EDC_INFO
7009 * instance
7010 */
7011 if (in_task()) {
7012 mutex_lock(&adev->grbm_idx_mutex);
7013 gfx_v8_0_select_se_sh(adev, se_id, sh_id, cu_id);
7014
7015 sq_edc_source = REG_GET_FIELD(RREG32(mmSQ_EDC_INFO), SQ_EDC_INFO, SOURCE);
7016
7017 gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
7018 mutex_unlock(&adev->grbm_idx_mutex);
7019 }
7020
6991 if (enc == 1) 7021 if (enc == 1)
6992 sprintf(type, "instruction intr"); 7022 sprintf(type, "instruction intr");
6993 else 7023 else
@@ -6995,20 +7025,46 @@ static int gfx_v8_0_sq_irq(struct amdgpu_device *adev,
6995 7025
6996 DRM_INFO( 7026 DRM_INFO(
6997 "SQ %s detected: " 7027 "SQ %s detected: "
6998 "se_id %d, cu_id %d, simd_id %d, wave_id %d, vm_id %d\n" 7028 "se_id %d, sh_id %d, cu_id %d, simd_id %d, wave_id %d, vm_id %d "
6999 "trap %s, sh_id %d. ", 7029 "trap %s, sq_ed_info.source %s.\n",
7000 type, se_id, 7030 type, se_id, sh_id, cu_id,
7001 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, CU_ID),
7002 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, SIMD_ID), 7031 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, SIMD_ID),
7003 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, WAVE_ID), 7032 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, WAVE_ID),
7004 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, VM_ID), 7033 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, VM_ID),
7005 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, PRIV) ? "true" : "false", 7034 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, PRIV) ? "true" : "false",
7006 REG_GET_FIELD(ih_data, SQ_INTERRUPT_WORD_WAVE, SH_ID) 7035 (sq_edc_source != -1) ? sq_edc_source_names[sq_edc_source] : "unavailable"
7007 ); 7036 );
7008 break; 7037 break;
7009 default: 7038 default:
7010 DRM_ERROR("SQ invalid encoding type\n."); 7039 DRM_ERROR("SQ invalid encoding type\n.");
7011 return -EINVAL; 7040 }
7041}
7042
7043static void gfx_v8_0_sq_irq_work_func(struct work_struct *work)
7044{
7045
7046 struct amdgpu_device *adev = container_of(work, struct amdgpu_device, gfx.sq_work.work);
7047 struct sq_work *sq_work = container_of(work, struct sq_work, work);
7048
7049 gfx_v8_0_parse_sq_irq(adev, sq_work->ih_data);
7050}
7051
7052static int gfx_v8_0_sq_irq(struct amdgpu_device *adev,
7053 struct amdgpu_irq_src *source,
7054 struct amdgpu_iv_entry *entry)
7055{
7056 unsigned ih_data = entry->src_data[0];
7057
7058 /*
7059 * Try to submit work so SQ_EDC_INFO can be accessed from
7060 * BH. If previous work submission hasn't finished yet
7061 * just print whatever info is possible directly from the ISR.
7062 */
7063 if (work_pending(&adev->gfx.sq_work.work)) {
7064 gfx_v8_0_parse_sq_irq(adev, ih_data);
7065 } else {
7066 adev->gfx.sq_work.ih_data = ih_data;
7067 schedule_work(&adev->gfx.sq_work.work);
7012 } 7068 }
7013 7069
7014 return 0; 7070 return 0;