From 6524e494a8acf1a281f349e6f726918d41b5a8de Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 7 Apr 2017 14:56:58 +0800 Subject: [PATCH 001/144] drm/amd/powerplay: align with VBIOS to support new AVFS structure Align the driver with the latest vbios structures. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/ppatomfwctrl.c | 21 ++--- .../drm/amd/powerplay/hwmgr/ppatomfwctrl.h | 24 ++--- .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 89 ++++++++++--------- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c index b71525f838e6..de3d8f3f052b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c @@ -314,52 +314,45 @@ int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, le32_to_cpu(profile->gb_vdroop_table_ckson_a2); param->ulGbFuseTableCksoffM1 = le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1); - param->usGbFuseTableCksoffM2 = + param->ulGbFuseTableCksoffM2 = le16_to_cpu(profile->avfsgb_fuse_table_cksoff_m2); param->ulGbFuseTableCksoffB = le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b); param->ulGbFuseTableCksonM1 = le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1); - param->usGbFuseTableCksonM2 = + param->ulGbFuseTableCksonM2 = le16_to_cpu(profile->avfsgb_fuse_table_ckson_m2); param->ulGbFuseTableCksonB = le32_to_cpu(profile->avfsgb_fuse_table_ckson_b); - param->usMaxVoltage025mv = - le16_to_cpu(profile->max_voltage_0_25mv); - param->ucEnableGbVdroopTableCksoff = - profile->enable_gb_vdroop_table_cksoff; + param->ucEnableGbVdroopTableCkson = profile->enable_gb_vdroop_table_ckson; - param->ucEnableGbFuseTableCksoff = - profile->enable_gb_fuse_table_cksoff; param->ucEnableGbFuseTableCkson = profile->enable_gb_fuse_table_ckson; param->usPsmAgeComfactor = le16_to_cpu(profile->psm_age_comfactor); - param->ucEnableApplyAvfsCksoffVoltage = - profile->enable_apply_avfs_cksoff_voltage; param->ulDispclk2GfxclkM1 = le32_to_cpu(profile->dispclk2gfxclk_a); - param->usDispclk2GfxclkM2 = + param->ulDispclk2GfxclkM2 = le16_to_cpu(profile->dispclk2gfxclk_b); param->ulDispclk2GfxclkB = le32_to_cpu(profile->dispclk2gfxclk_c); param->ulDcefclk2GfxclkM1 = le32_to_cpu(profile->dcefclk2gfxclk_a); - param->usDcefclk2GfxclkM2 = + param->ulDcefclk2GfxclkM2 = le16_to_cpu(profile->dcefclk2gfxclk_b); param->ulDcefclk2GfxclkB = le32_to_cpu(profile->dcefclk2gfxclk_c); param->ulPixelclk2GfxclkM1 = le32_to_cpu(profile->pixclk2gfxclk_a); - param->usPixelclk2GfxclkM2 = + param->ulPixelclk2GfxclkM2 = le16_to_cpu(profile->pixclk2gfxclk_b); param->ulPixelclk2GfxclkB = le32_to_cpu(profile->pixclk2gfxclk_c); param->ulPhyclk2GfxclkM1 = le32_to_cpu(profile->phyclk2gfxclk_a); - param->usPhyclk2GfxclkM2 = + param->ulPhyclk2GfxclkM2 = le16_to_cpu(profile->phyclk2gfxclk_b); param->ulPhyclk2GfxclkB = le32_to_cpu(profile->phyclk2gfxclk_c); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h index 7efe9b96cb33..be1579e87caf 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h @@ -69,7 +69,7 @@ struct pp_atomfwctrl_clock_dividers_soc15 { struct pp_atomfwctrl_avfs_parameters { uint32_t ulMaxVddc; uint32_t ulMinVddc; - uint8_t ucMaxVidStep; + uint32_t ulMeanNsigmaAcontant0; uint32_t ulMeanNsigmaAcontant1; uint32_t ulMeanNsigmaAcontant2; @@ -82,30 +82,30 @@ struct pp_atomfwctrl_avfs_parameters { uint32_t ulGbVdroopTableCksonA0; uint32_t ulGbVdroopTableCksonA1; uint32_t ulGbVdroopTableCksonA2; + uint32_t ulGbFuseTableCksoffM1; - uint16_t usGbFuseTableCksoffM2; - uint32_t ulGbFuseTableCksoffB;\ + uint32_t ulGbFuseTableCksoffM2; + uint32_t ulGbFuseTableCksoffB; + uint32_t ulGbFuseTableCksonM1; - uint16_t usGbFuseTableCksonM2; + uint32_t ulGbFuseTableCksonM2; uint32_t ulGbFuseTableCksonB; - uint16_t usMaxVoltage025mv; - uint8_t ucEnableGbVdroopTableCksoff; + uint8_t ucEnableGbVdroopTableCkson; - uint8_t ucEnableGbFuseTableCksoff; uint8_t ucEnableGbFuseTableCkson; uint16_t usPsmAgeComfactor; - uint8_t ucEnableApplyAvfsCksoffVoltage; + uint32_t ulDispclk2GfxclkM1; - uint16_t usDispclk2GfxclkM2; + uint32_t ulDispclk2GfxclkM2; uint32_t ulDispclk2GfxclkB; uint32_t ulDcefclk2GfxclkM1; - uint16_t usDcefclk2GfxclkM2; + uint32_t ulDcefclk2GfxclkM2; uint32_t ulDcefclk2GfxclkB; uint32_t ulPixelclk2GfxclkM1; - uint16_t usPixelclk2GfxclkM2; + uint32_t ulPixelclk2GfxclkM2; uint32_t ulPixelclk2GfxclkB; uint32_t ulPhyclk2GfxclkM1; - uint16_t usPhyclk2GfxclkM2; + uint32_t ulPhyclk2GfxclkM2; uint32_t ulPhyclk2GfxclkB; }; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 83949550edac..561b837b09be 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -2073,66 +2073,70 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); if (!result) { pp_table->MinVoltageVid = (uint8_t) - convert_to_vid((uint16_t)(avfs_params.ulMaxVddc)); - pp_table->MaxVoltageVid = (uint8_t) convert_to_vid((uint16_t)(avfs_params.ulMinVddc)); - pp_table->BtcGbVdroopTableCksOn.a0 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0); - pp_table->BtcGbVdroopTableCksOn.a1 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1); - pp_table->BtcGbVdroopTableCksOn.a2 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2); + pp_table->MaxVoltageVid = (uint8_t) + convert_to_vid((uint16_t)(avfs_params.ulMaxVddc)); + + pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0); + pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1); + pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2); + pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); + pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean); + pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); + pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor); pp_table->BtcGbVdroopTableCksOff.a0 = cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0); + pp_table->BtcGbVdroopTableCksOff.a0_shift = 20; pp_table->BtcGbVdroopTableCksOff.a1 = cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1); + pp_table->BtcGbVdroopTableCksOff.a1_shift = 20; pp_table->BtcGbVdroopTableCksOff.a2 = cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2); + pp_table->BtcGbVdroopTableCksOff.a2_shift = 20; + + pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson; + pp_table->BtcGbVdroopTableCksOn.a0 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0); + pp_table->BtcGbVdroopTableCksOn.a0_shift = 20; + pp_table->BtcGbVdroopTableCksOn.a1 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1); + pp_table->BtcGbVdroopTableCksOn.a1_shift = 20; + pp_table->BtcGbVdroopTableCksOn.a2 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2); + pp_table->BtcGbVdroopTableCksOn.a2_shift = 20; pp_table->AvfsGbCksOn.m1 = cpu_to_le32(avfs_params.ulGbFuseTableCksonM1); pp_table->AvfsGbCksOn.m2 = - cpu_to_le16(avfs_params.usGbFuseTableCksonM2); + cpu_to_le16(avfs_params.ulGbFuseTableCksonM2); pp_table->AvfsGbCksOn.b = cpu_to_le32(avfs_params.ulGbFuseTableCksonB); pp_table->AvfsGbCksOn.m1_shift = 24; pp_table->AvfsGbCksOn.m2_shift = 12; + pp_table->AvfsGbCksOn.b_shift = 0; + pp_table->OverrideAvfsGbCksOn = + avfs_params.ucEnableGbFuseTableCkson; pp_table->AvfsGbCksOff.m1 = cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1); pp_table->AvfsGbCksOff.m2 = - cpu_to_le16(avfs_params.usGbFuseTableCksoffM2); + cpu_to_le16(avfs_params.ulGbFuseTableCksoffM2); pp_table->AvfsGbCksOff.b = cpu_to_le32(avfs_params.ulGbFuseTableCksoffB); pp_table->AvfsGbCksOff.m1_shift = 24; pp_table->AvfsGbCksOff.m2_shift = 12; + pp_table->AvfsGbCksOff.b_shift = 0; - pp_table->AConstant[0] = - cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0); - pp_table->AConstant[1] = - cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1); - pp_table->AConstant[2] = - cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2); - pp_table->DC_tol_sigma = - cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); - pp_table->Platform_mean = - cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean); - pp_table->PSM_Age_CompFactor = - cpu_to_le16(avfs_params.usPsmAgeComfactor); - pp_table->Platform_sigma = - cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); - - for (i = 0; i < dep_table->count; i++) - pp_table->StaticVoltageOffsetVid[i] = (uint8_t) - (dep_table->entries[i].sclk_offset * + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].sclk_offset == 0) + pp_table->StaticVoltageOffsetVid[i] = 248; + else + pp_table->StaticVoltageOffsetVid[i] = + (uint8_t)(dep_table->entries[i].sclk_offset * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - pp_table->OverrideBtcGbCksOn = - avfs_params.ucEnableGbVdroopTableCkson; - pp_table->OverrideAvfsGbCksOn = - avfs_params.ucEnableGbFuseTableCkson; + } if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != data->disp_clk_quad_eqn_a) && @@ -2141,20 +2145,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = (int32_t)data->disp_clk_quad_eqn_a; pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = - (int16_t)data->disp_clk_quad_eqn_b; + (int32_t)data->disp_clk_quad_eqn_b; pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = (int32_t)data->disp_clk_quad_eqn_c; } else { pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = (int32_t)avfs_params.ulDispclk2GfxclkM1; pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = - (int16_t)avfs_params.usDispclk2GfxclkM2; + (int32_t)avfs_params.ulDispclk2GfxclkM2; pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = (int32_t)avfs_params.ulDispclk2GfxclkB; } pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 0; if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != data->dcef_clk_quad_eqn_a) && @@ -2163,20 +2168,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = (int32_t)data->dcef_clk_quad_eqn_a; pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = - (int16_t)data->dcef_clk_quad_eqn_b; + (int32_t)data->dcef_clk_quad_eqn_b; pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = (int32_t)data->dcef_clk_quad_eqn_c; } else { pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = (int32_t)avfs_params.ulDcefclk2GfxclkM1; pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = - (int16_t)avfs_params.usDcefclk2GfxclkM2; + (int32_t)avfs_params.ulDcefclk2GfxclkM2; pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = (int32_t)avfs_params.ulDcefclk2GfxclkB; } pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 0; if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != data->pixel_clk_quad_eqn_a) && @@ -2185,14 +2191,14 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = (int32_t)data->pixel_clk_quad_eqn_a; pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = - (int16_t)data->pixel_clk_quad_eqn_b; + (int32_t)data->pixel_clk_quad_eqn_b; pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = (int32_t)data->pixel_clk_quad_eqn_c; } else { pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = (int32_t)avfs_params.ulPixelclk2GfxclkM1; pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = - (int16_t)avfs_params.usPixelclk2GfxclkM2; + (int32_t)avfs_params.ulPixelclk2GfxclkM2; pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = (int32_t)avfs_params.ulPixelclk2GfxclkB; } @@ -2207,20 +2213,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = (int32_t)data->phy_clk_quad_eqn_a; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = - (int16_t)data->phy_clk_quad_eqn_b; + (int32_t)data->phy_clk_quad_eqn_b; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = (int32_t)data->phy_clk_quad_eqn_c; } else { pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = (int32_t)avfs_params.ulPhyclk2GfxclkM1; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = - (int16_t)avfs_params.usPhyclk2GfxclkM2; + (int32_t)avfs_params.ulPhyclk2GfxclkM2; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = (int32_t)avfs_params.ulPhyclk2GfxclkB; } pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 0; } else { data->smu_features[GNLD_AVFS].supported = false; } From 6f2b1fcccb6dad1d68c0955144af3ad56bacb25c Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Mar 2017 16:18:11 +0800 Subject: [PATCH 002/144] drm/amdgpu: split psp tmr init function Rework in order to properly support suspend. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 27 ++++++++++++++++--------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index ed6e5799016e..6aba417b7c95 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -152,11 +152,6 @@ static void psp_prep_tmr_cmd_buf(struct psp_gfx_cmd_resp *cmd, static int psp_tmr_init(struct psp_context *psp) { int ret; - struct psp_gfx_cmd_resp *cmd; - - cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); - if (!cmd) - return -ENOMEM; /* * Allocate 3M memory aligned to 1M from Frame Buffer (local @@ -168,22 +163,30 @@ static int psp_tmr_init(struct psp_context *psp) ret = amdgpu_bo_create_kernel(psp->adev, 0x300000, 0x100000, AMDGPU_GEM_DOMAIN_VRAM, &psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); - if (ret) - goto failed; + + return ret; +} + +static int psp_tmr_load(struct psp_context *psp) +{ + int ret; + struct psp_gfx_cmd_resp *cmd; + + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); + if (!cmd) + return -ENOMEM; psp_prep_tmr_cmd_buf(cmd, psp->tmr_mc_addr, 0x300000); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr, 1); if (ret) - goto failed_mem; + goto failed; kfree(cmd); return 0; -failed_mem: - amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); failed: kfree(cmd); return ret; @@ -298,6 +301,10 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) goto failed_mem; + ret = psp_tmr_load(psp); + if (ret) + goto failed_mem; + ret = psp_asd_load(psp); if (ret) goto failed_mem; From 53a5cf57d819f12b2de365aa3137c9175a032608 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Mar 2017 16:51:00 +0800 Subject: [PATCH 003/144] drm/amdgpu: add psp firmware private memory Needed for proper suspend support. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 23 +++++++++++++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 6 ++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 6aba417b7c95..f70ab550934c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -275,17 +275,25 @@ static int psp_load_fw(struct amdgpu_device *adev) if (!cmd) return -ENOMEM; - ret = psp_bootloader_load_sysdrv(psp); + ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, + AMDGPU_GEM_DOMAIN_GTT, + &psp->fw_pri_bo, + &psp->fw_pri_mc_addr, + &psp->fw_pri_buf); if (ret) goto failed; + ret = psp_bootloader_load_sysdrv(psp); + if (ret) + goto failed_mem1; + ret = psp_bootloader_load_sos(psp); if (ret) - goto failed; + goto failed_mem1; ret = psp_ring_init(psp, PSP_RING_TYPE__KM); if (ret) - goto failed; + goto failed_mem1; ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, @@ -293,7 +301,7 @@ static int psp_load_fw(struct amdgpu_device *adev) &psp->fence_buf_mc_addr, &psp->fence_buf); if (ret) - goto failed; + goto failed_mem1; memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE); @@ -343,6 +351,9 @@ static int psp_load_fw(struct amdgpu_device *adev) failed_mem: amdgpu_bo_free_kernel(&psp->fence_buf_bo, &psp->fence_buf_mc_addr, &psp->fence_buf); +failed_mem1: + amdgpu_bo_free_kernel(&psp->fw_pri_bo, + &psp->fw_pri_mc_addr, &psp->fw_pri_buf); failed: kfree(cmd); return ret; @@ -392,6 +403,10 @@ static int psp_hw_fini(void *handle) if (psp->tmr_buf) amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); + if (psp->fw_pri_buf) + amdgpu_bo_free_kernel(&psp->fw_pri_bo, + &psp->fw_pri_mc_addr, &psp->fw_pri_buf); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index e9f35e025b59..b309b6a62c65 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -32,6 +32,7 @@ #define PSP_CMD_BUFFER_SIZE 0x1000 #define PSP_ASD_BIN_SIZE 0x40000 #define PSP_ASD_SHARED_MEM_SIZE 0x4000 +#define PSP_1_MEG 0x100000 enum psp_ring_type { @@ -71,6 +72,11 @@ struct psp_context enum AMDGPU_UCODE_ID ucode_type); bool (*smu_reload_quirk)(struct psp_context *psp); + /* fence buffer */ + struct amdgpu_bo *fw_pri_bo; + uint64_t fw_pri_mc_addr; + void *fw_pri_buf; + /* sos firmware */ const struct firmware *sos_fw; uint32_t sos_fw_version; From 2b0c3aee2172451e9f982b25f3fdf59a1b687dc3 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 22 Mar 2017 10:16:05 +0800 Subject: [PATCH 004/144] drm/amdgpu: use private memory to store psp firmware data Rework in order to properly support suspend. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 28 +++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 1 - drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 48 +++++-------------------- 3 files changed, 16 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index f70ab550934c..ed9c04b7a286 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -209,9 +209,9 @@ static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd, static int psp_asd_load(struct psp_context *psp) { int ret; - struct amdgpu_bo *asd_bo, *asd_shared_bo; - uint64_t asd_mc_addr, asd_shared_mc_addr; - void *asd_buf, *asd_shared_buf; + struct amdgpu_bo *asd_shared_bo; + uint64_t asd_shared_mc_addr; + void *asd_shared_buf; struct psp_gfx_cmd_resp *cmd; cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); @@ -224,38 +224,26 @@ static int psp_asd_load(struct psp_context *psp) */ ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, - &asd_shared_bo, &asd_shared_mc_addr, &asd_buf); + &asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); if (ret) goto failed; - /* - * Allocate 256k memory aligned to 4k from Frame Buffer (local - * physical) for ASD firmware - */ - ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_BIN_SIZE, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &asd_bo, &asd_mc_addr, &asd_buf); - if (ret) - goto failed_mem; + memset(psp->fw_pri_buf, 0, PSP_1_MEG); + memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size); - memcpy(asd_buf, psp->asd_start_addr, psp->asd_ucode_size); - - psp_prep_asd_cmd_buf(cmd, asd_mc_addr, asd_shared_mc_addr, + psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, asd_shared_mc_addr, psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr, 2); if (ret) - goto failed_mem1; + goto failed_mem; - amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf); amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); kfree(cmd); return 0; -failed_mem1: - amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf); failed_mem: amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); failed: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index b309b6a62c65..125a5dc0c0e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -30,7 +30,6 @@ #define PSP_FENCE_BUFFER_SIZE 0x1000 #define PSP_CMD_BUFFER_SIZE 0x1000 -#define PSP_ASD_BIN_SIZE 0x40000 #define PSP_ASD_SHARED_MEM_SIZE 0x4000 #define PSP_1_MEG 0x100000 diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index c3588d1c7cb0..aae6b6540161 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -166,11 +166,8 @@ int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp) { int ret; uint32_t psp_gfxdrv_command_reg = 0; - struct amdgpu_bo *psp_sysdrv; - void *psp_sysdrv_virt = NULL; - uint64_t psp_sysdrv_mem; struct amdgpu_device *adev = psp->adev; - uint32_t size, sol_reg; + uint32_t sol_reg; /* Check sOS sign of life register to confirm sys driver and sOS * are already been loaded. @@ -185,27 +182,14 @@ int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp) if (ret) return ret; - /* - * Create a 1 meg GART memory to store the psp sys driver - * binary with a 1 meg aligned address - */ - size = (psp->sys_bin_size + (PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)) & - (~(PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)); - - ret = amdgpu_bo_create_kernel(adev, size, PSP_BOOTLOADER_1_MEG_ALIGNMENT, - AMDGPU_GEM_DOMAIN_GTT, - &psp_sysdrv, - &psp_sysdrv_mem, - &psp_sysdrv_virt); - if (ret) - return ret; + memset(psp->fw_pri_buf, 0, PSP_1_MEG); /* Copy PSP System Driver binary to memory */ - memcpy(psp_sysdrv_virt, psp->sys_start_addr, psp->sys_bin_size); + memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size); /* Provide the sys driver to bootrom */ WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_36), - (uint32_t)(psp_sysdrv_mem >> 20)); + (uint32_t)(psp->fw_pri_mc_addr >> 20)); psp_gfxdrv_command_reg = 1 << 16; WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), psp_gfxdrv_command_reg); @@ -216,8 +200,6 @@ int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp) ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), 0x80000000, 0x80000000, false); - amdgpu_bo_free_kernel(&psp_sysdrv, &psp_sysdrv_mem, &psp_sysdrv_virt); - return ret; } @@ -225,11 +207,8 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp) { int ret; unsigned int psp_gfxdrv_command_reg = 0; - struct amdgpu_bo *psp_sos; - void *psp_sos_virt = NULL; - uint64_t psp_sos_mem; struct amdgpu_device *adev = psp->adev; - uint32_t size, sol_reg; + uint32_t sol_reg; /* Check sOS sign of life register to confirm sys driver and sOS * are already been loaded. @@ -244,23 +223,14 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp) if (ret) return ret; - size = (psp->sos_bin_size + (PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)) & - (~((uint64_t)PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)); - - ret = amdgpu_bo_create_kernel(adev, size, PSP_BOOTLOADER_1_MEG_ALIGNMENT, - AMDGPU_GEM_DOMAIN_GTT, - &psp_sos, - &psp_sos_mem, - &psp_sos_virt); - if (ret) - return ret; + memset(psp->fw_pri_buf, 0, PSP_1_MEG); /* Copy Secure OS binary to PSP memory */ - memcpy(psp_sos_virt, psp->sos_start_addr, psp->sos_bin_size); + memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size); /* Provide the PSP secure OS to bootrom */ WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_36), - (uint32_t)(psp_sos_mem >> 20)); + (uint32_t)(psp->fw_pri_mc_addr >> 20)); psp_gfxdrv_command_reg = 2 << 16; WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), psp_gfxdrv_command_reg); @@ -273,8 +243,6 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp) 0, true); #endif - amdgpu_bo_free_kernel(&psp_sos, &psp_sos_mem, &psp_sos_virt); - return ret; } From f5cfef98f736f9aa42e9ad41e67b5abd96b77835 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Mar 2017 18:02:04 +0800 Subject: [PATCH 005/144] drm/amdgpu: split psp asd function Rework in order to properly support suspend. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 45 ++++++++++++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 5 ++- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index ed9c04b7a286..ea5616036bf6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -206,48 +206,43 @@ static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd, cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; } +static int psp_asd_init(struct psp_context *psp) +{ + int ret; + + /* + * Allocate 16k memory aligned to 4k from Frame Buffer (local + * physical) for shared ASD <-> Driver + */ + ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, + &psp->asd_shared_bo, + &psp->asd_shared_mc_addr, + &psp->asd_shared_buf); + + return ret; +} + static int psp_asd_load(struct psp_context *psp) { int ret; - struct amdgpu_bo *asd_shared_bo; - uint64_t asd_shared_mc_addr; - void *asd_shared_buf; struct psp_gfx_cmd_resp *cmd; cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); if (!cmd) return -ENOMEM; - /* - * Allocate 16k memory aligned to 4k from Frame Buffer (local - * physical) for shared ASD <-> Driver - */ - ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); - if (ret) - goto failed; - memset(psp->fw_pri_buf, 0, PSP_1_MEG); memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size); - psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, asd_shared_mc_addr, + psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->asd_shared_mc_addr, psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr, 2); - if (ret) - goto failed_mem; - amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); kfree(cmd); - return 0; - -failed_mem: - amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); -failed: - kfree(cmd); return ret; } @@ -301,6 +296,10 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) goto failed_mem; + ret = psp_asd_init(psp); + if (ret) + goto failed_mem; + ret = psp_asd_load(psp); if (ret) goto failed_mem; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 125a5dc0c0e1..1f1f057c7c42 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -90,12 +90,15 @@ struct psp_context uint64_t tmr_mc_addr; void *tmr_buf; - /* asd firmware */ + /* asd firmware and buffer */ const struct firmware *asd_fw; uint32_t asd_fw_version; uint32_t asd_feature_version; uint32_t asd_ucode_size; uint8_t *asd_start_addr; + struct amdgpu_bo *asd_shared_bo; + uint64_t asd_shared_mc_addr; + void *asd_shared_buf; /* fence buffer */ struct amdgpu_bo *fence_buf_bo; From be70bbda3fb9a1b876ed80e2ebc292203eb0ffec Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 21 Mar 2017 18:36:57 +0800 Subject: [PATCH 006/144] drm/amdgpu: split psp ring init function Rework in order to properly support suspend. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 115 +++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 3 + drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 11 ++- drivers/gpu/drm/amd/amdgpu/psp_v3_1.h | 2 + 4 files changed, 87 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index ea5616036bf6..0d20dc3ea84e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -55,6 +55,7 @@ static int psp_sw_init(void *handle) psp->bootloader_load_sos = psp_v3_1_bootloader_load_sos; psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf; psp->ring_init = psp_v3_1_ring_init; + psp->ring_create = psp_v3_1_ring_create; psp->cmd_submit = psp_v3_1_cmd_submit; psp->compare_sram_data = psp_v3_1_compare_sram_data; psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk; @@ -246,18 +247,79 @@ static int psp_asd_load(struct psp_context *psp) return ret; } +static int psp_hw_start(struct psp_context *psp) +{ + int ret; + + ret = psp_bootloader_load_sysdrv(psp); + if (ret) + return ret; + + ret = psp_bootloader_load_sos(psp); + if (ret) + return ret; + + ret = psp_ring_create(psp, PSP_RING_TYPE__KM); + if (ret) + return ret; + + ret = psp_tmr_load(psp); + if (ret) + return ret; + + ret = psp_asd_load(psp); + if (ret) + return ret; + + return 0; +} + +static int psp_np_fw_load(struct psp_context *psp) +{ + int i, ret; + struct amdgpu_firmware_info *ucode; + struct amdgpu_device* adev = psp->adev; + + for (i = 0; i < adev->firmware.max_ucodes; i++) { + ucode = &adev->firmware.ucode[i]; + if (!ucode->fw) + continue; + + if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && + psp_smu_reload_quirk(psp)) + continue; + + ret = psp_prep_cmd_buf(ucode, psp->cmd); + if (ret) + return ret; + + ret = psp_cmd_submit_buf(psp, ucode, psp->cmd, + psp->fence_buf_mc_addr, i + 3); + if (ret) + return ret; + +#if 0 + /* check if firmware loaded sucessfully */ + if (!amdgpu_psp_check_fw_loading_status(adev, i)) + return -EINVAL; +#endif + } + + return 0; +} + static int psp_load_fw(struct amdgpu_device *adev) { int ret; - struct psp_gfx_cmd_resp *cmd; - int i; - struct amdgpu_firmware_info *ucode; struct psp_context *psp = &adev->psp; + struct psp_gfx_cmd_resp *cmd; cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); if (!cmd) return -ENOMEM; + psp->cmd = cmd; + ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG, AMDGPU_GEM_DOMAIN_GTT, &psp->fw_pri_bo, @@ -266,18 +328,6 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) goto failed; - ret = psp_bootloader_load_sysdrv(psp); - if (ret) - goto failed_mem1; - - ret = psp_bootloader_load_sos(psp); - if (ret) - goto failed_mem1; - - ret = psp_ring_init(psp, PSP_RING_TYPE__KM); - if (ret) - goto failed_mem1; - ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &psp->fence_buf_bo, @@ -288,11 +338,11 @@ static int psp_load_fw(struct amdgpu_device *adev) memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE); - ret = psp_tmr_init(psp); + ret = psp_ring_init(psp, PSP_RING_TYPE__KM); if (ret) - goto failed_mem; + goto failed_mem1; - ret = psp_tmr_load(psp); + ret = psp_tmr_init(psp); if (ret) goto failed_mem; @@ -300,34 +350,13 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) goto failed_mem; - ret = psp_asd_load(psp); + ret = psp_hw_start(psp); if (ret) goto failed_mem; - for (i = 0; i < adev->firmware.max_ucodes; i++) { - ucode = &adev->firmware.ucode[i]; - if (!ucode->fw) - continue; - - if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && - psp_smu_reload_quirk(psp)) - continue; - - ret = psp_prep_cmd_buf(ucode, cmd); - if (ret) - goto failed_mem; - - ret = psp_cmd_submit_buf(psp, ucode, cmd, - psp->fence_buf_mc_addr, i + 3); - if (ret) - goto failed_mem; - -#if 0 - /* check if firmware loaded sucessfully */ - if (!amdgpu_psp_check_fw_loading_status(adev, i)) - return -EINVAL; -#endif - } + ret = psp_np_fw_load(psp); + if (ret) + goto failed_mem; amdgpu_bo_free_kernel(&psp->fence_buf_bo, &psp->fence_buf_mc_addr, &psp->fence_buf); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 1f1f057c7c42..28faba5b7dd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -57,6 +57,7 @@ struct psp_context { struct amdgpu_device *adev; struct psp_ring km_ring; + struct psp_gfx_cmd_resp *cmd; int (*init_microcode)(struct psp_context *psp); int (*bootloader_load_sysdrv)(struct psp_context *psp); @@ -64,6 +65,7 @@ struct psp_context int (*prep_cmd_buf)(struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd); int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); + int (*ring_create)(struct psp_context *psp, enum psp_ring_type ring_type); int (*cmd_submit)(struct psp_context *psp, struct amdgpu_firmware_info *ucode, uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, int index); bool (*compare_sram_data)(struct psp_context *psp, @@ -113,6 +115,7 @@ struct amdgpu_psp_funcs { #define psp_prep_cmd_buf(ucode, type) (psp)->prep_cmd_buf((ucode), (type)) #define psp_ring_init(psp, type) (psp)->ring_init((psp), (type)) +#define psp_ring_create(psp, type) (psp)->ring_create((psp), (type)) #define psp_cmd_submit(psp, ucode, cmd_mc, fence_mc, index) \ (psp)->cmd_submit((psp), (ucode), (cmd_mc), (fence_mc), (index)) #define psp_compare_sram_data(psp, ucode, type) \ diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index aae6b6540161..d351583785e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -268,7 +268,6 @@ int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type) { int ret = 0; - unsigned int psp_ring_reg = 0; struct psp_ring *ring; struct amdgpu_device *adev = psp->adev; @@ -288,6 +287,16 @@ int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type) return ret; } + return 0; +} + +int psp_v3_1_ring_create(struct psp_context *psp, enum psp_ring_type ring_type) +{ + int ret = 0; + unsigned int psp_ring_reg = 0; + struct psp_ring *ring = &psp->km_ring; + struct amdgpu_device *adev = psp->adev; + /* Write low address of the ring to C2PMSG_69 */ psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_69), psp_ring_reg); diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h index e82eff741a08..5230d27867c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h @@ -39,6 +39,8 @@ extern int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd); extern int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type); +extern int psp_v3_1_ring_create(struct psp_context *psp, + enum psp_ring_type ring_type); extern int psp_v3_1_cmd_submit(struct psp_context *psp, struct amdgpu_firmware_info *ucode, uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, From 93ea9b9f7cec596adac13b944a122e4c69de18a4 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 23 Mar 2017 11:20:25 +0800 Subject: [PATCH 007/144] drm/amdgpu: add hw_start and non-psp firmware loading into resume Rework in order to properly support suspend. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 0d20dc3ea84e..68ccaedad0f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -435,18 +435,30 @@ static int psp_resume(void *handle) { int ret; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct psp_context *psp = &adev->psp; if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) return 0; + DRM_INFO("PSP is resuming...\n"); + mutex_lock(&adev->firmware.mutex); - ret = psp_load_fw(adev); + ret = psp_hw_start(psp); if (ret) - DRM_ERROR("PSP resume failed\n"); + goto failed; + + ret = psp_np_fw_load(psp); + if (ret) + goto failed; mutex_unlock(&adev->firmware.mutex); + return 0; + +failed: + DRM_ERROR("PSP resume failed\n"); + mutex_unlock(&adev->firmware.mutex); return ret; } From b1bb8c0118b3b9d44a6a31ea5242bdd9ed040a9b Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 7 Apr 2017 07:53:31 -0400 Subject: [PATCH 008/144] drm/amd/amdgpu: Introduce new read/write macros for SOC15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 --- drivers/gpu/drm/amd/amdgpu/soc15_common.h | 20 +++++++++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 6a8129949333..c4f6211640da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1704,9 +1704,6 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v); #define WREG32_FIELD_OFFSET(reg, offset, field, val) \ WREG32(mm##reg + offset, (RREG32(mm##reg + offset) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field)) -#define WREG32_FIELD15(ip, idx, reg, field, val) \ - WREG32(SOC15_REG_OFFSET(ip, idx, mm##reg), (RREG32(SOC15_REG_OFFSET(ip, idx, mm##reg)) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field)) - /* * BIOS helpers. */ diff --git a/drivers/gpu/drm/amd/amdgpu/soc15_common.h b/drivers/gpu/drm/amd/amdgpu/soc15_common.h index 2b96c806baa1..e8df6d820dbe 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15_common.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15_common.h @@ -45,13 +45,31 @@ struct nbio_pcie_index_data { u32 index_offset; u32 data_offset; }; -// Register Access Macro + +/* Register Access Macros */ #define SOC15_REG_OFFSET(ip, inst, reg) (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \ (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \ (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \ (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \ (ip##_BASE__INST##inst##_SEG4 + reg))))) +#define WREG32_FIELD15(ip, idx, reg, field, val) \ + WREG32(SOC15_REG_OFFSET(ip, idx, mm##reg), (RREG32(SOC15_REG_OFFSET(ip, idx, mm##reg)) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field)) + +#define RREG32_SOC15(ip, inst, reg) \ + RREG32( (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \ + (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \ + (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \ + (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \ + (ip##_BASE__INST##inst##_SEG4 + reg)))))) + +#define WREG32_SOC15(ip, inst, reg, value) \ + WREG32( (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \ + (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \ + (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \ + (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \ + (ip##_BASE__INST##inst##_SEG4 + reg))))), value) + #endif From 5e78835abdabc303ba980f50e9f71039e7689cc9 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 7 Apr 2017 07:53:53 -0400 Subject: [PATCH 009/144] drm/amd/amdgpu: Port gfx9 driver over to new read/write macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tom St Denis Acked-by: Christian König Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 406 +++++++++++++------------- 1 file changed, 203 insertions(+), 203 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index a447b70841c9..e58fb05bc904 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -705,19 +705,19 @@ static void gfx_v9_0_compute_mqd_sw_fini(struct amdgpu_device *adev) static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_INDEX), + WREG32_SOC15(GC, 0, mmSQ_IND_INDEX, (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) | (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) | (address << SQ_IND_INDEX__INDEX__SHIFT) | (SQ_IND_INDEX__FORCE_READ_MASK)); - return RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_DATA)); + return RREG32_SOC15(GC, 0, mmSQ_IND_DATA); } static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t thread, uint32_t regno, uint32_t num, uint32_t *out) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_INDEX), + WREG32_SOC15(GC, 0, mmSQ_IND_INDEX, (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) | (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) | (regno << SQ_IND_INDEX__INDEX__SHIFT) | @@ -725,7 +725,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd, (SQ_IND_INDEX__FORCE_READ_MASK) | (SQ_IND_INDEX__AUTO_INCR_MASK)); while (num--) - *(out++) = RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_DATA)); + *(out++) = RREG32_SOC15(GC, 0, mmSQ_IND_DATA); } static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields) @@ -953,7 +953,7 @@ static int gfx_v9_0_ngg_en(struct amdgpu_device *adev) size = adev->gfx.ngg.buf[POS].size / 256; data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, POS_BUF_SIZE, size); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_BUF_RESOURCE_1), data); + WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_1, data); data = 0; size = adev->gfx.ngg.buf[CNTL].size / 256; @@ -962,32 +962,32 @@ static int gfx_v9_0_ngg_en(struct amdgpu_device *adev) size = adev->gfx.ngg.buf[PARAM].size / 1024; data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, PARAM_BUF_SIZE, size); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_BUF_RESOURCE_2), data); + WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_2, data); /* Program buffer base address */ base = lower_32_bits(adev->gfx.ngg.buf[PRIM].gpu_addr); data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE, BASE, base); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_INDEX_BUF_BASE), data); + WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE, data); base = upper_32_bits(adev->gfx.ngg.buf[PRIM].gpu_addr); data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE_HI, BASE_HI, base); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_INDEX_BUF_BASE_HI), data); + WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE_HI, data); base = lower_32_bits(adev->gfx.ngg.buf[POS].gpu_addr); data = REG_SET_FIELD(0, WD_POS_BUF_BASE, BASE, base); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_POS_BUF_BASE), data); + WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE, data); base = upper_32_bits(adev->gfx.ngg.buf[POS].gpu_addr); data = REG_SET_FIELD(0, WD_POS_BUF_BASE_HI, BASE_HI, base); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_POS_BUF_BASE_HI), data); + WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE_HI, data); base = lower_32_bits(adev->gfx.ngg.buf[CNTL].gpu_addr); data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE, BASE, base); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_CNTL_SB_BUF_BASE), data); + WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE, data); base = upper_32_bits(adev->gfx.ngg.buf[CNTL].gpu_addr); data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE_HI, BASE_HI, base); - WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_CNTL_SB_BUF_BASE_HI), data); + WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE_HI, data); /* Clear GDS reserved memory */ r = amdgpu_ring_alloc(ring, 17); @@ -1203,7 +1203,7 @@ static void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh data = REG_SET_FIELD(data, GRBM_GFX_INDEX, SH_INDEX, sh_num); data = REG_SET_FIELD(data, GRBM_GFX_INDEX, SE_INDEX, se_num); } - WREG32( SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX), data); + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); } static u32 gfx_v9_0_create_bitmask(u32 bit_width) @@ -1215,8 +1215,8 @@ static u32 gfx_v9_0_get_rb_active_bitmap(struct amdgpu_device *adev) { u32 data, mask; - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCC_RB_BACKEND_DISABLE)); - data |= RREG32(SOC15_REG_OFFSET(GC, 0, mmGC_USER_RB_BACKEND_DISABLE)); + data = RREG32_SOC15(GC, 0, mmCC_RB_BACKEND_DISABLE); + data |= RREG32_SOC15(GC, 0, mmGC_USER_RB_BACKEND_DISABLE); data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK; data >>= GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT; @@ -1276,8 +1276,8 @@ static void gfx_v9_0_init_compute_vmid(struct amdgpu_device *adev) for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) { soc15_grbm_select(adev, 0, 0, 0, i); /* CP and shaders */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config); - WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases); + WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config); + WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases); } soc15_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); @@ -1304,8 +1304,8 @@ static void gfx_v9_0_gpu_init(struct amdgpu_device *adev) tmp = 0; tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, ALIGNMENT_MODE, SH_MEM_ALIGNMENT_MODE_UNALIGNED); - WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), tmp); - WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), 0); + WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, tmp); + WREG32_SOC15(GC, 0, mmSH_MEM_BASES, 0); } soc15_grbm_select(adev, 0, 0, 0, 0); @@ -1320,7 +1320,7 @@ static void gfx_v9_0_gpu_init(struct amdgpu_device *adev) */ gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); - WREG32(SOC15_REG_OFFSET(GC, 0, mmPA_SC_FIFO_SIZE), + WREG32_SOC15(GC, 0, mmPA_SC_FIFO_SIZE, (adev->gfx.config.sc_prim_fifo_size_frontend << PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT) | (adev->gfx.config.sc_prim_fifo_size_backend << @@ -1343,7 +1343,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev) for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff); for (k = 0; k < adev->usec_timeout; k++) { - if (RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY)) == 0) + if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0) break; udelay(1); } @@ -1357,7 +1357,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev) RLC_SERDES_NONCU_MASTER_BUSY__TC0_MASTER_BUSY_MASK | RLC_SERDES_NONCU_MASTER_BUSY__TC1_MASTER_BUSY_MASK; for (k = 0; k < adev->usec_timeout; k++) { - if ((RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SERDES_NONCU_MASTER_BUSY)) & mask) == 0) + if ((RREG32_SOC15(GC, 0, mmRLC_SERDES_NONCU_MASTER_BUSY) & mask) == 0) break; udelay(1); } @@ -1366,7 +1366,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev) static void gfx_v9_0_enable_gui_idle_interrupt(struct amdgpu_device *adev, bool enable) { - u32 tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_INT_CNTL_RING0)); + u32 tmp = RREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0); if (enable) return; @@ -1376,15 +1376,15 @@ static void gfx_v9_0_enable_gui_idle_interrupt(struct amdgpu_device *adev, tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0); tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_INT_CNTL_RING0), tmp); + WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp); } void gfx_v9_0_rlc_stop(struct amdgpu_device *adev) { - u32 tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL)); + u32 tmp = RREG32_SOC15(GC, 0, mmRLC_CNTL); tmp = REG_SET_FIELD(tmp, RLC_CNTL, RLC_ENABLE_F32, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL), tmp); + WREG32_SOC15(GC, 0, mmRLC_CNTL, tmp); gfx_v9_0_enable_gui_idle_interrupt(adev, false); @@ -1415,17 +1415,17 @@ static void gfx_v9_0_rlc_start(struct amdgpu_device *adev) #ifdef AMDGPU_RLC_DEBUG_RETRY /* RLC_GPM_GENERAL_6 : RLC Ucode version */ - rlc_ucode_ver = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_GENERAL_6)); + rlc_ucode_ver = RREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_6); if(rlc_ucode_ver == 0x108) { DRM_INFO("Using rlc debug ucode. mmRLC_GPM_GENERAL_6 ==0x08%x / fw_ver == %i \n", rlc_ucode_ver, adev->gfx.rlc_fw_version); /* RLC_GPM_TIMER_INT_3 : Timer interval in RefCLK cycles, * default is 0x9C4 to create a 100us interval */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_TIMER_INT_3), 0x9C4); + WREG32_SOC15(GC, 0, mmRLC_GPM_TIMER_INT_3, 0x9C4); /* RLC_GPM_GENERAL_12 : Minimum gap between wptr and rptr * to disable the page fault retry interrupts, default is * 0x100 (256) */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_GENERAL_12), 0x100); + WREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_12, 0x100); } #endif } @@ -1446,11 +1446,11 @@ static int gfx_v9_0_rlc_load_microcode(struct amdgpu_device *adev) le32_to_cpu(hdr->header.ucode_array_offset_bytes)); fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4; - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR), + WREG32_SOC15(GC, 0, mmRLC_GPM_UCODE_ADDR, RLCG_UCODE_LOADING_START_ADDRESS); for (i = 0; i < fw_size; i++) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA), le32_to_cpup(fw_data++)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR), adev->gfx.rlc_fw_version); + WREG32_SOC15(GC, 0, mmRLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++)); + WREG32_SOC15(GC, 0, mmRLC_GPM_UCODE_ADDR, adev->gfx.rlc_fw_version); return 0; } @@ -1465,10 +1465,10 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev) gfx_v9_0_rlc_stop(adev); /* disable CG */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL), 0); + WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, 0); /* disable PG */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), 0); + WREG32_SOC15(GC, 0, mmRLC_PG_CNTL, 0); gfx_v9_0_rlc_reset(adev); @@ -1487,7 +1487,7 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev) static void gfx_v9_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable) { int i; - u32 tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_CNTL)); + u32 tmp = RREG32_SOC15(GC, 0, mmCP_ME_CNTL); tmp = REG_SET_FIELD(tmp, CP_ME_CNTL, ME_HALT, enable ? 0 : 1); tmp = REG_SET_FIELD(tmp, CP_ME_CNTL, PFP_HALT, enable ? 0 : 1); @@ -1496,7 +1496,7 @@ static void gfx_v9_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable) for (i = 0; i < adev->gfx.num_gfx_rings; i++) adev->gfx.gfx_ring[i].ready = false; } - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_CNTL), tmp); + WREG32_SOC15(GC, 0, mmCP_ME_CNTL, tmp); udelay(50); } @@ -1529,30 +1529,30 @@ static int gfx_v9_0_cp_gfx_load_microcode(struct amdgpu_device *adev) (adev->gfx.pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes)); fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_ADDR), 0); + WREG32_SOC15(GC, 0, mmCP_PFP_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_DATA), le32_to_cpup(fw_data++)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_ADDR), adev->gfx.pfp_fw_version); + WREG32_SOC15(GC, 0, mmCP_PFP_UCODE_DATA, le32_to_cpup(fw_data++)); + WREG32_SOC15(GC, 0, mmCP_PFP_UCODE_ADDR, adev->gfx.pfp_fw_version); /* CE */ fw_data = (const __le32 *) (adev->gfx.ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes)); fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_ADDR), 0); + WREG32_SOC15(GC, 0, mmCP_CE_UCODE_ADDR, 0); for (i = 0; i < fw_size; i++) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_DATA), le32_to_cpup(fw_data++)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_ADDR), adev->gfx.ce_fw_version); + WREG32_SOC15(GC, 0, mmCP_CE_UCODE_DATA, le32_to_cpup(fw_data++)); + WREG32_SOC15(GC, 0, mmCP_CE_UCODE_ADDR, adev->gfx.ce_fw_version); /* ME */ fw_data = (const __le32 *) (adev->gfx.me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes)); fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_RAM_WADDR), 0); + WREG32_SOC15(GC, 0, mmCP_ME_RAM_WADDR, 0); for (i = 0; i < fw_size; i++) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_RAM_DATA), le32_to_cpup(fw_data++)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_RAM_WADDR), adev->gfx.me_fw_version); + WREG32_SOC15(GC, 0, mmCP_ME_RAM_DATA, le32_to_cpup(fw_data++)); + WREG32_SOC15(GC, 0, mmCP_ME_RAM_WADDR, adev->gfx.me_fw_version); return 0; } @@ -1594,8 +1594,8 @@ static int gfx_v9_0_cp_gfx_start(struct amdgpu_device *adev) int r, i; /* init the CP */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MAX_CONTEXT), adev->gfx.config.max_hw_contexts - 1); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_DEVICE_ID), 1); + WREG32_SOC15(GC, 0, mmCP_MAX_CONTEXT, adev->gfx.config.max_hw_contexts - 1); + WREG32_SOC15(GC, 0, mmCP_DEVICE_ID, 1); gfx_v9_0_cp_gfx_enable(adev, true); @@ -1650,10 +1650,10 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev) u64 rb_addr, rptr_addr, wptr_gpu_addr; /* Set the write pointer delay */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_DELAY), 0); + WREG32_SOC15(GC, 0, mmCP_RB_WPTR_DELAY, 0); /* set the RB to use vmid 0 */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_VMID), 0); + WREG32_SOC15(GC, 0, mmCP_RB_VMID, 0); /* Set ring buffer size */ ring = &adev->gfx.gfx_ring[0]; @@ -1663,30 +1663,30 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev) #ifdef __BIG_ENDIAN tmp = REG_SET_FIELD(tmp, CP_RB0_CNTL, BUF_SWAP, 1); #endif - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_CNTL), tmp); + WREG32_SOC15(GC, 0, mmCP_RB0_CNTL, tmp); /* Initialize the ring buffer's write pointers */ ring->wptr = 0; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR), lower_32_bits(ring->wptr)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR_HI), upper_32_bits(ring->wptr)); + WREG32_SOC15(GC, 0, mmCP_RB0_WPTR, lower_32_bits(ring->wptr)); + WREG32_SOC15(GC, 0, mmCP_RB0_WPTR_HI, upper_32_bits(ring->wptr)); /* set the wb address wether it's enabled or not */ rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_RPTR_ADDR), lower_32_bits(rptr_addr)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_RPTR_ADDR_HI), upper_32_bits(rptr_addr) & CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK); + WREG32_SOC15(GC, 0, mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr)); + WREG32_SOC15(GC, 0, mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK); wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO), lower_32_bits(wptr_gpu_addr)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI), upper_32_bits(wptr_gpu_addr)); + WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO, lower_32_bits(wptr_gpu_addr)); + WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI, upper_32_bits(wptr_gpu_addr)); mdelay(1); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_CNTL), tmp); + WREG32_SOC15(GC, 0, mmCP_RB0_CNTL, tmp); rb_addr = ring->gpu_addr >> 8; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_BASE), rb_addr); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_BASE_HI), upper_32_bits(rb_addr)); + WREG32_SOC15(GC, 0, mmCP_RB0_BASE, rb_addr); + WREG32_SOC15(GC, 0, mmCP_RB0_BASE_HI, upper_32_bits(rb_addr)); - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_CONTROL); if (ring->use_doorbell) { tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, DOORBELL_OFFSET, ring->doorbell_index); @@ -1695,13 +1695,13 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev) } else { tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, DOORBELL_EN, 0); } - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_CONTROL), tmp); + WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_CONTROL, tmp); tmp = REG_SET_FIELD(0, CP_RB_DOORBELL_RANGE_LOWER, DOORBELL_RANGE_LOWER, ring->doorbell_index); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_RANGE_LOWER), tmp); + WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_RANGE_LOWER, tmp); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_RANGE_UPPER), + WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_RANGE_UPPER, CP_RB_DOORBELL_RANGE_UPPER__DOORBELL_RANGE_UPPER_MASK); @@ -1717,9 +1717,9 @@ static void gfx_v9_0_cp_compute_enable(struct amdgpu_device *adev, bool enable) int i; if (enable) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_CNTL), 0); + WREG32_SOC15(GC, 0, mmCP_MEC_CNTL, 0); } else { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_CNTL), + WREG32_SOC15(GC, 0, mmCP_MEC_CNTL, (CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK)); for (i = 0; i < adev->gfx.num_compute_rings; i++) adev->gfx.compute_ring[i].ready = false; @@ -1756,21 +1756,21 @@ static int gfx_v9_0_cp_compute_load_microcode(struct amdgpu_device *adev) tmp = 0; tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CPC_IC_BASE_CNTL), tmp); + WREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_CNTL, tmp); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CPC_IC_BASE_LO), + WREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_LO, adev->gfx.mec.mec_fw_gpu_addr & 0xFFFFF000); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CPC_IC_BASE_HI), + WREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_HI, upper_32_bits(adev->gfx.mec.mec_fw_gpu_addr)); /* MEC1 */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_ADDR), + WREG32_SOC15(GC, 0, mmCP_MEC_ME1_UCODE_ADDR, mec_hdr->jt_offset); for (i = 0; i < mec_hdr->jt_size; i++) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_DATA), + WREG32_SOC15(GC, 0, mmCP_MEC_ME1_UCODE_DATA, le32_to_cpup(fw_data + mec_hdr->jt_offset + i)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_ADDR), + WREG32_SOC15(GC, 0, mmCP_MEC_ME1_UCODE_ADDR, adev->gfx.mec_fw_version); /* Todo : Loading MEC2 firmware is only necessary if MEC2 should run different microcode than MEC1. */ @@ -1823,12 +1823,12 @@ static void gfx_v9_0_kiq_setting(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; /* tell RLC which is KIQ queue */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS)); + tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS); tmp &= 0xffffff00; tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue); - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS), tmp); + WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp); tmp |= 0x80; - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS), tmp); + WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp); } static void gfx_v9_0_kiq_enable(struct amdgpu_ring *ring) @@ -1898,14 +1898,14 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr); /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, (order_base_2(MEC_HPD_SIZE / 4) - 1)); mqd->cp_hqd_eop_control = tmp; /* enable doorbell? */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); if (ring->use_doorbell) { tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, @@ -1935,7 +1935,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) mqd->cp_mqd_base_addr_hi = upper_32_bits(ring->mqd_gpu_addr); /* set MQD vmid to 0 */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_MQD_CONTROL); tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); mqd->cp_mqd_control = tmp; @@ -1945,7 +1945,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); /* set up the HQD, this is similar to CP_RB0_CNTL */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, (order_base_2(ring->ring_size / 4) - 1)); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, @@ -1973,7 +1973,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) tmp = 0; /* enable the doorbell if requested */ if (ring->use_doorbell) { - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_OFFSET, ring->doorbell_index); @@ -2013,94 +2013,94 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) /* disable wptr polling */ WREG32_FIELD15(GC, 0, CP_PQ_WPTR_POLL_CNTL, EN, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR), + WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR, mqd->cp_hqd_eop_base_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI, mqd->cp_hqd_eop_base_addr_hi); /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL), + WREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL, mqd->cp_hqd_eop_control); /* enable doorbell? */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control); /* disable the queue if it's active */ - if (RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), 1); + if (RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1) { + WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1); for (j = 0; j < adev->usec_timeout; j++) { - if (!(RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1)) + if (!(RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1)) break; udelay(1); } - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), + WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, mqd->cp_hqd_dequeue_request); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO, mqd->cp_hqd_pq_wptr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI, mqd->cp_hqd_pq_wptr_hi); } /* set the pointer to the MQD */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR), + WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR_HI), + WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi); /* set MQD vmid to 0 */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL), + WREG32_SOC15(GC, 0, mmCP_MQD_CONTROL, mqd->cp_mqd_control); /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi); /* set up the HQD, this is similar to CP_RB0_CNTL */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL, mqd->cp_hqd_pq_control); /* set the wb address whether it's enabled or not */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->cp_hqd_pq_rptr_report_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->cp_hqd_pq_rptr_report_addr_hi); /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi); /* enable the doorbell if requested */ if (ring->use_doorbell) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER), + WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (AMDGPU_DOORBELL64_KIQ *2) << 2); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER), + WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, (AMDGPU_DOORBELL64_USERQUEUE_END * 2) << 2); } - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control); /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO, mqd->cp_hqd_pq_wptr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI, mqd->cp_hqd_pq_wptr_hi); /* set the vmid for the queue */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_VMID), mqd->cp_hqd_vmid); + WREG32_SOC15(GC, 0, mmCP_HQD_VMID, mqd->cp_hqd_vmid); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PERSISTENT_STATE), + WREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE, mqd->cp_hqd_persistent_state); /* activate the queue */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), + WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, mqd->cp_hqd_active); if (ring->use_doorbell) @@ -2323,7 +2323,7 @@ static bool gfx_v9_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (REG_GET_FIELD(RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS)), + if (REG_GET_FIELD(RREG32_SOC15(GC, 0, mmGRBM_STATUS), GRBM_STATUS, GUI_ACTIVE)) return false; else @@ -2338,7 +2338,7 @@ static int gfx_v9_0_wait_for_idle(void *handle) for (i = 0; i < adev->usec_timeout; i++) { /* read MC_STATUS */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS)) & + tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK; if (!REG_GET_FIELD(tmp, GRBM_STATUS, GUI_ACTIVE)) @@ -2355,7 +2355,7 @@ static int gfx_v9_0_soft_reset(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* GRBM_STATUS */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS)); + tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS); if (tmp & (GRBM_STATUS__PA_BUSY_MASK | GRBM_STATUS__SC_BUSY_MASK | GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK | GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__VGT_BUSY_MASK | @@ -2374,7 +2374,7 @@ static int gfx_v9_0_soft_reset(void *handle) } /* GRBM_STATUS2 */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS2)); + tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS2); if (REG_GET_FIELD(tmp, GRBM_STATUS2, RLC_BUSY)) grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_RLC, 1); @@ -2391,17 +2391,17 @@ static int gfx_v9_0_soft_reset(void *handle) gfx_v9_0_cp_compute_enable(adev, false); if (grbm_soft_reset) { - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET)); + tmp = RREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET); tmp |= grbm_soft_reset; dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp); - WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET), tmp); - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET)); + WREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET, tmp); + tmp = RREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET); udelay(50); tmp &= ~grbm_soft_reset; - WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET), tmp); - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET)); + WREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET, tmp); + tmp = RREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET); } /* Wait a little for things to settle down */ @@ -2415,9 +2415,9 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev) uint64_t clock; mutex_lock(&adev->gfx.gpu_clock_mutex); - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT), 1); - clock = (uint64_t)RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB)) | - ((uint64_t)RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB)) << 32ULL); + WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1); + clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) | + ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL); mutex_unlock(&adev->gfx.gpu_clock_mutex); return clock; } @@ -2497,7 +2497,7 @@ static void gfx_v9_0_enter_rlc_safe_mode(struct amdgpu_device *adev) return; /* if RLC is not enabled, do nothing */ - rlc_setting = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL)); + rlc_setting = RREG32_SOC15(GC, 0, mmRLC_CNTL); if (!(rlc_setting & RLC_CNTL__RLC_ENABLE_F32_MASK)) return; @@ -2506,7 +2506,7 @@ static void gfx_v9_0_enter_rlc_safe_mode(struct amdgpu_device *adev) AMD_CG_SUPPORT_GFX_3D_CGCG)) { data = RLC_SAFE_MODE__CMD_MASK; data |= (1 << RLC_SAFE_MODE__MESSAGE__SHIFT); - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SAFE_MODE), data); + WREG32_SOC15(GC, 0, mmRLC_SAFE_MODE, data); /* wait for RLC_SAFE_MODE */ for (i = 0; i < adev->usec_timeout; i++) { @@ -2526,7 +2526,7 @@ static void gfx_v9_0_exit_rlc_safe_mode(struct amdgpu_device *adev) return; /* if RLC is not enabled, do nothing */ - rlc_setting = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL)); + rlc_setting = RREG32_SOC15(GC, 0, mmRLC_CNTL); if (!(rlc_setting & RLC_CNTL__RLC_ENABLE_F32_MASK)) return; @@ -2537,7 +2537,7 @@ static void gfx_v9_0_exit_rlc_safe_mode(struct amdgpu_device *adev) * mode. */ data = RLC_SAFE_MODE__CMD_MASK; - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SAFE_MODE), data); + WREG32_SOC15(GC, 0, mmRLC_SAFE_MODE, data); adev->gfx.rlc.in_safe_mode = false; } } @@ -2550,7 +2550,7 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev /* It is disabled by HW by default */ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) { /* 1 - RLC_CGTT_MGCG_OVERRIDE */ - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE)); + def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | @@ -2560,48 +2560,48 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev data |= RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK; if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data); + WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); /* MGLS is a global flag to control all MGLS in GFX */ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) { /* 2 - RLC memory Light sleep */ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) { - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL)); + def = data = RREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL); data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK; if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL), data); + WREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL, data); } /* 3 - CP memory Light sleep */ if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) { - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL)); + def = data = RREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL); data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK; if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL), data); + WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data); } } } else { /* 1 - MGCG_OVERRIDE */ - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE)); + def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); data |= (RLC_CGTT_MGCG_OVERRIDE__CPF_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK); if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data); + WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); /* 2 - disable MGLS in RLC */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL)); + data = RREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL); if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) { data &= ~RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK; - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL), data); + WREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL, data); } /* 3 - disable MGLS in CP */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL)); + data = RREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL); if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) { data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL), data); + WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data); } } } @@ -2616,37 +2616,37 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev, /* Enable 3D CGCG/CGLS */ if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)) { /* write cmd to clear cgcg/cgls ov */ - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE)); + def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); /* unset CGCG override */ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK; /* update CGCG and CGLS override bits */ if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data); + WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); /* enable 3Dcgcg FSM(0x0020003f) */ - def = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D)); + def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D); data = (0x2000 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK; if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS) data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) | RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK; if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D), data); + WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data); /* set IDLE_POLL_COUNT(0x00900100) */ - def = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL)); + def = RREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL); data = (0x0100 << CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT) | (0x0090 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT); if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL), data); + WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data); } else { /* Disable CGCG/CGLS */ - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D)); + def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D); /* disable cgcg, cgls should be disabled */ data &= ~(RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK); /* disable cgcg and cgls in FSM */ if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D), data); + WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data); } adev->gfx.rlc.funcs->exit_safe_mode(adev); @@ -2660,7 +2660,7 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev adev->gfx.rlc.funcs->enter_safe_mode(adev); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) { - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE)); + def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); /* unset CGCG override */ data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK; if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) @@ -2669,31 +2669,31 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK; /* update CGCG and CGLS override bits */ if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data); + WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); /* enable cgcg FSM(0x0020003F) */ - def = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL)); + def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL); data = (0x2000 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK; if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) data |= (0x000F << RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT) | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK; if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL), data); + WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data); /* set IDLE_POLL_COUNT(0x00900100) */ - def = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL)); + def = RREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL); data = (0x0100 << CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT) | (0x0090 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT); if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL), data); + WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data); } else { - def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL)); + def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL); /* reset CGCG/CGLS bits */ data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK); /* disable cgcg and cgls in FSM */ if (def != data) - WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL), data); + WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data); } adev->gfx.rlc.funcs->exit_safe_mode(adev); @@ -2760,12 +2760,12 @@ static void gfx_v9_0_get_clockgating_state(void *handle, u32 *flags) *flags = 0; /* AMD_CG_SUPPORT_GFX_MGCG */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE)); + data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK)) *flags |= AMD_CG_SUPPORT_GFX_MGCG; /* AMD_CG_SUPPORT_GFX_CGCG */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL)); + data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL); if (data & RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK) *flags |= AMD_CG_SUPPORT_GFX_CGCG; @@ -2774,17 +2774,17 @@ static void gfx_v9_0_get_clockgating_state(void *handle, u32 *flags) *flags |= AMD_CG_SUPPORT_GFX_CGLS; /* AMD_CG_SUPPORT_GFX_RLC_LS */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL)); + data = RREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL); if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) *flags |= AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_MGLS; /* AMD_CG_SUPPORT_GFX_CP_LS */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL)); + data = RREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL); if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) *flags |= AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_MGLS; /* AMD_CG_SUPPORT_GFX_3D_CGCG */ - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D)); + data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D); if (data & RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK) *flags |= AMD_CG_SUPPORT_GFX_3D_CGCG; @@ -2807,8 +2807,8 @@ static u64 gfx_v9_0_ring_get_wptr_gfx(struct amdgpu_ring *ring) if (ring->use_doorbell) { wptr = atomic64_read((atomic64_t *)&adev->wb.wb[ring->wptr_offs]); } else { - wptr = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR)); - wptr += (u64)RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR_HI)) << 32; + wptr = RREG32_SOC15(GC, 0, mmCP_RB0_WPTR); + wptr += (u64)RREG32_SOC15(GC, 0, mmCP_RB0_WPTR_HI) << 32; } return wptr; @@ -2823,8 +2823,8 @@ static void gfx_v9_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) atomic64_set((atomic64_t*)&adev->wb.wb[ring->wptr_offs], ring->wptr); WDOORBELL64(ring->doorbell_index, ring->wptr); } else { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR), lower_32_bits(ring->wptr)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR_HI), upper_32_bits(ring->wptr)); + WREG32_SOC15(GC, 0, mmCP_RB0_WPTR, lower_32_bits(ring->wptr)); + WREG32_SOC15(GC, 0, mmCP_RB0_WPTR_HI, upper_32_bits(ring->wptr)); } } @@ -3386,20 +3386,20 @@ static int gfx_v9_0_kiq_set_interrupt_state(struct amdgpu_device *adev, switch (type) { case AMDGPU_CP_KIQ_IRQ_DRIVER0: if (state == AMDGPU_IRQ_STATE_DISABLE) { - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL)); + tmp = RREG32_SOC15(GC, 0, mmCPC_INT_CNTL); tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL, GENERIC2_INT_ENABLE, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL), tmp); + WREG32_SOC15(GC, 0, mmCPC_INT_CNTL, tmp); tmp = RREG32(target); tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL, GENERIC2_INT_ENABLE, 0); WREG32(target, tmp); } else { - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL)); + tmp = RREG32_SOC15(GC, 0, mmCPC_INT_CNTL); tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL, GENERIC2_INT_ENABLE, 1); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL), tmp); + WREG32_SOC15(GC, 0, mmCPC_INT_CNTL, tmp); tmp = RREG32(target); tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL, @@ -3612,7 +3612,7 @@ static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev) static void gfx_v9_0_set_gds_init(struct amdgpu_device *adev) { /* init asci gds info */ - adev->gds.mem.total_size = RREG32(SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_SIZE)); + adev->gds.mem.total_size = RREG32_SOC15(GC, 0, mmGDS_VMID0_SIZE); adev->gds.gws.total_size = 64; adev->gds.oa.total_size = 16; @@ -3641,8 +3641,8 @@ static u32 gfx_v9_0_get_cu_active_bitmap(struct amdgpu_device *adev) { u32 data, mask; - data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG)); - data |= RREG32(SOC15_REG_OFFSET(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG)); + data = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG); + data |= RREG32_SOC15(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG); data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK; data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT; @@ -3763,25 +3763,25 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring) eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (ring->queue * MEC_HPD_SIZE); eop_gpu_addr >>= 8; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR), lower_32_bits(eop_gpu_addr)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI), upper_32_bits(eop_gpu_addr)); + WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR, lower_32_bits(eop_gpu_addr)); + WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr)); mqd->cp_hqd_eop_base_addr_lo = lower_32_bits(eop_gpu_addr); mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_gpu_addr); /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE, (order_base_2(MEC_HPD_SIZE / 4) - 1)); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL), tmp); + WREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL, tmp); /* enable doorbell? */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); if (use_doorbell) tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1); else tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), tmp); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, tmp); mqd->cp_hqd_pq_doorbell_control = tmp; /* disable the queue if it's active */ @@ -3790,40 +3790,40 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring) mqd->cp_hqd_pq_rptr = 0; mqd->cp_hqd_pq_wptr_lo = 0; mqd->cp_hqd_pq_wptr_hi = 0; - if (RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), 1); + if (RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1) { + WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1); for (j = 0; j < adev->usec_timeout; j++) { - if (!(RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1)) + if (!(RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1)) break; udelay(1); } - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), mqd->cp_hqd_dequeue_request); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR), mqd->cp_hqd_pq_rptr); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO), mqd->cp_hqd_pq_wptr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI), mqd->cp_hqd_pq_wptr_hi); + WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, mqd->cp_hqd_dequeue_request); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO, mqd->cp_hqd_pq_wptr_lo); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI, mqd->cp_hqd_pq_wptr_hi); } /* set the pointer to the MQD */ mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc; mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR), mqd->cp_mqd_base_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR_HI), mqd->cp_mqd_base_addr_hi); + WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo); + WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi); /* set MQD vmid to 0 */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_MQD_CONTROL); tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL), tmp); + WREG32_SOC15(GC, 0, mmCP_MQD_CONTROL, tmp); mqd->cp_mqd_control = tmp; /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */ hqd_gpu_addr = ring->gpu_addr >> 8; mqd->cp_hqd_pq_base_lo = hqd_gpu_addr; mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE), mqd->cp_hqd_pq_base_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI), mqd->cp_hqd_pq_base_hi); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi); /* set up the HQD, this is similar to CP_RB0_CNTL */ - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE, (order_base_2(ring->ring_size / 4) - 1)); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, @@ -3835,7 +3835,7 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring) tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP, 0); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL), tmp); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL, tmp); mqd->cp_hqd_pq_control = tmp; /* set the wb address wether it's enabled or not */ @@ -3843,27 +3843,27 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring) mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc; mqd->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR, mqd->cp_hqd_pq_rptr_report_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI, mqd->cp_hqd_pq_rptr_report_addr_hi); /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */ wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4); mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc; mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI, mqd->cp_hqd_pq_wptr_poll_addr_hi); /* enable the doorbell if requested */ if (use_doorbell) { - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER), + WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (AMDGPU_DOORBELL64_KIQ * 2) << 2); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER), + WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, (AMDGPU_DOORBELL64_MEC_RING7 * 2) << 2); - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_OFFSET, ring->doorbell_index); tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1); @@ -3874,25 +3874,25 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring) } else { mqd->cp_hqd_pq_doorbell_control = 0; } - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, mqd->cp_hqd_pq_doorbell_control); /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO), mqd->cp_hqd_pq_wptr_lo); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI), mqd->cp_hqd_pq_wptr_hi); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO, mqd->cp_hqd_pq_wptr_lo); + WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI, mqd->cp_hqd_pq_wptr_hi); /* set the vmid for the queue */ mqd->cp_hqd_vmid = 0; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_VMID), mqd->cp_hqd_vmid); + WREG32_SOC15(GC, 0, mmCP_HQD_VMID, mqd->cp_hqd_vmid); - tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PERSISTENT_STATE)); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE); tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53); - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PERSISTENT_STATE), tmp); + WREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE, tmp); mqd->cp_hqd_persistent_state = tmp; /* activate the queue */ mqd->cp_hqd_active = 1; - WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), mqd->cp_hqd_active); + WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, mqd->cp_hqd_active); soc15_grbm_select(adev, 0, 0, 0, 0); mutex_unlock(&adev->srbm_mutex); From d7b1eeb2ca039d04f1a1fcb241920cb112b4b52a Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Fri, 7 Apr 2017 18:39:07 +0800 Subject: [PATCH 010/144] drm/amdgpu:fix race condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sequence is protected by spinlock so don't access sequence in paramter seq when invoking this function. ~0 means to get the latest sequence number and 0 means none to get. Change-Id: Ib7a03f3cf5594deeb4ad333cc59b47a6bddfd1ad Signed-off-by: Monk Liu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 3 +++ include/uapi/drm/amdgpu_drm.h | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index cf0500671353..90d1ac8a80f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -273,6 +273,9 @@ struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, spin_lock(&ctx->ring_lock); + if (seq == ~0ull) + seq = ctx->rings[ring->idx].sequence - 1; + if (seq >= cring->sequence) { spin_unlock(&ctx->ring_lock); return ERR_PTR(-EINVAL); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 516a9f285730..92262d81d41e 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -295,7 +295,10 @@ union drm_amdgpu_gem_wait_idle { }; struct drm_amdgpu_wait_cs_in { - /** Command submission handle */ + /* Command submission handle + * handle equals 0 means none to wait for + * handle equal ~0ull meanas wait for the latest sequence number + */ __u64 handle; /** Absolute timeout to wait */ __u64 timeout; From 4573f0f21d6c40a9426d0418646d87bbf77d6ab5 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 10 Apr 2017 14:40:51 +0800 Subject: [PATCH 011/144] drm/amd/powerplay: fix suspend error on DPM disabled Don't fail if DPM is disabled. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 9da5b0bb66d8..f73e80c4bf33 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -251,7 +251,9 @@ static int pp_suspend(void *handle) ret = pp_check(pp_handle); - if (ret != 0) + if (ret == PP_DPM_DISABLED) + return 0; + else if (ret != 0) return ret; eventmgr = pp_handle->eventmgr; From b4de2c5aab2d5cd84c2a648d825b0e48ca426e27 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 10 Apr 2017 15:29:42 +0800 Subject: [PATCH 012/144] drm/amdgpu: do not free fence buf when driver probes. Fence buf needs to be used on suspend/resume phase. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 68ccaedad0f7..19180aaa8bf2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -358,8 +358,6 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) goto failed_mem; - amdgpu_bo_free_kernel(&psp->fence_buf_bo, - &psp->fence_buf_mc_addr, &psp->fence_buf); kfree(cmd); return 0; @@ -423,6 +421,10 @@ static int psp_hw_fini(void *handle) amdgpu_bo_free_kernel(&psp->fw_pri_bo, &psp->fw_pri_mc_addr, &psp->fw_pri_buf); + if (psp->fence_buf_bo) + amdgpu_bo_free_kernel(&psp->fence_buf_bo, + &psp->fence_buf_mc_addr, &psp->fence_buf); + return 0; } From 692bb1ac038a0b736c2b6e9bba41ac2da38e16cf Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 10 Apr 2017 09:29:13 +0800 Subject: [PATCH 013/144] drm/amdgpu: fix to clear ASIC INIT COMPLETE bit on resuming phase ASIC_INIT_COMPLETE bit must be cleared during S3 resuming phase, because VBIOS will check the bit to decide if execute ASIC_Init posting via kernel driver. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index ad4329922f79..1cf78f4dd339 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1727,6 +1727,12 @@ void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev) { int i; + /* + * VBIOS will check ASIC_INIT_COMPLETE bit to decide if + * execute ASIC_Init posting via driver + */ + adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK; + for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) WREG32(mmBIOS_SCRATCH_0 + i, adev->bios_scratch[i]); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 4b9abd68e04f..d735cd1807b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -26,6 +26,7 @@ #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" #include "atom.h" +#include "atombios.h" #define get_index_into_master_table(master_table, table_name) (offsetof(struct master_table, table_name) / sizeof(uint16_t)) @@ -77,6 +78,12 @@ void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev) { int i; + /* + * VBIOS will check ASIC_INIT_COMPLETE bit to decide if + * execute ASIC_Init posting via driver + */ + adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK; + for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++) WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]); } From cbcbea982af59d0a4c40dacfb6ff164a533fd1d9 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 11 Apr 2017 09:24:56 +0800 Subject: [PATCH 014/144] drm/amdgpu: fix to add buffer funcs check This patch fixes the case when buffer funcs is empty and bo evict is executing. It must double check buffer funcs, otherwise, a NULL pointer dereference kernel panic will be encountered. BUG: unable to handle kernel NULL pointer dereference at 00000000000001a4 IP: [] amdgpu_evict_flags+0x3d/0xf0 [amdgpu] PGD 0 Oops: 0000 [#1] SMP Modules linked in: amdgpu(OE) ttm drm_kms_helper drm i2c_algo_bit fb_sys_fops syscopyarea sysfillrect sysimgblt fmem(OE) physmem_drv(OE) rpcsec_gss_krb5 nfsv4 nfs fscache intel_rapl x86_pkg_temp_thermal intel_powerclamp snd_hda_codec_realtek snd_hda_codec_hdmi snd_hda_codec_generic kvm_intel snd_hda_intel snd_hda_codec kvm snd_hda_core joydev eeepc_wmi asus_wmi sparse_keymap snd_hwdep snd_pcm irqbypass crct10dif_pclmul snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq crc32_pclmul snd_seq_device ghash_clmulni_intel aesni_intel aes_x86_64 snd_timer lrw gf128mul mei_me snd glue_helper ablk_helper cryptd tpm_infineon mei lpc_ich serio_raw soundcore shpchp mac_hid nfsd auth_rpcgss nfs_acl lockd grace coretemp sunrpc parport_pc ppdev lp parport autofs4 hid_generic mxm_wmi r8169 usbhid ahci psmouse libahci nvme mii hid nvme_core wmi video CPU: 3 PID: 1627 Comm: kworker/u8:17 Tainted: G OE 4.9.0-custom #1 Hardware name: ASUS All Series/Z87-A, BIOS 1802 01/28/2014 Workqueue: events_unbound async_run_entry_fn task: ffff88021e7057c0 task.stack: ffffc9000262c000 RIP: 0010:[] [] amdgpu_evict_flags+0x3d/0xf0 [amdgpu] RSP: 0018:ffffc9000262fb30 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88021e8a5858 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffffc9000262fb58 RDI: ffff88021e8a5800 RBP: ffffc9000262fb48 R08: 0000000000000000 R09: ffff88021e8a5814 R10: 000000001def8f01 R11: ffff88021def8c80 R12: ffffc9000262fb58 R13: ffff88021d2b1990 R14: 0000000000000000 R15: ffff88021e8a5858 FS: 0000000000000000(0000) GS:ffff88022ed80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000001a4 CR3: 0000000001c07000 CR4: 00000000001406e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Signed-off-by: Huang Rui Reviewed-by: Ken Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 35d53a0d9ba6..23f7fe8fdc3d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -203,7 +203,9 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, abo = container_of(bo, struct amdgpu_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: - if (adev->mman.buffer_funcs_ring->ready == false) { + if (adev->mman.buffer_funcs && + adev->mman.buffer_funcs_ring && + adev->mman.buffer_funcs_ring->ready == false) { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); } else { amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT); From bc108ec78e2af5c7a5f6ef27e264b8093bd60e3b Mon Sep 17 00:00:00 2001 From: Trigger Huang Date: Tue, 11 Apr 2017 01:56:36 -0400 Subject: [PATCH 015/144] drm/amdgpu: Fix firmware UCODE_ID_STORAGE issue (v2) In Tonga's virtualization environment, for firmware UCODE_ID_STORAGE, there is no actual firmware data, but we still need alloc a BO and tell the BO's mc address to HW, or world switch will hang on VFs. v2: fix coding style (Alex) Signed-off-by: Trigger Huang Reviewed-by: Xiangliang Yu Reviewed-by: Monk Liu Acked-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index a1891c93cdbf..dfd1c98efa7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -382,10 +382,14 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) * if SMU loaded firmware, it needn't add SMC, UVD, and VCE * ucode info here */ - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) - adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 4; - else + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { + if (amdgpu_sriov_vf(adev)) + adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 3; + else + adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 4; + } else { adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM; + } for (i = 0; i < adev->firmware.max_ucodes; i++) { ucode = &adev->firmware.ucode[i]; From 71f2af890a337dec5a792846a9db36943651e4d0 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Fri, 7 Apr 2017 10:38:52 +0800 Subject: [PATCH 016/144] drm/amdgpu/vce4: update VCE initialization sequence for SRIOV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the initialization sequence of VCE to make VCE work. Signed-off-by: Frank Min Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index edde5fe938d6..255326eac7ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -280,18 +280,11 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev) init_table += header->vce_table_offset; ring = &adev->vce.ring[0]; - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_RPTR), ring->wptr); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_WPTR), ring->wptr); INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_LO), lower_32_bits(ring->gpu_addr)); INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_HI), upper_32_bits(ring->gpu_addr)); INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_SIZE), ring->ring_size / 4); /* BEGING OF MC_RESUME */ - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_CLOCK_GATING_A), ~(1 << 16), 0); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_UENC_CLOCK_GATING), ~0xFF9FF000, 0x1FF000); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_UENC_REG_CLOCK_GATING), ~0x3F, 0x3F); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_CLOCK_GATING_B), 0x1FF); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL), 0x398000); INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CACHE_CTRL), ~0x1, 0); INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL), 0); @@ -322,6 +315,8 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev) 0xffffffff, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); /* end of MC_RESUME */ + INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), + VCE_STATUS__JOB_BUSY_MASK, ~VCE_STATUS__JOB_BUSY_MASK); INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CNTL), ~0x200001, VCE_VCPU_CNTL__CLK_EN_MASK); INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SOFT_RESET), From a2f537e03b678887fdd8d0810b03ecad01ba5d36 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Thu, 6 Apr 2017 14:43:48 +0800 Subject: [PATCH 017/144] drm/amdgpu/vce4: workaround VCE ring test slow issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add VCE ring test slow workaround for SRIOV. Signed-off-by: Frank Min Signed-off-by: Xiangliang Yu Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index c853400805d1..7a8eaeaae94a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -955,7 +955,11 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) struct amdgpu_device *adev = ring->adev; uint32_t rptr = amdgpu_ring_get_rptr(ring); unsigned i; - int r; + int r, timeout = adev->usec_timeout; + + /* workaround VCE ring test slow issue for sriov*/ + if (amdgpu_sriov_vf(adev)) + timeout *= 10; /* TODO: remove it if VCE can work for sriov */ if (amdgpu_sriov_vf(adev)) @@ -970,13 +974,13 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) amdgpu_ring_write(ring, VCE_CMD_END); amdgpu_ring_commit(ring); - for (i = 0; i < adev->usec_timeout; i++) { + for (i = 0; i < timeout; i++) { if (amdgpu_ring_get_rptr(ring) != rptr) break; DRM_UDELAY(1); } - if (i < adev->usec_timeout) { + if (i < timeout) { DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); } else { From 0381631299e54128be5180d0a169b06cd3ce1ba6 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Thu, 6 Apr 2017 14:46:50 +0800 Subject: [PATCH 018/144] drm/amdgpu/vce4: enable ring & ib test for sriov MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now VCE block can work for SRIOV, enable ring & ib test. Signed-off-by: Frank Min Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 7a8eaeaae94a..735c38d7db0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -961,10 +961,6 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) if (amdgpu_sriov_vf(adev)) timeout *= 10; - /* TODO: remove it if VCE can work for sriov */ - if (amdgpu_sriov_vf(adev)) - return 0; - r = amdgpu_ring_alloc(ring, 16); if (r) { DRM_ERROR("amdgpu: vce failed to lock ring %d (%d).\n", @@ -1003,10 +999,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) struct dma_fence *fence = NULL; long r; - /* TODO: remove it if VCE can work for sriov */ - if (amdgpu_sriov_vf(ring->adev)) - return 0; - /* skip vce ring1/2 ib test for now, since it's not reliable */ if (ring != &ring->adev->vce.ring[0]) return 0; From 0eeb68b390377148e31f000db1c533a9a49bf950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 30 Mar 2017 14:49:50 +0200 Subject: [PATCH 019/144] drm/amdgpu: add VMHUB to ring association MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the info which ring belonging to which VMHUB. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Andres Rodriguez Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 +++ drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 1 + drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 2 ++ drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 1 + 5 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 63e56398ca9a..de12f7549e6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -99,6 +99,7 @@ struct amdgpu_ring_funcs { uint32_t align_mask; u32 nop; bool support_64bit_ptrs; + unsigned vmhub; /* ring read/write ptr handling */ u64 (*get_rptr)(struct amdgpu_ring *ring); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index e58fb05bc904..4a7fe9727e95 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3456,6 +3456,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = { .align_mask = 0xff, .nop = PACKET3(PACKET3_NOP, 0x3FFF), .support_64bit_ptrs = true, + .vmhub = AMDGPU_GFXHUB, .get_rptr = gfx_v9_0_ring_get_rptr_gfx, .get_wptr = gfx_v9_0_ring_get_wptr_gfx, .set_wptr = gfx_v9_0_ring_set_wptr_gfx, @@ -3500,6 +3501,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = { .align_mask = 0xff, .nop = PACKET3(PACKET3_NOP, 0x3FFF), .support_64bit_ptrs = true, + .vmhub = AMDGPU_GFXHUB, .get_rptr = gfx_v9_0_ring_get_rptr_compute, .get_wptr = gfx_v9_0_ring_get_wptr_compute, .set_wptr = gfx_v9_0_ring_set_wptr_compute, @@ -3529,6 +3531,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { .align_mask = 0xff, .nop = PACKET3(PACKET3_NOP, 0x3FFF), .support_64bit_ptrs = true, + .vmhub = AMDGPU_GFXHUB, .get_rptr = gfx_v9_0_ring_get_rptr_compute, .get_wptr = gfx_v9_0_ring_get_wptr_compute, .set_wptr = gfx_v9_0_ring_set_wptr_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 21f38d882335..7ba3e85a96c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1473,6 +1473,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = { .align_mask = 0xf, .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), .support_64bit_ptrs = true, + .vmhub = AMDGPU_MMHUB, .get_rptr = sdma_v4_0_ring_get_rptr, .get_wptr = sdma_v4_0_ring_get_wptr, .set_wptr = sdma_v4_0_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index 9bcf01469282..b5429223618f 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -1448,6 +1448,7 @@ static const struct amdgpu_ring_funcs uvd_v7_0_ring_vm_funcs = { .align_mask = 0xf, .nop = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP), 0), .support_64bit_ptrs = false, + .vmhub = AMDGPU_MMHUB, .get_rptr = uvd_v7_0_ring_get_rptr, .get_wptr = uvd_v7_0_ring_get_wptr, .set_wptr = uvd_v7_0_ring_set_wptr, @@ -1475,6 +1476,7 @@ static const struct amdgpu_ring_funcs uvd_v7_0_enc_ring_vm_funcs = { .align_mask = 0x3f, .nop = HEVC_ENC_CMD_NO_OP, .support_64bit_ptrs = false, + .vmhub = AMDGPU_MMHUB, .get_rptr = uvd_v7_0_enc_ring_get_rptr, .get_wptr = uvd_v7_0_enc_ring_get_wptr, .set_wptr = uvd_v7_0_enc_ring_set_wptr, diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 255326eac7ed..f68ab3b24c31 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -1073,6 +1073,7 @@ static const struct amdgpu_ring_funcs vce_v4_0_ring_vm_funcs = { .align_mask = 0x3f, .nop = VCE_CMD_NO_OP, .support_64bit_ptrs = false, + .vmhub = AMDGPU_MMHUB, .get_rptr = vce_v4_0_ring_get_rptr, .get_wptr = vce_v4_0_ring_get_wptr, .set_wptr = vce_v4_0_ring_set_wptr, From 4f618e737fafed22302d4b660eecfe1dce971b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 6 Apr 2017 15:18:21 +0200 Subject: [PATCH 020/144] drm/amdgpu: drop VMID per ring tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit David suggested this a long time ago, instead of checking each ring just walk over all the VMIDs in reverse LRU order. Signed-off-by: Christian König Reviewed-by: Andres Rodriguez Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 17 +++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 3 --- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 7ed5302b511a..8d96da53990a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -463,17 +463,10 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, job->vm_needs_flush = true; /* Check if we can use a VMID already assigned to this VM */ - i = ring->idx; - do { + list_for_each_entry_reverse(id, &adev->vm_manager.ids_lru, list) { struct dma_fence *flushed; - id = vm->ids[i++]; - if (i == AMDGPU_MAX_RINGS) - i = 0; - /* Check all the prerequisites to using this VMID */ - if (!id) - continue; if (amdgpu_vm_had_gpu_reset(adev, id)) continue; @@ -503,7 +496,6 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, goto error; list_move_tail(&id->list, &adev->vm_manager.ids_lru); - vm->ids[ring->idx] = id; job->vm_id = id - adev->vm_manager.ids; job->vm_needs_flush = false; @@ -512,7 +504,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, mutex_unlock(&adev->vm_manager.lock); return 0; - } while (i != ring->idx); + }; /* Still no ID to use? Then use the idle one found earlier */ id = idle; @@ -532,7 +524,6 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter); list_move_tail(&id->list, &adev->vm_manager.ids_lru); atomic64_set(&id->owner, vm->client_id); - vm->ids[ring->idx] = id; job->vm_id = id - adev->vm_manager.ids; trace_amdgpu_vm_grab_id(vm, ring->idx, job); @@ -2117,10 +2108,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) unsigned ring_instance; struct amdgpu_ring *ring; struct amd_sched_rq *rq; - int i, r; + int r; - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - vm->ids[i] = NULL; vm->va = RB_ROOT; vm->client_id = atomic64_inc_return(&adev->vm_manager.client_counter); spin_lock_init(&vm->status_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index d9e57290dc71..ba9c39317dd3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -114,9 +114,6 @@ struct amdgpu_vm { struct dma_fence *last_dir_update; uint64_t last_eviction_counter; - /* for id and flush management per ring */ - struct amdgpu_vm_id *ids[AMDGPU_MAX_RINGS]; - /* protecting freed */ spinlock_t freed_lock; From 7645670decdb677e2f415ff91609d31e5d4777d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 6 Apr 2017 17:52:39 +0200 Subject: [PATCH 021/144] drm/amdgpu: split VMID management by VMHUB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way GFX and MM won't fight for VMIDs any more. Initially disabled since we need to stop flushing all HUBS at the same time as well. Signed-off-by: Christian König Reviewed-by: Andres Rodriguez Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 82 +++++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 15 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 +- 10 files changed, 69 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 483660742f75..724b4c1c80f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1854,7 +1854,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* mutex initialization are all done here so we * can recall function without having locking issues */ - mutex_init(&adev->vm_manager.lock); atomic_set(&adev->irq.ih.lock, 0); mutex_init(&adev->firmware.mutex); mutex_init(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index aab857d89d03..2d11ac8d1aa9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -217,7 +217,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (r) { dev_err(adev->dev, "failed to emit fence (%d)\n", r); if (job && job->vm_id) - amdgpu_vm_reset_id(adev, job->vm_id); + amdgpu_vm_reset_id(adev, ring->funcs->vmhub, + job->vm_id); amdgpu_ring_undo(ring); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 8d96da53990a..3455b2c8652c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -406,6 +406,9 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_job *job) { struct amdgpu_device *adev = ring->adev; + /* Temporary use only the first VM manager */ + unsigned vmhub = 0; /*ring->funcs->vmhub;*/ + struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub]; uint64_t fence_context = adev->fence_context + ring->idx; struct dma_fence *updates = sync->last_vm_update; struct amdgpu_vm_id *id, *idle; @@ -413,16 +416,15 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, unsigned i; int r = 0; - fences = kmalloc_array(sizeof(void *), adev->vm_manager.num_ids, - GFP_KERNEL); + fences = kmalloc_array(sizeof(void *), id_mgr->num_ids, GFP_KERNEL); if (!fences) return -ENOMEM; - mutex_lock(&adev->vm_manager.lock); + mutex_lock(&id_mgr->lock); /* Check if we have an idle VMID */ i = 0; - list_for_each_entry(idle, &adev->vm_manager.ids_lru, list) { + list_for_each_entry(idle, &id_mgr->ids_lru, list) { fences[i] = amdgpu_sync_peek_fence(&idle->active, ring); if (!fences[i]) break; @@ -430,7 +432,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, } /* If we can't find a idle VMID to use, wait till one becomes available */ - if (&idle->list == &adev->vm_manager.ids_lru) { + if (&idle->list == &id_mgr->ids_lru) { u64 fence_context = adev->vm_manager.fence_context + ring->idx; unsigned seqno = ++adev->vm_manager.seqno[ring->idx]; struct dma_fence_array *array; @@ -455,7 +457,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; - mutex_unlock(&adev->vm_manager.lock); + mutex_unlock(&id_mgr->lock); return 0; } @@ -463,7 +465,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, job->vm_needs_flush = true; /* Check if we can use a VMID already assigned to this VM */ - list_for_each_entry_reverse(id, &adev->vm_manager.ids_lru, list) { + list_for_each_entry_reverse(id, &id_mgr->ids_lru, list) { struct dma_fence *flushed; /* Check all the prerequisites to using this VMID */ @@ -495,13 +497,13 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; - list_move_tail(&id->list, &adev->vm_manager.ids_lru); + list_move_tail(&id->list, &id_mgr->ids_lru); - job->vm_id = id - adev->vm_manager.ids; + job->vm_id = id - id_mgr->ids; job->vm_needs_flush = false; trace_amdgpu_vm_grab_id(vm, ring->idx, job); - mutex_unlock(&adev->vm_manager.lock); + mutex_unlock(&id_mgr->lock); return 0; }; @@ -522,14 +524,14 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, id->pd_gpu_addr = job->vm_pd_addr; id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter); - list_move_tail(&id->list, &adev->vm_manager.ids_lru); + list_move_tail(&id->list, &id_mgr->ids_lru); atomic64_set(&id->owner, vm->client_id); - job->vm_id = id - adev->vm_manager.ids; + job->vm_id = id - id_mgr->ids; trace_amdgpu_vm_grab_id(vm, ring->idx, job); error: - mutex_unlock(&adev->vm_manager.lock); + mutex_unlock(&id_mgr->lock); return r; } @@ -581,7 +583,9 @@ static u64 amdgpu_vm_adjust_mc_addr(struct amdgpu_device *adev, u64 mc_addr) int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) { struct amdgpu_device *adev = ring->adev; - struct amdgpu_vm_id *id = &adev->vm_manager.ids[job->vm_id]; + unsigned vmhub = ring->funcs->vmhub; + struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub]; + struct amdgpu_vm_id *id = &id_mgr->ids[job->vm_id]; bool gds_switch_needed = ring->funcs->emit_gds_switch && ( id->gds_base != job->gds_base || id->gds_size != job->gds_size || @@ -619,10 +623,10 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) if (r) return r; - mutex_lock(&adev->vm_manager.lock); + mutex_lock(&id_mgr->lock); dma_fence_put(id->last_flush); id->last_flush = fence; - mutex_unlock(&adev->vm_manager.lock); + mutex_unlock(&id_mgr->lock); } if (gds_switch_needed) { @@ -657,9 +661,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) * * Reset saved GDW, GWS and OA to force switch on next flush. */ -void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id) +void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub, + unsigned vmid) { - struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id]; + struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub]; + struct amdgpu_vm_id *id = &id_mgr->ids[vmid]; id->gds_base = 0; id->gds_size = 0; @@ -2230,16 +2236,21 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) */ void amdgpu_vm_manager_init(struct amdgpu_device *adev) { - unsigned i; + unsigned i, j; - INIT_LIST_HEAD(&adev->vm_manager.ids_lru); + for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { + struct amdgpu_vm_id_manager *id_mgr = + &adev->vm_manager.id_mgr[i]; - /* skip over VMID 0, since it is the system VM */ - for (i = 1; i < adev->vm_manager.num_ids; ++i) { - amdgpu_vm_reset_id(adev, i); - amdgpu_sync_create(&adev->vm_manager.ids[i].active); - list_add_tail(&adev->vm_manager.ids[i].list, - &adev->vm_manager.ids_lru); + mutex_init(&id_mgr->lock); + INIT_LIST_HEAD(&id_mgr->ids_lru); + + /* skip over VMID 0, since it is the system VM */ + for (j = 1; j < id_mgr->num_ids; ++j) { + amdgpu_vm_reset_id(adev, i, j); + amdgpu_sync_create(&id_mgr->ids[i].active); + list_add_tail(&id_mgr->ids[j].list, &id_mgr->ids_lru); + } } adev->vm_manager.fence_context = @@ -2247,6 +2258,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) for (i = 0; i < AMDGPU_MAX_RINGS; ++i) adev->vm_manager.seqno[i] = 0; + atomic_set(&adev->vm_manager.vm_pte_next_ring, 0); atomic64_set(&adev->vm_manager.client_counter, 0); spin_lock_init(&adev->vm_manager.prt_lock); @@ -2262,13 +2274,19 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev) */ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) { - unsigned i; + unsigned i, j; - for (i = 0; i < AMDGPU_NUM_VM; ++i) { - struct amdgpu_vm_id *id = &adev->vm_manager.ids[i]; + for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { + struct amdgpu_vm_id_manager *id_mgr = + &adev->vm_manager.id_mgr[i]; - amdgpu_sync_free(&adev->vm_manager.ids[i].active); - dma_fence_put(id->flushed_updates); - dma_fence_put(id->last_flush); + mutex_destroy(&id_mgr->lock); + for (j = 0; j < AMDGPU_NUM_VM; ++j) { + struct amdgpu_vm_id *id = &id_mgr->ids[j]; + + amdgpu_sync_free(&id->active); + dma_fence_put(id->flushed_updates); + dma_fence_put(id->last_flush); + } } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index ba9c39317dd3..661a8f6826ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -146,12 +146,16 @@ struct amdgpu_vm_id { uint32_t oa_size; }; +struct amdgpu_vm_id_manager { + struct mutex lock; + unsigned num_ids; + struct list_head ids_lru; + struct amdgpu_vm_id ids[AMDGPU_NUM_VM]; +}; + struct amdgpu_vm_manager { /* Handling of VMIDs */ - struct mutex lock; - unsigned num_ids; - struct list_head ids_lru; - struct amdgpu_vm_id ids[AMDGPU_NUM_VM]; + struct amdgpu_vm_id_manager id_mgr[AMDGPU_MAX_VMHUBS]; /* Handling of VM fences */ u64 fence_context; @@ -197,7 +201,8 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync, struct dma_fence *fence, struct amdgpu_job *job); int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job); -void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id); +void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub, + unsigned vmid); int amdgpu_vm_update_directories(struct amdgpu_device *adev, struct amdgpu_vm *vm); int amdgpu_vm_clear_freed(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 8a8bc2fe6f2e..eca022eaff44 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -1935,7 +1935,7 @@ static void gfx_v7_0_gpu_init(struct amdgpu_device *adev) INDEX_STRIDE, 3); mutex_lock(&adev->srbm_mutex); - for (i = 0; i < adev->vm_manager.num_ids; i++) { + for (i = 0; i < adev->vm_manager.id_mgr[0].num_ids; i++) { if (i == 0) sh_mem_base = 0; else diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index dad8a4cd1b37..0115c5f65c01 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3890,7 +3890,7 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev) sh_static_mem_cfg = REG_SET_FIELD(sh_static_mem_cfg, SH_STATIC_MEM_CONFIG, INDEX_STRIDE, 3); mutex_lock(&adev->srbm_mutex); - for (i = 0; i < adev->vm_manager.num_ids; i++) { + for (i = 0; i < adev->vm_manager.id_mgr[0].num_ids; i++) { vi_srbm_select(adev, 0, 0, 0, i); /* CP and shaders */ if (i == 0) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 631aef38126d..31c50b2dbbc1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -621,7 +621,7 @@ static int gmc_v6_0_vm_init(struct amdgpu_device *adev) * amdgpu graphics/compute will use VMIDs 1-7 * amdkfd will use VMIDs 8-15 */ - adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS; + adev->vm_manager.id_mgr[0].num_ids = AMDGPU_NUM_OF_VMIDS; adev->vm_manager.num_level = 1; amdgpu_vm_manager_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 92abe12d92bb..2217d4d0f895 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -746,7 +746,7 @@ static int gmc_v7_0_vm_init(struct amdgpu_device *adev) * amdgpu graphics/compute will use VMIDs 1-7 * amdkfd will use VMIDs 8-15 */ - adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS; + adev->vm_manager.id_mgr[0].num_ids = AMDGPU_NUM_OF_VMIDS; adev->vm_manager.num_level = 1; amdgpu_vm_manager_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index f2ccefc66fd4..e4f5df32f31e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -949,7 +949,7 @@ static int gmc_v8_0_vm_init(struct amdgpu_device *adev) * amdgpu graphics/compute will use VMIDs 1-7 * amdkfd will use VMIDs 8-15 */ - adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS; + adev->vm_manager.id_mgr[0].num_ids = AMDGPU_NUM_OF_VMIDS; adev->vm_manager.num_level = 1; amdgpu_vm_manager_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 3b045e0b114e..7f5cc75f0da5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -519,7 +519,8 @@ static int gmc_v9_0_vm_init(struct amdgpu_device *adev) * amdgpu graphics/compute will use VMIDs 1-7 * amdkfd will use VMIDs 8-15 */ - adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS; + adev->vm_manager.id_mgr[AMDGPU_GFXHUB].num_ids = AMDGPU_NUM_OF_VMIDS; + adev->vm_manager.id_mgr[AMDGPU_MMHUB].num_ids = AMDGPU_NUM_OF_VMIDS; /* TODO: fix num_level for APU when updating vm size and block size */ if (adev->flags & AMD_IS_APU) From 2e81984988adf8de92b7d3a14ba0fe8310d0bcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 30 Mar 2017 16:50:47 +0200 Subject: [PATCH 022/144] drm/amdgpu: invalidate only the currently needed VMHUB v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop invalidating both hubs from each engine. v2: don't use hardcoded values Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Andres Rodriguez Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 3 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 36 ++++------ drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 54 +++++++-------- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 95 ++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 49 ++++++------- 5 files changed, 104 insertions(+), 133 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 3455b2c8652c..b38a8d7714c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -406,8 +406,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_job *job) { struct amdgpu_device *adev = ring->adev; - /* Temporary use only the first VM manager */ - unsigned vmhub = 0; /*ring->funcs->vmhub;*/ + unsigned vmhub = ring->funcs->vmhub; struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub]; uint64_t fence_context = adev->fence_context + ring->idx; struct dma_fence *updates = sync->last_vm_update; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 4a7fe9727e95..1badd294ff18 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2956,35 +2956,29 @@ static void gfx_v9_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) static void gfx_v9_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { + struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); unsigned eng = ring->idx; - unsigned i; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ BUG_ON(pd_addr & 0xFFFF00000000003EULL); - for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { - struct amdgpu_vmhub *hub = &ring->adev->vmhub[i]; + gfx_v9_0_write_data_to_reg(ring, usepfp, true, + hub->ctx0_ptb_addr_lo32 + (2 * vm_id), + lower_32_bits(pd_addr)); - gfx_v9_0_write_data_to_reg(ring, usepfp, true, - hub->ctx0_ptb_addr_lo32 - + (2 * vm_id), - lower_32_bits(pd_addr)); + gfx_v9_0_write_data_to_reg(ring, usepfp, true, + hub->ctx0_ptb_addr_hi32 + (2 * vm_id), + upper_32_bits(pd_addr)); - gfx_v9_0_write_data_to_reg(ring, usepfp, true, - hub->ctx0_ptb_addr_hi32 - + (2 * vm_id), - upper_32_bits(pd_addr)); + gfx_v9_0_write_data_to_reg(ring, usepfp, true, + hub->vm_inv_eng0_req + eng, req); - gfx_v9_0_write_data_to_reg(ring, usepfp, true, - hub->vm_inv_eng0_req + eng, req); - - /* wait for the invalidate to complete */ - gfx_v9_0_wait_reg_mem(ring, 0, 0, 0, hub->vm_inv_eng0_ack + - eng, 0, 1 << vm_id, 1 << vm_id, 0x20); - } + /* wait for the invalidate to complete */ + gfx_v9_0_wait_reg_mem(ring, 0, 0, 0, hub->vm_inv_eng0_ack + + eng, 0, 1 << vm_id, 1 << vm_id, 0x20); /* compute doesn't have PFP */ if (usepfp) { @@ -3463,7 +3457,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = { .emit_frame_size = /* totally 242 maximum if 16 IBs */ 5 + /* COND_EXEC */ 7 + /* PIPELINE_SYNC */ - 46 + /* VM_FLUSH */ + 24 + /* VM_FLUSH */ 8 + /* FENCE for VM_FLUSH */ 20 + /* GDS switch */ 4 + /* double SWITCH_BUFFER, @@ -3510,7 +3504,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = { 7 + /* gfx_v9_0_ring_emit_hdp_flush */ 5 + /* gfx_v9_0_ring_emit_hdp_invalidate */ 7 + /* gfx_v9_0_ring_emit_pipeline_sync */ - 64 + /* gfx_v9_0_ring_emit_vm_flush */ + 24 + /* gfx_v9_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */ .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_compute */ .emit_ib = gfx_v9_0_ring_emit_ib_compute, @@ -3540,7 +3534,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { 7 + /* gfx_v9_0_ring_emit_hdp_flush */ 5 + /* gfx_v9_0_ring_emit_hdp_invalidate */ 7 + /* gfx_v9_0_ring_emit_pipeline_sync */ - 64 + /* gfx_v9_0_ring_emit_vm_flush */ + 24 + /* gfx_v9_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_compute */ .emit_ib = gfx_v9_0_ring_emit_ib_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 7ba3e85a96c6..c3cf6bcadc60 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1039,44 +1039,40 @@ static void sdma_v4_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) static void sdma_v4_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { + struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); unsigned eng = ring->idx; - unsigned i; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ BUG_ON(pd_addr & 0xFFFF00000000003EULL); - for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { - struct amdgpu_vmhub *hub = &ring->adev->vmhub[i]; + amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | + SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); + amdgpu_ring_write(ring, hub->ctx0_ptb_addr_lo32 + vm_id * 2); + amdgpu_ring_write(ring, lower_32_bits(pd_addr)); - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | - SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); - amdgpu_ring_write(ring, hub->ctx0_ptb_addr_lo32 + vm_id * 2); - amdgpu_ring_write(ring, lower_32_bits(pd_addr)); + amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | + SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); + amdgpu_ring_write(ring, hub->ctx0_ptb_addr_hi32 + vm_id * 2); + amdgpu_ring_write(ring, upper_32_bits(pd_addr)); - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | - SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); - amdgpu_ring_write(ring, hub->ctx0_ptb_addr_hi32 + vm_id * 2); - amdgpu_ring_write(ring, upper_32_bits(pd_addr)); + /* flush TLB */ + amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | + SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); + amdgpu_ring_write(ring, hub->vm_inv_eng0_req + eng); + amdgpu_ring_write(ring, req); - /* flush TLB */ - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) | - SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf)); - amdgpu_ring_write(ring, hub->vm_inv_eng0_req + eng); - amdgpu_ring_write(ring, req); - - /* wait for flush */ - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) | - SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) | - SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* equal */ - amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2); - amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, 1 << vm_id); /* reference */ - amdgpu_ring_write(ring, 1 << vm_id); /* mask */ - amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) | - SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); - } + /* wait for flush */ + amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) | + SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) | + SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* equal */ + amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 1 << vm_id); /* reference */ + amdgpu_ring_write(ring, 1 << vm_id); /* mask */ + amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) | + SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); } static int sdma_v4_0_early_init(void *handle) @@ -1481,7 +1477,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = { 6 + /* sdma_v4_0_ring_emit_hdp_flush */ 3 + /* sdma_v4_0_ring_emit_hdp_invalidate */ 6 + /* sdma_v4_0_ring_emit_pipeline_sync */ - 36 + /* sdma_v4_0_ring_emit_vm_flush */ + 18 + /* sdma_v4_0_ring_emit_vm_flush */ 10 + 10 + 10, /* sdma_v4_0_ring_emit_fence x3 for user fence, vm fence */ .emit_ib_size = 7 + 6, /* sdma_v4_0_ring_emit_ib */ .emit_ib = sdma_v4_0_ring_emit_ib, diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index b5429223618f..dc3a2145a452 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -1034,42 +1034,38 @@ static void uvd_v7_0_vm_reg_wait(struct amdgpu_ring *ring, static void uvd_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { + struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); uint32_t data0, data1, mask; unsigned eng = ring->idx; - unsigned i; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ BUG_ON(pd_addr & 0xFFFF00000000003EULL); - for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { - struct amdgpu_vmhub *hub = &ring->adev->vmhub[i]; + data0 = (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2; + data1 = upper_32_bits(pd_addr); + uvd_v7_0_vm_reg_write(ring, data0, data1); - data0 = (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2; - data1 = upper_32_bits(pd_addr); - uvd_v7_0_vm_reg_write(ring, data0, data1); + data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2; + data1 = lower_32_bits(pd_addr); + uvd_v7_0_vm_reg_write(ring, data0, data1); - data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2; - data1 = lower_32_bits(pd_addr); - uvd_v7_0_vm_reg_write(ring, data0, data1); + data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2; + data1 = lower_32_bits(pd_addr); + mask = 0xffffffff; + uvd_v7_0_vm_reg_wait(ring, data0, data1, mask); - data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2; - data1 = lower_32_bits(pd_addr); - mask = 0xffffffff; - uvd_v7_0_vm_reg_wait(ring, data0, data1, mask); + /* flush TLB */ + data0 = (hub->vm_inv_eng0_req + eng) << 2; + data1 = req; + uvd_v7_0_vm_reg_write(ring, data0, data1); - /* flush TLB */ - data0 = (hub->vm_inv_eng0_req + eng) << 2; - data1 = req; - uvd_v7_0_vm_reg_write(ring, data0, data1); - - /* wait for flush */ - data0 = (hub->vm_inv_eng0_ack + eng) << 2; - data1 = 1 << vm_id; - mask = 1 << vm_id; - uvd_v7_0_vm_reg_wait(ring, data0, data1, mask); - } + /* wait for flush */ + data0 = (hub->vm_inv_eng0_ack + eng) << 2; + data1 = 1 << vm_id; + mask = 1 << vm_id; + uvd_v7_0_vm_reg_wait(ring, data0, data1, mask); } static void uvd_v7_0_enc_ring_insert_end(struct amdgpu_ring *ring) @@ -1080,44 +1076,37 @@ static void uvd_v7_0_enc_ring_insert_end(struct amdgpu_ring *ring) static void uvd_v7_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned int vm_id, uint64_t pd_addr) { + struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); unsigned eng = ring->idx; - unsigned i; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ BUG_ON(pd_addr & 0xFFFF00000000003EULL); - for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { - struct amdgpu_vmhub *hub = &ring->adev->vmhub[i]; + amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE); + amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2); + amdgpu_ring_write(ring, upper_32_bits(pd_addr)); - amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE); - amdgpu_ring_write(ring, - (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2); - amdgpu_ring_write(ring, upper_32_bits(pd_addr)); + amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE); + amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); + amdgpu_ring_write(ring, lower_32_bits(pd_addr)); - amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE); - amdgpu_ring_write(ring, - (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); - amdgpu_ring_write(ring, lower_32_bits(pd_addr)); + amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT); + amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); + amdgpu_ring_write(ring, 0xffffffff); + amdgpu_ring_write(ring, lower_32_bits(pd_addr)); - amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT); - amdgpu_ring_write(ring, - (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); - amdgpu_ring_write(ring, 0xffffffff); - amdgpu_ring_write(ring, lower_32_bits(pd_addr)); + /* flush TLB */ + amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE); + amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2); + amdgpu_ring_write(ring, req); - /* flush TLB */ - amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE); - amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2); - amdgpu_ring_write(ring, req); - - /* wait for flush */ - amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT); - amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2); - amdgpu_ring_write(ring, 1 << vm_id); - amdgpu_ring_write(ring, 1 << vm_id); - } + /* wait for flush */ + amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT); + amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2); + amdgpu_ring_write(ring, 1 << vm_id); + amdgpu_ring_write(ring, 1 << vm_id); } #if 0 @@ -1455,7 +1444,7 @@ static const struct amdgpu_ring_funcs uvd_v7_0_ring_vm_funcs = { .emit_frame_size = 2 + /* uvd_v7_0_ring_emit_hdp_flush */ 2 + /* uvd_v7_0_ring_emit_hdp_invalidate */ - 34 * AMDGPU_MAX_VMHUBS + /* uvd_v7_0_ring_emit_vm_flush */ + 34 + /* uvd_v7_0_ring_emit_vm_flush */ 14 + 14, /* uvd_v7_0_ring_emit_fence x2 vm fence */ .emit_ib_size = 8, /* uvd_v7_0_ring_emit_ib */ .emit_ib = uvd_v7_0_ring_emit_ib, @@ -1481,7 +1470,7 @@ static const struct amdgpu_ring_funcs uvd_v7_0_enc_ring_vm_funcs = { .get_wptr = uvd_v7_0_enc_ring_get_wptr, .set_wptr = uvd_v7_0_enc_ring_set_wptr, .emit_frame_size = - 17 * AMDGPU_MAX_VMHUBS + /* uvd_v7_0_enc_ring_emit_vm_flush */ + 17 + /* uvd_v7_0_enc_ring_emit_vm_flush */ 5 + 5 + /* uvd_v7_0_enc_ring_emit_fence x2 vm fence */ 1, /* uvd_v7_0_enc_ring_insert_end */ .emit_ib_size = 5, /* uvd_v7_0_enc_ring_emit_ib */ diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index f68ab3b24c31..2ffafbe6cd80 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -968,44 +968,37 @@ static void vce_v4_0_ring_insert_end(struct amdgpu_ring *ring) static void vce_v4_0_emit_vm_flush(struct amdgpu_ring *ring, unsigned int vm_id, uint64_t pd_addr) { + struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); unsigned eng = ring->idx; - unsigned i; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ BUG_ON(pd_addr & 0xFFFF00000000003EULL); - for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) { - struct amdgpu_vmhub *hub = &ring->adev->vmhub[i]; + amdgpu_ring_write(ring, VCE_CMD_REG_WRITE); + amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2); + amdgpu_ring_write(ring, upper_32_bits(pd_addr)); - amdgpu_ring_write(ring, VCE_CMD_REG_WRITE); - amdgpu_ring_write(ring, - (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2); - amdgpu_ring_write(ring, upper_32_bits(pd_addr)); + amdgpu_ring_write(ring, VCE_CMD_REG_WRITE); + amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); + amdgpu_ring_write(ring, lower_32_bits(pd_addr)); - amdgpu_ring_write(ring, VCE_CMD_REG_WRITE); - amdgpu_ring_write(ring, - (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); - amdgpu_ring_write(ring, lower_32_bits(pd_addr)); + amdgpu_ring_write(ring, VCE_CMD_REG_WAIT); + amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); + amdgpu_ring_write(ring, 0xffffffff); + amdgpu_ring_write(ring, lower_32_bits(pd_addr)); - amdgpu_ring_write(ring, VCE_CMD_REG_WAIT); - amdgpu_ring_write(ring, - (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2); - amdgpu_ring_write(ring, 0xffffffff); - amdgpu_ring_write(ring, lower_32_bits(pd_addr)); + /* flush TLB */ + amdgpu_ring_write(ring, VCE_CMD_REG_WRITE); + amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2); + amdgpu_ring_write(ring, req); - /* flush TLB */ - amdgpu_ring_write(ring, VCE_CMD_REG_WRITE); - amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2); - amdgpu_ring_write(ring, req); - - /* wait for flush */ - amdgpu_ring_write(ring, VCE_CMD_REG_WAIT); - amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2); - amdgpu_ring_write(ring, 1 << vm_id); - amdgpu_ring_write(ring, 1 << vm_id); - } + /* wait for flush */ + amdgpu_ring_write(ring, VCE_CMD_REG_WAIT); + amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2); + amdgpu_ring_write(ring, 1 << vm_id); + amdgpu_ring_write(ring, 1 << vm_id); } static int vce_v4_0_set_interrupt_state(struct amdgpu_device *adev, @@ -1079,7 +1072,7 @@ static const struct amdgpu_ring_funcs vce_v4_0_ring_vm_funcs = { .set_wptr = vce_v4_0_ring_set_wptr, .parse_cs = amdgpu_vce_ring_parse_cs_vm, .emit_frame_size = - 17 * AMDGPU_MAX_VMHUBS + /* vce_v4_0_emit_vm_flush */ + 17 + /* vce_v4_0_emit_vm_flush */ 5 + 5 + /* amdgpu_vce_ring_emit_fence x2 vm fence */ 1, /* vce_v4_0_ring_insert_end */ .emit_ib_size = 5, /* vce_v4_0_ring_emit_ib */ From 4789c463cb04d725170406873caaec5208c99eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 31 Mar 2017 11:03:50 +0200 Subject: [PATCH 023/144] drm/amdgpu: assign VM invalidation engine manually v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For Vega10 we have 18 VM invalidation engines for each VMHUB. Start to assign them manually to the rings. v2: add a BUG_ON if we use to many engines Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Andres Rodriguez Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 16 ++++++++++++++++ drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 2 +- 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index de12f7549e6d..944443c5b90a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -179,6 +179,7 @@ struct amdgpu_ring { unsigned cond_exe_offs; u64 cond_exe_gpu_addr; volatile u32 *cond_exe_cpu_addr; + unsigned vm_inv_eng; #if defined(CONFIG_DEBUG_FS) struct dentry *ent; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 1badd294ff18..87596e48f65d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2959,7 +2959,7 @@ static void gfx_v9_0_ring_emit_vm_flush(struct amdgpu_ring *ring, struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX); uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); - unsigned eng = ring->idx; + unsigned eng = ring->vm_inv_eng; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 7f5cc75f0da5..a71521e10763 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -386,6 +386,22 @@ static int gmc_v9_0_early_init(void *handle) static int gmc_v9_0_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 0 }; + unsigned i; + + for(i = 0; i < adev->num_rings; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + unsigned vmhub = ring->funcs->vmhub; + + ring->vm_inv_eng = vm_inv_eng[vmhub]++; + dev_info(adev->dev, "ring %u uses VM inv eng %u on hub %u\n", + ring->idx, ring->vm_inv_eng, ring->funcs->vmhub); + } + + /* Engine 17 is used for GART flushes */ + for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i) + BUG_ON(vm_inv_eng[i] > 17); + return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0); } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index c3cf6bcadc60..88c5d8f6f414 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1041,7 +1041,7 @@ static void sdma_v4_0_ring_emit_vm_flush(struct amdgpu_ring *ring, { struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); - unsigned eng = ring->idx; + unsigned eng = ring->vm_inv_eng; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index dc3a2145a452..c646570d1421 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -1037,7 +1037,7 @@ static void uvd_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring, struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); uint32_t data0, data1, mask; - unsigned eng = ring->idx; + unsigned eng = ring->vm_inv_eng; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ @@ -1078,7 +1078,7 @@ static void uvd_v7_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, { struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); - unsigned eng = ring->idx; + unsigned eng = ring->vm_inv_eng; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 2ffafbe6cd80..72d0edb9bc39 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -970,7 +970,7 @@ static void vce_v4_0_emit_vm_flush(struct amdgpu_ring *ring, { struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub]; uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id); - unsigned eng = ring->idx; + unsigned eng = ring->vm_inv_eng; pd_addr = pd_addr | 0x1; /* valid bit */ /* now only use physical base address of PDE and valid */ From 87c910d806295df26069d0325f517ed72ce29d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 30 Mar 2017 16:56:20 +0200 Subject: [PATCH 024/144] drm/amdgpu: allow concurrent VM flushes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable concurrent VM flushes for Vega10. Signed-off-by: Christian König Acked-by: Alex Deucher Reviewed-by: Andres Rodriguez Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 50 ++++++++++++++------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b38a8d7714c7..4e6c1e4072ca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -462,10 +462,11 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, } kfree(fences); - job->vm_needs_flush = true; + job->vm_needs_flush = false; /* Check if we can use a VMID already assigned to this VM */ list_for_each_entry_reverse(id, &id_mgr->ids_lru, list) { struct dma_fence *flushed; + bool needs_flush = false; /* Check all the prerequisites to using this VMID */ if (amdgpu_vm_had_gpu_reset(adev, id)) @@ -477,16 +478,17 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (job->vm_pd_addr != id->pd_gpu_addr) continue; - if (!id->last_flush) - continue; - - if (id->last_flush->context != fence_context && - !dma_fence_is_signaled(id->last_flush)) - continue; + if (!id->last_flush || + (id->last_flush->context != fence_context && + !dma_fence_is_signaled(id->last_flush))) + needs_flush = true; flushed = id->flushed_updates; - if (updates && - (!flushed || dma_fence_is_later(updates, flushed))) + if (updates && (!flushed || dma_fence_is_later(updates, flushed))) + needs_flush = true; + + /* Concurrent flushes are only possible starting with Vega10 */ + if (adev->asic_type < CHIP_VEGA10 && needs_flush) continue; /* Good we can use this VMID. Remember this submission as @@ -496,14 +498,15 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; - list_move_tail(&id->list, &id_mgr->ids_lru); + if (updates && (!flushed || dma_fence_is_later(updates, flushed))) { + dma_fence_put(id->flushed_updates); + id->flushed_updates = dma_fence_get(updates); + } - job->vm_id = id - id_mgr->ids; - job->vm_needs_flush = false; - trace_amdgpu_vm_grab_id(vm, ring->idx, job); - - mutex_unlock(&id_mgr->lock); - return 0; + if (needs_flush) + goto needs_flush; + else + goto no_flush_needed; }; @@ -515,16 +518,19 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; + id->pd_gpu_addr = job->vm_pd_addr; + dma_fence_put(id->flushed_updates); + id->flushed_updates = dma_fence_get(updates); + id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter); + atomic64_set(&id->owner, vm->client_id); + +needs_flush: + job->vm_needs_flush = true; dma_fence_put(id->last_flush); id->last_flush = NULL; - dma_fence_put(id->flushed_updates); - id->flushed_updates = dma_fence_get(updates); - - id->pd_gpu_addr = job->vm_pd_addr; - id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter); +no_flush_needed: list_move_tail(&id->list, &id_mgr->ids_lru); - atomic64_set(&id->owner, vm->client_id); job->vm_id = id - id_mgr->ids; trace_amdgpu_vm_grab_id(vm, ring->idx, job); From c5296d1401fb01ceb3a3cf781cc572b1847953c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 7 Apr 2017 15:31:13 +0200 Subject: [PATCH 025/144] drm/amdgpu: trace the vmhub in grab_id as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trace on which VMHUB we assigned an VMID. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 17 ++++++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index ee9d0f346d75..a98e4b8dd136 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -190,26 +190,29 @@ TRACE_EVENT(amdgpu_sched_run_job, TRACE_EVENT(amdgpu_vm_grab_id, - TP_PROTO(struct amdgpu_vm *vm, int ring, struct amdgpu_job *job), + TP_PROTO(struct amdgpu_vm *vm, struct amdgpu_ring *ring, + struct amdgpu_job *job), TP_ARGS(vm, ring, job), TP_STRUCT__entry( __field(struct amdgpu_vm *, vm) __field(u32, ring) - __field(u32, vmid) + __field(u32, vm_id) + __field(u32, vm_hub) __field(u64, pd_addr) __field(u32, needs_flush) ), TP_fast_assign( __entry->vm = vm; - __entry->ring = ring; - __entry->vmid = job->vm_id; + __entry->ring = ring->idx; + __entry->vm_id = job->vm_id; + __entry->vm_hub = ring->funcs->vmhub, __entry->pd_addr = job->vm_pd_addr; __entry->needs_flush = job->vm_needs_flush; ), - TP_printk("vm=%p, ring=%u, id=%u, pd_addr=%010Lx needs_flush=%u", - __entry->vm, __entry->ring, __entry->vmid, - __entry->pd_addr, __entry->needs_flush) + TP_printk("vm=%p, ring=%u, id=%u, hub=%u, pd_addr=%010Lx needs_flush=%u", + __entry->vm, __entry->ring, __entry->vm_id, + __entry->vm_hub, __entry->pd_addr, __entry->needs_flush) ); TRACE_EVENT(amdgpu_vm_bo_map, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 4e6c1e4072ca..f23f1b09d8a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -533,7 +533,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, list_move_tail(&id->list, &id_mgr->ids_lru); job->vm_id = id - id_mgr->ids; - trace_amdgpu_vm_grab_id(vm, ring->idx, job); + trace_amdgpu_vm_grab_id(vm, ring, job); error: mutex_unlock(&id_mgr->lock); From 5f1bcf511f6e5f54fffa6365286af1e88b18f54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 7 Apr 2017 17:43:19 +0200 Subject: [PATCH 026/144] drm/amdgpu: trace vm hub during flush as well v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trace on which hub we are doing the flush. v2: fix typo in commit message Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Andres Rodriguez Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 20 ++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index a98e4b8dd136..8601904e670a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -334,21 +334,25 @@ TRACE_EVENT(amdgpu_vm_copy_ptes, ); TRACE_EVENT(amdgpu_vm_flush, - TP_PROTO(uint64_t pd_addr, unsigned ring, unsigned id), - TP_ARGS(pd_addr, ring, id), + TP_PROTO(struct amdgpu_ring *ring, unsigned vm_id, + uint64_t pd_addr), + TP_ARGS(ring, vm_id, pd_addr), TP_STRUCT__entry( - __field(u64, pd_addr) __field(u32, ring) - __field(u32, id) + __field(u32, vm_id) + __field(u32, vm_hub) + __field(u64, pd_addr) ), TP_fast_assign( + __entry->ring = ring->idx; + __entry->vm_id = vm_id; + __entry->vm_hub = ring->funcs->vmhub; __entry->pd_addr = pd_addr; - __entry->ring = ring; - __entry->id = id; ), - TP_printk("ring=%u, id=%u, pd_addr=%010Lx", - __entry->ring, __entry->id, __entry->pd_addr) + TP_printk("ring=%u, id=%u, hub=%u, pd_addr=%010Lx", + __entry->ring, __entry->vm_id, + __entry->vm_hub,__entry->pd_addr) ); TRACE_EVENT(amdgpu_bo_list_set, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f23f1b09d8a9..6b95176d3f75 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -621,7 +621,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) u64 pd_addr = amdgpu_vm_adjust_mc_addr(adev, job->vm_pd_addr); struct dma_fence *fence; - trace_amdgpu_vm_flush(pd_addr, ring->idx, job->vm_id); + trace_amdgpu_vm_flush(ring, job->vm_id, pd_addr); amdgpu_ring_emit_vm_flush(ring, job->vm_id, pd_addr); r = amdgpu_fence_emit(ring, &fence); From 080b24ebdf230c80fe63e64633c0d52aca5d1a8e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Apr 2017 15:32:43 -0400 Subject: [PATCH 027/144] drm/amdgpu: fix spelling in header comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Christian König Signed-off-by: Alex Deucher --- include/uapi/drm/amdgpu_drm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 92262d81d41e..95260e5043af 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -297,7 +297,7 @@ union drm_amdgpu_gem_wait_idle { struct drm_amdgpu_wait_cs_in { /* Command submission handle * handle equals 0 means none to wait for - * handle equal ~0ull meanas wait for the latest sequence number + * handle equals ~0ull means wait for the latest sequence number */ __u64 handle; /** Absolute timeout to wait */ From 203eb0cb0eab990347e646c89a7134e60713133a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Apr 2017 15:36:32 -0400 Subject: [PATCH 028/144] drm/amdgpu: bump version number to note race fix and new fence functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixed in: "drm/amdgpu:fix race condition" Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 4e0f7d2d87f1..bb47fb3ce341 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -63,9 +63,10 @@ * - 3.11.0 - Add support for sensor query info (clocks, temp, etc). * - 3.12.0 - Add query for double offchip LDS buffers * - 3.13.0 - Add PRT support + * - 3.14.0 - Fix race in amdgpu_ctx_get_fence() and note new functionality */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 13 +#define KMS_DRIVER_MINOR 14 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; From 8f12bbe6d94a51f3ae314c27cc7b9b315adfe383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 11 Apr 2017 19:20:20 +0200 Subject: [PATCH 029/144] drm/radeon: force the UVD DPB into VRAM as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems to be mandatory for WMV playback. Bugs: https://bugs.freedesktop.org/show_bug.cgi?id=100510 Signed-off-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_cs.c | 10 ++++++---- drivers/gpu/drm/radeon/radeon_uvd.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index df6b58c08544..3ac671f6c8e1 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -117,11 +117,13 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) priority = (r->flags & RADEON_RELOC_PRIO_MASK) * 2 + !!r->write_domain; - /* the first reloc of an UVD job is the msg and that must be in - VRAM, also but everything into VRAM on AGP cards and older - IGP chips to avoid image corruptions */ + /* The first reloc of an UVD job is the msg and that must be in + * VRAM, the second reloc is the DPB and for WMV that must be in + * VRAM as well. Also put everything into VRAM on AGP cards and older + * IGP chips to avoid image corruptions + */ if (p->ring == R600_RING_TYPE_UVD_INDEX && - (i == 0 || pci_find_capability(p->rdev->ddev->pdev, + (i <= 0 || pci_find_capability(p->rdev->ddev->pdev, PCI_CAP_ID_AGP) || p->rdev->family == CHIP_RS780 || p->rdev->family == CHIP_RS880)) { diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index d34d1cf33895..7431eb4a11b7 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -621,7 +621,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, } /* TODO: is this still necessary on NI+ ? */ - if ((cmd == 0 || cmd == 0x3) && + if ((cmd == 0 || cmd == 1 || cmd == 0x3) && (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) { DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n", start, end); From 03161a6ecb7576492bb37e9bfc68a0330fc6a41d Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 13 Apr 2017 16:12:26 +0800 Subject: [PATCH 030/144] drm/amdgpu: fix dead lock if any ip block resume failed in s3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driver must free the console lock whether driver resuming successful or not. Otherwise, fb_console will be always waiting for the lock and then cause system stuck. [ 244.405541] INFO: task kworker/0:0:4 blocked for more than 120 seconds. [ 244.405543] Tainted: G OE 4.9.0-custom #1 [ 244.405544] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 244.405541] INFO: task kworker/0:0:4 blocked for more than 120 seconds. [ 244.405543] Tainted: G OE 4.9.0-custom #1 [ 244.405544] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 244.405550] kworker/0:0 D 0 4 2 0x00080000 [ 244.405559] Workqueue: events console_callback [ 244.405564] ffff88045a2cfc00 0000000000000000 ffff880462b75940 ffffffff81c0e500 [ 244.405568] ffff880476419280 ffffc900018f7c90 ffffffff817dcf62 000000000000003c [ 244.405572] 0000000100000000 0000000000000002 ffff880462b75940 ffff880462b75940 [ 244.405573] Call Trace: [ 244.405580] [] ? __schedule+0x222/0x6a0 [ 244.405584] [] schedule+0x36/0x80 [ 244.405588] [] schedule_timeout+0x1fc/0x390 [ 244.405592] [] __down_common+0xa5/0xf8 [ 244.405598] [] ? put_prev_entity+0x48/0x710 [ 244.405601] [] __down+0x1d/0x1f [ 244.405606] [] down+0x41/0x50 [ 244.405611] [] console_lock+0x1a/0x40 [ 244.405614] [] console_callback+0x13/0x160 [ 244.405617] [] ? __schedule+0x22a/0x6a0 [ 244.405623] [] process_one_work+0x153/0x3f0 [ 244.405628] [] worker_thread+0x12b/0x4b0 [ 244.405633] [] ? rescuer_thread+0x350/0x350 [ 244.405637] [] kthread+0xd3/0xf0 [ 244.405641] [] ? kthread_park+0x60/0x60 [ 244.405645] [] ? kthread_park+0x60/0x60 [ 244.405649] [] ret_from_fork+0x25/0x30 Signed-off-by: Huang Rui Reviewed-by: Michel Dänzer Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 28 ++++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 724b4c1c80f6..fbda93a87648 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2215,7 +2215,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) struct drm_connector *connector; struct amdgpu_device *adev = dev->dev_private; struct drm_crtc *crtc; - int r; + int r = 0; if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; @@ -2227,11 +2227,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) pci_set_power_state(dev->pdev, PCI_D0); pci_restore_state(dev->pdev); r = pci_enable_device(dev->pdev); - if (r) { - if (fbcon) - console_unlock(); - return r; - } + if (r) + goto unlock; } if (adev->is_atom_fw) amdgpu_atomfirmware_scratch_regs_restore(adev); @@ -2248,7 +2245,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) r = amdgpu_resume(adev); if (r) { DRM_ERROR("amdgpu_resume failed (%d).\n", r); - return r; + goto unlock; } amdgpu_fence_driver_resume(adev); @@ -2259,11 +2256,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) } r = amdgpu_late_init(adev); - if (r) { - if (fbcon) - console_unlock(); - return r; - } + if (r) + goto unlock; /* pin cursors */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -2313,12 +2307,14 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) dev->dev->power.disable_depth--; #endif - if (fbcon) { + if (fbcon) amdgpu_fbdev_set_suspend(adev, 0); - console_unlock(); - } - return 0; +unlock: + if (fbcon) + console_unlock(); + + return r; } static bool amdgpu_check_soft_reset(struct amdgpu_device *adev) From b3124dfcce8147e1340a06952f32443dc7e102b1 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 14 Apr 2017 10:50:03 +0800 Subject: [PATCH 031/144] drm/amdgpu: fix to print incorrect wptr address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Huang Rui Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 88c5d8f6f414..bc8313b5be0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -289,8 +289,8 @@ static void sdma_v4_0_ring_set_wptr(struct amdgpu_ring *ring) "mmSDMA%i_GFX_RB_WPTR == 0x%08x " "mmSDMA%i_GFX_RB_WPTR_HI == 0x%08x \n", me, - me, lower_32_bits(ring->wptr << 2), + me, upper_32_bits(ring->wptr << 2)); WREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR), lower_32_bits(ring->wptr << 2)); WREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR_HI), upper_32_bits(ring->wptr << 2)); From aef1ba58f5c60ec2de38258cb76db7842ccb6e1b Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 17 Apr 2017 15:32:52 +0800 Subject: [PATCH 032/144] drm/ttm: cleanup unuse ret value The ret must be 0 here, otherwise, the function will return after init_mem_type. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_bo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index e44626a2e698..a6d7fcb99c0b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1394,7 +1394,7 @@ EXPORT_SYMBOL(ttm_bo_evict_mm); int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, unsigned long p_size) { - int ret = -EINVAL; + int ret; struct ttm_mem_type_manager *man; unsigned i; @@ -1412,7 +1412,6 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, return ret; man->bdev = bdev; - ret = 0; if (type != TTM_PL_SYSTEM) { ret = (*man->func->init)(man, p_size); if (ret) From 79690b84db904669256fe3ef66dd175ce201817d Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 17 Apr 2017 18:46:57 +0800 Subject: [PATCH 033/144] drm/amdgpu: Remove redundant itermediate return val in sdma_v4_0.c Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index bc8313b5be0b..91947753946a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -744,10 +744,8 @@ static int sdma_v4_0_start(struct amdgpu_device *adev) if (r) return r; r = sdma_v4_0_rlc_resume(adev); - if (r) - return r; - return 0; + return r; } /** @@ -1158,8 +1156,6 @@ static int sdma_v4_0_hw_init(void *handle) sdma_v4_0_init_golden_registers(adev); r = sdma_v4_0_start(adev); - if (r) - return r; return r; } From 4bdcc4ea3ac11eddacbadd43128e1aba0122700b Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 17 Apr 2017 19:44:23 +0800 Subject: [PATCH 034/144] drm/amd/amdgpu: coding style refine in sdma_v4_0.c Replace 8 spaces with tabs. correct {} braces, etc. Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 151 ++++++++++++------------- 1 file changed, 75 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 91947753946a..ecc70a730a54 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -48,8 +48,7 @@ static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev); static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev); static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev); -static const u32 golden_settings_sdma_4[] = -{ +static const u32 golden_settings_sdma_4[] = { SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CHICKEN_BITS), 0xfe931f07, 0x02831f07, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL), 0xff000ff0, 0x3f000100, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_IB_CNTL), 0x800f0100, 0x00000100, @@ -76,8 +75,7 @@ static const u32 golden_settings_sdma_4[] = SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_UTCL1_PAGE), 0x000003ff, 0x000003c0 }; -static const u32 golden_settings_sdma_vg10[] = -{ +static const u32 golden_settings_sdma_vg10[] = { SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG), 0x0018773f, 0x00104002, SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ), 0x0018773f, 0x00104002, SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG), 0x0018773f, 0x00104002, @@ -87,16 +85,17 @@ static const u32 golden_settings_sdma_vg10[] = static u32 sdma_v4_0_get_reg_offset(u32 instance, u32 internal_offset) { u32 base = 0; + switch (instance) { - case 0: - base = SDMA0_BASE.instance[0].segment[0]; - break; - case 1: - base = SDMA1_BASE.instance[0].segment[0]; - break; - default: - BUG(); - break; + case 0: + base = SDMA0_BASE.instance[0].segment[0]; + break; + case 1: + base = SDMA1_BASE.instance[0].segment[0]; + break; + default: + BUG(); + break; } return base + internal_offset; @@ -159,7 +158,8 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev) case CHIP_VEGA10: chip_name = "vega10"; break; - default: BUG(); + default: + BUG(); } for (i = 0; i < adev->sdma.num_instances; i++) { @@ -179,7 +179,7 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev) if (adev->sdma.instance[i].feature_version >= 20) adev->sdma.instance[i].burst_nop = true; DRM_DEBUG("psp_load == '%s'\n", - adev->firmware.load_type == AMDGPU_FW_LOAD_PSP? "true": "false"); + adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false"); if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i]; @@ -192,9 +192,7 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev) } out: if (err) { - printk(KERN_ERR - "sdma_v4_0: Failed to load firmware \"%s\"\n", - fw_name); + DRM_ERROR("sdma_v4_0: Failed to load firmware \"%s\"\n", fw_name); for (i = 0; i < adev->sdma.num_instances; i++) { release_firmware(adev->sdma.instance[i].fw); adev->sdma.instance[i].fw = NULL; @@ -212,10 +210,10 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev) */ static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring) { - u64* rptr; + u64 *rptr; /* XXX check if swapping is necessary on BE */ - rptr =((u64*)&ring->adev->wb.wb[ring->rptr_offs]); + rptr = ((u64 *)&ring->adev->wb.wb[ring->rptr_offs]); DRM_DEBUG("rptr before shift == 0x%016llx\n", *rptr); return ((*rptr) >> 2); @@ -231,19 +229,20 @@ static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring) static uint64_t sdma_v4_0_ring_get_wptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; - u64* wptr = NULL; - uint64_t local_wptr=0; + u64 *wptr = NULL; + uint64_t local_wptr = 0; if (ring->use_doorbell) { /* XXX check if swapping is necessary on BE */ - wptr = ((u64*)&adev->wb.wb[ring->wptr_offs]); + wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]); DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr); *wptr = (*wptr) >> 2; DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr); } else { u32 lowbit, highbit; int me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1; - wptr=&local_wptr; + + wptr = &local_wptr; lowbit = RREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR)) >> 2; highbit = RREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2; @@ -285,9 +284,10 @@ static void sdma_v4_0_ring_set_wptr(struct amdgpu_ring *ring) WDOORBELL64(ring->doorbell_index, ring->wptr << 2); } else { int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1; + DRM_DEBUG("Not using doorbell -- " "mmSDMA%i_GFX_RB_WPTR == 0x%08x " - "mmSDMA%i_GFX_RB_WPTR_HI == 0x%08x \n", + "mmSDMA%i_GFX_RB_WPTR_HI == 0x%08x\n", me, lower_32_bits(ring->wptr << 2), me, @@ -319,22 +319,22 @@ static void sdma_v4_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count) * Schedule an IB in the DMA ring (VEGA10). */ static void sdma_v4_0_ring_emit_ib(struct amdgpu_ring *ring, - struct amdgpu_ib *ib, - unsigned vm_id, bool ctx_switch) + struct amdgpu_ib *ib, + unsigned vm_id, bool ctx_switch) { - u32 vmid = vm_id & 0xf; + u32 vmid = vm_id & 0xf; - /* IB packet must end on a 8 DW boundary */ - sdma_v4_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8); + /* IB packet must end on a 8 DW boundary */ + sdma_v4_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8); - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) | - SDMA_PKT_INDIRECT_HEADER_VMID(vmid)); - /* base must be 32 byte aligned */ - amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr) & 0xffffffe0); - amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); - amdgpu_ring_write(ring, ib->length_dw); - amdgpu_ring_write(ring, 0); - amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) | + SDMA_PKT_INDIRECT_HEADER_VMID(vmid)); + /* base must be 32 byte aligned */ + amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr) & 0xffffffe0); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, ib->length_dw); + amdgpu_ring_write(ring, 0); + amdgpu_ring_write(ring, 0); } @@ -523,7 +523,7 @@ static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev) u32 doorbell; u32 doorbell_offset; u32 temp; - int i,r; + int i, r; for (i = 0; i < adev->sdma.num_instances; i++) { ring = &adev->sdma.instance[i].ring; @@ -572,7 +572,7 @@ static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev) doorbell = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_DOORBELL)); doorbell_offset = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_DOORBELL_OFFSET)); - if (ring->use_doorbell){ + if (ring->use_doorbell) { doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 1); doorbell_offset = REG_SET_FIELD(doorbell_offset, SDMA0_GFX_DOORBELL_OFFSET, OFFSET, ring->doorbell_index); @@ -694,9 +694,7 @@ static int sdma_v4_0_load_microcode(struct amdgpu_device *adev) for (j = 0; j < fw_size; j++) - { WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_UCODE_DATA), le32_to_cpup(fw_data++)); - } WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_UCODE_ADDR), adev->sdma.instance[i].fw_version); } @@ -795,9 +793,8 @@ static int sdma_v4_0_ring_test_ring(struct amdgpu_ring *ring) for (i = 0; i < adev->usec_timeout; i++) { tmp = le32_to_cpu(adev->wb.wb[index]); - if (tmp == 0xDEADBEEF) { + if (tmp == 0xDEADBEEF) break; - } DRM_UDELAY(1); } @@ -862,29 +859,29 @@ static int sdma_v4_0_ring_test_ib(struct amdgpu_ring *ring, long timeout) if (r) goto err1; - r = dma_fence_wait_timeout(f, false, timeout); - if (r == 0) { - DRM_ERROR("amdgpu: IB test timed out\n"); - r = -ETIMEDOUT; - goto err1; - } else if (r < 0) { - DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); - goto err1; - } - tmp = le32_to_cpu(adev->wb.wb[index]); - if (tmp == 0xDEADBEEF) { - DRM_INFO("ib test on ring %d succeeded\n", ring->idx); - r = 0; - } else { - DRM_ERROR("amdgpu: ib test failed (0x%08X)\n", tmp); - r = -EINVAL; - } + r = dma_fence_wait_timeout(f, false, timeout); + if (r == 0) { + DRM_ERROR("amdgpu: IB test timed out\n"); + r = -ETIMEDOUT; + goto err1; + } else if (r < 0) { + DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); + goto err1; + } + tmp = le32_to_cpu(adev->wb.wb[index]); + if (tmp == 0xDEADBEEF) { + DRM_INFO("ib test on ring %d succeeded\n", ring->idx); + r = 0; + } else { + DRM_ERROR("amdgpu: ib test failed (0x%08X)\n", tmp); + r = -EINVAL; + } err1: - amdgpu_ib_free(adev, &ib, NULL); - dma_fence_put(f); + amdgpu_ib_free(adev, &ib, NULL); + dma_fence_put(f); err0: - amdgpu_wb_free(adev, index); - return r; + amdgpu_wb_free(adev, index); + return r; } @@ -1191,10 +1188,12 @@ static bool sdma_v4_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; u32 i; + for (i = 0; i < adev->sdma.num_instances; i++) { u32 tmp = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_STATUS_REG)); + if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK)) - return false; + return false; } return true; @@ -1203,8 +1202,9 @@ static bool sdma_v4_0_is_idle(void *handle) static int sdma_v4_0_wait_for_idle(void *handle) { unsigned i; - u32 sdma0,sdma1; + u32 sdma0, sdma1; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + for (i = 0; i < adev->usec_timeout; i++) { sdma0 = RREG32(sdma_v4_0_get_reg_offset(0, mmSDMA0_STATUS_REG)); sdma1 = RREG32(sdma_v4_0_get_reg_offset(1, mmSDMA0_STATUS_REG)); @@ -1232,7 +1232,7 @@ static int sdma_v4_0_set_trap_irq_state(struct amdgpu_device *adev, u32 reg_offset = (type == AMDGPU_SDMA_IRQ_TRAP0) ? sdma_v4_0_get_reg_offset(0, mmSDMA0_CNTL) : - sdma_v4_0_get_reg_offset(1, mmSDMA0_CNTL); + sdma_v4_0_get_reg_offset(1, mmSDMA0_CNTL); sdma_cntl = RREG32(reg_offset); sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA0_CNTL, TRAP_ENABLE, @@ -1324,7 +1324,7 @@ static void sdma_v4_0_update_medium_grain_clock_gating( SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK | SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK | SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK); - if(def != data) + if (def != data) WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_CLK_CTRL), data); } } else { @@ -1374,17 +1374,17 @@ static void sdma_v4_0_update_medium_grain_light_sleep( /* 1-not override: enable sdma1 mem light sleep */ if (adev->asic_type == CHIP_VEGA10) { - def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL)); - data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; - if (def != data) - WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL), data); + def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL)); + data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; + if (def != data) + WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL), data); } } else { /* 0-override:disable sdma0 mem light sleep */ def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL)); data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; if (def != data) - WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data); + WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data); /* 0-override:disable sdma1 mem light sleep */ if (adev->asic_type == CHIP_VEGA10) { @@ -1599,8 +1599,7 @@ static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev) } } -const struct amdgpu_ip_block_version sdma_v4_0_ip_block = -{ +const struct amdgpu_ip_block_version sdma_v4_0_ip_block = { .type = AMD_IP_BLOCK_TYPE_SDMA, .major = 4, .minor = 0, From 2211a787dee798131a4774ee7df9aa758ebe07aa Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Mon, 17 Apr 2017 20:46:29 +0800 Subject: [PATCH 035/144] drm/amd/powerplay: delete dead functions in vega10. Vega10 does not support AVFS BTC, remove function. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 30 ++----------------- .../drm/amd/powerplay/smumgr/vega10_smumgr.c | 9 ------ .../drm/amd/powerplay/smumgr/vega10_smumgr.h | 1 - 3 files changed, 2 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 561b837b09be..3e11abe9cd0a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -2411,35 +2411,9 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(!result, "Failed to upload PPtable!", return result); - if (data->smu_features[GNLD_AVFS].supported) { - uint32_t features_enabled; - result = vega10_get_smc_features(hwmgr->smumgr, &features_enabled); - PP_ASSERT_WITH_CODE(!result, - "Failed to Retrieve Enabled Features!", - return result); - if (!(features_enabled & (1 << FEATURE_AVFS_BIT))) { - result = vega10_perform_btc(hwmgr->smumgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to Perform BTC!", + result = vega10_avfs_enable(hwmgr, true); + PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!", return result); - result = vega10_avfs_enable(hwmgr, true); - PP_ASSERT_WITH_CODE(!result, - "Attempt to enable AVFS feature Failed!", - return result); - result = vega10_save_vft_table(hwmgr->smumgr, - (uint8_t *)&(data->smc_state_table.avfs_table)); - PP_ASSERT_WITH_CODE(!result, - "Attempt to save VFT table Failed!", - return result); - } else { - data->smu_features[GNLD_AVFS].enabled = true; - result = vega10_restore_vft_table(hwmgr->smumgr, - (uint8_t *)&(data->smc_state_table.avfs_table)); - PP_ASSERT_WITH_CODE(!result, - "Attempt to restore VFT table Failed!", - return result;); - } - } return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 2685f02ab551..7a36a7404f73 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -299,15 +299,6 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, return 0; } -int vega10_perform_btc(struct pp_smumgr *smumgr) -{ - PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc_with_parameter( - smumgr, PPSMC_MSG_RunBtc, 0), - "Attempt to run DC BTC Failed!", - return -1); - return 0; -} - int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table) { PP_ASSERT_WITH_CODE(avfs_table, diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h index ad050212426d..71e9b6492647 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h @@ -62,7 +62,6 @@ int vega10_get_smc_features(struct pp_smumgr *smumgr, uint32_t *features_enabled); int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table); int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table); -int vega10_perform_btc(struct pp_smumgr *smumgr); int vega10_set_tools_address(struct pp_smumgr *smumgr); From ad2fed9ad5907c35e132e43420a0e47ab22350f0 Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Thu, 23 Feb 2017 11:01:40 +0800 Subject: [PATCH 036/144] drm/amdgpu: fix double_offchip_lds_buf for gfx v6 Was incorrect for SI. Signed-off-by: Junwei Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 4c4874fdf59f..0ce977783943 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -1579,7 +1579,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev) static void gfx_v6_0_config_init(struct amdgpu_device *adev) { - adev->gfx.config.double_offchip_lds_buf = 1; + adev->gfx.config.double_offchip_lds_buf = 0; } static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) From ee73164a0d8d2fd98f666a5dd35da1d9a19ec009 Mon Sep 17 00:00:00 2001 From: Pixel Ding Date: Thu, 23 Feb 2017 11:10:33 +0800 Subject: [PATCH 037/144] drm/amdgpu/virt: don't check VALID bit for FLR completion message The interrupt after FLR is missed sometimes due to hardware reason, so guest driver get the notification of FLR completion via polling message. Then host doesn't write VALID bit to avoid sending interrupt, otherwise the completion will be handled twice. So there's a valid message without VALID bit for FLR completion, driver should handle it without checking. Signed-off-by: Pixel Ding Reviewed-by: Xiangliang Yu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c index 70a3dd13cb02..7bdc51b02326 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c @@ -368,9 +368,12 @@ static int xgpu_vi_mailbox_rcv_msg(struct amdgpu_device *adev, u32 reg; u32 mask = REG_FIELD_MASK(MAILBOX_CONTROL, RCV_MSG_VALID); - reg = RREG32_NO_KIQ(mmMAILBOX_CONTROL); - if (!(reg & mask)) - return -ENOENT; + /* workaround: host driver doesn't set VALID for CMPL now */ + if (event != IDH_FLR_NOTIFICATION_CMPL) { + reg = RREG32_NO_KIQ(mmMAILBOX_CONTROL); + if (!(reg & mask)) + return -ENOENT; + } reg = RREG32_NO_KIQ(mmMAILBOX_MSGBUF_RCV_DW0); if (reg != event) From 8972e5d26996e3f04e1cf29b7d7edd3ec5614bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 6 Mar 2017 13:34:57 +0100 Subject: [PATCH 038/144] drm/amdgpu: fix coding style and printing in amdgpu_doorbell_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on commit "drm/radeon: remove useless and potentially wrong message". The size of the info printing is incorrect and the PCI subsystems prints the same info on boot anyway. Signed-off-by: Christian König Reviewed-by: Edward O'Callaghan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index fbda93a87648..8aad6f4a5241 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -422,12 +422,11 @@ static int amdgpu_doorbell_init(struct amdgpu_device *adev) if (adev->doorbell.num_doorbells == 0) return -EINVAL; - adev->doorbell.ptr = ioremap(adev->doorbell.base, adev->doorbell.num_doorbells * sizeof(u32)); - if (adev->doorbell.ptr == NULL) { + adev->doorbell.ptr = ioremap(adev->doorbell.base, + adev->doorbell.num_doorbells * + sizeof(u32)); + if (adev->doorbell.ptr == NULL) return -ENOMEM; - } - DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)adev->doorbell.base); - DRM_INFO("doorbell mmio size: %u\n", (unsigned)adev->doorbell.size); return 0; } From 98c24b24dfef209eb8bb164550e1567c7ba82c52 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Fri, 14 Apr 2017 17:40:57 +0800 Subject: [PATCH 039/144] drm/amdgpu/mmhub_v1: bypass clockgating setting For SRIOV doesn't need CG, so bypass it. Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 62684510ddcd..dbfe48d1207a 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -511,6 +511,9 @@ static int mmhub_v1_0_set_clockgating_state(void *handle, { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (amdgpu_sriov_vf(adev)) + return 0; + switch (adev->asic_type) { case CHIP_VEGA10: mmhub_v1_0_update_medium_grain_clock_gating(adev, From fb82afab134ab71b3b52224b6da12daea8662c28 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Fri, 14 Apr 2017 17:43:02 +0800 Subject: [PATCH 040/144] drm/amdgpu/gfx9: bypass clockgating setting For SRIOV doesn't need clockgating, bypass it. Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 87596e48f65d..cc60dafb7d94 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2740,6 +2740,9 @@ static int gfx_v9_0_set_clockgating_state(void *handle, { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (amdgpu_sriov_vf(adev)) + return 0; + switch (adev->asic_type) { case CHIP_VEGA10: gfx_v9_0_update_gfx_clock_gating(adev, From 7ef69843def65bdbf69a5be784e6a9e080f22ef6 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 18 Apr 2017 19:21:44 +0800 Subject: [PATCH 041/144] drm/amdgpu: fix memory clock can't switch on CI. if we set only lowest mclk level enabled, when we enable uvd dpm during boot time, mclk will be fixed in the lowest level. the mclk switch will fail if try to enable other level of mclk at this time. so set all mclk levels enabled. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 11ccda83d767..a6dda3470003 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -3036,6 +3036,7 @@ static int ci_populate_single_memory_level(struct amdgpu_device *adev, memory_clock, &memory_level->MinVddcPhases); + memory_level->EnabledForActivity = 1; memory_level->EnabledForThrottle = 1; memory_level->UpH = 0; memory_level->DownH = 100; @@ -3468,8 +3469,6 @@ static int ci_populate_all_memory_levels(struct amdgpu_device *adev) return ret; } - pi->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - if ((dpm_table->mclk_table.count >= 2) && ((adev->pdev->device == 0x67B0) || (adev->pdev->device == 0x67B1))) { pi->smc_state_table.MemoryLevel[1].MinVddc = From 1c4ecf48cfee8e138c6483bafd1425628a413315 Mon Sep 17 00:00:00 2001 From: Trigger Huang Date: Mon, 17 Apr 2017 10:56:02 -0400 Subject: [PATCH 042/144] drm/amdgpu: Fix module unload hang by KIQ on Vega10 Apply commit 4e683cb2644f ("drm/amdgpu: Fix module unload hang by KIQ IRQ set")to vega10 V2: delete reduant kiq irq funcs type check (suggested by Rex.Zhu) Signed-off-by: Trigger Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index cc60dafb7d94..574c017a50a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -631,7 +631,6 @@ static int gfx_v9_0_kiq_init_ring(struct amdgpu_device *adev, ring->pipe = 1; } - irq->data = ring; ring->queue = 0; ring->eop_gpu_addr = kiq->eop_gpu_addr; sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring->queue); @@ -647,7 +646,6 @@ static void gfx_v9_0_kiq_free_ring(struct amdgpu_ring *ring, { amdgpu_wb_free(ring->adev, ring->adev->virt.reg_val_offs); amdgpu_ring_fini(ring); - irq->data = NULL; } /* create MQD for each compute queue */ @@ -3370,9 +3368,7 @@ static int gfx_v9_0_kiq_set_interrupt_state(struct amdgpu_device *adev, enum amdgpu_interrupt_state state) { uint32_t tmp, target; - struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data; - - BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ)); + struct amdgpu_ring *ring = &(adev->gfx.kiq.ring); if (ring->me == 1) target = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL); @@ -3416,9 +3412,7 @@ static int gfx_v9_0_kiq_irq(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry) { u8 me_id, pipe_id, queue_id; - struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data; - - BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ)); + struct amdgpu_ring *ring = &(adev->gfx.kiq.ring); me_id = (entry->ring_id & 0x0c) >> 2; pipe_id = (entry->ring_id & 0x03) >> 0; From 15ff510bbfd7170fa5af8924fe0503f4d116e7d2 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 19 Apr 2017 09:01:42 -0400 Subject: [PATCH 043/144] drm/amd/amdgpu: Change comp GFXv6 ring name to remove space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit umr expects the ring name to be a complete word. This also makes it consistent with GFXv7/8. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 0ce977783943..6a429e927297 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -3292,7 +3292,7 @@ static int gfx_v6_0_sw_init(void *handle) ring->me = 1; ring->pipe = i; ring->queue = i; - sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue); + sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue); irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq, irq_type); From e182e234c8658c0880401052fd364b1a1a59b03d Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 19 Apr 2017 09:02:41 -0400 Subject: [PATCH 044/144] drm/amd/amdgpu: Change comp GFXv9 ring name to remove space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit umr expects the ring name to be a complete word. This also makes it consistent with GFXv7/8. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 574c017a50a2..9a9cb90e2f5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1094,7 +1094,7 @@ static int gfx_v9_0_sw_init(void *handle) ring->pipe = i / 8; ring->queue = i % 8; ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * MEC_HPD_SIZE); - sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue); + sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue); irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe; /* type-2 packets are deprecated on MEC, use type-3 instead */ r = amdgpu_ring_init(adev, ring, 1024, From 775f55f1b5b65c6cfc52555d9a8b80de5429d21b Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Wed, 19 Apr 2017 11:03:04 -0400 Subject: [PATCH 045/144] drm/amd/amdgpu: Print out ring name in dev_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So it's more obvious which rings are using which INV engines. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index a71521e10763..edf43769ae70 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -394,8 +394,9 @@ static int gmc_v9_0_late_init(void *handle) unsigned vmhub = ring->funcs->vmhub; ring->vm_inv_eng = vm_inv_eng[vmhub]++; - dev_info(adev->dev, "ring %u uses VM inv eng %u on hub %u\n", - ring->idx, ring->vm_inv_eng, ring->funcs->vmhub); + dev_info(adev->dev, "ring %u(%s) uses VM inv eng %u on hub %u\n", + ring->idx, ring->name, ring->vm_inv_eng, + ring->funcs->vmhub); } /* Engine 17 is used for GART flushes */ From e0b2f8cff15b2d20a427c381247a8ff6bb28d21e Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Apr 2017 17:34:26 +0800 Subject: [PATCH 046/144] drm/amdgpu: update smu9 driver interface Updated interface between the driver and the SMU controller. Signed-off-by: Evan Quan Signed-off-by: Alex Deucher Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/inc/smu9_driver_if.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h index 2037910adcb1..d43f98a910b0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h @@ -30,7 +30,7 @@ * SMU TEAM: Always increment the interface version if * any structure is changed in this file */ -#define SMU9_DRIVER_IF_VERSION 0xB +#define SMU9_DRIVER_IF_VERSION 0xD #define PPTABLE_V10_SMU_VERSION 1 @@ -302,7 +302,17 @@ typedef struct { uint32_t DpmLevelPowerDelta; - uint32_t Reserved[19]; + uint8_t EnableBoostState; + uint8_t AConstant_Shift; + uint8_t DC_tol_sigma_Shift; + uint8_t PSM_Age_CompFactor_Shift; + + uint16_t BoostStartTemperature; + uint16_t BoostStopTemperature; + + PllSetting_t GfxBoostState; + + uint32_t Reserved[14]; /* Padding - ignore */ uint32_t MmHubPadding[7]; /* SMU internal use */ @@ -464,4 +474,8 @@ typedef struct { #define DB_PCC_SHIFT 26 #define DB_EDC_SHIFT 27 +#define REMOVE_FMAX_MARGIN_BIT 0x0 +#define REMOVE_DCTOL_MARGIN_BIT 0x1 +#define REMOVE_PLATFORM_MARGIN_BIT 0x2 + #endif From e3c5e9826d60630236de105c05e7a58f12c45ab5 Mon Sep 17 00:00:00 2001 From: Trigger Huang Date: Mon, 17 Apr 2017 08:50:18 -0400 Subject: [PATCH 047/144] drm/amdgpu: Destroy psp ring in hw_fini Fix issue that PSP initialization will fail if reload amdgpu module. That's because the PSP ring must be destroyed to be ready for the next time PSP initialization. Changes in v2: - Move psp_ring_destroy before all BOs free (suggested by Ray Huang). Changes in v3: - Check firmware load type, if it is not PSP, we should do nothing in fw_fini(), and of course will not destroy PSP ring too (suggested by Ray Huang). Signed-off-by: Trigger Huang Reviewed-by: Xiangliang Yu Reviewed-by: Huang Rui Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 9 +++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 3 +++ drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 27 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/psp_v3_1.h | 2 ++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 19180aaa8bf2..1e380fe29b5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -56,6 +56,7 @@ static int psp_sw_init(void *handle) psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf; psp->ring_init = psp_v3_1_ring_init; psp->ring_create = psp_v3_1_ring_create; + psp->ring_destroy = psp_v3_1_ring_destroy; psp->cmd_submit = psp_v3_1_cmd_submit; psp->compare_sram_data = psp_v3_1_compare_sram_data; psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk; @@ -411,8 +412,12 @@ static int psp_hw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct psp_context *psp = &adev->psp; - if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) - amdgpu_ucode_fini_bo(adev); + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) + return 0; + + amdgpu_ucode_fini_bo(adev); + + psp_ring_destroy(psp, PSP_RING_TYPE__KM); if (psp->tmr_buf) amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 28faba5b7dd6..0301e4e0b297 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -66,6 +66,8 @@ struct psp_context struct psp_gfx_cmd_resp *cmd); int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); int (*ring_create)(struct psp_context *psp, enum psp_ring_type ring_type); + int (*ring_destroy)(struct psp_context *psp, + enum psp_ring_type ring_type); int (*cmd_submit)(struct psp_context *psp, struct amdgpu_firmware_info *ucode, uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, int index); bool (*compare_sram_data)(struct psp_context *psp, @@ -116,6 +118,7 @@ struct amdgpu_psp_funcs { #define psp_prep_cmd_buf(ucode, type) (psp)->prep_cmd_buf((ucode), (type)) #define psp_ring_init(psp, type) (psp)->ring_init((psp), (type)) #define psp_ring_create(psp, type) (psp)->ring_create((psp), (type)) +#define psp_ring_destroy(psp, type) ((psp)->ring_destroy((psp), (type))) #define psp_cmd_submit(psp, ucode, cmd_mc, fence_mc, index) \ (psp)->cmd_submit((psp), (ucode), (cmd_mc), (fence_mc), (index)) #define psp_compare_sram_data(psp, ucode, type) \ diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index d351583785e5..60a6407ba267 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -321,6 +321,33 @@ int psp_v3_1_ring_create(struct psp_context *psp, enum psp_ring_type ring_type) return ret; } +int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type) +{ + int ret = 0; + struct psp_ring *ring; + unsigned int psp_ring_reg = 0; + struct amdgpu_device *adev = psp->adev; + + ring = &psp->km_ring; + + /* Write the ring destroy command to C2PMSG_64 */ + psp_ring_reg = 3 << 16; + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), psp_ring_reg); + + /* there might be handshake issue with hardware which needs delay */ + mdelay(20); + + /* Wait for response flag (bit 31) in C2PMSG_64 */ + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), + 0x80000000, 0x80000000, false); + + if (ring->ring_mem) + amdgpu_bo_free_kernel(&adev->firmware.rbuf, + &ring->ring_mem_mc_addr, + (void **)&ring->ring_mem); + return ret; +} + int psp_v3_1_cmd_submit(struct psp_context *psp, struct amdgpu_firmware_info *ucode, uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h index 5230d27867c9..9dcd0b25c4c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.h @@ -41,6 +41,8 @@ extern int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type); extern int psp_v3_1_ring_create(struct psp_context *psp, enum psp_ring_type ring_type); +extern int psp_v3_1_ring_destroy(struct psp_context *psp, + enum psp_ring_type ring_type); extern int psp_v3_1_cmd_submit(struct psp_context *psp, struct amdgpu_firmware_info *ucode, uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, From fc6aa33da4b1043ad1b337d051770993418256d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 19 Apr 2017 14:41:19 +0200 Subject: [PATCH 048/144] drm/amdgpu: fix amdgpu_vm_clear_freed v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use amdgpu_vm_bo_update_mapping() instead of amdgpu_vm_bo_split_mapping() here. We don't want any flags set in the cleared areas and splitting shouldn't be necessary. v2: fix typo in commit message Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6b95176d3f75..f34d822f92ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1631,8 +1631,9 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping, list); list_del(&mapping->list); - r = amdgpu_vm_bo_split_mapping(adev, NULL, 0, NULL, vm, mapping, - 0, 0, &f); + r = amdgpu_vm_bo_update_mapping(adev, NULL, 0, NULL, vm, + mapping->start, mapping->last, + 0, 0, &f); amdgpu_vm_free_mapping(adev, vm, mapping, f); if (r) { dma_fence_put(f); From d0766e981b36608f9fe9b29985d4cd696099c3f8 Mon Sep 17 00:00:00 2001 From: "Zhang, Jerry" Date: Wed, 19 Apr 2017 09:53:29 +0800 Subject: [PATCH 049/144] drm/amdgpu: PRT support for gfx9 (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix PRT handling on gfx9 v2: unify PRT bit for all ASICs v3: move PRT flag checking in amdgpu_vm_bo_split_mapping() Signed-off-by: Junwei Zhang Acked-by: David Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f34d822f92ac..c42a9979d056 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1338,6 +1338,12 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, flags &= ~AMDGPU_PTE_MTYPE_MASK; flags |= (mapping->flags & AMDGPU_PTE_MTYPE_MASK); + if ((mapping->flags & AMDGPU_PTE_PRT) && + (adev->asic_type >= CHIP_VEGA10)) { + flags |= AMDGPU_PTE_PRT; + flags &= ~AMDGPU_PTE_VALID; + } + trace_amdgpu_vm_bo_update(mapping); pfn = mapping->offset >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 661a8f6826ef..d97e28b4bdc4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -65,7 +65,8 @@ struct amdgpu_bo_list_entry; #define AMDGPU_PTE_FRAG(x) ((x & 0x1fULL) << 7) -#define AMDGPU_PTE_PRT (1ULL << 63) +/* TILED for VEGA10, reserved for older ASICs */ +#define AMDGPU_PTE_PRT (1ULL << 51) /* VEGA10 only */ #define AMDGPU_PTE_MTYPE(a) ((uint64_t)a << 57) From 7ad87b96962a01830b0751d11a389b4039eb4460 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Apr 2017 13:51:52 -0400 Subject: [PATCH 050/144] Revert "drm/amd/amdgpu: Set VCE/UVD off during late init" This leads to hangs on init. This reverts commit d1aff8ec49c3ece05cee9b6e63d44e96a420b068. --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8aad6f4a5241..75f851bd5b63 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -53,7 +53,6 @@ #include "bif/bif_4_1_d.h" #include #include -#include "amdgpu_pm.h" static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev); static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev); @@ -1583,9 +1582,6 @@ static int amdgpu_late_init(struct amdgpu_device *adev) } } - amdgpu_dpm_enable_uvd(adev, false); - amdgpu_dpm_enable_vce(adev, false); - return 0; } From 42f72d0b3754a7ecf1208f90cef45ba89a89f2e7 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 20 Apr 2017 15:25:39 +0800 Subject: [PATCH 051/144] drm/amd/powerplay: add error message to remind user updating firmware Signed-off-by: Huang Rui Reviewed-by: Evan Quan Reviewed-by: Edward O'Callaghan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 7a36a7404f73..21b61315fc40 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -369,8 +369,11 @@ static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) "Attempt to read SMC IF Version Number Failed!", return -1); - if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) - return -1; + if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) { + pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n", + smc_driver_if_version, SMU9_DRIVER_IF_VERSION); + return -EINVAL; + } return 0; } From 67131aa525d22fe21904bfd463520e98b5d67566 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 12 Apr 2017 17:32:35 +0800 Subject: [PATCH 052/144] drm/amd/powerplay: enable AGM logging while dpm disabled. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 2 -- drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 3e11abe9cd0a..deb112485f82 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -2583,8 +2583,6 @@ static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) "Failed to configure telemetry!", return tmp_result); - vega10_set_tools_address(hwmgr->smumgr); - smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_NumOfDisplays, 0); diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 21b61315fc40..9987d5b80d82 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -491,7 +491,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) priv->smu_tables.entry[AVFSTABLE].table = kaddr; priv->smu_tables.entry[AVFSTABLE].handle = handle; - tools_size = 0; + tools_size = 0x19000; if (tools_size) { smu_allocate_memory(smumgr->device, tools_size, @@ -511,6 +511,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) smu_lower_32_bits(mc_addr); priv->smu_tables.entry[TOOLSTABLE].table = kaddr; priv->smu_tables.entry[TOOLSTABLE].handle = handle; + vega10_set_tools_address(smumgr); } } From d475ce6296d702c16c96790a390ad7b4616f18b4 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 12 Apr 2017 17:52:07 +0800 Subject: [PATCH 053/144] drm/amd/powerplay: allocate fb for avfs fuse table on vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/smumgr/vega10_smumgr.c | 36 +++++++++++++++++++ .../drm/amd/powerplay/smumgr/vega10_smumgr.h | 1 + 2 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 9987d5b80d82..5980f02f2ce9 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -515,6 +515,40 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) } } + /* allocate space for AVFS Fuse table */ + smu_allocate_memory(smumgr->device, + sizeof(AvfsFuseOverride_t), + CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, + PAGE_SIZE, + &mc_addr, + &kaddr, + &handle); + + PP_ASSERT_WITH_CODE(kaddr, + "[vega10_smu_init] Out of memory for avfs fuse table.", + kfree(smumgr->backend); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)handle); + return -1); + + priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01; + priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t); + priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE; + priv->smu_tables.entry[AVFSFUSETABLE].table_addr_high = + smu_upper_32_bits(mc_addr); + priv->smu_tables.entry[AVFSFUSETABLE].table_addr_low = + smu_lower_32_bits(mc_addr); + priv->smu_tables.entry[AVFSFUSETABLE].table = kaddr; + priv->smu_tables.entry[AVFSFUSETABLE].handle = handle; + return 0; } @@ -533,6 +567,8 @@ static int vega10_smu_fini(struct pp_smumgr *smumgr) if (priv->smu_tables.entry[TOOLSTABLE].table) cgs_free_gpu_mem(smumgr->device, (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle); kfree(smumgr->backend); smumgr->backend = NULL; } diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h index 71e9b6492647..821425c1e4e0 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h @@ -30,6 +30,7 @@ enum smu_table_id { WMTABLE, AVFSTABLE, TOOLSTABLE, + AVFSFUSETABLE, MAX_SMU_TABLE, }; From 2d5f5f949680bc02bd5f98ee9ec6d08f67e9ca4c Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 20 Apr 2017 16:38:36 +0800 Subject: [PATCH 054/144] drm/amd/powerplay: enable pcie dpm on Vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index deb112485f82..ee40378c3e82 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -111,6 +111,8 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true; data->registry_data.mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; + data->registry_data.pcie_dpm_key_disabled = + hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; data->registry_data.dcefclk_dpm_key_disabled = hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true; @@ -121,7 +123,6 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) data->registry_data.enable_tdc_limit_feature = 1; } - data->registry_data.pcie_dpm_key_disabled = 1; data->registry_data.disable_water_mark = 0; data->registry_data.fan_control_support = 1; From afc0255c9a5ecede2f235f4d117c2913059aa3c3 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 19 Apr 2017 16:00:21 +0800 Subject: [PATCH 055/144] drm/amd/powerplay: enable clock stretch feature on Vega10. Correctly calculate CKSVidOffset Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index ee40378c3e82..0042c339415f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -123,6 +123,9 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) data->registry_data.enable_tdc_limit_feature = 1; } + data->registry_data.clock_stretcher_support = + hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false; + data->registry_data.disable_water_mark = 0; data->registry_data.fan_control_support = 1; @@ -2045,10 +2048,10 @@ static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr) table_info->vdd_dep_on_sclk; uint32_t i; - for (i = 0; dep_table->count; i++) { + for (i = 0; i < dep_table->count; i++) { pp_table->CksEnable[i] = dep_table->entries[i].cks_enable; - pp_table->CksVidOffset[i] = convert_to_vid( - dep_table->entries[i].cks_voffset); + pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset + * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); } return 0; @@ -2380,8 +2383,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) "Failed to initialize UVD Level!", return result); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { + if (data->registry_data.clock_stretcher_support) { result = vega10_populate_clock_stretcher_table(hwmgr); PP_ASSERT_WITH_CODE(!result, "Failed to populate Clock Stretcher Table!", From 4bae05e196c518c2c95022fbdbee551bbc6893a5 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 20 Apr 2017 16:33:23 +0800 Subject: [PATCH 056/144] drm/amd/powerplay: Fix AVFS param. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 0042c339415f..278def7380e7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -2163,7 +2163,7 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 0; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12; if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != data->dcef_clk_quad_eqn_a) && @@ -2186,7 +2186,7 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 0; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12; if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != data->pixel_clk_quad_eqn_a) && @@ -2209,7 +2209,7 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12; - + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12; if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != data->phy_clk_quad_eqn_a) && (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != @@ -2231,7 +2231,7 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24; pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 0; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12; } else { data->smu_features[GNLD_AVFS].supported = false; } From 4fcae787866915161f22d627328fa8d2e13d215b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 20 Apr 2017 12:11:47 +0200 Subject: [PATCH 057/144] drm/amdgpu: fix amdgpu_ttm_bo_eviction_valuable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BOs not mapped into the GART are always valuable for an eviction. Otherwise we don't correctly swap them out on VRAM evictions during memory pressure. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 23f7fe8fdc3d..eadbcfad2299 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1040,11 +1040,17 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm, static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { - if (bo->mem.mem_type == TTM_PL_VRAM && - bo->mem.start == AMDGPU_BO_INVALID_OFFSET) { - unsigned long num_pages = bo->mem.num_pages; - struct drm_mm_node *node = bo->mem.mm_node; + unsigned long num_pages = bo->mem.num_pages; + struct drm_mm_node *node = bo->mem.mm_node; + if (bo->mem.start != AMDGPU_BO_INVALID_OFFSET) + return ttm_bo_eviction_valuable(bo, place); + + switch (bo->mem.mem_type) { + case TTM_PL_TT: + return true; + + case TTM_PL_VRAM: /* Check each drm MM node individually */ while (num_pages) { if (place->fpfn < (node->start + node->size) && @@ -1054,8 +1060,10 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, num_pages -= node->size; ++node; } + break; - return false; + default: + break; } return ttm_bo_eviction_valuable(bo, place); From 05a72a2864c2b27471e9f5365448563c78f9b114 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Thu, 13 Apr 2017 16:16:51 +0800 Subject: [PATCH 058/144] drm/amdgpu: add gtt print like vram when dump mm table V2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Chunming Zhou Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 0335c2f331e9..f7d22c44034d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -134,6 +134,15 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, return r; } +void amdgpu_gtt_mgr_print(struct seq_file *m, struct ttm_mem_type_manager *man) +{ + struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev); + struct amdgpu_gtt_mgr *mgr = man->priv; + + seq_printf(m, "man size:%llu pages, gtt available:%llu pages, usage:%lluMB\n", + man->size, mgr->available, (u64)atomic64_read(&adev->gtt_usage) >> 20); + +} /** * amdgpu_gtt_mgr_new - allocate a new node * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index eadbcfad2299..24ca251f82ca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1411,6 +1411,8 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, #if defined(CONFIG_DEBUG_FS) +extern void amdgpu_gtt_mgr_print(struct seq_file *m, struct ttm_mem_type_manager + *man); static int amdgpu_mm_dump_table(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; @@ -1424,11 +1426,17 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data) spin_lock(&glob->lru_lock); drm_mm_print(mm, &p); spin_unlock(&glob->lru_lock); - if (ttm_pl == TTM_PL_VRAM) + switch (ttm_pl) { + case TTM_PL_VRAM: seq_printf(m, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n", adev->mman.bdev.man[ttm_pl].size, (u64)atomic64_read(&adev->vram_usage) >> 20, (u64)atomic64_read(&adev->vram_vis_usage) >> 20); + break; + case TTM_PL_TT: + amdgpu_gtt_mgr_print(m, &adev->mman.bdev.man[TTM_PL_TT]); + break; + } return 0; } From 5a0f3b5f6d798637b0af5d6d3ab3eb02063e0317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 21 Apr 2017 10:05:56 +0200 Subject: [PATCH 059/144] drm/amdgpu: fix VM clearing in amdgpu_gem_object_close MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to check if the VM is swapped out before trying to update it. Fixes: 23e0563e48f7 ("drm/amdgpu: clear freed mappings immediately when BO may be freed") Signed-off-by: Christian König Reviewed-by: Nicolai Hähnle Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 68 ++++++++++++++----------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 03a9c5cad222..94cb91cf93eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -139,6 +139,35 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, return 0; } +static int amdgpu_gem_vm_check(void *param, struct amdgpu_bo *bo) +{ + /* if anything is swapped out don't swap it in here, + just abort and wait for the next CS */ + if (!amdgpu_bo_gpu_accessible(bo)) + return -ERESTARTSYS; + + if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) + return -ERESTARTSYS; + + return 0; +} + +static bool amdgpu_gem_vm_ready(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + struct list_head *list) +{ + struct ttm_validate_buffer *entry; + + list_for_each_entry(entry, list, head) { + struct amdgpu_bo *bo = + container_of(entry->bo, struct amdgpu_bo, tbo); + if (amdgpu_gem_vm_check(NULL, bo)) + return false; + } + + return !amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_gem_vm_check, NULL); +} + void amdgpu_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv) { @@ -148,15 +177,13 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_bo_list_entry vm_pd; - struct list_head list, duplicates; + struct list_head list; struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; struct amdgpu_bo_va *bo_va; - struct dma_fence *fence = NULL; int r; INIT_LIST_HEAD(&list); - INIT_LIST_HEAD(&duplicates); tv.bo = &bo->tbo; tv.shared = true; @@ -164,16 +191,18 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj, amdgpu_vm_get_pd_bo(vm, &list, &vm_pd); - r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates); + r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); if (r) { dev_err(adev->dev, "leaking bo va because " "we fail to reserve bo (%d)\n", r); return; } bo_va = amdgpu_vm_bo_find(vm, bo); - if (bo_va) { - if (--bo_va->ref_count == 0) { - amdgpu_vm_bo_rmv(adev, bo_va); + if (bo_va && --bo_va->ref_count == 0) { + amdgpu_vm_bo_rmv(adev, bo_va); + + if (amdgpu_gem_vm_ready(adev, vm, &list)) { + struct dma_fence *fence = NULL; r = amdgpu_vm_clear_freed(adev, vm, &fence); if (unlikely(r)) { @@ -502,19 +531,6 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data, return r; } -static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) -{ - /* if anything is swapped out don't swap it in here, - just abort and wait for the next CS */ - if (!amdgpu_bo_gpu_accessible(bo)) - return -ERESTARTSYS; - - if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) - return -ERESTARTSYS; - - return 0; -} - /** * amdgpu_gem_va_update_vm -update the bo_va in its VM * @@ -533,19 +549,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct list_head *list, uint32_t operation) { - struct ttm_validate_buffer *entry; int r = -ERESTARTSYS; - list_for_each_entry(entry, list, head) { - struct amdgpu_bo *bo = - container_of(entry->bo, struct amdgpu_bo, tbo); - if (amdgpu_gem_va_check(NULL, bo)) - goto error; - } - - r = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_gem_va_check, - NULL); - if (r) + if (!amdgpu_gem_vm_ready(adev, vm, list)) goto error; r = amdgpu_vm_update_directories(adev, vm); From 55ed8caf14fdfecf300d35cfe2e04b670b0191c1 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Fri, 21 Apr 2017 16:40:00 +0800 Subject: [PATCH 060/144] drm/amdgpu: increase gtt size to 3GB by default v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: address Alex's comment, add AMDGPU_DEFAULT_GTT_SIZE_MB. Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 ++- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c4f6211640da..a4fc54c70f30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -110,6 +110,7 @@ extern int amdgpu_pos_buf_per_se; extern int amdgpu_cntl_sb_buf_per_se; extern int amdgpu_param_buf_per_se; +#define AMDGPU_DEFAULT_GTT_SIZE_MB 3072ULL /* 3GB by default */ #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ #define AMDGPU_FENCE_JIFFIES_TIMEOUT (HZ / 2) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 31c50b2dbbc1..a572979f186c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -346,7 +346,8 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev) * size equal to the 1024 or vram, whichever is larger. */ if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size); + adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.mc_vram_size); else adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 2217d4d0f895..a9083a16a250 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -395,7 +395,8 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev) * size equal to the 1024 or vram, whichever is larger. */ if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size); + adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.mc_vram_size); else adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index e4f5df32f31e..4ac99784160a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -557,7 +557,8 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev) * size equal to the 1024 or vram, whichever is larger. */ if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size); + adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.mc_vram_size); else adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index edf43769ae70..e5d4dfeae3fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -486,7 +486,8 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev) * size equal to the 1024 or vram, whichever is larger. */ if (amdgpu_gart_size == -1) - adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size); + adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20), + adev->mc.mc_vram_size); else adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20; From 23d2e5049c080abda50810d21c8be20b5d65d191 Mon Sep 17 00:00:00 2001 From: "Roger.He" Date: Fri, 21 Apr 2017 14:24:26 +0800 Subject: [PATCH 061/144] drm/amdgpu: fix indent Reviewed-by: Alex Deucher Signed-off-by: Roger.He Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 75f851bd5b63..61716a2d4484 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2420,25 +2420,25 @@ static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev, uint32_t domain; int r; - if (!bo->shadow) - return 0; + if (!bo->shadow) + return 0; - r = amdgpu_bo_reserve(bo, false); - if (r) - return r; - domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); - /* if bo has been evicted, then no need to recover */ - if (domain == AMDGPU_GEM_DOMAIN_VRAM) { - r = amdgpu_bo_restore_from_shadow(adev, ring, bo, + r = amdgpu_bo_reserve(bo, false); + if (r) + return r; + domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); + /* if bo has been evicted, then no need to recover */ + if (domain == AMDGPU_GEM_DOMAIN_VRAM) { + r = amdgpu_bo_restore_from_shadow(adev, ring, bo, NULL, fence, true); - if (r) { - DRM_ERROR("recover page table failed!\n"); - goto err; - } - } + if (r) { + DRM_ERROR("recover page table failed!\n"); + goto err; + } + } err: - amdgpu_bo_unreserve(bo); - return r; + amdgpu_bo_unreserve(bo); + return r; } /** From 6c98d31ee83ddd351e89d5e2002e678fdaf9d2af Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Fri, 21 Apr 2017 17:58:42 +0800 Subject: [PATCH 062/144] drm/amdgpu: fix no-vmid job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ 132.036658] amdgpu 0000:22:00.0: VM IB without ID [ 132.036709] [drm:amdgpu_job_run [amdgpu]] *ERROR* Error scheduling IBs (-22) [ 132.036755] [drm:amd_sched_main [amdgpu]] *ERROR* Failed to run job! root cause is fence is signaled during sync transfer. Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 86a12424c162..c3cfeb335d99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -139,7 +139,7 @@ static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) struct dma_fence *fence = amdgpu_sync_get_fence(&job->sync); - if (fence == NULL && vm && !job->vm_id) { + while (fence == NULL && vm && !job->vm_id) { struct amdgpu_ring *ring = job->ring; int r; From 51687759be93fbc553f2727e86be25c38126ba93 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Mon, 24 Apr 2017 17:09:15 +0800 Subject: [PATCH 063/144] drm/amdgpu: fix gpu reset crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ 413.687439] BUG: unable to handle kernel NULL pointer dereference at 0000000000000548 [ 413.687479] IP: [] to_live_kthread+0x5/0x60 [ 413.687507] PGD 1efd12067 [ 413.687519] PUD 1efd11067 [ 413.687531] PMD 0 [ 413.687543] Oops: 0000 [#1] SMP [ 413.687557] Modules linked in: amdgpu(OE) ttm(OE) drm_kms_helper(E) drm(E) i2c_algo_bit(E) fb_sys_fops(E) syscopyarea(E) sysfillrect(E) sysimgblt(E) rpcsec_gss_krb5(E) nfsv4(E) nfs(E) fscache(E) snd_hda_codec_realtek(E) snd_hda_codec_generic(E) snd_hda_codec_hdmi(E) snd_hda_intel(E) eeepc_wmi(E) snd_hda_codec(E) asus_wmi(E) snd_hda_core(E) sparse_keymap(E) snd_hwdep(E) video(E) snd_pcm(E) snd_seq_midi(E) joydev(E) snd_seq_midi_event(E) snd_rawmidi(E) snd_seq(E) snd_seq_device(E) snd_timer(E) kvm(E) irqbypass(E) crct10dif_pclmul(E) snd(E) crc32_pclmul(E) ghash_clmulni_intel(E) soundcore(E) aesni_intel(E) aes_x86_64(E) lrw(E) gf128mul(E) glue_helper(E) ablk_helper(E) cryptd(E) shpchp(E) serio_raw(E) i2c_piix4(E) 8250_dw(E) i2c_designware_platform(E) i2c_designware_core(E) mac_hid(E) binfmt_misc(E) [ 413.687894] parport_pc(E) ppdev(E) lp(E) parport(E) nfsd(E) auth_rpcgss(E) nfs_acl(E) lockd(E) grace(E) sunrpc(E) autofs4(E) hid_generic(E) usbhid(E) hid(E) psmouse(E) ahci(E) r8169(E) mii(E) libahci(E) wmi(E) [ 413.687989] CPU: 13 PID: 1134 Comm: kworker/13:2 Tainted: G OE 4.9.0-custom #4 [ 413.688019] Hardware name: System manufacturer System Product Name/PRIME B350-PLUS, BIOS 0606 04/06/2017 [ 413.688089] Workqueue: events amd_sched_job_timedout [amdgpu] [ 413.688116] task: ffff88020f9657c0 task.stack: ffffc90001a88000 [ 413.688139] RIP: 0010:[] [] to_live_kthread+0x5/0x60 [ 413.688171] RSP: 0018:ffffc90001a8bd60 EFLAGS: 00010282 [ 413.688191] RAX: ffff88020f0073f8 RBX: ffff88020f000000 RCX: 0000000000000000 [ 413.688217] RDX: 0000000000000001 RSI: ffff88020f9670c0 RDI: 0000000000000000 [ 413.688243] RBP: ffffc90001a8bd78 R08: 0000000000000000 R09: 0000000000001000 [ 413.688269] R10: 0000006051b11a82 R11: 0000000000000001 R12: 0000000000000000 [ 413.688295] R13: ffff88020f002770 R14: ffff88020f004838 R15: ffff8801b23c2c60 [ 413.688321] FS: 0000000000000000(0000) GS:ffff88021ef40000(0000) knlGS:0000000000000000 [ 413.688352] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 413.688373] CR2: 0000000000000548 CR3: 00000001efd0f000 CR4: 00000000003406e0 [ 413.688399] Stack: [ 413.688407] ffffffff8109b304 ffff88020f000000 0000000000000070 ffffc90001a8bdf0 [ 413.688439] ffffffffa05ce29d ffffffffa052feb7 ffffffffa07b5820 ffffc90001a8bda0 [ 413.688470] ffffffff00000018 ffff8801bb88f060 0000000001a8bdb8 ffff88021ef59280 [ 413.688502] Call Trace: [ 413.688514] [] ? kthread_park+0x14/0x60 [ 413.688555] [] amdgpu_gpu_reset+0x7d/0x670 [amdgpu] [ 413.688589] [] ? drm_printk+0x97/0xa0 [drm] [ 413.688643] [] amdgpu_job_timedout+0x46/0x50 [amdgpu] [ 413.688700] [] amd_sched_job_timedout+0x17/0x20 [amdgpu] [ 413.688727] [] process_one_work+0x153/0x3f0 [ 413.688751] [] worker_thread+0x12b/0x4b0 [ 413.688773] [] ? do_syscall_64+0x6e/0x180 [ 413.688795] [] ? rescuer_thread+0x350/0x350 [ 413.688818] [] ? do_syscall_64+0x6e/0x180 [ 413.688839] [] kthread+0xd3/0xf0 [ 413.688858] [] ? kthread_park+0x60/0x60 [ 413.688881] [] ret_from_fork+0x25/0x30 [ 413.688901] Code: 25 40 d3 00 00 48 8b 80 48 05 00 00 48 89 e5 5d 48 8b 40 c8 48 c1 e8 02 83 e0 01 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 <48> 8b b7 48 05 00 00 55 48 89 e5 48 85 f6 74 31 8b 97 f8 18 00 [ 413.689045] RIP [] to_live_kthread+0x5/0x60 [ 413.689064] RSP [ 413.689076] CR2: 0000000000000548 [ 413.697985] ---[ end trace 0a314a64821f84e9 ]--- The root cause is some ring doesn't have scheduler, like KIQ ring Reviewed-by: Christian König Signed-off-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 61716a2d4484..eadd6e0a4152 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2583,7 +2583,7 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { struct amdgpu_ring *ring = adev->rings[i]; - if (!ring) + if (!ring || !ring->sched.thread) continue; kthread_park(ring->sched.thread); amd_sched_hw_job_reset(&ring->sched); @@ -2678,7 +2678,8 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) } for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { struct amdgpu_ring *ring = adev->rings[i]; - if (!ring) + + if (!ring || !ring->sched.thread) continue; amd_sched_job_recovery(&ring->sched); @@ -2687,7 +2688,7 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) } else { dev_err(adev->dev, "asic resume failed (%d).\n", r); for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { - if (adev->rings[i]) { + if (adev->rings[i] && adev->rings[i]->sched.thread) { kthread_unpark(adev->rings[i]->sched.thread); } } From e993ca4f3b18a649e20db387f09649694043b3d4 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Thu, 20 Apr 2017 11:45:09 +0800 Subject: [PATCH 064/144] drm/amdgpu/psp: skip loading SDMA/RLCG under SRIOV VF Now GPU hypervisor will load SDMA and RLCG ucode, so skip it in guest. Signed-off-by: Daniel Wang Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 1e380fe29b5e..ac5e92e5d59d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -289,6 +289,12 @@ static int psp_np_fw_load(struct psp_context *psp) if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && psp_smu_reload_quirk(psp)) continue; + if (amdgpu_sriov_vf(adev) && + (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0 + || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 + || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G)) + /*skip ucode loading in SRIOV VF */ + continue; ret = psp_prep_cmd_buf(ucode, psp->cmd); if (ret) From b53b8cdac621da0a4bac5f83e0004dd9b74a9160 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Wed, 19 Apr 2017 16:09:08 +0800 Subject: [PATCH 065/144] drm/amdgpu/vce4: fix a PSP loading VCE issue Fixed PSP loading issue for sriov. Signed-off-by: Daniel Wang Signed-off-by: Xiangliang Yu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 72d0edb9bc39..08ff7f4f91aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -291,9 +291,21 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev) INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL1), 0); INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VM_CTRL), 0); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), adev->vce.gpu_addr >> 8); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), adev->vce.gpu_addr >> 8); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), adev->vce.gpu_addr >> 8); + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); + INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); + INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); + } else { + INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), + adev->vce.gpu_addr >> 8); + INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), + adev->vce.gpu_addr >> 8); + INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), + adev->vce.gpu_addr >> 8); + } offset = AMDGPU_VCE_FIRMWARE_OFFSET; size = VCE_V4_0_FW_SIZE; From a92f5ec0c1341466bbfe98e1abc3cf5427ba4a67 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Sun, 16 Apr 2017 13:37:07 +0800 Subject: [PATCH 066/144] drm/amdgpu/vce4: move mm table constructions functions into mmsch header file Move mm table construction functions into mmsch header file so that UVD can reuse it. Signed-off-by: Frank Min Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h | 57 ++++++++++ drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 143 ++++++++---------------- 2 files changed, 103 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h b/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h index 5f0fc8bf16a9..8af0bddf85e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h @@ -84,4 +84,61 @@ struct mmsch_v1_0_cmd_indirect_write { uint32_t reg_value; }; +static inline void mmsch_v1_0_insert_direct_wt(struct mmsch_v1_0_cmd_direct_write *direct_wt, + uint32_t *init_table, + uint32_t reg_offset, + uint32_t value) +{ + direct_wt->cmd_header.reg_offset = reg_offset; + direct_wt->reg_value = value; + memcpy((void *)init_table, direct_wt, sizeof(struct mmsch_v1_0_cmd_direct_write)); +} + +static inline void mmsch_v1_0_insert_direct_rd_mod_wt(struct mmsch_v1_0_cmd_direct_read_modify_write *direct_rd_mod_wt, + uint32_t *init_table, + uint32_t reg_offset, + uint32_t mask, uint32_t data) +{ + direct_rd_mod_wt->cmd_header.reg_offset = reg_offset; + direct_rd_mod_wt->mask_value = mask; + direct_rd_mod_wt->write_data = data; + memcpy((void *)init_table, direct_rd_mod_wt, + sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)); +} + +static inline void mmsch_v1_0_insert_direct_poll(struct mmsch_v1_0_cmd_direct_polling *direct_poll, + uint32_t *init_table, + uint32_t reg_offset, + uint32_t mask, uint32_t wait) +{ + direct_poll->cmd_header.reg_offset = reg_offset; + direct_poll->mask_value = mask; + direct_poll->wait_value = wait; + memcpy((void *)init_table, direct_poll, sizeof(struct mmsch_v1_0_cmd_direct_polling)); +} + +#define MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(reg, mask, data) { \ + mmsch_v1_0_insert_direct_rd_mod_wt(&direct_rd_mod_wt, \ + init_table, (reg), \ + (mask), (data)); \ + init_table += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \ + table_size += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \ +} + +#define MMSCH_V1_0_INSERT_DIRECT_WT(reg, value) { \ + mmsch_v1_0_insert_direct_wt(&direct_wt, \ + init_table, (reg), \ + (value)); \ + init_table += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \ + table_size += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \ +} + +#define MMSCH_V1_0_INSERT_DIRECT_POLL(reg, mask, wait) { \ + mmsch_v1_0_insert_direct_poll(&direct_poll, \ + init_table, (reg), \ + (mask), (wait)); \ + init_table += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \ + table_size += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \ +} + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 08ff7f4f91aa..69efd3094f89 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -49,63 +49,6 @@ static void vce_v4_0_mc_resume(struct amdgpu_device *adev); static void vce_v4_0_set_ring_funcs(struct amdgpu_device *adev); static void vce_v4_0_set_irq_funcs(struct amdgpu_device *adev); -static inline void mmsch_insert_direct_wt(struct mmsch_v1_0_cmd_direct_write *direct_wt, - uint32_t *init_table, - uint32_t reg_offset, - uint32_t value) -{ - direct_wt->cmd_header.reg_offset = reg_offset; - direct_wt->reg_value = value; - memcpy((void *)init_table, direct_wt, sizeof(struct mmsch_v1_0_cmd_direct_write)); -} - -static inline void mmsch_insert_direct_rd_mod_wt(struct mmsch_v1_0_cmd_direct_read_modify_write *direct_rd_mod_wt, - uint32_t *init_table, - uint32_t reg_offset, - uint32_t mask, uint32_t data) -{ - direct_rd_mod_wt->cmd_header.reg_offset = reg_offset; - direct_rd_mod_wt->mask_value = mask; - direct_rd_mod_wt->write_data = data; - memcpy((void *)init_table, direct_rd_mod_wt, - sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)); -} - -static inline void mmsch_insert_direct_poll(struct mmsch_v1_0_cmd_direct_polling *direct_poll, - uint32_t *init_table, - uint32_t reg_offset, - uint32_t mask, uint32_t wait) -{ - direct_poll->cmd_header.reg_offset = reg_offset; - direct_poll->mask_value = mask; - direct_poll->wait_value = wait; - memcpy((void *)init_table, direct_poll, sizeof(struct mmsch_v1_0_cmd_direct_polling)); -} - -#define INSERT_DIRECT_RD_MOD_WT(reg, mask, data) { \ - mmsch_insert_direct_rd_mod_wt(&direct_rd_mod_wt, \ - init_table, (reg), \ - (mask), (data)); \ - init_table += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \ - table_size += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \ -} - -#define INSERT_DIRECT_WT(reg, value) { \ - mmsch_insert_direct_wt(&direct_wt, \ - init_table, (reg), \ - (value)); \ - init_table += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \ - table_size += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \ -} - -#define INSERT_DIRECT_POLL(reg, mask, wait) { \ - mmsch_insert_direct_poll(&direct_poll, \ - init_table, (reg), \ - (mask), (wait)); \ - init_table += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \ - table_size += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \ -} - /** * vce_v4_0_ring_get_rptr - get read pointer * @@ -280,67 +223,73 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev) init_table += header->vce_table_offset; ring = &adev->vce.ring[0]; - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_LO), lower_32_bits(ring->gpu_addr)); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_HI), upper_32_bits(ring->gpu_addr)); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_SIZE), ring->ring_size / 4); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_LO), + lower_32_bits(ring->gpu_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_HI), + upper_32_bits(ring->gpu_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_SIZE), + ring->ring_size / 4); /* BEGING OF MC_RESUME */ - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL), 0x398000); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CACHE_CTRL), ~0x1, 0); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL), 0); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL1), 0); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VM_CTRL), 0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL), 0x398000); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CACHE_CTRL), ~0x1, 0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL), 0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL1), 0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VM_CTRL), 0); if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), - adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), - adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), - adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), + adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8); } else { - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), - adev->vce.gpu_addr >> 8); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), - adev->vce.gpu_addr >> 8); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), - adev->vce.gpu_addr >> 8); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), + adev->vce.gpu_addr >> 8); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), + adev->vce.gpu_addr >> 8); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), + adev->vce.gpu_addr >> 8); } offset = AMDGPU_VCE_FIRMWARE_OFFSET; size = VCE_V4_0_FW_SIZE; - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0), offset & 0x7FFFFFFF); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE0), size); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0), + offset & 0x7FFFFFFF); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE0), size); offset += size; size = VCE_V4_0_STACK_SIZE; - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET1), offset & 0x7FFFFFFF); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE1), size); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET1), + offset & 0x7FFFFFFF); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE1), size); offset += size; size = VCE_V4_0_DATA_SIZE; - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET2), offset & 0x7FFFFFFF); - INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE2), size); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET2), + offset & 0x7FFFFFFF); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE2), size); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL2), ~0x100, 0); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SYS_INT_EN), - 0xffffffff, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL2), ~0x100, 0); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SYS_INT_EN), + 0xffffffff, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK); /* end of MC_RESUME */ - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), - VCE_STATUS__JOB_BUSY_MASK, ~VCE_STATUS__JOB_BUSY_MASK); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CNTL), - ~0x200001, VCE_VCPU_CNTL__CLK_EN_MASK); - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SOFT_RESET), - ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 0); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), + VCE_STATUS__JOB_BUSY_MASK, ~VCE_STATUS__JOB_BUSY_MASK); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CNTL), + ~0x200001, VCE_VCPU_CNTL__CLK_EN_MASK); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SOFT_RESET), + ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 0); - INSERT_DIRECT_POLL(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), - VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK, - VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK); + MMSCH_V1_0_INSERT_DIRECT_POLL(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), + VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK, + VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK); /* clear BUSY flag */ - INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), - ~VCE_STATUS__JOB_BUSY_MASK, 0); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS), + ~VCE_STATUS__JOB_BUSY_MASK, 0); /* add end packet */ memcpy((void *)init_table, &end, sizeof(struct mmsch_v1_0_cmd_end)); From 904cd3891dd390b109c8146974b47fca78b97c98 Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Fri, 21 Apr 2017 15:40:25 +0800 Subject: [PATCH 067/144] drm/amdgpu/virt: add two functions for MM table Add two functions to allocate & free MM table memory. Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 46 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 2 ++ 2 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index ba8b8ae6234f..6bf5cea294f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -225,3 +225,49 @@ int amdgpu_virt_reset_gpu(struct amdgpu_device *adev) return 0; } + +/** + * amdgpu_virt_alloc_mm_table() - alloc memory for mm table + * @amdgpu: amdgpu device. + * MM table is used by UVD and VCE for its initialization + * Return: Zero if allocate success. + */ +int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev) +{ + int r; + + if (!amdgpu_sriov_vf(adev) || adev->virt.mm_table.gpu_addr) + return 0; + + r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->virt.mm_table.bo, + &adev->virt.mm_table.gpu_addr, + (void *)&adev->virt.mm_table.cpu_addr); + if (r) { + DRM_ERROR("failed to alloc mm table and error = %d.\n", r); + return r; + } + + memset((void *)adev->virt.mm_table.cpu_addr, 0, PAGE_SIZE); + DRM_INFO("MM table gpu addr = 0x%llx, cpu addr = %p.\n", + adev->virt.mm_table.gpu_addr, + adev->virt.mm_table.cpu_addr); + return 0; +} + +/** + * amdgpu_virt_free_mm_table() - free mm table memory + * @amdgpu: amdgpu device. + * Free MM table memory + */ +void amdgpu_virt_free_mm_table(struct amdgpu_device *adev) +{ + if (!amdgpu_sriov_vf(adev) || !adev->virt.mm_table.gpu_addr) + return; + + amdgpu_bo_free_kernel(&adev->virt.mm_table.bo, + &adev->virt.mm_table.gpu_addr, + (void *)&adev->virt.mm_table.cpu_addr); + adev->virt.mm_table.gpu_addr = 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 1ee0a190b33b..a8ed162cc0bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -98,5 +98,7 @@ int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init); int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init); int amdgpu_virt_reset_gpu(struct amdgpu_device *adev); int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, bool voluntary); +int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev); +void amdgpu_virt_free_mm_table(struct amdgpu_device *adev); #endif From 7006dde2ef6110b11a76b0f972950d6da0ff3d6c Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Fri, 21 Apr 2017 16:21:41 +0800 Subject: [PATCH 068/144] drm/amdgpu/vce4: replaced with virt_alloc_mm_table Used virt_alloc_mm_table function to allocate MM table memory. Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 69efd3094f89..139f964196b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -450,20 +450,9 @@ static int vce_v4_0_sw_init(void *handle) return r; } - if (amdgpu_sriov_vf(adev)) { - r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->virt.mm_table.bo, - &adev->virt.mm_table.gpu_addr, - (void *)&adev->virt.mm_table.cpu_addr); - if (!r) { - memset((void *)adev->virt.mm_table.cpu_addr, 0, PAGE_SIZE); - printk("mm table gpu addr = 0x%llx, cpu addr = %p. \n", - adev->virt.mm_table.gpu_addr, - adev->virt.mm_table.cpu_addr); - } + r = amdgpu_virt_alloc_mm_table(adev); + if (r) return r; - } return r; } @@ -474,10 +463,7 @@ static int vce_v4_0_sw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* free MM table */ - if (amdgpu_sriov_vf(adev)) - amdgpu_bo_free_kernel(&adev->virt.mm_table.bo, - &adev->virt.mm_table.gpu_addr, - (void *)&adev->virt.mm_table.cpu_addr); + amdgpu_virt_free_mm_table(adev); r = amdgpu_vce_suspend(adev); if (r) From 247ac95141740157bd86d29819ff46e7ab396113 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Mon, 17 Apr 2017 11:28:12 +0800 Subject: [PATCH 069/144] drm/amdgpu/uvd7: add sriov uvd initialization sequences Add UVD initialization for SRIOV. Signed-off-by: Frank Min Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 246 ++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index c646570d1421..46c7bc490809 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -27,10 +27,14 @@ #include "amdgpu_uvd.h" #include "soc15d.h" #include "soc15_common.h" +#include "mmsch_v1_0.h" #include "vega10/soc15ip.h" #include "vega10/UVD/uvd_7_0_offset.h" #include "vega10/UVD/uvd_7_0_sh_mask.h" +#include "vega10/VCE/vce_4_0_offset.h" +#include "vega10/VCE/vce_4_0_default.h" +#include "vega10/VCE/vce_4_0_sh_mask.h" #include "vega10/NBIF/nbif_6_1_offset.h" #include "vega10/HDP/hdp_4_0_offset.h" #include "vega10/MMHUB/mmhub_1_0_offset.h" @@ -41,6 +45,7 @@ static void uvd_v7_0_set_enc_ring_funcs(struct amdgpu_device *adev); static void uvd_v7_0_set_irq_funcs(struct amdgpu_device *adev); static int uvd_v7_0_start(struct amdgpu_device *adev); static void uvd_v7_0_stop(struct amdgpu_device *adev); +static int uvd_v7_0_sriov_start(struct amdgpu_device *adev); /** * uvd_v7_0_ring_get_rptr - get read pointer @@ -618,6 +623,247 @@ static void uvd_v7_0_mc_resume(struct amdgpu_device *adev) WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_GP_SCRATCH4), adev->uvd.max_handles); } +static int uvd_v7_0_mmsch_start(struct amdgpu_device *adev, + struct amdgpu_mm_table *table) +{ + uint32_t data = 0, loop; + uint64_t addr = table->gpu_addr; + struct mmsch_v1_0_init_header *header = (struct mmsch_v1_0_init_header *)table->cpu_addr; + uint32_t size; + + size = header->header_size + header->vce_table_size + header->uvd_table_size; + + /* 1, write to vce_mmsch_vf_ctx_addr_lo/hi register with GPU mc addr of memory descriptor location */ + WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_CTX_ADDR_LO), lower_32_bits(addr)); + WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_CTX_ADDR_HI), upper_32_bits(addr)); + + /* 2, update vmid of descriptor */ + data = RREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_VMID)); + data &= ~VCE_MMSCH_VF_VMID__VF_CTX_VMID_MASK; + data |= (0 << VCE_MMSCH_VF_VMID__VF_CTX_VMID__SHIFT); /* use domain0 for MM scheduler */ + WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_VMID), data); + + /* 3, notify mmsch about the size of this descriptor */ + WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_CTX_SIZE), size); + + /* 4, set resp to zero */ + WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP), 0); + + /* 5, kick off the initialization and wait until VCE_MMSCH_VF_MAILBOX_RESP becomes non-zero */ + WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_HOST), 0x10000001); + + data = RREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP)); + loop = 1000; + while ((data & 0x10000002) != 0x10000002) { + udelay(10); + data = RREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP)); + loop--; + if (!loop) + break; + } + + if (!loop) { + dev_err(adev->dev, "failed to init MMSCH, mmVCE_MMSCH_VF_MAILBOX_RESP = %x\n", data); + return -EBUSY; + } + + return 0; +} + +static int uvd_v7_0_sriov_start(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring; + uint32_t offset, size, tmp; + uint32_t table_size = 0; + struct mmsch_v1_0_cmd_direct_write direct_wt = { {0} }; + struct mmsch_v1_0_cmd_direct_read_modify_write direct_rd_mod_wt = { {0} }; + struct mmsch_v1_0_cmd_direct_polling direct_poll = { {0} }; + //struct mmsch_v1_0_cmd_indirect_write indirect_wt = {{0}}; + struct mmsch_v1_0_cmd_end end = { {0} }; + uint32_t *init_table = adev->virt.mm_table.cpu_addr; + struct mmsch_v1_0_init_header *header = (struct mmsch_v1_0_init_header *)init_table; + + direct_wt.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_WRITE; + direct_rd_mod_wt.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_READ_MODIFY_WRITE; + direct_poll.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_POLLING; + end.cmd_header.command_type = MMSCH_COMMAND__END; + + if (header->uvd_table_offset == 0 && header->uvd_table_size == 0) { + header->version = MMSCH_VERSION; + header->header_size = sizeof(struct mmsch_v1_0_init_header) >> 2; + + if (header->vce_table_offset == 0 && header->vce_table_size == 0) + header->uvd_table_offset = header->header_size; + else + header->uvd_table_offset = header->vce_table_size + header->vce_table_offset; + + init_table += header->uvd_table_offset; + + ring = &adev->uvd.ring; + size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4); + + /* disable clock gating */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS), + ~UVD_POWER_STATUS__UVD_PG_MODE_MASK, 0); + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS), + 0xFFFFFFFF, 0x00000004); + /* mc resume*/ + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), + lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), + upper_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr)); + offset = 0; + } else { + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), + lower_32_bits(adev->uvd.gpu_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), + upper_32_bits(adev->uvd.gpu_addr)); + offset = size; + } + + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0), + AMDGPU_UVD_FIRMWARE_OFFSET >> 3); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE0), size); + + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), + lower_32_bits(adev->uvd.gpu_addr + offset)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), + upper_32_bits(adev->uvd.gpu_addr + offset)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1), (1 << 21)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE1), AMDGPU_UVD_HEAP_SIZE); + + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW), + lower_32_bits(adev->uvd.gpu_addr + offset + AMDGPU_UVD_HEAP_SIZE)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH), + upper_32_bits(adev->uvd.gpu_addr + offset + AMDGPU_UVD_HEAP_SIZE)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2), (2 << 21)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE2), + AMDGPU_UVD_STACK_SIZE + (AMDGPU_UVD_SESSION_SIZE * 40)); + + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_UDEC_ADDR_CONFIG), + adev->gfx.config.gb_addr_config); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_UDEC_DB_ADDR_CONFIG), + adev->gfx.config.gb_addr_config); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_UDEC_DBW_ADDR_CONFIG), + adev->gfx.config.gb_addr_config); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_GP_SCRATCH4), adev->uvd.max_handles); + /* mc resume end*/ + + /* disable clock gating */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_CGC_CTRL), + ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK, 0); + + /* disable interupt */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), + ~UVD_MASTINT_EN__VCPU_EN_MASK, 0); + + /* stall UMC and register bus before resetting VCPU */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2), + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK, + UVD_LMI_CTRL2__STALL_ARB_UMC_MASK); + + /* put LMI, VCPU, RBC etc... into reset */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), + (uint32_t)(UVD_SOFT_RESET__LMI_SOFT_RESET_MASK | + UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK | + UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK | + UVD_SOFT_RESET__RBC_SOFT_RESET_MASK | + UVD_SOFT_RESET__CSM_SOFT_RESET_MASK | + UVD_SOFT_RESET__CXW_SOFT_RESET_MASK | + UVD_SOFT_RESET__TAP_SOFT_RESET_MASK | + UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK)); + + /* initialize UVD memory controller */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL), + (uint32_t)((0x40 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) | + UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK | + UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK | + UVD_LMI_CTRL__REQ_MODE_MASK | + 0x00100000L)); + + /* disable byte swapping */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_SWAP_CNTL), 0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MP_SWAP_CNTL), 0); + + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXA0), 0x40c2040); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXA1), 0x0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXB0), 0x40c2040); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXB1), 0x0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_ALU), 0); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUX), 0x88); + + /* take all subblocks out of reset, except VCPU */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), + UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK); + + /* enable VCPU clock */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CNTL), + UVD_VCPU_CNTL__CLK_EN_MASK); + + /* enable UMC */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2), + ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK, 0); + + /* boot up the VCPU */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0); + + MMSCH_V1_0_INSERT_DIRECT_POLL(SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS), 0x02, 0x02); + + /* enable master interrupt */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN), + ~(UVD_MASTINT_EN__VCPU_EN_MASK|UVD_MASTINT_EN__SYS_EN_MASK), + (UVD_MASTINT_EN__VCPU_EN_MASK|UVD_MASTINT_EN__SYS_EN_MASK)); + + /* clear the bit 4 of UVD_STATUS */ + MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS), + ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT), 0); + + /* force RBC into idle state */ + size = order_base_2(ring->ring_size); + tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, size); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_WPTR_POLL_EN, 0); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1); + tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), tmp); + + /* set the write pointer delay */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_WPTR_CNTL), 0); + + /* set the wb address */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR), + (upper_32_bits(ring->gpu_addr) >> 2)); + + /* programm the RB_BASE for ring buffer */ + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW), + lower_32_bits(ring->gpu_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH), + upper_32_bits(ring->gpu_addr)); + + ring->wptr = 0; + ring = &adev->uvd.ring_enc[0]; + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_LO), ring->gpu_addr); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI), upper_32_bits(ring->gpu_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE), ring->ring_size / 4); + + ring = &adev->uvd.ring_enc[1]; + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_LO2), ring->gpu_addr); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI2), upper_32_bits(ring->gpu_addr)); + MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE2), ring->ring_size / 4); + + /* add end packet */ + memcpy((void *)init_table, &end, sizeof(struct mmsch_v1_0_cmd_end)); + table_size += sizeof(struct mmsch_v1_0_cmd_end) / 4; + header->uvd_table_size = table_size; + + return uvd_v7_0_mmsch_start(adev, &adev->virt.mm_table); + } + return -EINVAL; /* already initializaed ? */ +} + /** * uvd_v7_0_start - start UVD block * From beb2ced51b70a6cbccd8676b450e282fecf65565 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Mon, 17 Apr 2017 11:45:35 +0800 Subject: [PATCH 070/144] drm/amdgpu/uvd7: add uvd doorbell initialization for sriov Add UVD doorbell for SRIOV. Signed-off-by: Frank Min Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index 46c7bc490809..552bfcdd3236 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -103,6 +103,9 @@ static uint64_t uvd_v7_0_enc_ring_get_wptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; + if (ring->use_doorbell) + return adev->wb.wb[ring->wptr_offs]; + if (ring == &adev->uvd.ring_enc[0]) return RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_WPTR)); else @@ -134,6 +137,13 @@ static void uvd_v7_0_enc_ring_set_wptr(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; + if (ring->use_doorbell) { + /* XXX check if swapping is necessary on BE */ + adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr); + WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); + return; + } + if (ring == &adev->uvd.ring_enc[0]) WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_WPTR), lower_32_bits(ring->wptr)); @@ -421,6 +431,10 @@ static int uvd_v7_0_sw_init(void *handle) for (i = 0; i < adev->uvd.num_enc_rings; ++i) { ring = &adev->uvd.ring_enc[i]; sprintf(ring->name, "uvd_enc%d", i); + if (amdgpu_sriov_vf(adev)) { + ring->use_doorbell = true; + ring->doorbell_index = AMDGPU_DOORBELL64_UVD_RING0_1 * 2; + } r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); if (r) return r; From 6fa336a777712fac9da763d3df348fcfc96633f8 Mon Sep 17 00:00:00 2001 From: Frank Min Date: Mon, 17 Apr 2017 11:51:44 +0800 Subject: [PATCH 071/144] drm/amdgpu/uvd7: add UVD hw init sequences for sriov Add UVD hw init. Signed-off-by: Frank Min Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 113 ++++++++++++++------------ 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index 552bfcdd3236..eca8f6e01e97 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -368,7 +368,10 @@ static int uvd_v7_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - adev->uvd.num_enc_rings = 2; + if (amdgpu_sriov_vf(adev)) + adev->uvd.num_enc_rings = 1; + else + adev->uvd.num_enc_rings = 2; uvd_v7_0_set_ring_funcs(adev); uvd_v7_0_set_enc_ring_funcs(adev); uvd_v7_0_set_irq_funcs(adev); @@ -421,12 +424,14 @@ static int uvd_v7_0_sw_init(void *handle) r = amdgpu_uvd_resume(adev); if (r) return r; + if (!amdgpu_sriov_vf(adev)) { + ring = &adev->uvd.ring; + sprintf(ring->name, "uvd"); + r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); + if (r) + return r; + } - ring = &adev->uvd.ring; - sprintf(ring->name, "uvd"); - r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); - if (r) - return r; for (i = 0; i < adev->uvd.num_enc_rings; ++i) { ring = &adev->uvd.ring_enc[i]; @@ -440,6 +445,10 @@ static int uvd_v7_0_sw_init(void *handle) return r; } + r = amdgpu_virt_alloc_mm_table(adev); + if (r) + return r; + return r; } @@ -448,6 +457,8 @@ static int uvd_v7_0_sw_fini(void *handle) int i, r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + amdgpu_virt_free_mm_table(adev); + r = amdgpu_uvd_suspend(adev); if (r) return r; @@ -474,49 +485,54 @@ static int uvd_v7_0_hw_init(void *handle) uint32_t tmp; int i, r; - r = uvd_v7_0_start(adev); + if (amdgpu_sriov_vf(adev)) + r = uvd_v7_0_sriov_start(adev); + else + r = uvd_v7_0_start(adev); if (r) goto done; - ring->ready = true; - r = amdgpu_ring_test_ring(ring); - if (r) { - ring->ready = false; - goto done; + if (!amdgpu_sriov_vf(adev)) { + ring->ready = true; + r = amdgpu_ring_test_ring(ring); + if (r) { + ring->ready = false; + goto done; + } + + r = amdgpu_ring_alloc(ring, 10); + if (r) { + DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r); + goto done; + } + + tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0, + mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL), 0); + amdgpu_ring_write(ring, tmp); + amdgpu_ring_write(ring, 0xFFFFF); + + tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0, + mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL), 0); + amdgpu_ring_write(ring, tmp); + amdgpu_ring_write(ring, 0xFFFFF); + + tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0, + mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL), 0); + amdgpu_ring_write(ring, tmp); + amdgpu_ring_write(ring, 0xFFFFF); + + /* Clear timeout status bits */ + amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0, + mmUVD_SEMA_TIMEOUT_STATUS), 0)); + amdgpu_ring_write(ring, 0x8); + + amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0, + mmUVD_SEMA_CNTL), 0)); + amdgpu_ring_write(ring, 3); + + amdgpu_ring_commit(ring); } - r = amdgpu_ring_alloc(ring, 10); - if (r) { - DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r); - goto done; - } - - tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0, - mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL), 0); - amdgpu_ring_write(ring, tmp); - amdgpu_ring_write(ring, 0xFFFFF); - - tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0, - mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL), 0); - amdgpu_ring_write(ring, tmp); - amdgpu_ring_write(ring, 0xFFFFF); - - tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0, - mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL), 0); - amdgpu_ring_write(ring, tmp); - amdgpu_ring_write(ring, 0xFFFFF); - - /* Clear timeout status bits */ - amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0, - mmUVD_SEMA_TIMEOUT_STATUS), 0)); - amdgpu_ring_write(ring, 0x8); - - amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0, - mmUVD_SEMA_CNTL), 0)); - amdgpu_ring_write(ring, 3); - - amdgpu_ring_commit(ring); - for (i = 0; i < adev->uvd.num_enc_rings; ++i) { ring = &adev->uvd.ring_enc[i]; ring->ready = true; @@ -692,7 +708,6 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev) struct mmsch_v1_0_cmd_direct_write direct_wt = { {0} }; struct mmsch_v1_0_cmd_direct_read_modify_write direct_rd_mod_wt = { {0} }; struct mmsch_v1_0_cmd_direct_polling direct_poll = { {0} }; - //struct mmsch_v1_0_cmd_indirect_write indirect_wt = {{0}}; struct mmsch_v1_0_cmd_end end = { {0} }; uint32_t *init_table = adev->virt.mm_table.cpu_addr; struct mmsch_v1_0_init_header *header = (struct mmsch_v1_0_init_header *)init_table; @@ -863,11 +878,6 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev) MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI), upper_32_bits(ring->gpu_addr)); MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE), ring->ring_size / 4); - ring = &adev->uvd.ring_enc[1]; - MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_LO2), ring->gpu_addr); - MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI2), upper_32_bits(ring->gpu_addr)); - MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE2), ring->ring_size / 4); - /* add end packet */ memcpy((void *)init_table, &end, sizeof(struct mmsch_v1_0_cmd_end)); table_size += sizeof(struct mmsch_v1_0_cmd_end) / 4; @@ -1489,7 +1499,8 @@ static int uvd_v7_0_process_interrupt(struct amdgpu_device *adev, amdgpu_fence_process(&adev->uvd.ring_enc[0]); break; case 120: - amdgpu_fence_process(&adev->uvd.ring_enc[1]); + if (!amdgpu_sriov_vf(adev)) + amdgpu_fence_process(&adev->uvd.ring_enc[1]); break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", From 91faed9ee150fb07b5b0e6601b96219a6c74301f Mon Sep 17 00:00:00 2001 From: Frank Min Date: Mon, 17 Apr 2017 11:19:45 +0800 Subject: [PATCH 072/144] drm/amdgpu/soc15: enable UVD code path for sriov Enable UVD block for SRIOV. Signed-off-by: Frank Min Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 385de8617075..02baa1d7bc23 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -505,8 +505,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev) amdgpu_ip_block_add(adev, &dce_virtual_ip_block); amdgpu_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_ip_block_add(adev, &sdma_v4_0_ip_block); - if (!amdgpu_sriov_vf(adev)) - amdgpu_ip_block_add(adev, &uvd_v7_0_ip_block); + amdgpu_ip_block_add(adev, &uvd_v7_0_ip_block); amdgpu_ip_block_add(adev, &vce_v4_0_ip_block); break; default: From c346fb74fb646352018800375c327ac35880b7e0 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 24 Apr 2017 16:38:05 +0800 Subject: [PATCH 073/144] drm/radeon: check return value of radeon_ring_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function radeon_ring_lock() returns an errno on failure, and its return value should be validated. However, in functions r420_cp_errata_init() and r420_cp_errata_fini(), its return value is not checked. This patch adds the checks. Reviewed-by: Christian König Signed-off-by: Pan Bian Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r420.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 3eb0c4f9f796..45e1d4e60759 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -203,6 +203,7 @@ static void r420_clock_resume(struct radeon_device *rdev) static void r420_cp_errata_init(struct radeon_device *rdev) { + int r; struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; /* RV410 and R420 can lock up if CP DMA to host memory happens @@ -212,7 +213,8 @@ static void r420_cp_errata_init(struct radeon_device *rdev) * of the CP init, apparently. */ radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); - radeon_ring_lock(rdev, ring, 8); + r = radeon_ring_lock(rdev, ring, 8); + WARN_ON(r); radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1)); radeon_ring_write(ring, rdev->config.r300.resync_scratch); radeon_ring_write(ring, 0xDEADBEEF); @@ -221,12 +223,14 @@ static void r420_cp_errata_init(struct radeon_device *rdev) static void r420_cp_errata_fini(struct radeon_device *rdev) { + int r; struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; /* Catch the RESYNC we dispatched all the way back, * at the very beginning of the CP init. */ - radeon_ring_lock(rdev, ring, 8); + r = radeon_ring_lock(rdev, ring, 8); + WARN_ON(r); radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); radeon_ring_write(ring, R300_RB3D_DC_FINISH); radeon_ring_unlock_commit(rdev, ring, false); From 2f2429c38eddbc4f988589099fd86bb6bb65b7e4 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Mon, 24 Apr 2017 16:45:51 +0800 Subject: [PATCH 074/144] drm/radeon: check return value of radeon_fence_emit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function radeon_fence_emit() returns -ENOMEM if there is no enough memory. And in this case, function radeon_ring_unlock_undo() rather than function radeon_ring_unlock_commit() should be called. However, in function radeon_test_create_and_emit_fence(), the return value of radeon_fence_emit() is ignored. This patch adds the check. Reviewed-by: Christian König Signed-off-by: Pan Bian Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_test.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 4fdc7bda7a7d..f5e9abfadb56 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -298,7 +298,12 @@ static int radeon_test_create_and_emit_fence(struct radeon_device *rdev, DRM_ERROR("Failed to lock ring A %d\n", ring->idx); return r; } - radeon_fence_emit(rdev, fence, ring->idx); + r = radeon_fence_emit(rdev, fence, ring->idx); + if (r) { + DRM_ERROR("Failed to emit fence\n"); + radeon_ring_unlock_undo(rdev, ring); + return r; + } radeon_ring_unlock_commit(rdev, ring, false); } return 0; From effaf848b957fbf72a3b6a1ad87f5e031eda0b75 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 01:02:46 +0200 Subject: [PATCH 075/144] drm/amdgpu: Add missing lb_vblank_lead_lines setup to DCE-6 path. This apparently got lost when implementing the new DCE-6 support and would cause failures in pageflip scheduling and timestamping. Signed-off-by: Mario Kleiner Cc: Alex Deucher Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 307269bda4fa..e146d252aa30 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -979,7 +979,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, u32 priority_a_mark = 0, priority_b_mark = 0; u32 priority_a_cnt = PRIORITY_OFF; u32 priority_b_cnt = PRIORITY_OFF; - u32 tmp, arb_control3; + u32 tmp, arb_control3, lb_vblank_lead_lines = 0; fixed20_12 a, b, c; if (amdgpu_crtc->base.enabled && num_heads && mode) { @@ -1091,6 +1091,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, c.full = dfixed_div(c, a); priority_b_mark = dfixed_trunc(c); priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK; + + lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay); } /* select wm A */ @@ -1120,6 +1122,9 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev, /* save values for DPM */ amdgpu_crtc->line_time = line_time; amdgpu_crtc->wm_high = latency_watermark_a; + + /* Save number of lines the linebuffer leads before the scanout */ + amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines; } /* watermark setup */ From ae45bbc2ba8f92b5a773fece6f5792f497c89282 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 01:33:08 +0200 Subject: [PATCH 076/144] drm/radeon: Avoid overflows/divide-by-zero in latency_watermark calculations. At dot clocks > approx. 250 Mhz, some of these calcs will overflow and cause miscalculation of latency watermarks, and for some overflows also divide-by-zero driver crash. Make calcs more overflow resistant. This is a direct port of the corresponding patch from amdgpu-kms, copy-paste for cik from dce-8 and si from dce-6, with a slightly simpler variant for evergreen dce-4/5. Only tested on DCE-4 evergreen with a Radeon HD-5770. Signed-off-by: Mario Kleiner Cc: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 19 +++---------------- drivers/gpu/drm/radeon/evergreen.c | 8 +------- drivers/gpu/drm/radeon/si.c | 19 +++---------------- 3 files changed, 7 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 53710dd7d5dd..4f034cbc4a6a 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -9150,23 +9150,10 @@ static u32 dce8_latency_watermark(struct dce8_wm_params *wm) a.full = dfixed_const(available_bandwidth); b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); + tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); + tmp = min(dfixed_trunc(a), tmp); - b.full = dfixed_const(mc_latency + 512); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(b, c); - - c.full = dfixed_const(dmif_size); - b.full = dfixed_div(c, b); - - tmp = min(dfixed_trunc(a), dfixed_trunc(b)); - - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(tmp, dfixed_trunc(b)); + lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index d1b1e0cc3c25..3c9c133bcccc 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2188,13 +2188,7 @@ static u32 evergreen_latency_watermark(struct evergreen_wm_params *wm) b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(dfixed_trunc(a), dfixed_trunc(b)); + lb_fill_bw = min(dfixed_trunc(a), wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 528e5a49a214..3efdfd04069a 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2204,23 +2204,10 @@ static u32 dce6_latency_watermark(struct dce6_wm_params *wm) a.full = dfixed_const(available_bandwidth); b.full = dfixed_const(wm->num_heads); a.full = dfixed_div(a, b); + tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512); + tmp = min(dfixed_trunc(a), tmp); - b.full = dfixed_const(mc_latency + 512); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(b, c); - - c.full = dfixed_const(dmif_size); - b.full = dfixed_div(c, b); - - tmp = min(dfixed_trunc(a), dfixed_trunc(b)); - - b.full = dfixed_const(1000); - c.full = dfixed_const(wm->disp_clk); - b.full = dfixed_div(c, b); - c.full = dfixed_const(wm->bytes_per_pixel); - b.full = dfixed_mul(b, c); - - lb_fill_bw = min(tmp, dfixed_trunc(b)); + lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000); a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel); b.full = dfixed_const(1000); From e6b9a6c84b936e61f1ccff779494f3bd38775503 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Mon, 24 Apr 2017 01:33:09 +0200 Subject: [PATCH 077/144] drm/radeon: Make display watermark calculations more accurate Avoid big roundoff errors in scanline/hactive durations for high pixel clocks, especially for >= 500 Mhz, and thereby program more accurate display fifo watermarks. This is a port of the corresponding amdgpu patch. Implemented for DCE 4,6,8. Tested on Evergreen/DCE-4 with Radeon HD-5770. Signed-off-by: Mario Kleiner Cc: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 10 +++++----- drivers/gpu/drm/radeon/evergreen.c | 10 +++++----- drivers/gpu/drm/radeon/si.c | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 4f034cbc4a6a..ccebe0f8d2e1 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -9261,14 +9261,14 @@ static void dce8_program_watermarks(struct radeon_device *rdev, { struct drm_display_mode *mode = &radeon_crtc->base.mode; struct dce8_wm_params wm_low, wm_high; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 tmp, wm_mask; if (radeon_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); /* watermark for high clocks */ if ((rdev->pm.pm_method == PM_METHOD_DPM) && @@ -9284,7 +9284,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -9324,7 +9324,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 3c9c133bcccc..f130ec41ee4b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2255,7 +2255,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, struct drm_display_mode *mode = &radeon_crtc->base.mode; struct evergreen_wm_params wm_low, wm_high; u32 dram_channels; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 priority_a_mark = 0, priority_b_mark = 0; @@ -2266,8 +2266,8 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, fixed20_12 a, b, c; if (radeon_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); priority_a_cnt = 0; priority_b_cnt = 0; dram_channels = evergreen_get_number_of_dram_channels(rdev); @@ -2285,7 +2285,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -2312,7 +2312,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3efdfd04069a..ceee87f029d9 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2274,7 +2274,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev, struct drm_display_mode *mode = &radeon_crtc->base.mode; struct dce6_wm_params wm_low, wm_high; u32 dram_channels; - u32 pixel_period; + u32 active_time; u32 line_time = 0; u32 latency_watermark_a = 0, latency_watermark_b = 0; u32 priority_a_mark = 0, priority_b_mark = 0; @@ -2284,8 +2284,8 @@ static void dce6_program_watermarks(struct radeon_device *rdev, fixed20_12 a, b, c; if (radeon_crtc->base.enabled && num_heads && mode) { - pixel_period = 1000000 / (u32)mode->clock; - line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535); + active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock; + line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535); priority_a_cnt = 0; priority_b_cnt = 0; @@ -2307,7 +2307,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev, wm_high.disp_clk = mode->clock; wm_high.src_width = mode->crtc_hdisplay; - wm_high.active_time = mode->crtc_hdisplay * pixel_period; + wm_high.active_time = active_time; wm_high.blank_time = line_time - wm_high.active_time; wm_high.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -2334,7 +2334,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev, wm_low.disp_clk = mode->clock; wm_low.src_width = mode->crtc_hdisplay; - wm_low.active_time = mode->crtc_hdisplay * pixel_period; + wm_low.active_time = active_time; wm_low.blank_time = line_time - wm_low.active_time; wm_low.interlaced = false; if (mode->flags & DRM_MODE_FLAG_INTERLACE) From 8ab25b4f51ffd2f859afaffa191d50a1eda4128f Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Mon, 24 Apr 2017 13:30:43 -0400 Subject: [PATCH 078/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If amdgpu_bo_reserve function is interrupted by signal, amdgpu_bo_kunmap function is not called. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index eadd6e0a4152..ebc0022a7ab4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -349,7 +349,7 @@ static void amdgpu_vram_scratch_fini(struct amdgpu_device *adev) if (adev->vram_scratch.robj == NULL) { return; } - r = amdgpu_bo_reserve(adev->vram_scratch.robj, false); + r = amdgpu_bo_reserve(adev->vram_scratch.robj, true); if (likely(r == 0)) { amdgpu_bo_kunmap(adev->vram_scratch.robj); amdgpu_bo_unpin(adev->vram_scratch.robj); From 7a6901d7d7e49ad50d477cd8f8ef79d079b5c6c5 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Mon, 24 Apr 2017 13:52:41 -0400 Subject: [PATCH 079/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. The signal interrupt can affect the expected behaviour. 2. There is no mechanism to handle the corresponding error. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index ebc0022a7ab4..3f01c4b92280 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2140,7 +2140,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) if (amdgpu_crtc->cursor_bo) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - r = amdgpu_bo_reserve(aobj, false); + r = amdgpu_bo_reserve(aobj, true); if (r == 0) { amdgpu_bo_unpin(aobj); amdgpu_bo_unreserve(aobj); @@ -2153,7 +2153,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon) robj = gem_to_amdgpu_bo(rfb->obj); /* don't unpin kernel fb objects */ if (!amdgpu_fbdev_robj_is_fb(adev, robj)) { - r = amdgpu_bo_reserve(robj, false); + r = amdgpu_bo_reserve(robj, true); if (r == 0) { amdgpu_bo_unpin(robj); amdgpu_bo_unreserve(robj); @@ -2260,7 +2260,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon) if (amdgpu_crtc->cursor_bo) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - r = amdgpu_bo_reserve(aobj, false); + r = amdgpu_bo_reserve(aobj, true); if (r == 0) { r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM, From 1d28479776fe932c32bda2366501fb2408557397 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Mon, 24 Apr 2017 13:53:04 -0400 Subject: [PATCH 080/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. The signal interrupt can affect the expected behaviour. 2. There is no good mechanism to handle the corresponding error. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 3f01c4b92280..234d90a12482 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2423,7 +2423,7 @@ static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev, if (!bo->shadow) return 0; - r = amdgpu_bo_reserve(bo, false); + r = amdgpu_bo_reserve(bo, true); if (r) return r; domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); From f3aa745eedc851742f6d6574ee2322c021b8f33c Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Mon, 24 Apr 2017 14:27:00 -0400 Subject: [PATCH 081/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. The signal interrupt can affect the expected behaviour. 2. There is no good mechanism to handle the corresponding error. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index cb89fff863c0..60de77b153b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -295,7 +295,7 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr, if (*bo == NULL) return; - if (likely(amdgpu_bo_reserve(*bo, false) == 0)) { + if (likely(amdgpu_bo_reserve(*bo, true) == 0)) { if (cpu_addr) amdgpu_bo_kunmap(*bo); From d159f26caaa91c88e9078c69fd159be9cec3a005 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Mon, 24 Apr 2017 15:26:57 -0400 Subject: [PATCH 082/144] drm/amdgpu: Real return value can be over-written when clean up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c index cc97eee93226..726b3e018eeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c @@ -117,6 +117,11 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size, } out_cleanup: + /* Check error value now. The value can be overwritten when clean up.*/ + if (r) { + DRM_ERROR("Error while benchmarking BO move.\n"); + } + if (sobj) { r = amdgpu_bo_reserve(sobj, false); if (likely(r == 0)) { @@ -133,10 +138,6 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size, } amdgpu_bo_unref(&dobj); } - - if (r) { - DRM_ERROR("Error while benchmarking BO move.\n"); - } } void amdgpu_benchmark(struct amdgpu_device *adev, int test_number) From 4a9ed1009b8b01409bdda899c0ff0d7fd2c6d094 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Mon, 24 Apr 2017 15:33:16 -0400 Subject: [PATCH 083/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. The signal interrupt can affect the expected behaviour. 2. There is no good mechanism to handle the corresponding error. When signal interrupt happens, unpin is not called. As a result, inside AMDGPU, the statistic of pin size will be wrong. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c index 726b3e018eeb..1beae5b930d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c @@ -123,7 +123,7 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size, } if (sobj) { - r = amdgpu_bo_reserve(sobj, false); + r = amdgpu_bo_reserve(sobj, true); if (likely(r == 0)) { amdgpu_bo_unpin(sobj); amdgpu_bo_unreserve(sobj); @@ -131,7 +131,7 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size, amdgpu_bo_unref(&sobj); } if (dobj) { - r = amdgpu_bo_reserve(dobj, false); + r = amdgpu_bo_reserve(dobj, true); if (likely(r == 0)) { amdgpu_bo_unpin(dobj); amdgpu_bo_unreserve(dobj); From 82521316395a37a2ec1d7e396c055f3c7de9d93b Mon Sep 17 00:00:00 2001 From: "Roger.He" Date: Fri, 21 Apr 2017 13:08:43 +0800 Subject: [PATCH 084/144] drm/amdgpu: validate shadow before restoring from it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Roger.He Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 ++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 21 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 1 + 3 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 234d90a12482..3c1754df4c40 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2429,6 +2429,18 @@ static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev, domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); /* if bo has been evicted, then no need to recover */ if (domain == AMDGPU_GEM_DOMAIN_VRAM) { + r = amdgpu_bo_validate(bo->shadow); + if (r) { + DRM_ERROR("bo validate failed!\n"); + goto err; + } + + r = amdgpu_ttm_bind(&bo->shadow->tbo, &bo->shadow->tbo.mem); + if (r) { + DRM_ERROR("%p bind failed\n", bo->shadow); + goto err; + } + r = amdgpu_bo_restore_from_shadow(adev, ring, bo, NULL, fence, true); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 60de77b153b7..365883d7948d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -543,6 +543,27 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, return r; } +int amdgpu_bo_validate(struct amdgpu_bo *bo) +{ + uint32_t domain; + int r; + + if (bo->pin_count) + return 0; + + domain = bo->prefered_domains; + +retry: + amdgpu_ttm_placement_from_domain(bo, domain); + r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false); + if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { + domain = bo->allowed_domains; + goto retry; + } + + return r; +} + int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 15a723adca76..382485115b06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -175,6 +175,7 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev, struct amdgpu_bo *bo, struct reservation_object *resv, struct dma_fence **fence, bool direct); +int amdgpu_bo_validate(struct amdgpu_bo *bo); int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev, struct amdgpu_ring *ring, struct amdgpu_bo *bo, From a6bef67e2abae4f19de8fb4ec34acb1df8156a75 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Mon, 24 Apr 2017 17:39:00 +0800 Subject: [PATCH 085/144] drm/amdgpu: fix NULL pointer error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ 141.420491] BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 [ 141.420532] IP: [] fence_remove_callback+0x11/0x60 [ 141.420563] PGD 20a030067 [ 141.420575] PUD 2088ca067 [ 141.420587] PMD 0 [ 141.420599] Oops: 0000 [#1] SMP [ 141.420612] Modules linked in: amdgpu(OE) ttm(OE) drm_kms_helper(E) drm(E) i2c_algo_bit(E) fb_sys_fops(E) syscopyarea(E) sysfillrect(E) sysimgblt(E) rpcsec_gss_krb5(E) nfsv4(E) nfs(E) fscache(E) eeepc_wmi(E) asus_wmi(E) sparse_keymap(E) snd_hda_codec_realtek(E) video(E) snd_hda_codec_generic(E) snd_hda_codec_hdmi(E) snd_hda_intel(E) joydev(E) snd_hda_codec(E) snd_seq_midi(E) snd_seq_midi_event(E) snd_hda_core(E) snd_hwdep(E) snd_rawmidi(E) snd_pcm(E) kvm(E) irqbypass(E) crct10dif_pclmul(E) snd_seq(E) crc32_pclmul(E) ghash_clmulni_intel(E) snd_seq_device(E) snd_timer(E) aesni_intel(E) aes_x86_64(E) lrw(E) gf128mul(E) glue_helper(E) ablk_helper(E) cryptd(E) snd(E) soundcore(E) serio_raw(E) shpchp(E) i2c_piix4(E) i2c_designware_platform(E) 8250_dw(E) i2c_designware_core(E) mac_hid(E) binfmt_misc(E) [ 141.420948] nfsd(E) auth_rpcgss(E) nfs_acl(E) lockd(E) grace(E) sunrpc(E) parport_pc(E) ppdev(E) lp(E) parport(E) autofs4(E) hid_generic(E) usbhid(E) hid(E) psmouse(E) r8169(E) ahci(E) mii(E) libahci(E) wmi(E) [ 141.421042] CPU: 14 PID: 223 Comm: kworker/14:2 Tainted: G OE 4.9.0-custom #4 [ 141.421074] Hardware name: System manufacturer System Product Name/PRIME B350-PLUS, BIOS 0606 04/06/2017 [ 141.421146] Workqueue: events amd_sched_job_timedout [amdgpu] [ 141.421169] task: ffff88020b03ba80 task.stack: ffffc900016f4000 [ 141.421193] RIP: 0010:[] [] fence_remove_callback+0x11/0x60 [ 141.421229] RSP: 0018:ffffc900016f7d30 EFLAGS: 00010202 [ 141.421250] RAX: ffff8801c049fc00 RBX: ffff8801d4d8dc00 RCX: 0000000000000000 [ 141.421278] RDX: 0000000000000001 RSI: ffff8801c049fcc0 RDI: 0000000000000000 [ 141.421307] RBP: ffffc900016f7d48 R08: 0000000000000000 R09: 0000000000000000 [ 141.421334] R10: 00000020ed512a30 R11: 0000000000000001 R12: 0000000000000000 [ 141.421362] R13: ffff880209ba4ba0 R14: ffff880209ba4c58 R15: ffff8801c055cc60 [ 141.421390] FS: 0000000000000000(0000) GS:ffff88021ef80000(0000) knlGS:0000000000000000 [ 141.421421] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 141.421443] CR2: 0000000000000030 CR3: 000000020b554000 CR4: 00000000003406e0 [ 141.421471] Stack: [ 141.421480] ffff8801d4d8dc00 ffff880209ba4c48 ffff880209ba4ba0 ffffc900016f7d78 [ 141.421513] ffffffffa0697920 ffff880209ba0000 0000000000000000 ffff880209ba2770 [ 141.421549] ffff880209ba4b08 ffffc900016f7df0 ffffffffa05ce2ae ffffffffa0509eb7 [ 141.421583] Call Trace: [ 141.421628] [] amd_sched_hw_job_reset+0x50/0xb0 [amdgpu] [ 141.421676] [] amdgpu_gpu_reset+0x8e/0x690 [amdgpu] [ 141.421712] [] ? drm_printk+0x97/0xa0 [drm] [ 141.421770] [] amdgpu_job_timedout+0x46/0x50 [amdgpu] [ 141.421829] [] amd_sched_job_timedout+0x17/0x20 [amdgpu] [ 141.421859] [] process_one_work+0x153/0x3f0 [ 141.421884] [] worker_thread+0x12b/0x4b0 [ 141.421907] [] ? rescuer_thread+0x350/0x350 [ 141.421931] [] kthread+0xd3/0xf0 [ 141.421951] [] ? kthread_park+0x60/0x60 [ 141.421975] [] ret_from_fork+0x25/0x30 [ 141.421996] Code: ac 81 e8 a3 1f b0 ff 48 c7 c0 ea ff ff ff e9 48 ff ff ff 0f 1f 80 00 00 00 00 0f 1f 44 00 00 55 48 89 e5 41 55 41 54 49 89 fc 53 <48> 8b 7f 30 48 89 f3 e8 73 7c 26 00 48 8b 13 48 39 d3 41 0f 95 [ 141.422156] RIP [] fence_remove_callback+0x11/0x60 [ 141.422183] RSP [ 141.422197] CR2: 0000000000000030 [ 141.433483] ---[ end trace bc0949bf7ddd6d4b ]--- if the job is reset twice, then the parent could be NULL. Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index acd882a188bc..5fd12db0fc58 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -387,7 +387,9 @@ void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched) spin_lock(&sched->job_list_lock); list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { - if (dma_fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) { + if (s_job->s_fence->parent && + dma_fence_remove_callback(s_job->s_fence->parent, + &s_job->s_fence->cb)) { dma_fence_put(s_job->s_fence->parent); s_job->s_fence->parent = NULL; } From cca7ecb32b5920f05bb940cbe01dde19c0125620 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Wed, 26 Apr 2017 13:31:01 -0400 Subject: [PATCH 086/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Either in cgs functions or for callers of cgs functions: 1. The signal interrupt can affect the expected behaviour 2. There is no good mechanism to handle the corresponding error 3. There is no chance of deadlock in these single BO waiting 4. There is no clear benefit for interruptible waiting 5. Future caller of these functions might have same issue. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 1c7e6c28f93a..013f5f14dd75 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -89,7 +89,7 @@ static int amdgpu_cgs_gmap_kmem(struct cgs_device *cgs_device, void *kmem, AMDGPU_GEM_DOMAIN_GTT, 0, sg, NULL, &bo); if (ret) return ret; - ret = amdgpu_bo_reserve(bo, false); + ret = amdgpu_bo_reserve(bo, true); if (unlikely(ret != 0)) return ret; @@ -107,7 +107,7 @@ static int amdgpu_cgs_gunmap_kmem(struct cgs_device *cgs_device, cgs_handle_t km struct amdgpu_bo *obj = (struct amdgpu_bo *)kmem_handle; if (obj) { - int r = amdgpu_bo_reserve(obj, false); + int r = amdgpu_bo_reserve(obj, true); if (likely(r == 0)) { amdgpu_bo_unpin(obj); amdgpu_bo_unreserve(obj); @@ -215,7 +215,7 @@ static int amdgpu_cgs_free_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h struct amdgpu_bo *obj = (struct amdgpu_bo *)handle; if (obj) { - int r = amdgpu_bo_reserve(obj, false); + int r = amdgpu_bo_reserve(obj, true); if (likely(r == 0)) { amdgpu_bo_kunmap(obj); amdgpu_bo_unpin(obj); @@ -239,7 +239,7 @@ static int amdgpu_cgs_gmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h min_offset = obj->placements[0].fpfn << PAGE_SHIFT; max_offset = obj->placements[0].lpfn << PAGE_SHIFT; - r = amdgpu_bo_reserve(obj, false); + r = amdgpu_bo_reserve(obj, true); if (unlikely(r != 0)) return r; r = amdgpu_bo_pin_restricted(obj, obj->prefered_domains, @@ -252,7 +252,7 @@ static int amdgpu_cgs_gunmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t { int r; struct amdgpu_bo *obj = (struct amdgpu_bo *)handle; - r = amdgpu_bo_reserve(obj, false); + r = amdgpu_bo_reserve(obj, true); if (unlikely(r != 0)) return r; r = amdgpu_bo_unpin(obj); @@ -265,7 +265,7 @@ static int amdgpu_cgs_kmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h { int r; struct amdgpu_bo *obj = (struct amdgpu_bo *)handle; - r = amdgpu_bo_reserve(obj, false); + r = amdgpu_bo_reserve(obj, true); if (unlikely(r != 0)) return r; r = amdgpu_bo_kmap(obj, map); @@ -277,7 +277,7 @@ static int amdgpu_cgs_kunmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t { int r; struct amdgpu_bo *obj = (struct amdgpu_bo *)handle; - r = amdgpu_bo_reserve(obj, false); + r = amdgpu_bo_reserve(obj, true); if (unlikely(r != 0)) return r; amdgpu_bo_kunmap(obj); From 12d39245f6bea9dfddc29d75225a1d5ffc290186 Mon Sep 17 00:00:00 2001 From: Alex Xie Date: Tue, 25 Apr 2017 17:09:24 -0400 Subject: [PATCH 087/144] drm/amdgpu: Fix use of interruptible waiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no good mechanism to handle the corresponding error. When signal interrupt happens, unpin is not called. As a result, inside AMDGPU, the statistic of pin size will be wrong. Signed-off-by: Alex Xie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 96926a221bd5..d46773b8f7e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -169,7 +169,7 @@ static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work, void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, struct amdgpu_bo *new_abo) { - if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { + if (unlikely(amdgpu_bo_reserve(new_abo, true) != 0)) { DRM_ERROR("failed to reserve new abo in error path\n"); amdgpu_flip_work_cleanup(work); return; From effa290caa9fa23d13b4531fcf55142a107a3b2a Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 21 Apr 2017 17:26:07 +0800 Subject: [PATCH 088/144] drm/amd/powerplay: correct UlvOffsetVid on Vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 278def7380e7..5bb18a9a1056 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -1436,9 +1436,7 @@ static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr) (struct phm_ppt_v2_information *)(hwmgr->pptable); data->smc_state_table.pp_table.UlvOffsetVid = - (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / - VOLTAGE_VID_OFFSET_SCALE1); + (uint8_t)table_info->us_ulv_voltage_offset; data->smc_state_table.pp_table.UlvSmnclkDid = (uint8_t)(table_info->us_ulv_smnclk_did); @@ -2342,6 +2340,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) (uint8_t)(table_info->uc_vce_dpm_voltage_mode); pp_table->Mp0DpmVoltageMode = (uint8_t)(table_info->uc_mp0_dpm_voltage_mode); + pp_table->DisplayDpmVoltageMode = (uint8_t)(table_info->uc_dcef_dpm_voltage_mode); From 97782cc93f4440ba2bc111b8c84644b304c56676 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 21 Apr 2017 18:33:05 +0800 Subject: [PATCH 089/144] drm/amd/powerplay: disable cks by default on vega10. run gpu test auto reboot when enable cks right now. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 5bb18a9a1056..be2b602fb8b4 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -124,7 +124,7 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) } data->registry_data.clock_stretcher_support = - hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false; + hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? false : true; data->registry_data.disable_water_mark = 0; From 00c4855ef874e41d6b9f9b19d1d1e04bc70f0b31 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 21 Apr 2017 18:52:12 +0800 Subject: [PATCH 090/144] drm/amd/powerplay: refine set pcie dpm default table on vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index be2b602fb8b4..5e3e89be9fb6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -1182,29 +1182,9 @@ static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr) else pcie_table->lclk[i] = bios_pcie_table->entries[i].pcie_sclk; - - pcie_table->count++; } - if (data->registry_data.pcieSpeedOverride) - pcie_table->pcie_gen[i] = data->registry_data.pcieSpeedOverride; - else - pcie_table->pcie_gen[i] = - bios_pcie_table->entries[bios_pcie_table->count - 1].gen_speed; - - if (data->registry_data.pcieLaneOverride) - pcie_table->pcie_lane[i] = data->registry_data.pcieLaneOverride; - else - pcie_table->pcie_lane[i] = - bios_pcie_table->entries[bios_pcie_table->count - 1].lane_width; - - if (data->registry_data.pcieClockOverride) - pcie_table->lclk[i] = data->registry_data.pcieClockOverride; - else - pcie_table->lclk[i] = - bios_pcie_table->entries[bios_pcie_table->count - 1].pcie_sclk; - - pcie_table->count++; + pcie_table->count = NUM_LINK_LEVELS; return 0; } From 2c55b16bf0e1492ba662d884c81d324538cafce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 27 Apr 2017 17:13:39 +0200 Subject: [PATCH 091/144] drm/amdgpu: remove unused and mostly unimplemented CGS functions v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those functions are all unused and some not even implemented. v2: keep cgs_get_pci_resource, it is used by the ACP driver. Signed-off-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c | 198 ----------------- drivers/gpu/drm/amd/include/cgs_common.h | 270 ----------------------- 2 files changed, 468 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 013f5f14dd75..c6dba1eaefbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -42,82 +42,6 @@ struct amdgpu_cgs_device { struct amdgpu_device *adev = \ ((struct amdgpu_cgs_device *)cgs_device)->adev -static int amdgpu_cgs_gpu_mem_info(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type, - uint64_t *mc_start, uint64_t *mc_size, - uint64_t *mem_size) -{ - CGS_FUNC_ADEV; - switch(type) { - case CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB: - case CGS_GPU_MEM_TYPE__VISIBLE_FB: - *mc_start = 0; - *mc_size = adev->mc.visible_vram_size; - *mem_size = adev->mc.visible_vram_size - adev->vram_pin_size; - break; - case CGS_GPU_MEM_TYPE__INVISIBLE_CONTIG_FB: - case CGS_GPU_MEM_TYPE__INVISIBLE_FB: - *mc_start = adev->mc.visible_vram_size; - *mc_size = adev->mc.real_vram_size - adev->mc.visible_vram_size; - *mem_size = *mc_size; - break; - case CGS_GPU_MEM_TYPE__GART_CACHEABLE: - case CGS_GPU_MEM_TYPE__GART_WRITECOMBINE: - *mc_start = adev->mc.gtt_start; - *mc_size = adev->mc.gtt_size; - *mem_size = adev->mc.gtt_size - adev->gart_pin_size; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int amdgpu_cgs_gmap_kmem(struct cgs_device *cgs_device, void *kmem, - uint64_t size, - uint64_t min_offset, uint64_t max_offset, - cgs_handle_t *kmem_handle, uint64_t *mcaddr) -{ - CGS_FUNC_ADEV; - int ret; - struct amdgpu_bo *bo; - struct page *kmem_page = vmalloc_to_page(kmem); - int npages = ALIGN(size, PAGE_SIZE) >> PAGE_SHIFT; - - struct sg_table *sg = drm_prime_pages_to_sg(&kmem_page, npages); - ret = amdgpu_bo_create(adev, size, PAGE_SIZE, false, - AMDGPU_GEM_DOMAIN_GTT, 0, sg, NULL, &bo); - if (ret) - return ret; - ret = amdgpu_bo_reserve(bo, true); - if (unlikely(ret != 0)) - return ret; - - /* pin buffer into GTT */ - ret = amdgpu_bo_pin_restricted(bo, AMDGPU_GEM_DOMAIN_GTT, - min_offset, max_offset, mcaddr); - amdgpu_bo_unreserve(bo); - - *kmem_handle = (cgs_handle_t)bo; - return ret; -} - -static int amdgpu_cgs_gunmap_kmem(struct cgs_device *cgs_device, cgs_handle_t kmem_handle) -{ - struct amdgpu_bo *obj = (struct amdgpu_bo *)kmem_handle; - - if (obj) { - int r = amdgpu_bo_reserve(obj, true); - if (likely(r == 0)) { - amdgpu_bo_unpin(obj); - amdgpu_bo_unreserve(obj); - } - amdgpu_bo_unref(&obj); - - } - return 0; -} - static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type, uint64_t size, uint64_t align, @@ -349,62 +273,6 @@ static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device, WARN(1, "Invalid indirect register space"); } -static uint8_t amdgpu_cgs_read_pci_config_byte(struct cgs_device *cgs_device, unsigned addr) -{ - CGS_FUNC_ADEV; - uint8_t val; - int ret = pci_read_config_byte(adev->pdev, addr, &val); - if (WARN(ret, "pci_read_config_byte error")) - return 0; - return val; -} - -static uint16_t amdgpu_cgs_read_pci_config_word(struct cgs_device *cgs_device, unsigned addr) -{ - CGS_FUNC_ADEV; - uint16_t val; - int ret = pci_read_config_word(adev->pdev, addr, &val); - if (WARN(ret, "pci_read_config_word error")) - return 0; - return val; -} - -static uint32_t amdgpu_cgs_read_pci_config_dword(struct cgs_device *cgs_device, - unsigned addr) -{ - CGS_FUNC_ADEV; - uint32_t val; - int ret = pci_read_config_dword(adev->pdev, addr, &val); - if (WARN(ret, "pci_read_config_dword error")) - return 0; - return val; -} - -static void amdgpu_cgs_write_pci_config_byte(struct cgs_device *cgs_device, unsigned addr, - uint8_t value) -{ - CGS_FUNC_ADEV; - int ret = pci_write_config_byte(adev->pdev, addr, value); - WARN(ret, "pci_write_config_byte error"); -} - -static void amdgpu_cgs_write_pci_config_word(struct cgs_device *cgs_device, unsigned addr, - uint16_t value) -{ - CGS_FUNC_ADEV; - int ret = pci_write_config_word(adev->pdev, addr, value); - WARN(ret, "pci_write_config_word error"); -} - -static void amdgpu_cgs_write_pci_config_dword(struct cgs_device *cgs_device, unsigned addr, - uint32_t value) -{ - CGS_FUNC_ADEV; - int ret = pci_write_config_dword(adev->pdev, addr, value); - WARN(ret, "pci_write_config_dword error"); -} - - static int amdgpu_cgs_get_pci_resource(struct cgs_device *cgs_device, enum cgs_resource_type resource_type, uint64_t size, @@ -477,56 +345,6 @@ static int amdgpu_cgs_atom_exec_cmd_table(struct cgs_device *cgs_device, unsigne adev->mode_info.atom_context, table, args); } -static int amdgpu_cgs_create_pm_request(struct cgs_device *cgs_device, cgs_handle_t *request) -{ - /* TODO */ - return 0; -} - -static int amdgpu_cgs_destroy_pm_request(struct cgs_device *cgs_device, cgs_handle_t request) -{ - /* TODO */ - return 0; -} - -static int amdgpu_cgs_set_pm_request(struct cgs_device *cgs_device, cgs_handle_t request, - int active) -{ - /* TODO */ - return 0; -} - -static int amdgpu_cgs_pm_request_clock(struct cgs_device *cgs_device, cgs_handle_t request, - enum cgs_clock clock, unsigned freq) -{ - /* TODO */ - return 0; -} - -static int amdgpu_cgs_pm_request_engine(struct cgs_device *cgs_device, cgs_handle_t request, - enum cgs_engine engine, int powered) -{ - /* TODO */ - return 0; -} - - - -static int amdgpu_cgs_pm_query_clock_limits(struct cgs_device *cgs_device, - enum cgs_clock clock, - struct cgs_clock_limits *limits) -{ - /* TODO */ - return 0; -} - -static int amdgpu_cgs_set_camera_voltages(struct cgs_device *cgs_device, uint32_t mask, - const uint32_t *voltages) -{ - DRM_ERROR("not implemented"); - return -EPERM; -} - struct cgs_irq_params { unsigned src_id; cgs_irq_source_set_func_t set; @@ -1269,9 +1087,6 @@ static int amdgpu_cgs_call_acpi_method(struct cgs_device *cgs_device, } static const struct cgs_ops amdgpu_cgs_ops = { - .gpu_mem_info = amdgpu_cgs_gpu_mem_info, - .gmap_kmem = amdgpu_cgs_gmap_kmem, - .gunmap_kmem = amdgpu_cgs_gunmap_kmem, .alloc_gpu_mem = amdgpu_cgs_alloc_gpu_mem, .free_gpu_mem = amdgpu_cgs_free_gpu_mem, .gmap_gpu_mem = amdgpu_cgs_gmap_gpu_mem, @@ -1282,23 +1097,10 @@ static const struct cgs_ops amdgpu_cgs_ops = { .write_register = amdgpu_cgs_write_register, .read_ind_register = amdgpu_cgs_read_ind_register, .write_ind_register = amdgpu_cgs_write_ind_register, - .read_pci_config_byte = amdgpu_cgs_read_pci_config_byte, - .read_pci_config_word = amdgpu_cgs_read_pci_config_word, - .read_pci_config_dword = amdgpu_cgs_read_pci_config_dword, - .write_pci_config_byte = amdgpu_cgs_write_pci_config_byte, - .write_pci_config_word = amdgpu_cgs_write_pci_config_word, - .write_pci_config_dword = amdgpu_cgs_write_pci_config_dword, .get_pci_resource = amdgpu_cgs_get_pci_resource, .atom_get_data_table = amdgpu_cgs_atom_get_data_table, .atom_get_cmd_table_revs = amdgpu_cgs_atom_get_cmd_table_revs, .atom_exec_cmd_table = amdgpu_cgs_atom_exec_cmd_table, - .create_pm_request = amdgpu_cgs_create_pm_request, - .destroy_pm_request = amdgpu_cgs_destroy_pm_request, - .set_pm_request = amdgpu_cgs_set_pm_request, - .pm_request_clock = amdgpu_cgs_pm_request_clock, - .pm_request_engine = amdgpu_cgs_pm_request_engine, - .pm_query_clock_limits = amdgpu_cgs_pm_query_clock_limits, - .set_camera_voltages = amdgpu_cgs_set_camera_voltages, .get_firmware_info = amdgpu_cgs_get_firmware_info, .rel_firmware = amdgpu_cgs_rel_firmware, .set_powergating_state = amdgpu_cgs_set_powergating_state, diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index 17b9d41f3e87..0a94f749e3c0 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -53,20 +53,6 @@ enum cgs_ind_reg { CGS_IND_REG__AUDIO_ENDPT }; -/** - * enum cgs_clock - Clocks controlled by the SMU - */ -enum cgs_clock { - CGS_CLOCK__SCLK, - CGS_CLOCK__MCLK, - CGS_CLOCK__VCLK, - CGS_CLOCK__DCLK, - CGS_CLOCK__ECLK, - CGS_CLOCK__ACLK, - CGS_CLOCK__ICLK, - /* ... */ -}; - /** * enum cgs_engine - Engines that can be statically power-gated */ @@ -81,15 +67,6 @@ enum cgs_engine { /* ... */ }; -/** - * enum cgs_voltage_planes - Voltage planes for external camera HW - */ -enum cgs_voltage_planes { - CGS_VOLTAGE_PLANE__SENSOR0, - CGS_VOLTAGE_PLANE__SENSOR1, - /* ... */ -}; - /* * enum cgs_ucode_id - Firmware types for different IPs */ @@ -146,17 +123,6 @@ enum cgs_resource_type { CGS_RESOURCE_TYPE_ROM, }; -/** - * struct cgs_clock_limits - Clock limits - * - * Clocks are specified in 10KHz units. - */ -struct cgs_clock_limits { - unsigned min; /**< Minimum supported frequency */ - unsigned max; /**< Maxumim supported frequency */ - unsigned sustainable; /**< Thermally sustainable frequency */ -}; - /** * struct cgs_firmware_info - Firmware information */ @@ -220,54 +186,6 @@ struct cgs_acpi_method_info { uint32_t padding[9]; }; -/** - * cgs_gpu_mem_info() - Return information about memory heaps - * @cgs_device: opaque device handle - * @type: memory type - * @mc_start: Start MC address of the heap (output) - * @mc_size: MC address space size (output) - * @mem_size: maximum amount of memory available for allocation (output) - * - * This function returns information about memory heaps. The type - * parameter is used to select the memory heap. The mc_start and - * mc_size for GART heaps may be bigger than the memory available for - * allocation. - * - * mc_start and mc_size are undefined for non-contiguous FB memory - * types, since buffers allocated with these types may or may not be - * GART mapped. - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_gpu_mem_info_t)(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type, - uint64_t *mc_start, uint64_t *mc_size, - uint64_t *mem_size); - -/** - * cgs_gmap_kmem() - map kernel memory to GART aperture - * @cgs_device: opaque device handle - * @kmem: pointer to kernel memory - * @size: size to map - * @min_offset: minimum offset from start of GART aperture - * @max_offset: maximum offset from start of GART aperture - * @kmem_handle: kernel memory handle (output) - * @mcaddr: MC address (output) - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_gmap_kmem_t)(struct cgs_device *cgs_device, void *kmem, uint64_t size, - uint64_t min_offset, uint64_t max_offset, - cgs_handle_t *kmem_handle, uint64_t *mcaddr); - -/** - * cgs_gunmap_kmem() - unmap kernel memory - * @cgs_device: opaque device handle - * @kmem_handle: kernel memory handle returned by gmap_kmem - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_gunmap_kmem_t)(struct cgs_device *cgs_device, cgs_handle_t kmem_handle); - /** * cgs_alloc_gpu_mem() - Allocate GPU memory * @cgs_device: opaque device handle @@ -391,62 +309,6 @@ typedef uint32_t (*cgs_read_ind_register_t)(struct cgs_device *cgs_device, enum typedef void (*cgs_write_ind_register_t)(struct cgs_device *cgs_device, enum cgs_ind_reg space, unsigned index, uint32_t value); -/** - * cgs_read_pci_config_byte() - Read byte from PCI configuration space - * @cgs_device: opaque device handle - * @addr: address - * - * Return: Value read - */ -typedef uint8_t (*cgs_read_pci_config_byte_t)(struct cgs_device *cgs_device, unsigned addr); - -/** - * cgs_read_pci_config_word() - Read word from PCI configuration space - * @cgs_device: opaque device handle - * @addr: address, must be word-aligned - * - * Return: Value read - */ -typedef uint16_t (*cgs_read_pci_config_word_t)(struct cgs_device *cgs_device, unsigned addr); - -/** - * cgs_read_pci_config_dword() - Read dword from PCI configuration space - * @cgs_device: opaque device handle - * @addr: address, must be dword-aligned - * - * Return: Value read - */ -typedef uint32_t (*cgs_read_pci_config_dword_t)(struct cgs_device *cgs_device, - unsigned addr); - -/** - * cgs_write_pci_config_byte() - Write byte to PCI configuration space - * @cgs_device: opaque device handle - * @addr: address - * @value: value to write - */ -typedef void (*cgs_write_pci_config_byte_t)(struct cgs_device *cgs_device, unsigned addr, - uint8_t value); - -/** - * cgs_write_pci_config_word() - Write byte to PCI configuration space - * @cgs_device: opaque device handle - * @addr: address, must be word-aligned - * @value: value to write - */ -typedef void (*cgs_write_pci_config_word_t)(struct cgs_device *cgs_device, unsigned addr, - uint16_t value); - -/** - * cgs_write_pci_config_dword() - Write byte to PCI configuration space - * @cgs_device: opaque device handle - * @addr: address, must be dword-aligned - * @value: value to write - */ -typedef void (*cgs_write_pci_config_dword_t)(struct cgs_device *cgs_device, unsigned addr, - uint32_t value); - - /** * cgs_get_pci_resource() - provide access to a device resource (PCI BAR) * @cgs_device: opaque device handle @@ -500,87 +362,6 @@ typedef int (*cgs_atom_get_cmd_table_revs_t)(struct cgs_device *cgs_device, unsi typedef int (*cgs_atom_exec_cmd_table_t)(struct cgs_device *cgs_device, unsigned table, void *args); -/** - * cgs_create_pm_request() - Create a power management request - * @cgs_device: opaque device handle - * @request: handle of created PM request (output) - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_create_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t *request); - -/** - * cgs_destroy_pm_request() - Destroy a power management request - * @cgs_device: opaque device handle - * @request: handle of created PM request - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_destroy_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t request); - -/** - * cgs_set_pm_request() - Activate or deactiveate a PM request - * @cgs_device: opaque device handle - * @request: PM request handle - * @active: 0 = deactivate, non-0 = activate - * - * While a PM request is active, its minimum clock requests are taken - * into account as the requested engines are powered up. When the - * request is inactive, the engines may be powered down and clocks may - * be lower, depending on other PM requests by other driver - * components. - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_set_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t request, - int active); - -/** - * cgs_pm_request_clock() - Request a minimum frequency for a specific clock - * @cgs_device: opaque device handle - * @request: PM request handle - * @clock: which clock? - * @freq: requested min. frequency in 10KHz units (0 to clear request) - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_pm_request_clock_t)(struct cgs_device *cgs_device, cgs_handle_t request, - enum cgs_clock clock, unsigned freq); - -/** - * cgs_pm_request_engine() - Request an engine to be powered up - * @cgs_device: opaque device handle - * @request: PM request handle - * @engine: which engine? - * @powered: 0 = powered down, non-0 = powered up - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_pm_request_engine_t)(struct cgs_device *cgs_device, cgs_handle_t request, - enum cgs_engine engine, int powered); - -/** - * cgs_pm_query_clock_limits() - Query clock frequency limits - * @cgs_device: opaque device handle - * @clock: which clock? - * @limits: clock limits - * - * Return: 0 on success, -errno otherwise - */ -typedef int (*cgs_pm_query_clock_limits_t)(struct cgs_device *cgs_device, - enum cgs_clock clock, - struct cgs_clock_limits *limits); - -/** - * cgs_set_camera_voltages() - Apply specific voltages to PMIC voltage planes - * @cgs_device: opaque device handle - * @mask: bitmask of voltages to change (1<os_ops->func(dev, ##__VA_ARGS__)) -#define cgs_gpu_mem_info(dev,type,mc_start,mc_size,mem_size) \ - CGS_CALL(gpu_mem_info,dev,type,mc_start,mc_size,mem_size) -#define cgs_gmap_kmem(dev,kmem,size,min_off,max_off,kmem_handle,mcaddr) \ - CGS_CALL(gmap_kmem,dev,kmem,size,min_off,max_off,kmem_handle,mcaddr) -#define cgs_gunmap_kmem(dev,kmem_handle) \ - CGS_CALL(gunmap_kmem,dev,keme_handle) #define cgs_alloc_gpu_mem(dev,type,size,align,min_off,max_off,handle) \ CGS_CALL(alloc_gpu_mem,dev,type,size,align,min_off,max_off,handle) #define cgs_free_gpu_mem(dev,handle) \ @@ -724,19 +481,6 @@ struct cgs_device #define cgs_write_ind_register(dev,space,index,value) \ CGS_CALL(write_ind_register,dev,space,index,value) -#define cgs_read_pci_config_byte(dev,addr) \ - CGS_CALL(read_pci_config_byte,dev,addr) -#define cgs_read_pci_config_word(dev,addr) \ - CGS_CALL(read_pci_config_word,dev,addr) -#define cgs_read_pci_config_dword(dev,addr) \ - CGS_CALL(read_pci_config_dword,dev,addr) -#define cgs_write_pci_config_byte(dev,addr,value) \ - CGS_CALL(write_pci_config_byte,dev,addr,value) -#define cgs_write_pci_config_word(dev,addr,value) \ - CGS_CALL(write_pci_config_word,dev,addr,value) -#define cgs_write_pci_config_dword(dev,addr,value) \ - CGS_CALL(write_pci_config_dword,dev,addr,value) - #define cgs_atom_get_data_table(dev,table,size,frev,crev) \ CGS_CALL(atom_get_data_table,dev,table,size,frev,crev) #define cgs_atom_get_cmd_table_revs(dev,table,frev,crev) \ @@ -744,20 +488,6 @@ struct cgs_device #define cgs_atom_exec_cmd_table(dev,table,args) \ CGS_CALL(atom_exec_cmd_table,dev,table,args) -#define cgs_create_pm_request(dev,request) \ - CGS_CALL(create_pm_request,dev,request) -#define cgs_destroy_pm_request(dev,request) \ - CGS_CALL(destroy_pm_request,dev,request) -#define cgs_set_pm_request(dev,request,active) \ - CGS_CALL(set_pm_request,dev,request,active) -#define cgs_pm_request_clock(dev,request,clock,freq) \ - CGS_CALL(pm_request_clock,dev,request,clock,freq) -#define cgs_pm_request_engine(dev,request,engine,powered) \ - CGS_CALL(pm_request_engine,dev,request,engine,powered) -#define cgs_pm_query_clock_limits(dev,clock,limits) \ - CGS_CALL(pm_query_clock_limits,dev,clock,limits) -#define cgs_set_camera_voltages(dev,mask,voltages) \ - CGS_CALL(set_camera_voltages,dev,mask,voltages) #define cgs_get_firmware_info(dev, type, info) \ CGS_CALL(get_firmware_info, dev, type, info) #define cgs_rel_firmware(dev, type) \ From 408bfe7c3c5d036947b509356f494dc6b46025ff Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Thu, 27 Apr 2017 11:12:07 +0800 Subject: [PATCH 092/144] drm/amdgpu: export more gpu info for gfx9 v2: 64-bit aligned for gpu info v3: squash in wave_front_fix Signed-off-by: Ken Wang Signed-off-by: Junwei Zhang Reviewed-by: Alex Deucher Reviewed-by: Qiang Yu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 11 +++++++++++ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 +++ include/uapi/drm/amdgpu_drm.h | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index a4fc54c70f30..c9f935710d40 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -967,6 +967,9 @@ struct amdgpu_gfx_config { unsigned mc_arb_ramcfg; unsigned gb_addr_config; unsigned num_rbs; + unsigned gs_vgt_table_depth; + unsigned gs_prim_buffer_depth; + unsigned max_gs_waves_per_vgt; uint32_t tile_mode_array[32]; uint32_t macrotile_mode_array[16]; @@ -981,6 +984,7 @@ struct amdgpu_gfx_config { struct amdgpu_cu_info { uint32_t number; /* total active CU number */ uint32_t ao_cu_mask; + uint32_t wave_front_size; uint32_t bitmap[4][4]; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 832be632478f..21f616cdb279 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -546,10 +546,21 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file if (amdgpu_ngg) { dev_info.prim_buf_gpu_addr = adev->gfx.ngg.buf[PRIM].gpu_addr; + dev_info.prim_buf_size = adev->gfx.ngg.buf[PRIM].size; dev_info.pos_buf_gpu_addr = adev->gfx.ngg.buf[POS].gpu_addr; + dev_info.pos_buf_size = adev->gfx.ngg.buf[POS].size; dev_info.cntl_sb_buf_gpu_addr = adev->gfx.ngg.buf[CNTL].gpu_addr; + dev_info.cntl_sb_buf_size = adev->gfx.ngg.buf[CNTL].size; dev_info.param_buf_gpu_addr = adev->gfx.ngg.buf[PARAM].gpu_addr; + dev_info.param_buf_size = adev->gfx.ngg.buf[PARAM].size; } + dev_info.wave_front_size = adev->gfx.cu_info.wave_front_size; + dev_info.num_shader_visible_vgprs = adev->gfx.config.max_gprs; + dev_info.num_cu_per_sh = adev->gfx.config.max_cu_per_sh; + dev_info.num_tcc_blocks = adev->gfx.config.max_texture_channel_caches; + dev_info.gs_vgt_table_depth = adev->gfx.config.gs_vgt_table_depth; + dev_info.gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth; + dev_info.max_gs_waves_per_vgt = adev->gfx.config.max_gs_waves_per_vgt; return copy_to_user(out, &dev_info, min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 9a9cb90e2f5f..210d21c085f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -785,6 +785,9 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) adev->gfx.config.sc_prim_fifo_size_backend = 0x100; adev->gfx.config.sc_hiz_tile_fifo_size = 0x30; adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0; + adev->gfx.config.gs_vgt_table_depth = 32; + adev->gfx.config.gs_prim_buffer_depth = 1792; + adev->gfx.config.max_gs_waves_per_vgt = 32; gb_addr_config = VEGA10_GB_ADDR_CONFIG_GOLDEN; break; default: diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 95260e5043af..6c249e5cfb09 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -767,6 +767,25 @@ struct drm_amdgpu_info_device { __u64 cntl_sb_buf_gpu_addr; /* NGG Parameter Cache */ __u64 param_buf_gpu_addr; + __u32 prim_buf_size; + __u32 pos_buf_size; + __u32 cntl_sb_buf_size; + __u32 param_buf_size; + /* wavefront size*/ + __u32 wave_front_size; + /* shader visible vgprs*/ + __u32 num_shader_visible_vgprs; + /* CU per shader array*/ + __u32 num_cu_per_sh; + /* number of tcc blocks*/ + __u32 num_tcc_blocks; + /* gs vgt table depth*/ + __u32 gs_vgt_table_depth; + /* gs primitive buffer depth*/ + __u32 gs_prim_buffer_depth; + /* max gs wavefront per vgt*/ + __u32 max_gs_waves_per_vgt; + __u32 _pad1; }; struct drm_amdgpu_info_hw_ip { From 44eb8c1b33619abc35cba0266ff497c843bd108d Mon Sep 17 00:00:00 2001 From: Junwei Zhang Date: Thu, 27 Apr 2017 16:27:43 +0800 Subject: [PATCH 093/144] drm/amdgpu: bump version for exporting gpu info for gfx9 Signed-off-by: Junwei Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index bb47fb3ce341..eb1345627501 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -64,9 +64,10 @@ * - 3.12.0 - Add query for double offchip LDS buffers * - 3.13.0 - Add PRT support * - 3.14.0 - Fix race in amdgpu_ctx_get_fence() and note new functionality + * - 3.15.0 - Export more gpu info for gfx9 */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 14 +#define KMS_DRIVER_MINOR 15 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; From 10e709cb296c98424c03408d23e3addeddcd4088 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Thu, 27 Apr 2017 15:13:52 +0800 Subject: [PATCH 094/144] drm/amdgpu: fix deadlock of reservation between cs and gpu reset v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the case could happen when gpu reset: 1. when gpu reset, cs can be continue until sw queue is full, then push job will wait with holding pd reservation. 2. gpu_reset routine will also need pd reservation to restore page table from their shadow. 3. cs is waiting for gpu_reset complete, but gpu reset is waiting for cs releases reservation. v2: handle amdgpu_cs_submit error path. Signed-off-by: Chunming Zhou Reviewed-by: Christian König Reviewed-by: Junwei Zhang Reviewed-by: Monk Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index ec71b9320561..4e6b9501ab0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1074,6 +1074,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence); job->uf_sequence = cs->out.handle; amdgpu_job_free_resources(job); + amdgpu_cs_parser_fini(p, 0, true); trace_amdgpu_cs_ioctl(job); amd_sched_entity_push_job(&job->base); @@ -1129,7 +1130,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) goto out; r = amdgpu_cs_submit(&parser, cs); + if (r) + goto out; + return 0; out: amdgpu_cs_parser_fini(&parser, r, reserved_buffers); return r; From 1dfc41d44c20dc3efbd0139d7f991d13c6daa875 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 27 Apr 2017 15:46:35 +0800 Subject: [PATCH 095/144] drm/amd/powerplay: add disable_smc_ctf callback in hwmgr. export disablesmcctf to eventmgr. need to disable temperature alert when s3/s4. otherwise, when resume back,enable temperature alert will fail. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c | 10 ++++++++++ drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 1 + drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h | 2 +- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c index 23bba2c8b18e..fcc722ea7649 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c @@ -501,3 +501,13 @@ int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_i return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks); } + +int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr); +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 8f663ab56a80..4ad84530c88a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4695,6 +4695,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .release_firmware = smu7_release_firmware, .set_power_profile_state = smu7_set_power_profile_state, .avfs_control = smu7_avfs_control, + .disable_smc_firmware_ctf = smu7_thermal_disable_alert, }; uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index 5345b50761f4..a1ebe1014492 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -431,6 +431,6 @@ extern int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, struct pp_display_clock_request *clock); extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); - +extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr); #endif /* _HARDWARE_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 320225dd3328..98d38c31f6a6 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -373,6 +373,7 @@ struct pp_hwmgr_func { int (*set_power_profile_state)(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request); int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); + int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); }; struct pp_table_func { From f8dc9476d9fe25b982e642a733967d7b5fbe5ae3 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 28 Apr 2017 12:54:26 +0800 Subject: [PATCH 096/144] drm/amd/powerplay: complete disable_smc_firmware_ctf_tasks. Disable ctf in eventmgr to fix S3/S4 support. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c | 2 +- drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c | 5 +++++ drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c index 9ef2d90e2886..b82c43af59ab 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c @@ -219,7 +219,7 @@ const pem_event_action notify_smu_suspend_tasks[] = { }; const pem_event_action disable_smc_firmware_ctf_tasks[] = { - /* PEM_Task_DisableSMCFirmwareCTF,*/ + pem_task_disable_smc_firmware_ctf, NULL }; diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c index e04216ec7ee1..8c4ebaae1e0c 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c @@ -173,6 +173,11 @@ int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_even return 0; } +int pem_task_disable_smc_firmware_ctf(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_disable_smc_firmware_ctf(eventmgr->hwmgr); +} + int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) { return phm_setup_asic(eventmgr->hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h index 6c6297e3b598..37e7ca5a58e0 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h @@ -84,5 +84,6 @@ int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, str /*thermal */ int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_disable_smc_firmware_ctf(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); #endif /* _EVENT_TASKS_H_ */ From 8b9242eddd51f17b8306d6c96172fd68ef1106c6 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 27 Apr 2017 15:48:56 +0800 Subject: [PATCH 097/144] drm/amd/powerplay: implement stop dpm task for vega10. Add functions to disable dpm for S3/S4. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 97 +++++++++++++++++++ .../amd/powerplay/hwmgr/vega10_powertune.c | 23 +++++ .../amd/powerplay/hwmgr/vega10_powertune.h | 1 + .../drm/amd/powerplay/hwmgr/vega10_thermal.c | 2 +- .../drm/amd/powerplay/hwmgr/vega10_thermal.h | 1 + 5 files changed, 123 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 5e3e89be9fb6..68eae529df50 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -2420,6 +2420,26 @@ static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr) return 0; } +static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_THERMAL].supported) { + if (!data->smu_features[GNLD_THERMAL].enabled) + pr_info("THERMAL Feature Already disabled!"); + + PP_ASSERT_WITH_CODE( + !vega10_enable_smc_features(hwmgr->smumgr, + false, + data->smu_features[GNLD_THERMAL].smu_feature_bitmap), + "disable THERMAL Feature Failed!", + return -1); + data->smu_features[GNLD_THERMAL].enabled = false; + } + + return 0; +} + static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = @@ -2498,6 +2518,37 @@ static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) return 0; } +static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) +{ + struct vega10_hwmgr *data = + (struct vega10_hwmgr *)(hwmgr->backend); + uint32_t i, feature_mask = 0; + + + if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), + "Attempt to Enable LED DPM feature Failed!", return -EINVAL); + data->smu_features[GNLD_LED_DISPLAY].enabled = true; + } + + for (i = 0; i < GNLD_DPM_MAX; i++) { + if (data->smu_features[i].smu_feature_bitmap & bitmap) { + if (data->smu_features[i].supported) { + if (data->smu_features[i].enabled) { + feature_mask |= data->smu_features[i]. + smu_feature_bitmap; + data->smu_features[i].enabled = false; + } + } + } + } + + vega10_enable_smc_features(hwmgr->smumgr, false, feature_mask); + + return 0; +} + /** * @brief Tell SMC to enabled the supported DPMs. * @@ -4356,11 +4407,55 @@ vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmg return is_update_required; } +static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = (vega10_is_dpm_running(hwmgr)) ? 0 : -1; + PP_ASSERT_WITH_CODE(tmp_result == 0, + "DPM is not running right now, no need to disable DPM!", + return 0); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)) + vega10_disable_thermal_protection(hwmgr); + + tmp_result = vega10_disable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable power containment!", result = tmp_result); + + tmp_result = vega10_avfs_enable(hwmgr, false); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable AVFS!", result = tmp_result); + + tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop DPM!", result = tmp_result); + + return result; +} + +static int vega10_power_off_asic(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); + int result; + + result = vega10_disable_dpm_tasks(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "[disable_dpm_tasks] Failed to disable DPM!", + ); + data->water_marks_bitmap &= ~(WaterMarksLoaded); + + return result; +} + + static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .backend_init = vega10_hwmgr_backend_init, .backend_fini = vega10_hwmgr_backend_fini, .asic_setup = vega10_setup_asic_task, .dynamic_state_management_enable = vega10_enable_dpm_tasks, + .dynamic_state_management_disable = vega10_disable_dpm_tasks, .get_num_of_pp_table_entries = vega10_get_number_of_powerplay_table_entries, .get_power_state_size = vega10_get_power_state_size, @@ -4400,6 +4495,8 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .check_states_equal = vega10_check_states_equal, .check_smc_update_required_for_display_configuration = vega10_check_smc_update_required_for_display_configuration, + .power_off_asic = vega10_power_off_asic, + .disable_smc_firmware_ctf = vega10_thermal_disable_alert, }; int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c index f1e244cd2370..692f752fbb27 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c @@ -113,6 +113,29 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr) return result; } +int vega10_disable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = + (struct vega10_hwmgr *)(hwmgr->backend); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (data->smu_features[GNLD_PPT].supported) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + false, data->smu_features[GNLD_PPT].smu_feature_bitmap), + "Attempt to disable PPT feature Failed!", + data->smu_features[GNLD_PPT].supported = false); + + if (data->smu_features[GNLD_TDC].supported) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + false, data->smu_features[GNLD_TDC].smu_feature_bitmap), + "Attempt to disable PPT feature Failed!", + data->smu_features[GNLD_TDC].supported = false); + } + + return 0; +} + static int vega10_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, uint32_t adjust_percent) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h index d9662bf4a4b4..9ecaa27c0bb5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h @@ -60,6 +60,7 @@ int vega10_enable_smc_cac(struct pp_hwmgr *hwmgr); int vega10_enable_power_containment(struct pp_hwmgr *hwmgr); int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); int vega10_power_control_set_level(struct pp_hwmgr *hwmgr); +int vega10_disable_power_containment(struct pp_hwmgr *hwmgr); #endif /* _VEGA10_POWERTUNE_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index f4d77b62e1ba..7062ec8cc4ac 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -501,7 +501,7 @@ static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) * Disable thermal alerts on the RV770 thermal controller. * @param hwmgr The address of the hardware manager. */ -static int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) +int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h index 8036808ec421..70c1d22b3d7d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h @@ -78,6 +78,7 @@ extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); extern uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr); +extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr); #endif From c81a1a74037f61c578f6b8218b079aa434e300b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 28 Apr 2017 17:28:14 +0900 Subject: [PATCH 098/144] drm/amdgpu: Make amdgpu_bo_reserve use uninterruptible waits for cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of these paths probably cannot be interrupted by a signal anyway. Those that can would fail to clean up things if they actually got interrupted. Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | 10 +++++----- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 8 ++++---- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 8 ++++---- 16 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index d46773b8f7e8..21125a9452b8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -123,7 +123,7 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) int r; /* unpin of the old buffer */ - r = amdgpu_bo_reserve(work->old_abo, false); + r = amdgpu_bo_reserve(work->old_abo, true); if (likely(r == 0)) { r = amdgpu_bo_unpin(work->old_abo); if (unlikely(r != 0)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index a48142d930c6..236d9950221b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -112,7 +112,7 @@ static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj) struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); int ret; - ret = amdgpu_bo_reserve(abo, false); + ret = amdgpu_bo_reserve(abo, true); if (likely(ret == 0)) { amdgpu_bo_kunmap(abo); amdgpu_bo_unpin(abo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 6d691abe889c..e7406ce7093c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -183,7 +183,7 @@ void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev) if (adev->gart.robj == NULL) { return; } - r = amdgpu_bo_reserve(adev->gart.robj, false); + r = amdgpu_bo_reserve(adev->gart.robj, true); if (likely(r == 0)) { amdgpu_bo_kunmap(adev->gart.robj); amdgpu_bo_unpin(adev->gart.robj); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 21f616cdb279..4f2b6679f72f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -821,7 +821,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (amdgpu_sriov_vf(adev)) { /* TODO: how to handle reserve failure */ - BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, false)); + BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true)); amdgpu_vm_bo_rmv(adev, fpriv->vm.csa_bo_va); fpriv->vm.csa_bo_va = NULL; amdgpu_bo_unreserve(adev->virt.csa_obj); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c index 3826d5aea0a6..6bdc866570ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c @@ -113,7 +113,7 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj) struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); int ret = 0; - ret = amdgpu_bo_reserve(bo, false); + ret = amdgpu_bo_reserve(bo, true); if (unlikely(ret != 0)) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index de9f919ae336..5ca75a456ad2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c @@ -130,7 +130,7 @@ int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev, return -EINVAL; } - r = amdgpu_bo_reserve(sa_manager->bo, false); + r = amdgpu_bo_reserve(sa_manager->bo, true); if (!r) { amdgpu_bo_kunmap(sa_manager->bo); amdgpu_bo_unpin(sa_manager->bo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 24ca251f82ca..7bb1bf76319a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1198,7 +1198,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) return; amdgpu_ttm_debugfs_fini(adev); if (adev->stollen_vga_memory) { - r = amdgpu_bo_reserve(adev->stollen_vga_memory, false); + r = amdgpu_bo_reserve(adev->stollen_vga_memory, true); if (r == 0) { amdgpu_bo_unpin(adev->stollen_vga_memory); amdgpu_bo_unreserve(adev->stollen_vga_memory); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index ba98d35340a3..0cdeb6a2e4a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2230,7 +2230,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, if (!atomic && fb && fb != crtc->primary->fb) { amdgpu_fb = to_amdgpu_framebuffer(fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) return r; amdgpu_bo_unpin(abo); @@ -2589,7 +2589,7 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc, unpin: if (amdgpu_crtc->cursor_bo) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - ret = amdgpu_bo_reserve(aobj, false); + ret = amdgpu_bo_reserve(aobj, true); if (likely(ret == 0)) { amdgpu_bo_unpin(aobj); amdgpu_bo_unreserve(aobj); @@ -2720,7 +2720,7 @@ static void dce_v10_0_crtc_disable(struct drm_crtc *crtc) amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r)) DRM_ERROR("failed to reserve abo before unpin\n"); else { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index e59bc42df18c..773654a19749 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2214,7 +2214,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, if (!atomic && fb && fb != crtc->primary->fb) { amdgpu_fb = to_amdgpu_framebuffer(fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) return r; amdgpu_bo_unpin(abo); @@ -2609,7 +2609,7 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc, unpin: if (amdgpu_crtc->cursor_bo) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - ret = amdgpu_bo_reserve(aobj, false); + ret = amdgpu_bo_reserve(aobj, true); if (likely(ret == 0)) { amdgpu_bo_unpin(aobj); amdgpu_bo_unreserve(aobj); @@ -2740,7 +2740,7 @@ static void dce_v11_0_crtc_disable(struct drm_crtc *crtc) amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r)) DRM_ERROR("failed to reserve abo before unpin\n"); else { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index e146d252aa30..1f3552967ba3 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -1645,7 +1645,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, if (!atomic && fb && fb != crtc->primary->fb) { amdgpu_fb = to_amdgpu_framebuffer(fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) return r; amdgpu_bo_unpin(abo); @@ -1962,7 +1962,7 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc, unpin: if (amdgpu_crtc->cursor_bo) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - ret = amdgpu_bo_reserve(aobj, false); + ret = amdgpu_bo_reserve(aobj, true); if (likely(ret == 0)) { amdgpu_bo_unpin(aobj); amdgpu_bo_unreserve(aobj); @@ -2088,7 +2088,7 @@ static void dce_v6_0_crtc_disable(struct drm_crtc *crtc) amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r)) DRM_ERROR("failed to reserve abo before unpin\n"); else { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 6df7a28e8aac..3c558c170e5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2089,7 +2089,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, if (!atomic && fb && fb != crtc->primary->fb) { amdgpu_fb = to_amdgpu_framebuffer(fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r != 0)) return r; amdgpu_bo_unpin(abo); @@ -2440,7 +2440,7 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc, unpin: if (amdgpu_crtc->cursor_bo) { struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - ret = amdgpu_bo_reserve(aobj, false); + ret = amdgpu_bo_reserve(aobj, true); if (likely(ret == 0)) { amdgpu_bo_unpin(aobj); amdgpu_bo_unreserve(aobj); @@ -2571,7 +2571,7 @@ static void dce_v8_0_crtc_disable(struct drm_crtc *crtc) amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r)) DRM_ERROR("failed to reserve abo before unpin\n"); else { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 81a24b6b4846..f1b479b6ac98 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -248,7 +248,7 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc) amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb); abo = gem_to_amdgpu_bo(amdgpu_fb->obj); - r = amdgpu_bo_reserve(abo, false); + r = amdgpu_bo_reserve(abo, true); if (unlikely(r)) DRM_ERROR("failed to reserve abo before unpin\n"); else { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 6a429e927297..a125f9d44577 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -2437,7 +2437,7 @@ static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev) int r; if (adev->gfx.rlc.save_restore_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC sr bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.save_restore_obj); @@ -2448,7 +2448,7 @@ static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev) } if (adev->gfx.rlc.clear_state_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC c bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj); @@ -2459,7 +2459,7 @@ static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev) } if (adev->gfx.rlc.cp_table_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index eca022eaff44..ee2f2139e2eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -2792,7 +2792,7 @@ static void gfx_v7_0_cp_compute_fini(struct amdgpu_device *adev) struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; if (ring->mqd_obj) { - r = amdgpu_bo_reserve(ring->mqd_obj, false); + r = amdgpu_bo_reserve(ring->mqd_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve MQD bo failed\n", r); @@ -2810,7 +2810,7 @@ static void gfx_v7_0_mec_fini(struct amdgpu_device *adev) int r; if (adev->gfx.mec.hpd_eop_obj) { - r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, false); + r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve HPD EOP bo failed\n", r); amdgpu_bo_unpin(adev->gfx.mec.hpd_eop_obj); @@ -3359,7 +3359,7 @@ static void gfx_v7_0_rlc_fini(struct amdgpu_device *adev) /* save restore block */ if (adev->gfx.rlc.save_restore_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC sr bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.save_restore_obj); @@ -3371,7 +3371,7 @@ static void gfx_v7_0_rlc_fini(struct amdgpu_device *adev) /* clear state block */ if (adev->gfx.rlc.clear_state_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC c bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj); @@ -3383,7 +3383,7 @@ static void gfx_v7_0_rlc_fini(struct amdgpu_device *adev) /* clear state block */ if (adev->gfx.rlc.cp_table_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 0115c5f65c01..703bd55d6075 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1239,7 +1239,7 @@ static void gfx_v8_0_rlc_fini(struct amdgpu_device *adev) /* clear state block */ if (adev->gfx.rlc.clear_state_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC cbs bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj); @@ -1250,7 +1250,7 @@ static void gfx_v8_0_rlc_fini(struct amdgpu_device *adev) /* jump table block */ if (adev->gfx.rlc.cp_table_obj) { - r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false); + r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r); amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj); @@ -1363,7 +1363,7 @@ static void gfx_v8_0_mec_fini(struct amdgpu_device *adev) int r; if (adev->gfx.mec.hpd_eop_obj) { - r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, false); + r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve HPD EOP bo failed\n", r); amdgpu_bo_unpin(adev->gfx.mec.hpd_eop_obj); @@ -1490,7 +1490,7 @@ static int gfx_v8_0_kiq_init(struct amdgpu_device *adev) memset(hpd, 0, MEC_HPD_SIZE); - r = amdgpu_bo_reserve(kiq->eop_obj, false); + r = amdgpu_bo_reserve(kiq->eop_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve kiq eop bo failed\n", r); amdgpu_bo_kunmap(kiq->eop_obj); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 210d21c085f2..4073fd24dd13 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -453,7 +453,7 @@ static void gfx_v9_0_mec_fini(struct amdgpu_device *adev) int r; if (adev->gfx.mec.hpd_eop_obj) { - r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, false); + r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve HPD EOP bo failed\n", r); amdgpu_bo_unpin(adev->gfx.mec.hpd_eop_obj); @@ -463,7 +463,7 @@ static void gfx_v9_0_mec_fini(struct amdgpu_device *adev) adev->gfx.mec.hpd_eop_obj = NULL; } if (adev->gfx.mec.mec_fw_obj) { - r = amdgpu_bo_reserve(adev->gfx.mec.mec_fw_obj, false); + r = amdgpu_bo_reserve(adev->gfx.mec.mec_fw_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve mec firmware bo failed\n", r); amdgpu_bo_unpin(adev->gfx.mec.mec_fw_obj); @@ -599,7 +599,7 @@ static int gfx_v9_0_kiq_init(struct amdgpu_device *adev) memset(hpd, 0, MEC_HPD_SIZE); - r = amdgpu_bo_reserve(kiq->eop_obj, false); + r = amdgpu_bo_reserve(kiq->eop_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve kiq eop bo failed\n", r); amdgpu_bo_kunmap(kiq->eop_obj); @@ -1786,7 +1786,7 @@ static void gfx_v9_0_cp_compute_fini(struct amdgpu_device *adev) struct amdgpu_ring *ring = &adev->gfx.compute_ring[i]; if (ring->mqd_obj) { - r = amdgpu_bo_reserve(ring->mqd_obj, false); + r = amdgpu_bo_reserve(ring->mqd_obj, true); if (unlikely(r != 0)) dev_warn(adev->dev, "(%d) reserve MQD bo failed\n", r); From 98da65d5e32583d89a1b1c760293b601816a98d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Fri, 28 Apr 2017 16:32:43 -0400 Subject: [PATCH 099/144] Revert "drm/amdgpu: Refactor flip into prepare submit and submit. (v3)" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit cb341a319f7e66f879d69af929c3dadfc1a8f31e. The purpose of the refactor was for amdgpu_crtc_prepare/submit_flip to be used by the DC code, but that's no longer the case. Reviewed-by: Christian König Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 142 +++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 15 --- 2 files changed, 31 insertions(+), 126 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 21125a9452b8..cdf2ab20166a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -138,52 +138,11 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) kfree(work); } - -static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work) -{ - int i; - - amdgpu_bo_unref(&work->old_abo); - dma_fence_put(work->excl); - for (i = 0; i < work->shared_count; ++i) - dma_fence_put(work->shared[i]); - kfree(work->shared); - kfree(work); -} - -static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - amdgpu_bo_unreserve(new_abo); - amdgpu_flip_work_cleanup(work); -} - -static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) - DRM_ERROR("failed to unpin new abo in error path\n"); - amdgpu_flip_cleanup_unreserve(work, new_abo); -} - -void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - if (unlikely(amdgpu_bo_reserve(new_abo, true) != 0)) { - DRM_ERROR("failed to reserve new abo in error path\n"); - amdgpu_flip_work_cleanup(work); - return; - } - amdgpu_flip_cleanup_unpin(work, new_abo); -} - -int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct amdgpu_flip_work **work_p, - struct amdgpu_bo **new_abo_p) +int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags, uint32_t target, + struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = crtc->dev; struct amdgpu_device *adev = dev->dev_private; @@ -196,7 +155,7 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, unsigned long flags; u64 tiling_flags; u64 base; - int r; + int i, r; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -257,80 +216,41 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, spin_unlock_irqrestore(&crtc->dev->event_lock, flags); r = -EBUSY; goto pflip_cleanup; - } - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - *work_p = work; - *new_abo_p = new_abo; - - return 0; - -pflip_cleanup: - amdgpu_crtc_cleanup_flip_ctx(work, new_abo); - return r; - -unpin: - amdgpu_flip_cleanup_unpin(work, new_abo); - return r; - -unreserve: - amdgpu_flip_cleanup_unreserve(work, new_abo); - return r; - -cleanup: - amdgpu_flip_work_cleanup(work); - return r; - -} - -void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo) -{ - unsigned long flags; - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - spin_lock_irqsave(&crtc->dev->event_lock, flags); amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; amdgpu_crtc->pflip_works = work; + + DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", + amdgpu_crtc->crtc_id, amdgpu_crtc, work); /* update crtc fb */ crtc->primary->fb = fb; spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - - DRM_DEBUG_DRIVER( - "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n", - amdgpu_crtc->crtc_id, amdgpu_crtc, work); - amdgpu_flip_work_func(&work->flip_work.work); -} - -int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct drm_modeset_acquire_ctx *ctx) -{ - struct amdgpu_bo *new_abo; - struct amdgpu_flip_work *work; - int r; - - r = amdgpu_crtc_prepare_flip(crtc, - fb, - event, - page_flip_flags, - target, - &work, - &new_abo); - if (r) - return r; - - amdgpu_crtc_submit_flip(crtc, fb, work, new_abo); - return 0; + +pflip_cleanup: + if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { + DRM_ERROR("failed to reserve new abo in error path\n"); + goto cleanup; + } +unpin: + if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { + DRM_ERROR("failed to unpin new abo in error path\n"); + } +unreserve: + amdgpu_bo_unreserve(new_abo); + +cleanup: + amdgpu_bo_unref(&work->old_abo); + dma_fence_put(work->excl); + for (i = 0; i < work->shared_count; ++i) + dma_fence_put(work->shared[i]); + kfree(work->shared); + kfree(work); + + return r; } int amdgpu_crtc_set_config(struct drm_mode_set *set, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index db8f8dda209c..dbd10618ec20 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -597,21 +597,6 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_pending_vblank_event *event, uint32_t page_flip_flags, uint32_t target, struct drm_modeset_acquire_ctx *ctx); -void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo); -int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags, - uint32_t target, - struct amdgpu_flip_work **work, - struct amdgpu_bo **new_abo); - -void amdgpu_crtc_submit_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct amdgpu_flip_work *work, - struct amdgpu_bo *new_abo); - extern const struct drm_mode_config_funcs amdgpu_mode_funcs; #endif From e345da82bd6bdfa8492f80b3ce4370acfd868d95 Mon Sep 17 00:00:00 2001 From: Mario Kleiner Date: Fri, 21 Apr 2017 17:05:08 +0200 Subject: [PATCH 100/144] drm/edid: Add 10 bpc quirk for LGD 764 panel in HP zBook 17 G2 The builtin eDP panel in the HP zBook 17 G2 supports 10 bpc, as advertised by the Laptops product specs and verified via injecting a fixed edid + photometer measurements, but edid reports unknown depth, so drivers fall back to 6 bpc. Add a quirk to get the full 10 bpc. Cc: stable@vger.kernel.org Signed-off-by: Mario Kleiner Acked-by: Harry Wentland Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1492787108-23959-1-git-send-email-mario.kleiner.de@gmail.com --- drivers/gpu/drm/drm_edid.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fad3d44e4642..2e55599816aa 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -80,6 +80,8 @@ #define EDID_QUIRK_FORCE_12BPC (1 << 9) /* Force 6bpc */ #define EDID_QUIRK_FORCE_6BPC (1 << 10) +/* Force 10bpc */ +#define EDID_QUIRK_FORCE_10BPC (1 << 11) struct detailed_mode_closure { struct drm_connector *connector; @@ -122,6 +124,9 @@ static const struct edid_quirk { { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | EDID_QUIRK_DETAILED_IN_CM }, + /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */ + { "LGD", 764, EDID_QUIRK_FORCE_10BPC }, + /* LG Philips LCD LP154W01-A5 */ { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE }, @@ -4244,6 +4249,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) if (quirks & EDID_QUIRK_FORCE_8BPC) connector->display_info.bpc = 8; + if (quirks & EDID_QUIRK_FORCE_10BPC) + connector->display_info.bpc = 10; + if (quirks & EDID_QUIRK_FORCE_12BPC) connector->display_info.bpc = 12; From 80112bffb0ed50257165f673aa73301a4458cd95 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Apr 2017 11:32:15 -0400 Subject: [PATCH 101/144] drm/amdgpu: update revision id settings for BR/ST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new RIDs. Acked-by: Christian König Acked-by: Alex Xie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 703bd55d6075..758d636a6f52 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1932,6 +1932,7 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev) case 0xca: case 0xce: case 0x88: + case 0xe6: /* B6 */ adev->gfx.config.max_cu_per_sh = 6; break; @@ -1964,17 +1965,28 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev) adev->gfx.config.max_backends_per_se = 1; switch (adev->pdev->revision) { + case 0x80: + case 0x81: case 0xc0: case 0xc1: case 0xc2: case 0xc4: case 0xc8: case 0xc9: + case 0xd6: + case 0xda: + case 0xe9: + case 0xea: adev->gfx.config.max_cu_per_sh = 3; break; + case 0x83: case 0xd0: case 0xd1: case 0xd2: + case 0xd4: + case 0xdb: + case 0xe1: + case 0xe2: default: adev->gfx.config.max_cu_per_sh = 2; break; From 42ce22439fdbbdb4d95d2979056ed5b075dd8403 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 1 May 2017 16:20:42 -0400 Subject: [PATCH 102/144] drm/amdgpu/gfx9: use actual gpu num se setting for ngg allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than using a hardcoded value. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 4073fd24dd13..ad2e08a943cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -39,7 +39,6 @@ #define GFX9_NUM_GFX_RINGS 1 #define GFX9_NUM_COMPUTE_RINGS 8 -#define GFX9_NUM_SE 4 #define RLCG_UCODE_LOADING_START_ADDRESS 0x2000 MODULE_FIRMWARE("amdgpu/vega10_ce.bin"); @@ -842,7 +841,7 @@ static int gfx_v9_0_ngg_create_buf(struct amdgpu_device *adev, } size_se = size_se ? size_se : default_size_se; - ngg_buf->size = size_se * GFX9_NUM_SE; + ngg_buf->size = size_se * adev->gfx.config.max_shader_engines; r = amdgpu_bo_create_kernel(adev, ngg_buf->size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &ngg_buf->bo, From 0274a9c55614a5c89dd04bca376dbe252f5ea334 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Apr 2017 17:30:27 -0400 Subject: [PATCH 103/144] drm/amdgpu/gfx9: fix typo in mpd init Using the wrong macro for soc15 register access. Reviewed-by: monk liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index ad2e08a943cd..178fe11bd7f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1989,12 +1989,12 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */ ring->wptr = 0; - mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR); + mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR); /* set the vmid for the queue */ mqd->cp_hqd_vmid = 0; - tmp = RREG32(mmCP_HQD_PERSISTENT_STATE); + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE); tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53); mqd->cp_hqd_persistent_state = tmp; From fca4ce697f304e5d1f739399d97cbfb2b918fa7f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Apr 2017 17:34:42 -0400 Subject: [PATCH 104/144] drm/amdgpu/gfx9: add additional MQD initialization Need to properly set the ROQ space setting. Reviewed-by: monk liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 178fe11bd7f9..5f2ae4cb510f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1998,6 +1998,11 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring) tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53); mqd->cp_hqd_persistent_state = tmp; + /* set MIN_IB_AVAIL_SIZE */ + tmp = RREG32_SOC15(GC, 0, mmCP_HQD_IB_CONTROL); + tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3); + mqd->cp_hqd_ib_control = tmp; + /* activate the queue */ mqd->cp_hqd_active = 1; From 43b9176faae1543d1a190db8eb098a8284d364f3 Mon Sep 17 00:00:00 2001 From: Shaoyun Liu Date: Fri, 28 Apr 2017 16:14:59 -0400 Subject: [PATCH 105/144] drm/amdgpu: Reserve 0-2 invalidation reg sets for none-amdgpu usages Firmware used reg set 2 for tlb invalidation. AMDGPU can start from reg set 3 to avoid the conflict. AMDKFD will use the reg set 0 or 1 when necesary. Signed-off-by: Shaoyun Liu Reviewws-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index e5d4dfeae3fe..dc1e1c1d6b24 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -386,7 +386,7 @@ static int gmc_v9_0_early_init(void *handle) static int gmc_v9_0_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 0 }; + unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 3, 3 }; unsigned i; for(i = 0; i < adev->num_rings; ++i) { From ef181f268e0e8d868f353b764799d96d6a8a2d86 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 2 May 2017 16:01:00 +0800 Subject: [PATCH 106/144] drm/amd/powerplay: refine code in vega10_smumgr.c 1. return error code instand of -1. 2. print msg info if send msg failed Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/smumgr/vega10_smumgr.c | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 5980f02f2ce9..05669cb5ab4e 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -85,7 +85,7 @@ static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr) uint32_t reg; if (!vega10_is_smc_ram_running(smumgr)) - return -1; + return -EINVAL; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90); @@ -109,7 +109,7 @@ int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, uint32_t reg; if (!vega10_is_smc_ram_running(smumgr)) - return -1; + return -EINVAL; reg = soc15_get_register_offset(MP1_HWID, 0, mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66); @@ -130,7 +130,7 @@ int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) uint32_t reg; if (!vega10_is_smc_ram_running(smumgr)) - return -1; + return -EINVAL; vega10_wait_for_response(smumgr); @@ -140,9 +140,8 @@ int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) vega10_send_msg_to_smc_without_waiting(smumgr, msg); - PP_ASSERT_WITH_CODE(vega10_wait_for_response(smumgr) == 1, - "Failed to send Message.", - return -1); + if (vega10_wait_for_response(smumgr) != 1) + pr_err("Failed to send Message: 0x%x\n.", msg); return 0; } @@ -160,7 +159,7 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, uint32_t reg; if (!vega10_is_smc_ram_running(smumgr)) - return -1; + return -EINVAL; vega10_wait_for_response(smumgr); @@ -174,9 +173,8 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, vega10_send_msg_to_smc_without_waiting(smumgr, msg); - PP_ASSERT_WITH_CODE(vega10_wait_for_response(smumgr) == 1, - "Failed to send Message.", - return -1); + if (vega10_wait_for_response(smumgr) != 1) + pr_err("Failed to send Message: 0x%x\n.", msg); return 0; } @@ -233,25 +231,25 @@ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, (struct vega10_smumgr *)(smumgr->backend); PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, - "Invalid SMU Table ID!", return -1;); + "Invalid SMU Table ID!", return -EINVAL); PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -1;); + "Invalid SMU Table version!", return -EINVAL); PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -1;); + "Invalid SMU Table Length!", return -EINVAL); PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SetDriverDramAddrHigh, priv->smu_tables.entry[table_id].table_addr_high) == 0, - "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -1;); + "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL); PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SetDriverDramAddrLow, priv->smu_tables.entry[table_id].table_addr_low) == 0, "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", - return -1;); + return -EINVAL); PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_TransferTableSmu2Dram, priv->smu_tables.entry[table_id].table_id) == 0, "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", - return -1;); + return -EINVAL); memcpy(table, priv->smu_tables.entry[table_id].table, priv->smu_tables.entry[table_id].size); @@ -271,11 +269,11 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, (struct vega10_smumgr *)(smumgr->backend); PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, - "Invalid SMU Table ID!", return -1;); + "Invalid SMU Table ID!", return -EINVAL); PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -1;); + "Invalid SMU Table version!", return -EINVAL); PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -1;); + "Invalid SMU Table Length!", return -EINVAL); memcpy(priv->smu_tables.entry[table_id].table, table, priv->smu_tables.entry[table_id].size); @@ -284,17 +282,17 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, PPSMC_MSG_SetDriverDramAddrHigh, priv->smu_tables.entry[table_id].table_addr_high) == 0, "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", - return -1;); + return -EINVAL;); PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SetDriverDramAddrLow, priv->smu_tables.entry[table_id].table_addr_low) == 0, "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", - return -1;); + return -EINVAL); PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_TransferTableDram2Smu, priv->smu_tables.entry[table_id].table_id) == 0, "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", - return -1;); + return -EINVAL); return 0; } @@ -303,7 +301,7 @@ int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table) { PP_ASSERT_WITH_CODE(avfs_table, "No access to SMC AVFS Table", - return -1); + return -EINVAL); return vega10_copy_table_from_smc(smumgr, avfs_table, AVFSTABLE); } @@ -312,7 +310,7 @@ int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table) { PP_ASSERT_WITH_CODE(avfs_table, "No access to SMC AVFS Table", - return -1); + return -EINVAL); return vega10_copy_table_to_smc(smumgr, avfs_table, AVFSTABLE); } @@ -330,13 +328,16 @@ int vega10_enable_smc_features(struct pp_smumgr *smumgr, int vega10_get_smc_features(struct pp_smumgr *smumgr, uint32_t *features_enabled) { + if (features_enabled == NULL) + return -EINVAL; + if (!vega10_send_msg_to_smc(smumgr, PPSMC_MSG_GetEnabledSmuFeatures)) { - if (!vega10_read_arg_from_smc(smumgr, features_enabled)) - return 0; + vega10_read_arg_from_smc(smumgr, features_enabled); + return 0; } - return -1; + return -EINVAL; } int vega10_set_tools_address(struct pp_smumgr *smumgr) @@ -363,15 +364,14 @@ static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(smumgr, PPSMC_MSG_GetDriverIfVersion), "Attempt to get SMC IF Version Number Failed!", - return -1); - PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(smumgr, - &smc_driver_if_version), - "Attempt to read SMC IF Version Number Failed!", - return -1); + return -EINVAL); + vega10_read_arg_from_smc(smumgr, &smc_driver_if_version); if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) { - pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n", - smc_driver_if_version, SMU9_DRIVER_IF_VERSION); + pr_err("Your firmware(0x%x) doesn't match \ + SMU9_DRIVER_IF_VERSION(0x%x). \ + Please update your firmware!\n", + smc_driver_if_version, SMU9_DRIVER_IF_VERSION); return -EINVAL; } @@ -421,7 +421,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) kfree(smumgr->backend); cgs_free_gpu_mem(smumgr->device, (cgs_handle_t)handle); - return -1); + return -EINVAL); priv->smu_tables.entry[PPTABLE].version = 0x01; priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t); @@ -449,7 +449,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle); cgs_free_gpu_mem(smumgr->device, (cgs_handle_t)handle); - return -1); + return -EINVAL); priv->smu_tables.entry[WMTABLE].version = 0x01; priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t); @@ -479,7 +479,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle); cgs_free_gpu_mem(smumgr->device, (cgs_handle_t)handle); - return -1); + return -EINVAL); priv->smu_tables.entry[AVFSTABLE].version = 0x01; priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t); @@ -537,7 +537,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr) (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle); cgs_free_gpu_mem(smumgr->device, (cgs_handle_t)handle); - return -1); + return -EINVAL); priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01; priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t); @@ -579,7 +579,7 @@ static int vega10_start_smu(struct pp_smumgr *smumgr) { PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(smumgr), "Failed to verify SMC interface!", - return -1); + return -EINVAL); return 0; } From 05ee3215110303b3ffacfb44fdae59a151799e89 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 2 May 2017 16:51:49 +0800 Subject: [PATCH 107/144] drm/amd/powerplay: set soc floor voltage on boot on vega10. Send the VBIOS bootup VDDC as a SOC floor voltage to SMU before populating the PPTABLE. After DPM is enabled, This floor voltage will be removed. This will prevent SMC from going to Vmin upon receiving PPTable causing a violation. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/ppatomfwctrl.c | 28 +++++++++++++++++++ .../drm/amd/powerplay/hwmgr/ppatomfwctrl.h | 15 ++++++++++ .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 25 +++++++++++++++++ .../drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 3 ++ 4 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c index de3d8f3f052b..56023114ad6f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c @@ -387,3 +387,31 @@ int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, return 0; } + +int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_bios_boot_up_values *boot_values) +{ + struct atom_firmware_info_v3_1 *info = NULL; + uint16_t ix; + + ix = GetIndexIntoMasterDataTable(firmwareinfo); + info = (struct atom_firmware_info_v3_1 *) + cgs_atom_get_data_table(hwmgr->device, + ix, NULL, NULL, NULL); + + if (!info) { + pr_info("Error retrieving BIOS firmwareinfo!"); + return -EINVAL; + } + + boot_values->ulRevision = info->firmware_revision; + boot_values->ulGfxClk = info->bootup_sclk_in10khz; + boot_values->ulUClk = info->bootup_mclk_in10khz; + boot_values->ulSocClk = 0; + boot_values->usVddc = info->bootup_vddc_mv; + boot_values->usVddci = info->bootup_vddci_mv; + boot_values->usMvddc = info->bootup_mvddc_mv; + boot_values->usVddGfx = info->bootup_vddgfx_mv; + + return 0; +} \ No newline at end of file diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h index be1579e87caf..43a6711e3c06 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h @@ -119,6 +119,18 @@ struct pp_atomfwctrl_gpio_parameters { uint8_t ucFwCtfGpio; uint8_t ucFwCtfPolarity; }; + +struct pp_atomfwctrl_bios_boot_up_values { + uint32_t ulRevision; + uint32_t ulGfxClk; + uint32_t ulUClk; + uint32_t ulSocClk; + uint16_t usVddc; + uint16_t usVddci; + uint16_t usMvddc; + uint16_t usVddGfx; +}; + int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, uint32_t clock_type, uint32_t clock_value, struct pp_atomfwctrl_clock_dividers_soc15 *dividers); @@ -136,5 +148,8 @@ int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, struct pp_atomfwctrl_gpio_parameters *param); +int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_bios_boot_up_values *boot_values); + #endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 68eae529df50..dbc1c03cb40a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -2298,6 +2298,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) (struct phm_ppt_v2_information *)(hwmgr->pptable); PPTable_t *pp_table = &(data->smc_state_table.pp_table); struct pp_atomfwctrl_voltage_table voltage_table; + struct pp_atomfwctrl_bios_boot_up_values boot_up_values; result = vega10_setup_default_dpm_tables(hwmgr); PP_ASSERT_WITH_CODE(!result, @@ -2369,6 +2370,24 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) return result); } + result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); + if (!result) { + data->vbios_boot_state.vddc = boot_up_values.usVddc; + data->vbios_boot_state.vddci = boot_up_values.usVddci; + data->vbios_boot_state.mvddc = boot_up_values.usMvddc; + data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; + data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; + data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; + if (0 != boot_up_values.usVddc) { + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFloorSocVoltage, + (boot_up_values.usVddc * 4)); + data->vbios_boot_state.bsoc_vddc_lock = true; + } else { + data->vbios_boot_state.bsoc_vddc_lock = false; + } + } + result = vega10_populate_avfs_parameters(hwmgr); PP_ASSERT_WITH_CODE(!result, "Failed to initialize AVFS Parameters!", @@ -2590,6 +2609,12 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) data->smu_features[GNLD_LED_DISPLAY].enabled = true; } + if (data->vbios_boot_state.bsoc_vddc_lock) { + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFloorSocVoltage, 0); + data->vbios_boot_state.bsoc_vddc_lock = false; + } + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Falcon_QuickTransition)) { if (data->smu_features[GNLD_ACDC].supported) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h index 83c67b9262ff..1912e086c0cf 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h @@ -177,8 +177,11 @@ struct vega10_dpmlevel_enable_mask { }; struct vega10_vbios_boot_state { + bool bsoc_vddc_lock; uint16_t vddc; uint16_t vddci; + uint16_t mvddc; + uint16_t vdd_gfx; uint32_t gfx_clock; uint32_t mem_clock; uint32_t soc_clock; From 56a2f08c418ec01d46851683ee0463a2d8a2504d Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 2 May 2017 17:11:29 +0800 Subject: [PATCH 108/144] drm/amd/powerplay: set fan target temperature by msg on vega10. SMU not support FanTargetTemperature in pptable, so send msg instand. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index 7062ec8cc4ac..5da88ba4a53c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -561,6 +561,11 @@ int tf_vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, advanceFanControlParameters.ulMinFanSCLKAcousticLimit); table->FanTargetTemperature = hwmgr->thermal_controller. advanceFanControlParameters.usTMax; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFanTemperatureTarget, + (uint32_t)table->FanTargetTemperature); + table->FanPwmMin = hwmgr->thermal_controller. advanceFanControlParameters.usPWMMin * 255 / 100; table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller. From b7a1f0e3cca40044952901e659939133e7cd1efe Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Tue, 2 May 2017 14:30:39 +0800 Subject: [PATCH 109/144] drm/amd/powerplay: Allow duplicate enteries in pptable. This is a valid configuration. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index dbc1c03cb40a..8baa890579d8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -1137,7 +1137,7 @@ static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr, int i; for (i = 0; i < dep_table->count; i++) { - if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value != + if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <= dep_table->entries[i].clk) { dpm_table->dpm_levels[dpm_table->count].value = dep_table->entries[i].clk; @@ -1274,7 +1274,7 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) dpm_table = &(data->dpm_table.eclk_table); for (i = 0; i < dep_mm_table->count; i++) { if (i == 0 || dpm_table->dpm_levels - [dpm_table->count - 1].value != + [dpm_table->count - 1].value <= dep_mm_table->entries[i].eclk) { dpm_table->dpm_levels[dpm_table->count].value = dep_mm_table->entries[i].eclk; @@ -1290,7 +1290,7 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) dpm_table = &(data->dpm_table.vclk_table); for (i = 0; i < dep_mm_table->count; i++) { if (i == 0 || dpm_table->dpm_levels - [dpm_table->count - 1].value != + [dpm_table->count - 1].value <= dep_mm_table->entries[i].vclk) { dpm_table->dpm_levels[dpm_table->count].value = dep_mm_table->entries[i].vclk; @@ -1304,7 +1304,7 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) dpm_table = &(data->dpm_table.dclk_table); for (i = 0; i < dep_mm_table->count; i++) { if (i == 0 || dpm_table->dpm_levels - [dpm_table->count - 1].value != + [dpm_table->count - 1].value <= dep_mm_table->entries[i].dclk) { dpm_table->dpm_levels[dpm_table->count].value = dep_mm_table->entries[i].dclk; From 0dca7047512cb31e7a08a677a69fa7d47959dbf8 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 28 Apr 2017 13:49:50 +0800 Subject: [PATCH 110/144] drm/amd/powerplay: correct LoadLineResistance value in pptable. this value is used by avfs to adjust inversion voltage. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c | 4 ++-- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c index 692f752fbb27..3f72268e99bb 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c @@ -48,8 +48,8 @@ void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) table->Tliquid1Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid1); table->Tliquid2Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid2); table->TplxLimit = cpu_to_le16(tdp_table->usTemperatureLimitPlx); - table->LoadLineResistance = cpu_to_le16( - hwmgr->platform_descriptor.LoadLineSlope); + table->LoadLineResistance = + hwmgr->platform_descriptor.LoadLineSlope * 256; table->FitLimit = 0; /* Not used for Vega10 */ table->Liquid1_I2C_address = tdp_table->ucLiquid1_I2C_address; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c index 8b55ae01132d..00e95511e19a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c @@ -407,7 +407,7 @@ static int get_tdp_table( tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address; tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL; tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA; - hwmgr->platform_descriptor.LoadLineSlope = power_tune_table->usLoadLineResistance; + hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(power_tune_table->usLoadLineResistance); } else { power_tune_table_v2 = (ATOM_Vega10_PowerTune_Table_V2 *)table; tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v2->usSocketPowerLimit); @@ -453,7 +453,7 @@ static int get_tdp_table( tdp_table->ucPlx_I2C_LineSDA = sda; hwmgr->platform_descriptor.LoadLineSlope = - power_tune_table_v2->usLoadLineResistance; + le16_to_cpu(power_tune_table_v2->usLoadLineResistance); } *info_tdp_table = tdp_table; From 1d1a2cd58f05da1167c04394292aef9fbcf29bff Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Thu, 27 Apr 2017 17:14:57 +0800 Subject: [PATCH 111/144] drm/amdgpu:PTE flag should be 64 bit width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit otherwise we'll lost the high 32 bit for pte, which lead to incorrect MTYPE for vega10. Signed-off-by: Monk Liu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7bb1bf76319a..5db0230e45c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -765,7 +765,7 @@ int amdgpu_ttm_recover_gart(struct amdgpu_device *adev) { struct amdgpu_ttm_tt *gtt, *tmp; struct ttm_mem_reg bo_mem; - uint32_t flags; + uint64_t flags; int r; bo_mem.mem_type = TTM_PL_TT; From 236763d340d6190c56554caee61c2bd5cfdf5217 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Mon, 1 May 2017 16:15:31 +0800 Subject: [PATCH 112/144] drm/amdgpu:fix waiting on dirty fence if bo->shadow is NULL (race issue:BO shadow was just released and gpu-reset kick in but BO hasn't yet) recover_vram_from_shadow won't set @next, so the following "fence=next" will wrongly use a fence pointer which may already dirty. fixing it by set next to NULL prior to recover_vram_from_shadow Signed-off-by: Monk Liu Reviewed-by: Chunming Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 3c1754df4c40..367811cd0763 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2522,6 +2522,7 @@ int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, bool voluntary) ring = adev->mman.buffer_funcs_ring; mutex_lock(&adev->shadow_list_lock); list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) { + next = NULL; amdgpu_recover_vram_from_shadow(adev, ring, bo, &next); if (fence) { r = dma_fence_wait(fence, false); @@ -2668,6 +2669,7 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev) DRM_INFO("recover vram bo from shadow\n"); mutex_lock(&adev->shadow_list_lock); list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) { + next = NULL; amdgpu_recover_vram_from_shadow(adev, ring, bo, &next); if (fence) { r = dma_fence_wait(fence, false); From b4a33e325c58579a2017d3b1c1a1227f78ae52cd Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 3 May 2017 12:48:52 +0800 Subject: [PATCH 113/144] drm/amd/powerplay: clean up code in vega10_smumgr.c 1. fix typo in print message info. 2. fix block comments's coding style. Signed-off-by: Rex Zhu Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/smumgr/vega10_smumgr.c | 101 ++++++++---------- 1 file changed, 45 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c index 05669cb5ab4e..115f0e4b1603 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c @@ -74,12 +74,12 @@ static bool vega10_is_smc_ram_running(struct pp_smumgr *smumgr) return false; } -/** -* Check if SMC has responded to previous message. -* -* @param smumgr the address of the powerplay hardware manager. -* @return TRUE SMC has responded, FALSE otherwise. -*/ +/* + * Check if SMC has responded to previous message. + * + * @param smumgr the address of the powerplay hardware manager. + * @return TRUE SMC has responded, FALSE otherwise. + */ static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr) { uint32_t reg; @@ -96,13 +96,12 @@ static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr) return cgs_read_register(smumgr->device, reg); } -/** -* Send a message to the SMC, and do not wait for its response. -* -* @param smumgr the address of the powerplay hardware manager. -* @param msg the message to send. -* @return Always return 0. -*/ +/* + * Send a message to the SMC, and do not wait for its response. + * @param smumgr the address of the powerplay hardware manager. + * @param msg the message to send. + * @return Always return 0. + */ int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, uint16_t msg) { @@ -118,13 +117,12 @@ int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, return 0; } -/** -* Send a message to the SMC, and wait for its response. -* -* @param smumgr the address of the powerplay hardware manager. -* @param msg the message to send. -* @return The response that came from the SMC. -*/ +/* + * Send a message to the SMC, and wait for its response. + * @param smumgr the address of the powerplay hardware manager. + * @param msg the message to send. + * @return Always return 0. + */ int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) { uint32_t reg; @@ -141,17 +139,17 @@ int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) vega10_send_msg_to_smc_without_waiting(smumgr, msg); if (vega10_wait_for_response(smumgr) != 1) - pr_err("Failed to send Message: 0x%x\n.", msg); + pr_err("Failed to send message: 0x%x\n", msg); return 0; } -/** +/* * Send a message to the SMC with parameter * @param smumgr: the address of the powerplay hardware manager. * @param msg: the message to send. * @param parameter: the parameter to send - * @return The response that came from the SMC. + * @return Always return 0. */ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter) @@ -174,20 +172,19 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, vega10_send_msg_to_smc_without_waiting(smumgr, msg); if (vega10_wait_for_response(smumgr) != 1) - pr_err("Failed to send Message: 0x%x\n.", msg); + pr_err("Failed to send message: 0x%x\n", msg); return 0; } -/** -* Send a message to the SMC with parameter, do not wait for response -* -* @param smumgr: the address of the powerplay hardware manager. -* @param msg: the message to send. -* @param parameter: the parameter to send -* @return The response that came from the SMC. -*/ +/* + * Send a message to the SMC with parameter, do not wait for response + * @param smumgr: the address of the powerplay hardware manager. + * @param msg: the message to send. + * @param parameter: the parameter to send + * @return The response that came from the SMC. + */ int vega10_send_msg_to_smc_with_parameter_without_waiting( struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter) { @@ -200,13 +197,12 @@ int vega10_send_msg_to_smc_with_parameter_without_waiting( return vega10_send_msg_to_smc_without_waiting(smumgr, msg); } -/** -* Retrieve an argument from SMC. -* -* @param smumgr the address of the powerplay hardware manager. -* @param arg pointer to store the argument from SMC. -* @return Always return 0. -*/ +/* + * Retrieve an argument from SMC. + * @param smumgr the address of the powerplay hardware manager. + * @param arg pointer to store the argument from SMC. + * @return Always return 0. + */ int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg) { uint32_t reg; @@ -219,11 +215,11 @@ int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg) return 0; } -/** -* Copy table from SMC into driver FB -* @param smumgr the address of the SMC manager -* @param table_id the driver's table ID to copy from -*/ +/* + * Copy table from SMC into driver FB + * @param smumgr the address of the SMC manager + * @param table_id the driver's table ID to copy from + */ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, uint8_t *table, int16_t table_id) { @@ -257,11 +253,11 @@ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr, return 0; } -/** -* Copy table from Driver FB into SMC -* @param smumgr the address of the SMC manager -* @param table_id the table to copy from -*/ +/* + * Copy table from Driver FB into SMC + * @param smumgr the address of the SMC manager + * @param table_id the table to copy from + */ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr, uint8_t *table, int16_t table_id) { @@ -378,13 +374,6 @@ static int vega10_verify_smc_interface(struct pp_smumgr *smumgr) return 0; } -/** -* Write a 32bit value to the SMC SRAM space. -* ALL PARAMETERS ARE IN HOST BYTE ORDER. -* @param smumgr the address of the powerplay hardware manager. -* @param smc_addr the address in the SMC RAM to access. -* @param value to write to the SMC SRAM. -*/ static int vega10_smu_init(struct pp_smumgr *smumgr) { struct vega10_smumgr *priv; From 327fce0c0d265b14be575bfe21a98c7c0dd932d8 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 4 May 2017 11:07:02 +0800 Subject: [PATCH 114/144] drm/amd/powerplay: disable engine spread spectrum feature on Vega10. Vega10 atomfirmware do not have ASIC_InternalSS_Info table so disable this feature by default in driver. Signed-off-by: Rex Zhu Reviewed-by: Ken Wang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 8baa890579d8..e24e54c294bd 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -1535,7 +1535,11 @@ static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr, current_gfxclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult); /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */ - current_gfxclk_level->SsOn = dividers.ucPll_ss_enable; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) + current_gfxclk_level->SsOn = dividers.ucPll_ss_enable; + else + current_gfxclk_level->SsOn = 0; current_gfxclk_level->SsFbMult = cpu_to_le32(dividers.ulPll_ss_fbsmult); current_gfxclk_level->SsSlewFrac = From f47b77b4e4baeb7922b5652ae7040d4d5de684a7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 May 2017 15:49:36 -0400 Subject: [PATCH 115/144] drm/amdgpu/gfx: drop max_gs_waves_per_vgt We already have this info: max_gs_threads. Drop the duplicate. Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c9f935710d40..8033001b913a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -969,7 +969,6 @@ struct amdgpu_gfx_config { unsigned num_rbs; unsigned gs_vgt_table_depth; unsigned gs_prim_buffer_depth; - unsigned max_gs_waves_per_vgt; uint32_t tile_mode_array[32]; uint32_t macrotile_mode_array[16]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 4f2b6679f72f..1a7830a291d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -560,7 +560,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file dev_info.num_tcc_blocks = adev->gfx.config.max_texture_channel_caches; dev_info.gs_vgt_table_depth = adev->gfx.config.gs_vgt_table_depth; dev_info.gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth; - dev_info.max_gs_waves_per_vgt = adev->gfx.config.max_gs_waves_per_vgt; + dev_info.max_gs_waves_per_vgt = adev->gfx.config.max_gs_threads; return copy_to_user(out, &dev_info, min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 5f2ae4cb510f..484ead2a20a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -786,7 +786,6 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0; adev->gfx.config.gs_vgt_table_depth = 32; adev->gfx.config.gs_prim_buffer_depth = 1792; - adev->gfx.config.max_gs_waves_per_vgt = 32; gb_addr_config = VEGA10_GB_ADDR_CONFIG_GOLDEN; break; default: From ad7d0ff3e79a100a24b66e8908a45402c20c3685 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 2 May 2017 16:15:06 -0400 Subject: [PATCH 116/144] drm/amdgpu/gfx9: derive tile pipes from golden settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rather than hardcoding it. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 484ead2a20a4..741b56f996c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -771,7 +771,6 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_VEGA10: adev->gfx.config.max_shader_engines = 4; - adev->gfx.config.max_tile_pipes = 8; //?? adev->gfx.config.max_cu_per_sh = 16; adev->gfx.config.max_sh_per_se = 1; adev->gfx.config.max_backends_per_se = 4; @@ -800,6 +799,10 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) adev->gfx.config.gb_addr_config, GB_ADDR_CONFIG, NUM_PIPES); + + adev->gfx.config.max_tile_pipes = + adev->gfx.config.gb_addr_config_fields.num_pipes; + adev->gfx.config.gb_addr_config_fields.num_banks = 1 << REG_GET_FIELD( adev->gfx.config.gb_addr_config, From af8baf1518d8b3d086ac6d11d8f6acd57e9cab99 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Wed, 3 May 2017 23:49:18 -0700 Subject: [PATCH 117/144] drm/amdgpu: Use less generic enum definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alpha:allmodconfig fails to build as follows. drivers/gpu/drm/amd/amdgpu/amdgpu.h:1006:2: error: expected identifier before '(' token drivers/gpu/drm/amd/amdgpu/amdgpu.h:1011:28: error: 'NGG_BUF_MAX' undeclared here The problem is not really the enum definition of NGG_BUF_MAX but PARAM, which happens to be defined differently for alpha and a couple of other architectures. Use less generic defines for NGG enums to solve the problem. Fixes: bce23e00f3369 ("drm/amdgpu: add NGG parameters") Cc: Christian König Cc: Alex Deucher Signed-off-by: Guenter Roeck Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 +++---- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 16 +++++++------- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 28 ++++++++++++------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 8033001b913a..86923c57908b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1004,10 +1004,10 @@ struct amdgpu_ngg_buf { }; enum { - PRIM = 0, - POS, - CNTL, - PARAM, + NGG_PRIM = 0, + NGG_POS, + NGG_CNTL, + NGG_PARAM, NGG_BUF_MAX }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 1a7830a291d6..96c341670782 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -545,14 +545,14 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file adev->gfx.config.double_offchip_lds_buf; if (amdgpu_ngg) { - dev_info.prim_buf_gpu_addr = adev->gfx.ngg.buf[PRIM].gpu_addr; - dev_info.prim_buf_size = adev->gfx.ngg.buf[PRIM].size; - dev_info.pos_buf_gpu_addr = adev->gfx.ngg.buf[POS].gpu_addr; - dev_info.pos_buf_size = adev->gfx.ngg.buf[POS].size; - dev_info.cntl_sb_buf_gpu_addr = adev->gfx.ngg.buf[CNTL].gpu_addr; - dev_info.cntl_sb_buf_size = adev->gfx.ngg.buf[CNTL].size; - dev_info.param_buf_gpu_addr = adev->gfx.ngg.buf[PARAM].gpu_addr; - dev_info.param_buf_size = adev->gfx.ngg.buf[PARAM].size; + dev_info.prim_buf_gpu_addr = adev->gfx.ngg.buf[NGG_PRIM].gpu_addr; + dev_info.prim_buf_size = adev->gfx.ngg.buf[NGG_PRIM].size; + dev_info.pos_buf_gpu_addr = adev->gfx.ngg.buf[NGG_POS].gpu_addr; + dev_info.pos_buf_size = adev->gfx.ngg.buf[NGG_POS].size; + dev_info.cntl_sb_buf_gpu_addr = adev->gfx.ngg.buf[NGG_CNTL].gpu_addr; + dev_info.cntl_sb_buf_size = adev->gfx.ngg.buf[NGG_CNTL].size; + dev_info.param_buf_gpu_addr = adev->gfx.ngg.buf[NGG_PARAM].gpu_addr; + dev_info.param_buf_size = adev->gfx.ngg.buf[NGG_PARAM].size; } dev_info.wave_front_size = adev->gfx.cu_info.wave_front_size; dev_info.num_shader_visible_vgprs = adev->gfx.config.max_gprs; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 741b56f996c4..0c16b7563b73 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -890,7 +890,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev) adev->gfx.ngg.gds_reserve_addr += adev->gds.mem.gfx_partition_size; /* Primitive Buffer */ - r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[PRIM], + r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_PRIM], amdgpu_prim_buf_per_se, 64 * 1024); if (r) { @@ -899,7 +899,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev) } /* Position Buffer */ - r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[POS], + r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_POS], amdgpu_pos_buf_per_se, 256 * 1024); if (r) { @@ -908,7 +908,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev) } /* Control Sideband */ - r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[CNTL], + r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_CNTL], amdgpu_cntl_sb_buf_per_se, 256); if (r) { @@ -920,7 +920,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev) if (amdgpu_param_buf_per_se <= 0) goto out; - r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[PARAM], + r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_PARAM], amdgpu_param_buf_per_se, 512 * 1024); if (r) { @@ -949,45 +949,45 @@ static int gfx_v9_0_ngg_en(struct amdgpu_device *adev) /* Program buffer size */ data = 0; - size = adev->gfx.ngg.buf[PRIM].size / 256; + size = adev->gfx.ngg.buf[NGG_PRIM].size / 256; data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, INDEX_BUF_SIZE, size); - size = adev->gfx.ngg.buf[POS].size / 256; + size = adev->gfx.ngg.buf[NGG_POS].size / 256; data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, POS_BUF_SIZE, size); WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_1, data); data = 0; - size = adev->gfx.ngg.buf[CNTL].size / 256; + size = adev->gfx.ngg.buf[NGG_CNTL].size / 256; data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, CNTL_SB_BUF_SIZE, size); - size = adev->gfx.ngg.buf[PARAM].size / 1024; + size = adev->gfx.ngg.buf[NGG_PARAM].size / 1024; data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, PARAM_BUF_SIZE, size); WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_2, data); /* Program buffer base address */ - base = lower_32_bits(adev->gfx.ngg.buf[PRIM].gpu_addr); + base = lower_32_bits(adev->gfx.ngg.buf[NGG_PRIM].gpu_addr); data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE, BASE, base); WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE, data); - base = upper_32_bits(adev->gfx.ngg.buf[PRIM].gpu_addr); + base = upper_32_bits(adev->gfx.ngg.buf[NGG_PRIM].gpu_addr); data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE_HI, BASE_HI, base); WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE_HI, data); - base = lower_32_bits(adev->gfx.ngg.buf[POS].gpu_addr); + base = lower_32_bits(adev->gfx.ngg.buf[NGG_POS].gpu_addr); data = REG_SET_FIELD(0, WD_POS_BUF_BASE, BASE, base); WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE, data); - base = upper_32_bits(adev->gfx.ngg.buf[POS].gpu_addr); + base = upper_32_bits(adev->gfx.ngg.buf[NGG_POS].gpu_addr); data = REG_SET_FIELD(0, WD_POS_BUF_BASE_HI, BASE_HI, base); WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE_HI, data); - base = lower_32_bits(adev->gfx.ngg.buf[CNTL].gpu_addr); + base = lower_32_bits(adev->gfx.ngg.buf[NGG_CNTL].gpu_addr); data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE, BASE, base); WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE, data); - base = upper_32_bits(adev->gfx.ngg.buf[CNTL].gpu_addr); + base = upper_32_bits(adev->gfx.ngg.buf[NGG_CNTL].gpu_addr); data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE_HI, BASE_HI, base); WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE_HI, data); From 652bd0c3441d861402bf7347088c846b6799c5b8 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 3 May 2017 15:38:58 +0800 Subject: [PATCH 118/144] drm/amd/powerplay: delete dead code in powerplay. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 28 ------------------- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 -- 2 files changed, 30 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 4ad84530c88a..b3d42858f68b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4522,32 +4522,6 @@ static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type return 0; } -static int smu7_request_firmware(struct pp_hwmgr *hwmgr) -{ - int ret; - struct cgs_firmware_info info = {0}; - - ret = cgs_get_firmware_info(hwmgr->device, - smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), - &info); - if (ret || !info.kptr) - return -EINVAL; - - return 0; -} - -static int smu7_release_firmware(struct pp_hwmgr *hwmgr) -{ - int ret; - - ret = cgs_rel_firmware(hwmgr->device, - smu7_convert_fw_type_to_cgs(UCODE_ID_SMU)); - if (ret) - return -EINVAL; - - return 0; -} - static void smu7_find_min_clock_masks(struct pp_hwmgr *hwmgr, uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t min_sclk, uint32_t min_mclk) @@ -4691,8 +4665,6 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .get_clock_by_type = smu7_get_clock_by_type, .read_sensor = smu7_read_sensor, .dynamic_state_management_disable = smu7_disable_dpm_tasks, - .request_firmware = smu7_request_firmware, - .release_firmware = smu7_release_firmware, .set_power_profile_state = smu7_set_power_profile_state, .avfs_control = smu7_avfs_control, .disable_smc_firmware_ctf = smu7_thermal_disable_alert, diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 98d38c31f6a6..e4574c215c38 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -368,8 +368,6 @@ struct pp_hwmgr_func { int (*get_mclk_od)(struct pp_hwmgr *hwmgr); int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value, int *size); - int (*request_firmware)(struct pp_hwmgr *hwmgr); - int (*release_firmware)(struct pp_hwmgr *hwmgr); int (*set_power_profile_state)(struct pp_hwmgr *hwmgr, struct amd_pp_profile *request); int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); From 5784d5cca66b362e3588c189eada757cf664ae6c Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 4 May 2017 14:51:31 +0800 Subject: [PATCH 119/144] drm/amd/powerplay: Setup sw CTF to allow graceful exit when temperature exceeds maximum. cherry-pick from amd windows driver. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/vega10_thermal.c | 73 ++++++++++++------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index 5da88ba4a53c..d5f53d04fa08 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -381,14 +381,10 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) temp = cgs_read_register(hwmgr->device, reg); - temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> - CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; + temp = (temp & CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP_MASK) >> + CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP__SHIFT; - /* Bit 9 means the reading is lower than the lowest usable value. */ - if (temp & 0x200) - temp = VEGA10_THERMAL_MAXIMUM_TEMP_READING; - else - temp = temp & 0x1ff; + temp = temp & 0x1ff; temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -424,23 +420,28 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, mmTHM_THERMAL_INT_CTRL_BASE_IDX, mmTHM_THERMAL_INT_CTRL); val = cgs_read_register(hwmgr->device, reg); - val &= ~(THM_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK); - val |= (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) << - THM_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT; - val &= ~(THM_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK); - val |= (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) << - THM_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT; + + val &= (~THM_THERMAL_INT_CTRL__MAX_IH_CREDIT_MASK); + val |= (5 << THM_THERMAL_INT_CTRL__MAX_IH_CREDIT__SHIFT); + + val &= (~THM_THERMAL_INT_CTRL__THERM_IH_HW_ENA_MASK); + val |= (1 << THM_THERMAL_INT_CTRL__THERM_IH_HW_ENA__SHIFT); + + val &= (~THM_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK); + val |= ((high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + << THM_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT); + + val &= (~THM_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK); + val |= ((low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + << THM_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT); + + val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + cgs_write_register(hwmgr->device, reg, val); reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_TCON_HTC_BASE_IDX, mmTHM_TCON_HTC); - val = cgs_read_register(hwmgr->device, reg); - val &= ~(THM_TCON_HTC__HTC_TMP_LMT_MASK); - val |= (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) << - THM_TCON_HTC__HTC_TMP_LMT__SHIFT; - cgs_write_register(hwmgr->device, reg, val); - return 0; } @@ -482,18 +483,28 @@ static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr) static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); + uint32_t val = 0; + uint32_t reg; if (data->smu_features[GNLD_FW_CTF].supported) { if (data->smu_features[GNLD_FW_CTF].enabled) printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n"); + + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + true, + data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), + "Attempt to Enable FW CTF feature Failed!", + return -1); + data->smu_features[GNLD_FW_CTF].enabled = true; } - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, - true, - data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), - "Attempt to Enable FW CTF feature Failed!", - return -1); - data->smu_features[GNLD_FW_CTF].enabled = true; + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); + + reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA); + cgs_write_register(hwmgr->device, reg, val); + return 0; } @@ -504,18 +515,24 @@ static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) { struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); + uint32_t reg; if (data->smu_features[GNLD_FW_CTF].supported) { if (!data->smu_features[GNLD_FW_CTF].enabled) printk("[Thermal_EnableAlert] FW CTF Already disabled!\n"); - } - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, + + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr, false, data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), "Attempt to disable FW CTF feature Failed!", return -1); - data->smu_features[GNLD_FW_CTF].enabled = false; + data->smu_features[GNLD_FW_CTF].enabled = false; + } + + reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA); + cgs_write_register(hwmgr->device, reg, 0); + return 0; } From 7b52db39a4c27c0020ff953a4bb0aa8bbe55e4a2 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 4 May 2017 13:32:01 +0800 Subject: [PATCH 120/144] drm/amd/powerplay: fix bug sclk/mclk level can't be set on vega10. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 67 ++++++++++--------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index e24e54c294bd..85a6c12ad1d4 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -4189,55 +4189,56 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, switch (type) { case PP_SCLK: - if (data->registry_data.sclk_dpm_key_disabled) - break; - for (i = 0; i < 32; i++) { if (mask & (1 << i)) break; } + data->smc_state_table.gfx_boot_level = i; - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, - PPSMC_MSG_SetSoftMinGfxclkByIndex, - i), - "Failed to set soft min sclk index!", - return -1); + for (i = 31; i >= 0; i--) { + if (mask & (1 << i)) + break; + } + data->smc_state_table.gfx_max_level = i; + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to lowest!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -EINVAL); break; case PP_MCLK: - if (data->registry_data.mclk_dpm_key_disabled) - break; - for (i = 0; i < 32; i++) { if (mask & (1 << i)) break; } - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, - PPSMC_MSG_SetSoftMinUclkByIndex, - i), - "Failed to set soft min mclk index!", - return -1); + for (i = 0; i < 32; i++) { + if (mask & (1 << i)) + break; + } + data->smc_state_table.mem_boot_level = i; + + for (i = 31; i >= 0; i--) { + if (mask & (1 << i)) + break; + } + data->smc_state_table.mem_max_level = i; + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to lowest!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -EINVAL); + break; case PP_PCIE: - if (data->registry_data.pcie_dpm_key_disabled) - break; - - for (i = 0; i < 32; i++) { - if (mask & (1 << i)) - break; - } - - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter( - hwmgr->smumgr, - PPSMC_MSG_SetMinLinkDpmByIndex, - i), - "Failed to set min pcie index!", - return -1); - break; default: break; } From db2c2a9798d266fd1d7c950b3937793b05533bf4 Mon Sep 17 00:00:00 2001 From: Pixel Ding Date: Tue, 25 Apr 2017 16:47:42 +0800 Subject: [PATCH 121/144] drm/amdgpu: fix mutex list null pointer reference Fix NULL pointer reference. Signed-off-by: Pixel Ding Signed-off-by: Xiangliang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 367811cd0763..43ca16b6eee2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2065,7 +2065,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev) DRM_INFO("amdgpu: finishing device.\n"); adev->shutdown = true; - drm_crtc_force_disable_all(adev->ddev); + if (adev->mode_info.mode_config_initialized) + drm_crtc_force_disable_all(adev->ddev); /* evict vram memory */ amdgpu_bo_evict_vram(adev); amdgpu_ib_pool_fini(adev); From 634b6a8a064576797120b74facf95ba79283b5d5 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Thu, 27 Apr 2017 15:10:08 +0100 Subject: [PATCH 122/144] drm/radeon: only warn once in radeon_ttm_bo_destroy if va list not empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Encountered a dozen of exact same backtraces when mesa's pb_cache_release_all_buffers is called after that a gpu reset failed. v2: Remove superfluous error message added in v1. bug: https://bugs.freedesktop.org/show_bug.cgi?id=96271 Signed-off-by: Julien Isorce Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index bec2ec056de4..8b722297a05c 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -81,7 +81,7 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) list_del_init(&bo->list); mutex_unlock(&bo->rdev->gem.mutex); radeon_bo_clear_surface_reg(bo); - WARN_ON(!list_empty(&bo->va)); + WARN_ON_ONCE(!list_empty(&bo->va)); drm_gem_object_release(&bo->gem_base); kfree(bo); } From de70c6357be23261c18fcccfd2ad148512fedd28 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 5 May 2017 10:21:36 -0400 Subject: [PATCH 123/144] drm/amdgpu/atomfirmware: add function to update engine hang status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the scratch reg for when the engine is hung. Reviewed-by: Chunming Zhou Acked-by: Harry Wentland Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index d735cd1807b3..4bdda56fccee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -88,6 +88,19 @@ void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev) WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]); } +void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev, + bool hung) +{ + u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3); + + if (hung) + tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; + else + tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; + + WREG32(adev->bios_scratch_reg_offset + 3, tmp); +} + int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) { struct atom_context *ctx = adev->mode_info.atom_context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h index d0c4dcd7fa96..a2c3ebe22c71 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h @@ -28,6 +28,8 @@ bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev) void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev); void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev); void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev); +void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev, + bool hung); int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev); #endif From bfc181af3b3978e4b9619e3b46b1c4f7e5adb43a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 5 May 2017 10:26:12 -0400 Subject: [PATCH 124/144] drm/amdgpu/soc15: use atomfirmware for setting bios scratch for reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to use the atomfirmware interface rather than atombios since soc15 is atomfirmware based. Reviewed-by: Chunming Zhou Acked-by: Harry Wentland Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 02baa1d7bc23..6b55d451ae7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -25,7 +25,7 @@ #include #include "drmP.h" #include "amdgpu.h" -#include "amdgpu_atombios.h" +#include "amdgpu_atomfirmware.h" #include "amdgpu_ih.h" #include "amdgpu_uvd.h" #include "amdgpu_vce.h" @@ -405,11 +405,11 @@ static void soc15_gpu_pci_config_reset(struct amdgpu_device *adev) static int soc15_asic_reset(struct amdgpu_device *adev) { - amdgpu_atombios_scratch_regs_engine_hung(adev, true); + amdgpu_atomfirmware_scratch_regs_engine_hung(adev, true); soc15_gpu_pci_config_reset(adev); - amdgpu_atombios_scratch_regs_engine_hung(adev, false); + amdgpu_atomfirmware_scratch_regs_engine_hung(adev, false); return 0; } From 09062ae1bb1c4a84e382560ff5059803d263a6c8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 9 May 2017 13:08:39 -0400 Subject: [PATCH 125/144] drm/amdgpu: add some additional vega10 pci ids Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index eb1345627501..f2d705e6a75a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -455,7 +455,9 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, {0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, {0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT}, {0, 0, 0} From cb3696fdeca24d3a347a5225d934ce50c6edccba Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Tue, 9 May 2017 15:34:07 +0800 Subject: [PATCH 126/144] drm/amd: fix init order of sched job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to increment after the fence check. Signed-off-by: Chunming Zhou Reviewed-by: Junwei Zhang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 5fd12db0fc58..28b92c8d9985 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -462,9 +462,9 @@ int amd_sched_job_init(struct amd_sched_job *job, job->sched = sched; job->s_entity = entity; job->s_fence = amd_sched_fence_create(entity, owner); - job->id = atomic64_inc_return(&sched->job_id_count); if (!job->s_fence) return -ENOMEM; + job->id = atomic64_inc_return(&sched->job_id_count); INIT_WORK(&job->finish_work, amd_sched_job_finish); INIT_LIST_HEAD(&job->node); From 30514decb27d45b98599612cb5d3e6a20ba733a5 Mon Sep 17 00:00:00 2001 From: Chunming Zhou Date: Tue, 9 May 2017 13:39:40 +0800 Subject: [PATCH 127/144] drm/amdgpu: fix dependency issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem is that executing the jobs in the right order doesn't give you the right result because consecutive jobs executed on the same engine are pipelined. In other words job B does it buffer read before job A has written it's result. Signed-off-by: Chunming Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- drivers/gpu/drm/amd/scheduler/gpu_scheduler.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/scheduler/gpu_scheduler.h | 2 ++ 6 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 86923c57908b..833c3c16501a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1129,6 +1129,7 @@ struct amdgpu_job { void *owner; uint64_t fence_ctx; /* the fence_context this job uses */ bool vm_needs_flush; + bool need_pipeline_sync; unsigned vm_id; uint64_t vm_pd_addr; uint32_t gds_base, gds_size; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 2d11ac8d1aa9..6e4ae0d983c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -160,6 +160,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, dev_err(adev->dev, "scheduling IB failed (%d).\n", r); return r; } + if (ring->funcs->emit_pipeline_sync && job && job->need_pipeline_sync) + amdgpu_ring_emit_pipeline_sync(ring); if (vm) { r = amdgpu_vm_flush(ring, job); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index c3cfeb335d99..7570f2439a11 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -57,6 +57,7 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, (*job)->vm = vm; (*job)->ibs = (void *)&(*job)[1]; (*job)->num_ibs = num_ibs; + (*job)->need_pipeline_sync = false; amdgpu_sync_create(&(*job)->sync); @@ -152,6 +153,9 @@ static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) fence = amdgpu_sync_get_fence(&job->sync); } + if (amd_sched_dependency_optimized(fence, sched_job->s_entity)) + job->need_pipeline_sync = true; + return fence; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index c42a9979d056..07ff3b1514f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -614,7 +614,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job) if (ring->funcs->init_cond_exec) patch_offset = amdgpu_ring_init_cond_exec(ring); - if (ring->funcs->emit_pipeline_sync) + if (ring->funcs->emit_pipeline_sync && !job->need_pipeline_sync) amdgpu_ring_emit_pipeline_sync(ring); if (ring->funcs->emit_vm_flush && vm_flush_needed) { diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 28b92c8d9985..fea96a765cf1 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -236,6 +236,23 @@ static void amd_sched_entity_clear_dep(struct dma_fence *f, struct dma_fence_cb dma_fence_put(f); } +bool amd_sched_dependency_optimized(struct dma_fence* fence, + struct amd_sched_entity *entity) +{ + struct amd_gpu_scheduler *sched = entity->sched; + struct amd_sched_fence *s_fence; + + if (!fence || dma_fence_is_signaled(fence)) + return false; + if (fence->context == entity->fence_context) + return true; + s_fence = to_amd_sched_fence(fence); + if (s_fence && s_fence->sched == sched) + return true; + + return false; +} + static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity) { struct amd_gpu_scheduler *sched = entity->sched; diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index 0255c7f8a6d8..924d4a5899e1 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h @@ -158,4 +158,6 @@ int amd_sched_job_init(struct amd_sched_job *job, void *owner); void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched); void amd_sched_job_recovery(struct amd_gpu_scheduler *sched); +bool amd_sched_dependency_optimized(struct dma_fence* fence, + struct amd_sched_entity *entity); #endif From ded96c7389c2fdef174d3dbdc6e8c2822312c364 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 21 Apr 2017 17:26:38 +0800 Subject: [PATCH 128/144] drm/amd/powerplay: add more smu message on Vega10. Add some new SMU messages. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h index 90beef35bba2..254974d3d371 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h @@ -122,7 +122,10 @@ typedef uint16_t PPSMC_Result; #define PPSMC_MSG_SetFanMinPwm 0x52 #define PPSMC_MSG_ConfigureGfxDidt 0x55 #define PPSMC_MSG_NumOfDisplays 0x56 -#define PPSMC_Message_Count 0x57 +#define PPSMC_MSG_ReadSerialNumTop32 0x58 +#define PPSMC_MSG_ReadSerialNumBottom32 0x59 +#define PPSMC_Message_Count 0x5A + typedef int PPSMC_Msg; From 4f93f09e5c3e59e72aa1ae877b24ae0cacdfdfa8 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 5 May 2017 17:37:20 +0800 Subject: [PATCH 129/144] drm/amdgpu: add amd fan ctrl mode enums. Add common fan enums that can be used for both powerplay and dpm. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/amd_shared.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 2ccf44e580de..1d1ac1ef94f7 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -138,6 +138,12 @@ struct amd_pp_profile { uint8_t down_hyst; }; +enum amd_fan_ctrl_mode { + AMD_FAN_CTRL_NONE = 0, + AMD_FAN_CTRL_MANUAL = 1, + AMD_FAN_CTRL_AUTO = 2, +}; + /* CG flags */ #define AMD_CG_SUPPORT_GFX_MGCG (1 << 0) #define AMD_CG_SUPPORT_GFX_MGLS (1 << 1) From aad22ca4368082cdd1cff1c55d8607c94ea1a74b Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 5 May 2017 16:56:45 +0800 Subject: [PATCH 130/144] drm/amdgpu: refine amdgpu pwm1_enable sysfs interface. Make the interface consistent. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 990fde2cf4fd..7df503aedb69 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -867,8 +867,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - /* never 0 (full-speed), fuse or smc-controlled always */ - return sprintf(buf, "%i\n", pwm_mode == FDO_PWM_MODE_STATIC ? 1 : 2); + return sprintf(buf, "%i\n", pwm_mode); } static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, @@ -887,14 +886,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, if (err) return err; - switch (value) { - case 1: /* manual, percent-based */ - amdgpu_dpm_set_fan_control_mode(adev, FDO_PWM_MODE_STATIC); - break; - default: /* disable */ - amdgpu_dpm_set_fan_control_mode(adev, 0); - break; - } + amdgpu_dpm_set_fan_control_mode(adev, value); return count; } From 7522ffc41b73a3dd1f9d19164f033bd649c0404b Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 5 May 2017 17:44:32 +0800 Subject: [PATCH 131/144] drm/amd/powerplay: refine pwm1_enable callback functions for Vega10. Use the new enums for setting and getting the fan control mode. Fixes problems due to previous inconsistencies between enums. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 44 ++++++++++--------- .../drm/amd/powerplay/hwmgr/vega10_thermal.h | 1 + 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 85a6c12ad1d4..ad30f5d3a10d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -3921,32 +3921,36 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { - if (mode) { - /* stop auto-manage */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) - vega10_fan_ctrl_stop_smc_fan_control(hwmgr); - vega10_fan_ctrl_set_static_mode(hwmgr, mode); - } else - /* restart auto-manage */ - vega10_fan_ctrl_reset_fan_speed_to_default(hwmgr); + int result = 0; - return 0; + switch (mode) { + case AMD_FAN_CTRL_NONE: + result = vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + break; + case AMD_FAN_CTRL_MANUAL: + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr); + break; + case AMD_FAN_CTRL_AUTO: + result = vega10_fan_ctrl_set_static_mode(hwmgr, mode); + if (!result) + result = vega10_fan_ctrl_start_smc_fan_control(hwmgr); + break; + default: + break; + } + return result; } static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) { - uint32_t reg; + struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend); - if (hwmgr->fan_ctrl_is_in_default_mode) { - return hwmgr->fan_ctrl_default_mode; - } else { - reg = soc15_get_register_offset(THM_HWID, 0, - mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2); - return (cgs_read_register(hwmgr->device, reg) & - CG_FDO_CTRL2__FDO_PWM_MODE_MASK) >> - CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT; - } + if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) + return AMD_FAN_CTRL_MANUAL; + else + return AMD_FAN_CTRL_AUTO; } static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h index 70c1d22b3d7d..776f3a2effc0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h @@ -79,6 +79,7 @@ extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); extern uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr); extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr); +int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); #endif From 2fde9ab218b7f8446c2428b7f9dad602afce8be6 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 5 May 2017 16:50:36 +0800 Subject: [PATCH 132/144] drm/amd/powerplay: refine pwm1_enable callback functions for vi. Use the new enums for setting and getting the fan control mode. Fixes problems due to previous inconsistencies between enums. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 35 +++++++++++-------- .../drm/amd/powerplay/hwmgr/smu7_thermal.c | 9 ++--- .../drm/amd/powerplay/hwmgr/smu7_thermal.h | 2 +- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index b3d42858f68b..a74a3db3056c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4334,26 +4334,31 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, static int smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { - if (mode) { - /* stop auto-manage */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) - smu7_fan_ctrl_stop_smc_fan_control(hwmgr); - smu7_fan_ctrl_set_static_mode(hwmgr, mode); - } else - /* restart auto-manage */ - smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); + int result = 0; - return 0; + switch (mode) { + case AMD_FAN_CTRL_NONE: + result = smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + break; + case AMD_FAN_CTRL_MANUAL: + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + result = smu7_fan_ctrl_stop_smc_fan_control(hwmgr); + break; + case AMD_FAN_CTRL_AUTO: + result = smu7_fan_ctrl_set_static_mode(hwmgr, mode); + if (!result) + result = smu7_fan_ctrl_start_smc_fan_control(hwmgr); + break; + default: + break; + } + return result; } static int smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr) { - if (hwmgr->fan_ctrl_is_in_default_mode) - return hwmgr->fan_ctrl_default_mode; - else - return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, FDO_PWM_MODE); + return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL; } static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c index 436ca5ce8248..baddb569a8b8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c @@ -112,10 +112,9 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) */ int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { - if (hwmgr->fan_ctrl_is_in_default_mode) { hwmgr->fan_ctrl_default_mode = - PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE); hwmgr->tmin = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, @@ -149,7 +148,7 @@ int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) return 0; } -static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) { int result; @@ -179,6 +178,7 @@ static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) PPSMC_MSG_SetFanTemperatureTarget, hwmgr->thermal_controller. advanceFanControlParameters.ucTargetTemperature); + hwmgr->fan_ctrl_enabled = true; return result; } @@ -186,6 +186,7 @@ static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) { + hwmgr->fan_ctrl_enabled = false; return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl); } @@ -280,7 +281,7 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_TACH_STATUS, TACH_PERIOD, tach_period); - return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); } /** diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h index 2ed774db42c7..ba71b608fa75 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h @@ -54,6 +54,6 @@ extern int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *spe extern int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); extern int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr); extern int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr); - +extern int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); #endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index e4574c215c38..805b9df452a3 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -764,6 +764,7 @@ struct pp_hwmgr { struct pp_thermal_controller_info thermal_controller; bool fan_ctrl_is_in_default_mode; uint32_t fan_ctrl_default_mode; + bool fan_ctrl_enabled; uint32_t tmin; struct phm_microcode_version_info microcode_version_info; uint32_t ps_size; From afa31879f0a62f769cdeeffc8cfec613da2bc482 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 5 May 2017 17:53:18 +0800 Subject: [PATCH 133/144] drm/amd/powerplay: refine pwm1_enable callback functions for CI. Use the new enums for setting and getting the fan control mode. Fixes problems due to previous inconsistencies between enums. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index a6dda3470003..6dc1410b380f 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -1267,30 +1267,33 @@ static int ci_dpm_set_fan_speed_percent(struct amdgpu_device *adev, static void ci_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode) { - if (mode) { - /* stop auto-manage */ + switch (mode) { + case AMD_FAN_CTRL_NONE: if (adev->pm.dpm.fan.ucode_fan_control) ci_fan_ctrl_stop_smc_fan_control(adev); - ci_fan_ctrl_set_static_mode(adev, mode); - } else { - /* restart auto-manage */ + ci_dpm_set_fan_speed_percent(adev, 100); + break; + case AMD_FAN_CTRL_MANUAL: + if (adev->pm.dpm.fan.ucode_fan_control) + ci_fan_ctrl_stop_smc_fan_control(adev); + break; + case AMD_FAN_CTRL_AUTO: if (adev->pm.dpm.fan.ucode_fan_control) ci_thermal_start_smc_fan_control(adev); - else - ci_fan_ctrl_set_default_mode(adev); + break; + default: + break; } } static u32 ci_dpm_get_fan_control_mode(struct amdgpu_device *adev) { struct ci_power_info *pi = ci_get_pi(adev); - u32 tmp; if (pi->fan_is_controlled_by_smc) - return 0; - - tmp = RREG32_SMC(ixCG_FDO_CTRL2) & CG_FDO_CTRL2__FDO_PWM_MODE_MASK; - return (tmp >> CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT); + return AMD_FAN_CTRL_AUTO; + else + return AMD_FAN_CTRL_MANUAL; } #if 0 From f42c5707f9344a2e30128cde5ca2a02775e58994 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 1 May 2017 16:59:29 +1000 Subject: [PATCH 134/144] drm/nouveau/kms/nv50: remove pointless argument to window atomic_check_acquire() Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index c9910c8537ed..b7dd5484e582 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -831,8 +831,7 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw, static int nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, - struct nv50_head_atom *asyh, - u32 pflip_flags) + struct nv50_head_atom *asyh) { struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb); struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev); @@ -848,7 +847,10 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, asyw->image.h = fb->base.height; asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8; - asyw->interval = pflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? 0 : 1; + if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) + asyw->interval = 0; + else + asyw->interval = 1; if (asyw->image.kind) { asyw->image.layout = 0; @@ -887,7 +889,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) struct nv50_head_atom *harm = NULL, *asyh = NULL; bool varm = false, asyv = false, asym = false; int ret; - u32 pflip_flags = 0; NV_ATOMIC(drm, "%s atomic_check\n", plane->name); if (asyw->state.crtc) { @@ -896,7 +897,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) return PTR_ERR(asyh); asym = drm_atomic_crtc_needs_modeset(&asyh->state); asyv = asyh->state.active; - pflip_flags = asyh->state.pageflip_flags; } if (armw->state.crtc) { @@ -913,8 +913,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) asyw->set.point = true; if (!varm || asym || armw->state.fb != asyw->state.fb) { - ret = nv50_wndw_atomic_check_acquire( - wndw, asyw, asyh, pflip_flags); + ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh); if (ret) return ret; } From 36601c2b36e27435d9be33cfa092120ff69914eb Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 1 May 2017 16:52:03 +1000 Subject: [PATCH 135/144] drm/nouveau/kms/nv50: fix source-rect-only plane updates This "optimisation" (which was originally meant to skip updating cursor settings in the core channel on position-only updates) turned out to be pointless in the final design of the code before it was merged. Remove it completely, as it breaks other cases. Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org [4.10+] --- drivers/gpu/drm/nouveau/nv50_display.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index b7dd5484e582..84b9bb43d93a 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -912,11 +912,9 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point))) asyw->set.point = true; - if (!varm || asym || armw->state.fb != asyw->state.fb) { - ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh); - if (ret) - return ret; - } + ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh); + if (ret) + return ret; } else if (varm) { nv50_wndw_atomic_check_release(wndw, asyw, harm); From e6db95799b1b870aae15682a6d0898df9e9dfb38 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 1 May 2017 16:53:40 +1000 Subject: [PATCH 136/144] drm/nouveau/kms/nv50: skip core channel cursor update on position-only changes The DRM core used to only call prepare_fb/cleanup_fb() when a plane's framebuffer changed, which achieved the desired effect. It's apparently now up to the driver to decide on its own. Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org [4.11+] --- drivers/gpu/drm/nouveau/nv50_display.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 84b9bb43d93a..fcec2aba9ad7 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1119,9 +1119,13 @@ static void nv50_curs_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh, struct nv50_wndw_atom *asyw) { - asyh->curs.handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle; - asyh->curs.offset = asyw->image.offset; - asyh->set.curs = asyh->curs.visible; + u32 handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle; + u32 offset = asyw->image.offset; + if (asyh->curs.handle != handle || asyh->curs.offset != offset) { + asyh->curs.handle = handle; + asyh->curs.offset = offset; + asyh->set.curs = asyh->curs.visible; + } } static void From 80a92865f2113fe8bc268218b0c4156cfab4c9ac Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 28 Mar 2017 11:46:37 +1000 Subject: [PATCH 137/144] drm/nouveau/fb/ram/gf100-: remove 0x10f200 read This reg has moved on Pascal, and causes a bus fault. We never use the value anyway, so just remove the read. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index c63975907c90..4a9bd4f1cb93 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -638,7 +638,6 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, return ret; } - ram->ranks = (nvkm_rd32(device, 0x10f200) & 0x00000004) ? 2 : 1; return 0; } From 89ed10a5721d569b053a8355c1a6bd812fed7c29 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 4 May 2017 17:29:03 +1000 Subject: [PATCH 138/144] drm/nouveau/core: fix static checker warning object->engine cannot be NULL, it's either valid, or an error pointer. This particular condition shouldn't actually be possible, but just in case, we'll keep it. Reported-by: Dan Carpenter Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/core/object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index 89d2e9da11c7..acd76fd4f6d8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -295,7 +295,7 @@ nvkm_object_ctor(const struct nvkm_object_func *func, INIT_LIST_HEAD(&object->head); INIT_LIST_HEAD(&object->tree); RB_CLEAR_NODE(&object->node); - WARN_ON(oclass->engine && !object->engine); + WARN_ON(IS_ERR(object->engine)); } int From 3733bd8b407211739e72d051e5f30ad82a52c4bc Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 16:53:42 +1000 Subject: [PATCH 139/144] drm/nouveau/tmr: ack interrupt before processing alarms Fixes a race where we can miss an alarm that triggers while we're already processing previous alarms. Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c index 7b9ce87f0617..7f48249f41de 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c @@ -76,8 +76,8 @@ nv04_timer_intr(struct nvkm_timer *tmr) u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0); if (stat & 0x00000001) { - nvkm_timer_alarm_trigger(tmr); nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001); + nvkm_timer_alarm_trigger(tmr); stat &= ~0x00000001; } From 1b0f84380b10ee97f7d2dd191294de9017e94d1d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:19:48 +1000 Subject: [PATCH 140/144] drm/nouveau/tmr: handle races with hw when updating the next alarm time If the time to the next alarm is short enough, we could race with HW and end up with an ~4 second delay until it triggers. Fix this by checking again after we update HW. Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- .../gpu/drm/nouveau/nvkm/subdev/timer/base.c | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 07dc82bfe346..4e696627fdcd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -36,23 +36,29 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr) unsigned long flags; LIST_HEAD(exec); - /* move any due alarms off the pending list */ + /* Process pending alarms. */ spin_lock_irqsave(&tmr->lock, flags); list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) { - if (alarm->timestamp <= nvkm_timer_read(tmr)) - list_move_tail(&alarm->head, &exec); + /* Have we hit the earliest alarm that hasn't gone off? */ + if (alarm->timestamp > nvkm_timer_read(tmr)) { + /* Schedule it. If we didn't race, we're done. */ + tmr->func->alarm_init(tmr, alarm->timestamp); + if (alarm->timestamp > nvkm_timer_read(tmr)) + break; + } + + /* Move to completed list. We'll drop the lock before + * executing the callback so it can reschedule itself. + */ + list_move_tail(&alarm->head, &exec); } - /* reschedule interrupt for next alarm time */ - if (!list_empty(&tmr->alarms)) { - alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head); - tmr->func->alarm_init(tmr, alarm->timestamp); - } else { + /* Shut down interrupt if no more pending alarms. */ + if (list_empty(&tmr->alarms)) tmr->func->alarm_fini(tmr); - } spin_unlock_irqrestore(&tmr->lock, flags); - /* execute any pending alarm handlers */ + /* Execute completed callbacks. */ list_for_each_entry_safe(alarm, atemp, &exec, head) { list_del_init(&alarm->head); alarm->func(alarm); From 9fc64667ee48c9a25e7dca1a6bcb6906fec5bcc5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:03:05 +1000 Subject: [PATCH 141/144] drm/nouveau/tmr: fix corruption of the pending list when rescheduling an alarm At least therm/fantog "attempts" to work around this issue, which could lead to corruption of the pending alarm list. Fix it properly by not updating the timestamp without the lock held, or trying to add an already pending alarm to the pending alarm list.... Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- .../gpu/drm/nouveau/nvkm/subdev/timer/base.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index 4e696627fdcd..d898787d514c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -71,14 +71,17 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) struct nvkm_alarm *list; unsigned long flags; - alarm->timestamp = nvkm_timer_read(tmr) + nsec; - - /* append new alarm to list, in soonest-alarm-first order */ + /* Remove alarm from pending list. + * + * This both protects against the corruption of the list, + * and implements alarm rescheduling/cancellation. + */ spin_lock_irqsave(&tmr->lock, flags); - if (!nsec) { - if (!list_empty(&alarm->head)) - list_del(&alarm->head); - } else { + list_del_init(&alarm->head); + + if (nsec) { + /* Insert into pending list, ordered earliest to latest. */ + alarm->timestamp = nvkm_timer_read(tmr) + nsec; list_for_each_entry(list, &tmr->alarms, head) { if (list->timestamp > alarm->timestamp) break; From 330bdf62fe6a6c5b99a647f7bf7157107c9348b3 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:13:29 +1000 Subject: [PATCH 142/144] drm/nouveau/tmr: avoid processing completed alarms when adding a new one The idea here was to avoid having to "manually" program the HW if there's a new earliest alarm. This was lazy and bad, as it leads to loads of fun races between inter-related callers (ie. therm). Turns out, it's not so difficult after all. Go figure ;) Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c index d898787d514c..f2a86eae0a0d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c @@ -86,12 +86,22 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm) if (list->timestamp > alarm->timestamp) break; } + list_add_tail(&alarm->head, &list->head); + + /* Update HW if this is now the earliest alarm. */ + list = list_first_entry(&tmr->alarms, typeof(*list), head); + if (list == alarm) { + tmr->func->alarm_init(tmr, alarm->timestamp); + /* This shouldn't happen if callers aren't stupid. + * + * Worst case scenario is that it'll take roughly + * 4 seconds for the next alarm to trigger. + */ + WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr)); + } } spin_unlock_irqrestore(&tmr->lock, flags); - - /* process pending alarms */ - nvkm_timer_alarm_trigger(tmr); } void From e4311ee51d1e2676001b2d8fcefd92bdd79aad85 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 11 May 2017 17:33:39 +1000 Subject: [PATCH 143/144] drm/nouveau/therm: remove ineffective workarounds for alarm bugs These were ineffective due to touching the list without the alarm lock, but should no longer be required. Signed-off-by: Ben Skeggs Cc: stable@vger.kernel.org --- drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index df949fa7d05d..be691a7b972f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -146,7 +146,7 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode) poll = false; } - if (list_empty(&therm->alarm.head) && poll) + if (poll) nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm); spin_unlock_irqrestore(&therm->lock, flags); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c index 91198d79393a..e2feccec25f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c @@ -83,7 +83,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target) spin_unlock_irqrestore(&fan->lock, flags); /* schedule next fan update, if not at target speed already */ - if (list_empty(&fan->alarm.head) && target != duty) { + if (target != duty) { u16 bump_period = fan->bios.bump_period; u16 slow_down_period = fan->bios.slow_down_period; u64 delay; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c index 59701b7a6597..ff9fbe7950e5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c @@ -53,7 +53,7 @@ nvkm_fantog_update(struct nvkm_fantog *fan, int percent) duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff); nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); - if (list_empty(&fan->alarm.head) && percent != (duty * 100)) { + if (percent != (duty * 100)) { u64 next_change = (percent * fan->period_us) / 100; if (!duty) next_change = fan->period_us - next_change; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c index b9703c02d8ca..9a79e91fdfdc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c @@ -185,7 +185,7 @@ alarm_timer_callback(struct nvkm_alarm *alarm) spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags); /* schedule the next poll in one second */ - if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head)) + if (therm->func->temp_get(therm) >= 0) nvkm_timer_alarm(tmr, 1000000000ULL, alarm); } From 7b8cd3363e8a0e6b90a7067f75aaeaae61a7d612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Sun, 7 May 2017 20:12:52 +0300 Subject: [PATCH 144/144] drm/i915: Make vblank evade warnings optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new Kconfig option to enable/disable the extra warnings from the vblank evade code. For now we'll keep the warning about an actually missed vblank always enabled as that can have an actual user visible impact. But if we miss the deadline othrwise there's no real need to bother the user with that. We'll want these warnings enabled during development however so that we can catch regressions. Based on the reports it looks like this is still very easy to hit on SKL, so we have more work ahead of us to optimize the crtiical section further. Cc: Daniel Vetter Cc: Jani Nikula Cc: Dave Airlie Cc: Jens Axboe Cc: Linus Torvalds Cc: Maarten Lankhorst Reported-by: Jens Axboe Reported-by: Linus Torvalds Fixes: e1edbd44e23b ("drm/i915: Complain if we take too long under vblank evasion.") Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/Kconfig.debug | 13 +++++++++++++ drivers/gpu/drm/i915/intel_sprite.c | 7 +++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index e091809a9a9e..b00edd3b8800 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -87,3 +87,16 @@ config DRM_I915_LOW_LEVEL_TRACEPOINTS and also analyze the request dependency resolving timeline. If in doubt, say "N". + +config DRM_I915_DEBUG_VBLANK_EVADE + bool "Enable extra debug warnings for vblank evasion" + depends on DRM_I915 + default n + help + Choose this option to turn on extra debug warnings for the + vblank evade mechanism. This gives a warning every time the + the deadline allotted for the vblank evade critical section + is exceeded, even if there isn't an actual risk of missing + the vblank. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index f7d431427115..8c87c717c7cd 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -198,12 +198,15 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), crtc->debug.min_vbl, crtc->debug.max_vbl, crtc->debug.scanline_start, scanline_end); - } else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > - VBLANK_EVASION_TIME_US) + } +#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE + else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) > + VBLANK_EVASION_TIME_US) DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n", pipe_name(pipe), ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), VBLANK_EVASION_TIME_US); +#endif } static void