From 6a8cf6349c7cae12f072889991a2aa0a1ba0bd32 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Jan 2022 16:24:17 -0500 Subject: [PATCH 001/339] drm/amdgpu/swsmu: make sienna cichlid function static Unused outside of the file. Reported-by: kernel test robot Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 777f717c37ae..d8c57b780bca 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3832,9 +3832,9 @@ static void sienna_cichlid_stb_init(struct smu_context *smu) } -int sienna_cichlid_stb_get_data_direct(struct smu_context *smu, - void *buf, - uint32_t size) +static int sienna_cichlid_stb_get_data_direct(struct smu_context *smu, + void *buf, + uint32_t size) { uint32_t *p = buf; struct amdgpu_device *adev = smu->adev; From de05abe6b9d0fe08f65d744f7f75a4cba4df27ad Mon Sep 17 00:00:00 2001 From: Solomon Chiu Date: Thu, 6 Jan 2022 17:11:48 +0800 Subject: [PATCH 002/339] drm/amd/display: Enable Freesync Video Mode by default [Why&How] Freesync Video Mode is a experimental feature previously, and need to be enabled by kernel parameter. We enable it by default with removing module paramterter in amdgpu_dm. v2: squash the patches together Signed-off-by: Solomon Chiu Reviewed-by: Aurabindo Jayamohanan Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 27 ------------------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++----- 3 files changed, 5 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 4f771f9eb0e3..182d673103ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -197,7 +197,6 @@ extern int amdgpu_emu_mode; extern uint amdgpu_smu_memory_pool_size; extern int amdgpu_smu_pptable_id; extern uint amdgpu_dc_feature_mask; -extern uint amdgpu_freesync_vid_mode; extern uint amdgpu_dc_debug_mask; extern uint amdgpu_dm_abm_level; extern int amdgpu_backlight; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 366e475056bd..10e01928ffad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -173,7 +173,6 @@ int amdgpu_mes; int amdgpu_noretry = -1; int amdgpu_force_asic_type = -1; int amdgpu_tmz = -1; /* auto */ -uint amdgpu_freesync_vid_mode; int amdgpu_reset_method = -1; /* auto */ int amdgpu_num_kcq = -1; int amdgpu_smartshift_bias; @@ -842,32 +841,6 @@ module_param_named(backlight, amdgpu_backlight, bint, 0444); MODULE_PARM_DESC(tmz, "Enable TMZ feature (-1 = auto (default), 0 = off, 1 = on)"); module_param_named(tmz, amdgpu_tmz, int, 0444); -/** - * DOC: freesync_video (uint) - * Enable the optimization to adjust front porch timing to achieve seamless - * mode change experience when setting a freesync supported mode for which full - * modeset is not needed. - * - * The Display Core will add a set of modes derived from the base FreeSync - * video mode into the corresponding connector's mode list based on commonly - * used refresh rates and VRR range of the connected display, when users enable - * this feature. From the userspace perspective, they can see a seamless mode - * change experience when the change between different refresh rates under the - * same resolution. Additionally, userspace applications such as Video playback - * can read this modeset list and change the refresh rate based on the video - * frame rate. Finally, the userspace can also derive an appropriate mode for a - * particular refresh rate based on the FreeSync Mode and add it to the - * connector's mode list. - * - * Note: This is an experimental feature. - * - * The default value: 0 (off). - */ -MODULE_PARM_DESC( - freesync_video, - "Enable freesync modesetting optimization feature (0 = off (default), 1 = on)"); -module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444); - /** * DOC: reset_method (int) * GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco, 5 = pci) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7f9773f8dab6..afadec2d1993 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6435,8 +6435,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, */ DRM_DEBUG_DRIVER("No preferred mode found\n"); } else { - recalculate_timing = amdgpu_freesync_vid_mode && - is_freesync_video_mode(&mode, aconnector); + recalculate_timing = is_freesync_video_mode(&mode, aconnector); if (recalculate_timing) { freesync_mode = get_highest_refresh_rate_mode(aconnector, false); saved_mode = mode; @@ -8304,7 +8303,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); - if (!(amdgpu_freesync_vid_mode && edid)) + if (!edid) return; if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) @@ -10271,8 +10270,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, * TODO: Refactor this function to allow this check to work * in all conditions. */ - if (amdgpu_freesync_vid_mode && - dm_new_crtc_state->stream && + if (dm_new_crtc_state->stream && is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) goto skip_modeset; @@ -10307,7 +10305,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, if (!dm_old_crtc_state->stream) goto skip_modeset; - if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && + if (dm_new_crtc_state->stream && is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) { new_crtc_state->mode_changed = false; @@ -10319,7 +10317,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, set_freesync_fixed_config(dm_new_crtc_state); goto skip_modeset; - } else if (amdgpu_freesync_vid_mode && aconnector && + } else if (aconnector && is_freesync_video_mode(&new_crtc_state->mode, aconnector)) { struct drm_display_mode *high_mode; From 8c2d34eb53b96755b33a125c65c3e807dbe430a1 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Thu, 30 Dec 2021 16:00:19 +1100 Subject: [PATCH 003/339] drm/radeon: use kernel is_power_of_2 rather than local version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow the amdgpu change made in 7611750784664db46d0db95631e322aeb263dde7 and replace local radeon function with is_power_of_2(). Reviewed-by: Christian König Signed-off-by: Jonathan Gray Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_device.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4f0fbf667431..15692cb241fc 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1085,19 +1085,6 @@ static unsigned int radeon_vga_set_decode(struct pci_dev *pdev, bool state) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; } -/** - * radeon_check_pot_argument - check that argument is a power of two - * - * @arg: value to check - * - * Validates that a certain argument is a power of two (all asics). - * Returns true if argument is valid. - */ -static bool radeon_check_pot_argument(int arg) -{ - return (arg & (arg - 1)) == 0; -} - /** * radeon_gart_size_auto - Determine a sensible default GART size * according to ASIC family. @@ -1126,7 +1113,7 @@ static int radeon_gart_size_auto(enum radeon_family family) static void radeon_check_arguments(struct radeon_device *rdev) { /* vramlimit must be a power of two */ - if (!radeon_check_pot_argument(radeon_vram_limit)) { + if (!is_power_of_2(radeon_vram_limit)) { dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", radeon_vram_limit); radeon_vram_limit = 0; @@ -1140,7 +1127,7 @@ static void radeon_check_arguments(struct radeon_device *rdev) dev_warn(rdev->dev, "gart size (%d) too small\n", radeon_gart_size); radeon_gart_size = radeon_gart_size_auto(rdev->family); - } else if (!radeon_check_pot_argument(radeon_gart_size)) { + } else if (!is_power_of_2(radeon_gart_size)) { dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", radeon_gart_size); radeon_gart_size = radeon_gart_size_auto(rdev->family); @@ -1163,7 +1150,7 @@ static void radeon_check_arguments(struct radeon_device *rdev) break; } - if (!radeon_check_pot_argument(radeon_vm_size)) { + if (!is_power_of_2(radeon_vm_size)) { dev_warn(rdev->dev, "VM size (%d) must be a power of 2\n", radeon_vm_size); radeon_vm_size = 4; From bc143d8b8387ff0a22e4ef8e2375e63aa24bc311 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 22 Nov 2021 10:57:20 +0800 Subject: [PATCH 004/339] drm/amd/pm: do not expose implementation details to other blocks out of power Those implementation details(whether swsmu supported, some ppt_funcs supported, accessing internal statistics ...)should be kept internally. It's not a good practice and even error prone to expose implementation details. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/aldebaran.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 25 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 18 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 7 -- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 5 +- drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 2 +- .../gpu/drm/amd/include/kgd_pp_interface.h | 4 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 90 +++++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 25 +++++- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 11 +-- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 26 +++--- 13 files changed, 161 insertions(+), 65 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c index bcfdb63b1d42..a545df4efce1 100644 --- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c +++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c @@ -260,7 +260,7 @@ static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev) adev->gfx.rlc.funcs->resume(adev); /* Wait for FW reset event complete */ - r = smu_wait_for_event(adev, SMU_EVENT_RESET_COMPLETE, 0); + r = amdgpu_dpm_wait_for_event(adev, SMU_EVENT_RESET_COMPLETE, 0); if (r) { dev_err(adev->dev, "Failed to get response from firmware after reset\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 25e2e5bf90eb..9aea1cc5b27e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1585,22 +1585,25 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val) return ret; } - if (is_support_sw_smu(adev)) { - ret = smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, &min_freq, &max_freq); - if (ret || val > max_freq || val < min_freq) - return -EINVAL; - ret = smu_set_soft_freq_range(&adev->smu, SMU_SCLK, (uint32_t)val, (uint32_t)val); - } else { - return 0; + ret = amdgpu_dpm_get_dpm_freq_range(adev, PP_SCLK, &min_freq, &max_freq); + if (ret == -EOPNOTSUPP) { + ret = 0; + goto out; + } + if (ret || val > max_freq || val < min_freq) { + ret = -EINVAL; + goto out; } + ret = amdgpu_dpm_set_soft_freq_range(adev, PP_SCLK, (uint32_t)val, (uint32_t)val); + if (ret) + ret = -EINVAL; + +out: pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - if (ret) - return -EINVAL; - - return 0; + return ret; } DEFINE_DEBUGFS_ATTRIBUTE(fops_ib_preempt, NULL, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index cf7fad88c138..596bb2fdb8a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2624,7 +2624,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev) /* For passthrough configuration on arcturus and aldebaran, enable special handling SBR */ if (amdgpu_passthrough(adev) && ((adev->asic_type == CHIP_ARCTURUS && adev->gmc.xgmi.num_physical_nodes > 1)|| adev->asic_type == CHIP_ALDEBARAN )) - smu_handle_passthrough_sbr(&adev->smu, true); + amdgpu_dpm_handle_passthrough_sbr(adev, true); if (adev->gmc.xgmi.num_physical_nodes > 1) { mutex_lock(&mgpu_info.mutex); @@ -2881,7 +2881,7 @@ static int amdgpu_device_ip_suspend_phase2(struct amdgpu_device *adev) int i, r; if (adev->in_s0ix) - amdgpu_gfx_state_change_set(adev, sGpuChangeState_D3Entry); + amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D3Entry); for (i = adev->num_ip_blocks - 1; i >= 0; i--) { if (!adev->ip_blocks[i].status.valid) @@ -4044,7 +4044,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) return 0; if (adev->in_s0ix) - amdgpu_gfx_state_change_set(adev, sGpuChangeState_D0Entry); + amdgpu_dpm_gfx_state_change(adev, sGpuChangeState_D0Entry); /* post card */ if (amdgpu_device_need_post(adev)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 1916ec84dd71..3d8f82dc8c97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -615,7 +615,7 @@ int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value) mutex_lock(&adev->gfx.gfx_off_mutex); - r = smu_get_status_gfxoff(adev, value); + r = amdgpu_dpm_get_status_gfxoff(adev, value); mutex_unlock(&adev->gfx.gfx_off_mutex); @@ -852,19 +852,3 @@ int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev) } return amdgpu_num_kcq; } - -/* amdgpu_gfx_state_change_set - Handle gfx power state change set - * @adev: amdgpu_device pointer - * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) - * - */ - -void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state) -{ - mutex_lock(&adev->pm.mutex); - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->gfx_state_change_set) - ((adev)->powerplay.pp_funcs->gfx_state_change_set( - (adev)->powerplay.pp_handle, state)); - mutex_unlock(&adev->pm.mutex); -} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index f851196c83a5..776c886fd94a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -47,12 +47,6 @@ enum amdgpu_gfx_pipe_priority { AMDGPU_GFX_PIPE_PRIO_HIGH = AMDGPU_RING_PRIO_2 }; -/* Argument for PPSMC_MSG_GpuChangeState */ -enum gfx_change_state { - sGpuChangeState_D0Entry = 1, - sGpuChangeState_D3Entry, -}; - #define AMDGPU_GFX_QUEUE_PRIORITY_MINIMUM 0 #define AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM 15 @@ -410,5 +404,4 @@ int amdgpu_gfx_cp_ecc_error_irq(struct amdgpu_device *adev, uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg); void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v); int amdgpu_gfx_get_num_kcq(struct amdgpu_device *adev); -void amdgpu_gfx_state_change_set(struct amdgpu_device *adev, enum gfx_change_state state); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 586a30ad13e2..4a9970423e7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -901,7 +901,7 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d * choosing right query method according to * whether smu support query error information */ - ret = smu_get_ecc_info(&adev->smu, (void *)&(ras->umc_ecc)); + ret = amdgpu_dpm_get_ecc_info(adev, (void *)&(ras->umc_ecc)); if (ret == -EOPNOTSUPP) { if (adev->umc.ras_funcs && adev->umc.ras_funcs->query_ras_error_count) @@ -2141,8 +2141,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) if (ret) goto free; - if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num) - adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs); + amdgpu_dpm_send_hbm_bad_pages_num(adev, con->eeprom_control.ras_num_recs); } #ifdef CONFIG_X86_MCE_AMD diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 46264a4002f7..25951b2d83b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -33,7 +33,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, int ret = 0; kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); - ret = smu_get_ecc_info(&adev->smu, (void *)&(con->umc_ecc)); + ret = amdgpu_dpm_get_ecc_info(adev, (void *)&(con->umc_ecc)); if (ret == -EOPNOTSUPP) { if (adev->umc.ras_funcs && adev->umc.ras_funcs->query_ras_error_count) @@ -96,8 +96,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, err_data->err_addr_cnt); amdgpu_ras_save_bad_pages(adev); - if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->send_hbm_bad_pages_num) - adev->smu.ppt_funcs->send_hbm_bad_pages_num(&adev->smu, con->eeprom_control.ras_num_recs); + amdgpu_dpm_send_hbm_bad_pages_num(adev, con->eeprom_control.ras_num_recs); } if (reset) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index deae12dc777d..329a4c89f1e6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -222,7 +222,7 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, len = snprintf(fifo_in, sizeof(fifo_in), "%x %llx:%llx\n", KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, - atomic64_read(&dev->adev->smu.throttle_int_counter)); + amdgpu_dpm_get_thermal_throttling_counter(dev->adev)); add_event_to_kfifo(dev, KFD_SMI_EVENT_THERMAL_THROTTLE, fifo_in, len); } diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 5c0867ebcfce..2e295facd086 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -26,6 +26,10 @@ extern const struct amdgpu_ip_block_version pp_smu_ip_block; +enum smu_event_type { + SMU_EVENT_RESET_COMPLETE = 0, +}; + struct amd_vce_state { /* vce clocks */ u32 evclk; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 08362d506534..73f3d2912f13 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1614,3 +1614,93 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio return 0; } + +int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) +{ + return smu_handle_passthrough_sbr(&adev->smu, enable); +} + +int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) +{ + return smu_send_hbm_bad_pages_num(&adev->smu, size); +} + +int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, + enum pp_clock_type type, + uint32_t *min, + uint32_t *max) +{ + if (!is_support_sw_smu(adev)) + return -EOPNOTSUPP; + + switch (type) { + case PP_SCLK: + return smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, min, max); + default: + return -EINVAL; + } +} + +int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, + enum pp_clock_type type, + uint32_t min, + uint32_t max) +{ + if (!is_support_sw_smu(adev)) + return -EOPNOTSUPP; + + switch (type) { + case PP_SCLK: + return smu_set_soft_freq_range(&adev->smu, SMU_SCLK, min, max); + default: + return -EINVAL; + } +} + +int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, + enum smu_event_type event, + uint64_t event_arg) +{ + if (!is_support_sw_smu(adev)) + return -EOPNOTSUPP; + + return smu_wait_for_event(&adev->smu, event, event_arg); +} + +int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) +{ + if (!is_support_sw_smu(adev)) + return -EOPNOTSUPP; + + return smu_get_status_gfxoff(&adev->smu, value); +} + +uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) +{ + return atomic64_read(&adev->smu.throttle_int_counter); +} + +/* amdgpu_dpm_gfx_state_change - Handle gfx power state change set + * @adev: amdgpu_device pointer + * @state: gfx power state(1 -sGpuChangeState_D0Entry and 2 -sGpuChangeState_D3Entry) + * + */ +void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, + enum gfx_change_state state) +{ + mutex_lock(&adev->pm.mutex); + if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->gfx_state_change_set) + ((adev)->powerplay.pp_funcs->gfx_state_change_set( + (adev)->powerplay.pp_handle, state)); + mutex_unlock(&adev->pm.mutex); +} + +int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, + void *umc_ecc) +{ + if (!is_support_sw_smu(adev)) + return -EOPNOTSUPP; + + return smu_get_ecc_info(&adev->smu, umc_ecc); +} diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index c464a045000d..b444937c3b68 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -23,6 +23,12 @@ #ifndef __AMDGPU_DPM_H__ #define __AMDGPU_DPM_H__ +/* Argument for PPSMC_MSG_GpuChangeState */ +enum gfx_change_state { + sGpuChangeState_D0Entry = 1, + sGpuChangeState_D3Entry, +}; + enum amdgpu_int_thermal_type { THERMAL_TYPE_NONE, THERMAL_TYPE_EXTERNAL, @@ -582,5 +588,22 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); void amdgpu_pm_print_power_states(struct amdgpu_device *adev); int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); - +int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable); +int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size); +int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, + enum pp_clock_type type, + uint32_t *min, + uint32_t *max); +int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, + enum pp_clock_type type, + uint32_t min, + uint32_t max); +int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, + uint64_t event_arg); +int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); +uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev); +void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, + enum gfx_change_state state); +int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, + void *umc_ecc); #endif diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index ba7565bc8104..b90ed0ec9322 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -241,11 +241,6 @@ struct smu_user_dpm_profile { uint32_t clk_dependency; }; -enum smu_event_type { - - SMU_EVENT_RESET_COMPLETE = 0, -}; - #define SMU_TABLE_INIT(tables, table_id, s, a, d) \ do { \ tables[table_id].size = s; \ @@ -1413,15 +1408,15 @@ int smu_set_ac_dc(struct smu_context *smu); int smu_allow_xgmi_power_down(struct smu_context *smu, bool en); -int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); +int smu_get_status_gfxoff(struct smu_context *smu, uint32_t *value); int smu_handle_passthrough_sbr(struct smu_context *smu, bool enable); -int smu_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, +int smu_wait_for_event(struct smu_context *smu, enum smu_event_type event, uint64_t event_arg); int smu_get_ecc_info(struct smu_context *smu, void *umc_ecc); int smu_stb_collect_info(struct smu_context *smu, void *buff, uint32_t size); void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev); - +int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size); #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index d93d28c1af95..9d5a5a1f15df 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -100,17 +100,14 @@ static int smu_sys_set_pp_feature_mask(void *handle, return ret; } -int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) +int smu_get_status_gfxoff(struct smu_context *smu, uint32_t *value) { - int ret = 0; - struct smu_context *smu = &adev->smu; + if (!smu->ppt_funcs->get_gfx_off_status) + return -EINVAL; - if (is_support_sw_smu(adev) && smu->ppt_funcs->get_gfx_off_status) - *value = smu_get_gfx_off_status(smu); - else - ret = -EINVAL; + *value = smu_get_gfx_off_status(smu); - return ret; + return 0; } int smu_set_soft_freq_range(struct smu_context *smu, @@ -3165,11 +3162,10 @@ static const struct amd_pm_funcs swsmu_pm_funcs = { .get_smu_prv_buf_details = smu_get_prv_buffer_details, }; -int smu_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, +int smu_wait_for_event(struct smu_context *smu, enum smu_event_type event, uint64_t event_arg) { int ret = -EINVAL; - struct smu_context *smu = &adev->smu; if (smu->ppt_funcs->wait_for_event) { mutex_lock(&smu->mutex); @@ -3283,3 +3279,13 @@ void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev) #endif } + +int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size) +{ + int ret = 0; + + if (smu->ppt_funcs && smu->ppt_funcs->send_hbm_bad_pages_num) + ret = smu->ppt_funcs->send_hbm_bad_pages_num(smu, size); + + return ret; +} From 79c65f3fcbb1288b84473d45e6d001820a971d54 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 22 Nov 2021 11:05:22 +0800 Subject: [PATCH 005/339] drm/amd/pm: do not expose power implementation details to amdgpu_pm.c amdgpu_pm.c holds all the user sysfs/hwmon interfaces. It's another client of our power APIs. It's not proper to spike into power implementation details there. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 461 ++++++++++++++++++- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 521 ++++++++-------------- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 160 +++---- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 3 - 4 files changed, 713 insertions(+), 432 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 73f3d2912f13..494cf1459d0f 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1453,7 +1453,9 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) if (equal) return; - amdgpu_dpm_set_power_state(adev); + if (adev->powerplay.pp_funcs->set_power_state) + adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); + amdgpu_dpm_post_set_power_state(adev); adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; @@ -1704,3 +1706,460 @@ int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, return smu_get_ecc_info(&adev->smu, umc_ecc); } + +struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, + uint32_t idx) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_vce_clock_state) + return NULL; + + return pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, + idx); +} + +void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type *state) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_current_power_state) { + *state = adev->pm.dpm.user_state; + return; + } + + *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); + if (*state < POWER_STATE_TYPE_DEFAULT || + *state > POWER_STATE_TYPE_INTERNAL_3DPERF) + *state = adev->pm.dpm.user_state; +} + +void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type state) +{ + adev->pm.dpm.user_state = state; + + if (is_support_sw_smu(adev)) + return; + + if (amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_ENABLE_USER_STATE, + &state) == -EOPNOTSUPP) + amdgpu_pm_compute_clocks(adev); +} + +enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + enum amd_dpm_forced_level level; + + if (pp_funcs->get_performance_level) + level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); + else + level = adev->pm.dpm.forced_level; + + return level; +} + +int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, + enum amd_dpm_forced_level level) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (pp_funcs->force_performance_level) { + if (adev->pm.dpm.thermal_active) + return -EINVAL; + + if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, + level)) + return -EINVAL; + + adev->pm.dpm.forced_level = level; + } + + return 0; +} + +int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, + struct pp_states_info *states) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_pp_num_states) + return -EOPNOTSUPP; + + return pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, states); +} + +int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, + enum amd_pp_task task_id, + enum amd_pm_state_type *user_state) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->dispatch_tasks) + return -EOPNOTSUPP; + + return pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, task_id, user_state); +} + +int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_pp_table) + return 0; + + return pp_funcs->get_pp_table(adev->powerplay.pp_handle, table); +} + +int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, + uint32_t type, + long *input, + uint32_t size) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_fine_grain_clk_vol) + return 0; + + return pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, + type, + input, + size); +} + +int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, + uint32_t type, + long *input, + uint32_t size) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->odn_edit_dpm_table) + return 0; + + return pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, + type, + input, + size); +} + +int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, + enum pp_clock_type type, + char *buf) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->print_clock_levels) + return 0; + + return pp_funcs->print_clock_levels(adev->powerplay.pp_handle, + type, + buf); +} + +int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, + uint64_t ppfeature_masks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_ppfeature_status) + return 0; + + return pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, + ppfeature_masks); +} + +int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_ppfeature_status) + return 0; + + return pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, + buf); +} + +int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, + enum pp_clock_type type, + uint32_t mask) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->force_clock_level) + return 0; + + return pp_funcs->force_clock_level(adev->powerplay.pp_handle, + type, + mask); +} + +int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_sclk_od) + return 0; + + return pp_funcs->get_sclk_od(adev->powerplay.pp_handle); +} + +int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (is_support_sw_smu(adev)) + return 0; + + if (pp_funcs->set_sclk_od) + pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); + + if (amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_READJUST_POWER_STATE, + NULL) == -EOPNOTSUPP) { + adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; + amdgpu_pm_compute_clocks(adev); + } + + return 0; +} + +int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_mclk_od) + return 0; + + return pp_funcs->get_mclk_od(adev->powerplay.pp_handle); +} + +int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (is_support_sw_smu(adev)) + return 0; + + if (pp_funcs->set_mclk_od) + pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); + + if (amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_READJUST_POWER_STATE, + NULL) == -EOPNOTSUPP) { + adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; + amdgpu_pm_compute_clocks(adev); + } + + return 0; +} + +int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, + char *buf) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_power_profile_mode) + return -EOPNOTSUPP; + + return pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, + buf); +} + +int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, + long *input, uint32_t size) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_power_profile_mode) + return 0; + + return pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, + input, + size); +} + +int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_gpu_metrics) + return 0; + + return pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, table); +} + +int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, + uint32_t *fan_mode) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_fan_control_mode) + return -EOPNOTSUPP; + + *fan_mode = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle); + + return 0; +} + +int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, + uint32_t speed) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_fan_speed_pwm) + return -EINVAL; + + return pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, speed); +} + +int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, + uint32_t *speed) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_fan_speed_pwm) + return -EINVAL; + + return pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, speed); +} + +int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, + uint32_t *speed) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_fan_speed_rpm) + return -EINVAL; + + return pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, speed); +} + +int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, + uint32_t speed) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_fan_speed_rpm) + return -EINVAL; + + return pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, speed); +} + +int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, + uint32_t mode) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_fan_control_mode) + return -EOPNOTSUPP; + + pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, mode); + + return 0; +} + +int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, + uint32_t *limit, + enum pp_power_limit_level pp_limit_level, + enum pp_power_type power_type) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_power_limit) + return -ENODATA; + + return pp_funcs->get_power_limit(adev->powerplay.pp_handle, + limit, + pp_limit_level, + power_type); +} + +int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, + uint32_t limit) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_power_limit) + return -EINVAL; + + return pp_funcs->set_power_limit(adev->powerplay.pp_handle, limit); +} + +int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) +{ + if (!is_support_sw_smu(adev)) + return false; + + return is_support_cclk_dpm(adev); +} + +int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, + struct seq_file *m) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->debugfs_print_current_performance_level) + return -EOPNOTSUPP; + + pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, + m); + + return 0; +} + +int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, + void **addr, + size_t *size) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_smu_prv_buf_details) + return -ENOSYS; + + return pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, + addr, + size); +} + +int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) +{ + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || + (is_support_sw_smu(adev) && adev->smu.is_apu) || + (!is_support_sw_smu(adev) && hwmgr->od_enabled)) + return true; + + return false; +} + +int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, + const char *buf, + size_t size) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_pp_table) + return -EOPNOTSUPP; + + return pp_funcs->set_pp_table(adev->powerplay.pp_handle, + buf, + size); +} + +int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) +{ + return adev->smu.cpu_core_num; +} + +void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) +{ + if (!is_support_sw_smu(adev)) + return; + + amdgpu_smu_stb_debug_fs_init(adev); +} diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index e2cae97f4ff1..b16bb67b93f1 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -34,7 +34,6 @@ #include #include #include -#include "hwmgr.h" static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"}, @@ -132,7 +131,6 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_pm_state_type pm; int ret; @@ -147,11 +145,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, return ret; } - if (pp_funcs->get_current_power_state) { - pm = amdgpu_dpm_get_current_power_state(adev); - } else { - pm = adev->pm.dpm.user_state; - } + amdgpu_dpm_get_current_power_state(adev, &pm); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -191,19 +185,8 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.user_state = state; - mutex_unlock(&adev->pm.mutex); - } else if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state); - } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.user_state = state; - mutex_unlock(&adev->pm.mutex); + amdgpu_dpm_set_power_state(adev, state); - amdgpu_pm_compute_clocks(adev); - } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -290,10 +273,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_performance_level) - level = amdgpu_dpm_get_performance_level(adev); - else - level = adev->pm.dpm.forced_level; + level = amdgpu_dpm_get_performance_level(adev); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -318,7 +298,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_dpm_forced_level level; enum amd_dpm_forced_level current_level; int ret = 0; @@ -358,11 +337,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } - if (pp_funcs->get_performance_level) - current_level = amdgpu_dpm_get_performance_level(adev); - else - current_level = adev->pm.dpm.forced_level; - + current_level = amdgpu_dpm_get_performance_level(adev); if (current_level == level) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -390,25 +365,12 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return -EINVAL; } - if (pp_funcs->force_performance_level) { - mutex_lock(&adev->pm.mutex); - if (adev->pm.dpm.thermal_active) { - mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - ret = amdgpu_dpm_force_performance_level(adev, level); - if (ret) { - mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } else { - adev->pm.dpm.forced_level = level; - } - mutex_unlock(&adev->pm.mutex); + if (amdgpu_dpm_force_performance_level(adev, level)) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; } + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -421,7 +383,6 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_states_info data; uint32_t i; int buf_len, ret; @@ -437,11 +398,8 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, return ret; } - if (pp_funcs->get_pp_num_states) { - amdgpu_dpm_get_pp_num_states(adev, &data); - } else { + if (amdgpu_dpm_get_pp_num_states(adev, &data)) memset(&data, 0, sizeof(data)); - } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -463,7 +421,6 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_states_info data = {0}; enum amd_pm_state_type pm = 0; int i = 0, ret = 0; @@ -479,15 +436,16 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, return ret; } - if (pp_funcs->get_current_power_state - && pp_funcs->get_pp_num_states) { - pm = amdgpu_dpm_get_current_power_state(adev); - amdgpu_dpm_get_pp_num_states(adev, &data); - } + amdgpu_dpm_get_current_power_state(adev, &pm); + + ret = amdgpu_dpm_get_pp_num_states(adev, &data); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + if (ret) + return ret; + for (i = 0; i < data.nums; i++) { if (pm == data.states[i]) break; @@ -525,6 +483,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type state = 0; + struct pp_states_info data; unsigned long idx; int ret; @@ -533,41 +492,49 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; + adev->pp_force_state_enabled = false; + if (strlen(buf) == 1) - adev->pp_force_state_enabled = false; - else if (is_support_sw_smu(adev)) - adev->pp_force_state_enabled = false; - else if (adev->powerplay.pp_funcs->dispatch_tasks && - adev->powerplay.pp_funcs->get_pp_num_states) { - struct pp_states_info data; + return count; - ret = kstrtoul(buf, 0, &idx); - if (ret || idx >= ARRAY_SIZE(data.states)) - return -EINVAL; + ret = kstrtoul(buf, 0, &idx); + if (ret || idx >= ARRAY_SIZE(data.states)) + return -EINVAL; - idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); + idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); - amdgpu_dpm_get_pp_num_states(adev, &data); - state = data.states[idx]; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - /* only set user selected power states */ - if (state != POWER_STATE_TYPE_INTERNAL_BOOT && - state != POWER_STATE_TYPE_DEFAULT) { - amdgpu_dpm_dispatch_task(adev, - AMD_PP_TASK_ENABLE_USER_STATE, &state); - adev->pp_force_state_enabled = true; - } - pm_runtime_mark_last_busy(ddev->dev); + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { pm_runtime_put_autosuspend(ddev->dev); + return ret; } + ret = amdgpu_dpm_get_pp_num_states(adev, &data); + if (ret) + goto err_out; + + state = data.states[idx]; + + /* only set user selected power states */ + if (state != POWER_STATE_TYPE_INTERNAL_BOOT && + state != POWER_STATE_TYPE_DEFAULT) { + ret = amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_ENABLE_USER_STATE, &state); + if (ret) + goto err_out; + + adev->pp_force_state_enabled = true; + } + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return count; + +err_out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return ret; } /** @@ -601,17 +568,13 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_pp_table) { - size = amdgpu_dpm_get_pp_table(adev, &table); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - if (size < 0) - return size; - } else { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return 0; - } + size = amdgpu_dpm_get_pp_table(adev, &table); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (size <= 0) + return size; if (size >= PAGE_SIZE) size = PAGE_SIZE - 1; @@ -642,15 +605,13 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, } ret = amdgpu_dpm_set_pp_table(adev, buf, count); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + if (ret) + return ret; + return count; } @@ -866,46 +827,32 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->set_fine_grain_clk_vol) { - ret = amdgpu_dpm_set_fine_grain_clk_vol(adev, type, - parameter, - parameter_size); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } + if (amdgpu_dpm_set_fine_grain_clk_vol(adev, + type, + parameter, + parameter_size)) + goto err_out; - if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { - ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, - parameter, parameter_size); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } + if (amdgpu_dpm_odn_edit_dpm_table(adev, type, + parameter, parameter_size)) + goto err_out; if (type == PP_OD_COMMIT_DPM_TABLE) { - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, - AMD_PP_TASK_READJUST_POWER_STATE, - NULL); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return count; - } else { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } + if (amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_READJUST_POWER_STATE, + NULL)) + goto err_out; } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); return count; + +err_out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; } static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, @@ -928,8 +875,8 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->print_clock_levels) { - size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + if (size > 0) { size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size); size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf+size); @@ -985,17 +932,14 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->set_ppfeature_status) { - ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } + ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + if (ret) + return -EINVAL; + return count; } @@ -1019,9 +963,8 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_ppfeature_status) - size = amdgpu_dpm_get_ppfeature_status(adev, buf); - else + size = amdgpu_dpm_get_ppfeature_status(adev, buf); + if (size <= 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -1080,9 +1023,8 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->print_clock_levels) - size = amdgpu_dpm_print_clock_levels(adev, type, buf); - else + size = amdgpu_dpm_print_clock_levels(adev, type, buf); + if (size <= 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -1151,10 +1093,7 @@ static ssize_t amdgpu_set_pp_dpm_clock(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->force_clock_level) - ret = amdgpu_dpm_force_clock_level(adev, type, mask); - else - ret = 0; + ret = amdgpu_dpm_force_clock_level(adev, type, mask); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1305,10 +1244,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) - value = 0; - else if (adev->powerplay.pp_funcs->get_sclk_od) - value = amdgpu_dpm_get_sclk_od(adev); + value = amdgpu_dpm_get_sclk_od(adev); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1342,19 +1278,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) { - value = 0; - } else { - if (adev->powerplay.pp_funcs->set_sclk_od) - amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); - - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); - } - } + amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1382,10 +1306,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) - value = 0; - else if (adev->powerplay.pp_funcs->get_mclk_od) - value = amdgpu_dpm_get_mclk_od(adev); + value = amdgpu_dpm_get_mclk_od(adev); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1419,19 +1340,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, return ret; } - if (is_support_sw_smu(adev)) { - value = 0; - } else { - if (adev->powerplay.pp_funcs->set_mclk_od) - amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); - - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); - } - } + amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1479,9 +1388,8 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_power_profile_mode) - size = amdgpu_dpm_get_power_profile_mode(adev, buf); - else + size = amdgpu_dpm_get_power_profile_mode(adev, buf); + if (size <= 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -1545,8 +1453,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->set_power_profile_mode) - ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); + ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1812,9 +1719,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, return ret; } - if (adev->powerplay.pp_funcs->get_gpu_metrics) - size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); - + size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); if (size <= 0) goto out; @@ -2053,7 +1958,6 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ { struct device_attribute *dev_attr = &attr->dev_attr; const char *attr_name = dev_attr->attr.name; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; enum amd_asic_type asic_type = adev->asic_type; if (!(attr->flags & mask)) { @@ -2076,9 +1980,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { *states = ATTR_STATE_UNSUPPORTED; - if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || - (is_support_sw_smu(adev) && adev->smu.is_apu) || - (!is_support_sw_smu(adev) && hwmgr->od_enabled)) + if (amdgpu_dpm_is_overdrive_supported(adev)) *states = ATTR_STATE_SUPPORTED; } else if (DEVICE_ATTR_IS(mem_busy_percent)) { if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) @@ -2106,8 +2008,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { - if (!adev->powerplay.pp_funcs->get_power_profile_mode || - amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) + if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; } @@ -2396,17 +2297,14 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, return ret; } - if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + ret = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (ret) + return -EINVAL; + return sysfs_emit(buf, "%u\n", pwm_mode); } @@ -2434,17 +2332,14 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, return ret; } - if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - amdgpu_dpm_set_fan_control_mode(adev, value); + ret = amdgpu_dpm_set_fan_control_mode(adev, value); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (ret) + return -EINVAL; + return count; } @@ -2476,32 +2371,29 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; + err = kstrtou32(buf, 10, &value); + if (err) + return err; + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + err = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); + if (err) + goto out; + if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - err = kstrtou32(buf, 10, &value); - if (err) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return err; - } - - if (adev->powerplay.pp_funcs->set_fan_speed_pwm) - err = amdgpu_dpm_set_fan_speed_pwm(adev, value); - else err = -EINVAL; + goto out; + } + err = amdgpu_dpm_set_fan_speed_pwm(adev, value); + +out: pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2530,10 +2422,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, return err; } - if (adev->powerplay.pp_funcs->get_fan_speed_pwm) - err = amdgpu_dpm_get_fan_speed_pwm(adev, &speed); - else - err = -EINVAL; + err = amdgpu_dpm_get_fan_speed_pwm(adev, &speed); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2563,10 +2452,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, return err; } - if (adev->powerplay.pp_funcs->get_fan_speed_rpm) - err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); - else - err = -EINVAL; + err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2660,10 +2546,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, return err; } - if (adev->powerplay.pp_funcs->get_fan_speed_rpm) - err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); - else - err = -EINVAL; + err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2688,32 +2571,28 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; + err = kstrtou32(buf, 10, &value); + if (err) + return err; + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + err = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); + if (err) + goto out; if (pwm_mode != AMD_FAN_CTRL_MANUAL) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -ENODATA; + err = -ENODATA; + goto out; } - err = kstrtou32(buf, 10, &value); - if (err) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return err; - } - - if (adev->powerplay.pp_funcs->set_fan_speed_rpm) - err = amdgpu_dpm_set_fan_speed_rpm(adev, value); - else - err = -EINVAL; + err = amdgpu_dpm_set_fan_speed_rpm(adev, value); +out: pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -2742,17 +2621,14 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, return ret; } - if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + ret = amdgpu_dpm_get_fan_control_mode(adev, &pwm_mode); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (ret) + return -EINVAL; + return sysfs_emit(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); } @@ -2788,16 +2664,14 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, return err; } - if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); - pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); - return -EINVAL; - } - amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); + err = amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + if (err) + return -EINVAL; + return count; } @@ -2933,7 +2807,6 @@ static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev, enum pp_power_limit_level pp_limit_level) { struct amdgpu_device *adev = dev_get_drvdata(dev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum pp_power_type power_type = to_sensor_dev_attr(attr)->index; uint32_t limit; ssize_t size; @@ -2944,16 +2817,13 @@ static ssize_t amdgpu_hwmon_show_power_cap_generic(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if ( !(pp_funcs && pp_funcs->get_power_limit)) - return -ENODATA; - r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } - r = pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, + r = amdgpu_dpm_get_power_limit(adev, &limit, pp_limit_level, power_type); if (!r) @@ -3008,7 +2878,6 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, size_t count) { struct amdgpu_device *adev = dev_get_drvdata(dev); - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int limit_type = to_sensor_dev_attr(attr)->index; int err; u32 value; @@ -3034,10 +2903,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, return err; } - if (pp_funcs && pp_funcs->set_power_limit) - err = pp_funcs->set_power_limit(adev->powerplay.pp_handle, value); - else - err = -EINVAL; + err = amdgpu_dpm_set_power_limit(adev, value); pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); @@ -3310,6 +3176,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; + uint32_t speed = 0; /* under multi-vf mode, the hwmon attributes are all not supported */ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) @@ -3374,20 +3241,18 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) return 0; - if (!is_support_sw_smu(adev)) { - /* mask fan attributes if we have no bindings for this asic to expose */ - if ((!adev->powerplay.pp_funcs->get_fan_speed_pwm && - attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ - (!adev->powerplay.pp_funcs->get_fan_control_mode && - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ - effective_mode &= ~S_IRUGO; + /* mask fan attributes if we have no bindings for this asic to expose */ + if (((amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ + ((amdgpu_dpm_get_fan_control_mode(adev, &speed) == -EOPNOTSUPP) && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ + effective_mode &= ~S_IRUGO; - if ((!adev->powerplay.pp_funcs->set_fan_speed_pwm && - attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ - (!adev->powerplay.pp_funcs->set_fan_control_mode && - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ - effective_mode &= ~S_IWUSR; - } + if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ + ((amdgpu_dpm_set_fan_control_mode(adev, speed) == -EOPNOTSUPP) && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ + effective_mode &= ~S_IWUSR; if (((adev->family == AMDGPU_FAMILY_SI) || ((adev->flags & AMD_IS_APU) && @@ -3404,22 +3269,20 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, (attr == &sensor_dev_attr_power1_average.dev_attr.attr)) return 0; - if (!is_support_sw_smu(adev)) { - /* hide max/min values if we can't both query and manage the fan */ - if ((!adev->powerplay.pp_funcs->set_fan_speed_pwm && - !adev->powerplay.pp_funcs->get_fan_speed_pwm) && - (!adev->powerplay.pp_funcs->set_fan_speed_rpm && - !adev->powerplay.pp_funcs->get_fan_speed_rpm) && - (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) - return 0; + /* hide max/min values if we can't both query and manage the fan */ + if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && + (amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && + (amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && + (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL)) && + (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) + return 0; - if ((!adev->powerplay.pp_funcs->set_fan_speed_rpm && - !adev->powerplay.pp_funcs->get_fan_speed_rpm) && - (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) - return 0; - } + if ((amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && + (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL) && + (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) + return 0; if ((adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ @@ -3549,14 +3412,15 @@ static void amdgpu_debugfs_prints_cpu_info(struct seq_file *m, uint16_t *p_val; uint32_t size; int i; + uint32_t num_cpu_cores = amdgpu_dpm_get_num_cpu_cores(adev); - if (is_support_cclk_dpm(adev)) { - p_val = kcalloc(adev->smu.cpu_core_num, sizeof(uint16_t), + if (amdgpu_dpm_is_cclk_dpm_supported(adev)) { + p_val = kcalloc(num_cpu_cores, sizeof(uint16_t), GFP_KERNEL); if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_CPU_CLK, (void *)p_val, &size)) { - for (i = 0; i < adev->smu.cpu_core_num; i++) + for (i = 0; i < num_cpu_cores; i++) seq_printf(m, "\t%u MHz (CPU%d)\n", *(p_val + i), i); } @@ -3684,27 +3548,11 @@ static int amdgpu_debugfs_pm_info_show(struct seq_file *m, void *unused) return r; } - if (!adev->pm.dpm_enabled) { - seq_printf(m, "dpm not enabled\n"); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); - return 0; - } - - if (!is_support_sw_smu(adev) && - adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { - mutex_lock(&adev->pm.mutex); - if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) - adev->powerplay.pp_funcs->debugfs_print_current_performance_level(adev, m); - else - seq_printf(m, "Debugfs support not implemented for this asic\n"); - mutex_unlock(&adev->pm.mutex); - r = 0; - } else { + if (amdgpu_dpm_debugfs_print_current_performance_level(adev, m)) { r = amdgpu_debugfs_pm_info_pp(m, adev); + if (r) + goto out; } - if (r) - goto out; amdgpu_device_ip_get_clockgating_state(adev, &flags); @@ -3730,21 +3578,18 @@ static ssize_t amdgpu_pm_prv_buffer_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { struct amdgpu_device *adev = file_inode(f)->i_private; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; size_t smu_prv_buf_size; void *smu_prv_buf; + int ret = 0; if (amdgpu_in_reset(adev)) return -EPERM; if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if (pp_funcs && pp_funcs->get_smu_prv_buf_details) - pp_funcs->get_smu_prv_buf_details(pp_handle, &smu_prv_buf, - &smu_prv_buf_size); - else - return -ENOSYS; + ret = amdgpu_dpm_get_smu_prv_buf_details(adev, &smu_prv_buf, &smu_prv_buf_size); + if (ret) + return ret; if (!smu_prv_buf || !smu_prv_buf_size) return -EINVAL; @@ -3777,6 +3622,6 @@ void amdgpu_debugfs_pm_init(struct amdgpu_device *adev) &amdgpu_debugfs_pm_prv_buffer_fops, adev->pm.smu_prv_buffer_size); - amdgpu_smu_stb_debug_fs_init(adev); + amdgpu_dpm_stb_debug_fs_init(adev); #endif } diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index b444937c3b68..ef0df75b4040 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -262,9 +262,6 @@ enum amdgpu_pcie_gen { #define amdgpu_dpm_pre_set_power_state(adev) \ ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) -#define amdgpu_dpm_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->set_power_state((adev)->powerplay.pp_handle)) - #define amdgpu_dpm_post_set_power_state(adev) \ ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) @@ -280,100 +277,13 @@ enum amdgpu_pcie_gen { #define amdgpu_dpm_enable_bapm(adev, e) \ ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) -#define amdgpu_dpm_set_fan_control_mode(adev, m) \ - ((adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m))) - -#define amdgpu_dpm_get_fan_control_mode(adev) \ - ((adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_fan_speed_pwm(adev, s) \ - ((adev)->powerplay.pp_funcs->set_fan_speed_pwm((adev)->powerplay.pp_handle, (s))) - -#define amdgpu_dpm_get_fan_speed_pwm(adev, s) \ - ((adev)->powerplay.pp_funcs->get_fan_speed_pwm((adev)->powerplay.pp_handle, (s))) - -#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \ - ((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) - -#define amdgpu_dpm_set_fan_speed_rpm(adev, s) \ - ((adev)->powerplay.pp_funcs->set_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) - -#define amdgpu_dpm_force_performance_level(adev, l) \ - ((adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l))) - -#define amdgpu_dpm_get_current_power_state(adev) \ - ((adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_get_pp_num_states(adev, data) \ - ((adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)) - -#define amdgpu_dpm_get_pp_table(adev, table) \ - ((adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)) - -#define amdgpu_dpm_set_pp_table(adev, buf, size) \ - ((adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)) - -#define amdgpu_dpm_print_clock_levels(adev, type, buf) \ - ((adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)) - -#define amdgpu_dpm_force_clock_level(adev, type, level) \ - ((adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)) - -#define amdgpu_dpm_get_sclk_od(adev) \ - ((adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_sclk_od(adev, value) \ - ((adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)) - -#define amdgpu_dpm_get_mclk_od(adev) \ - ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_mclk_od(adev, value) \ - ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) - -#define amdgpu_dpm_dispatch_task(adev, task_id, user_state) \ - ((adev)->powerplay.pp_funcs->dispatch_tasks)((adev)->powerplay.pp_handle, (task_id), (user_state)) - #define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) -#define amdgpu_dpm_get_vce_clock_state(adev, i) \ - ((adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i))) - -#define amdgpu_dpm_get_performance_level(adev) \ - ((adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)) - #define amdgpu_dpm_reset_power_profile_state(adev, request) \ ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ (adev)->powerplay.pp_handle, request)) -#define amdgpu_dpm_get_power_profile_mode(adev, buf) \ - ((adev)->powerplay.pp_funcs->get_power_profile_mode(\ - (adev)->powerplay.pp_handle, buf)) - -#define amdgpu_dpm_set_power_profile_mode(adev, parameter, size) \ - ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ - (adev)->powerplay.pp_handle, parameter, size)) - -#define amdgpu_dpm_set_fine_grain_clk_vol(adev, type, parameter, size) \ - ((adev)->powerplay.pp_funcs->set_fine_grain_clk_vol(\ - (adev)->powerplay.pp_handle, type, parameter, size)) - -#define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ - ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ - (adev)->powerplay.pp_handle, type, parameter, size)) - -#define amdgpu_dpm_get_ppfeature_status(adev, buf) \ - ((adev)->powerplay.pp_funcs->get_ppfeature_status(\ - (adev)->powerplay.pp_handle, (buf))) - -#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \ - ((adev)->powerplay.pp_funcs->set_ppfeature_status(\ - (adev)->powerplay.pp_handle, (ppfeatures))) - -#define amdgpu_dpm_get_gpu_metrics(adev, table) \ - ((adev)->powerplay.pp_funcs->get_gpu_metrics((adev)->powerplay.pp_handle, table)) - struct amdgpu_dpm { struct amdgpu_ps *ps; /* number of valid power states */ @@ -606,4 +516,74 @@ void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, enum gfx_change_state state); int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, void *umc_ecc); +struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, + uint32_t idx); +void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, enum amd_pm_state_type *state); +void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type state); +enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev); +int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, + enum amd_dpm_forced_level level); +int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, + struct pp_states_info *states); +int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, + enum amd_pp_task task_id, + enum amd_pm_state_type *user_state); +int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table); +int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, + uint32_t type, + long *input, + uint32_t size); +int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, + uint32_t type, + long *input, + uint32_t size); +int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, + enum pp_clock_type type, + char *buf); +int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, + uint64_t ppfeature_masks); +int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf); +int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, + enum pp_clock_type type, + uint32_t mask); +int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev); +int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value); +int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev); +int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value); +int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, + char *buf); +int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, + long *input, uint32_t size); +int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table); +int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, + uint32_t *fan_mode); +int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, + uint32_t speed); +int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, + uint32_t *speed); +int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, + uint32_t *speed); +int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, + uint32_t speed); +int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, + uint32_t mode); +int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, + uint32_t *limit, + enum pp_power_limit_level pp_limit_level, + enum pp_power_type power_type); +int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, + uint32_t limit); +int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev); +int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, + struct seq_file *m); +int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, + void **addr, + size_t *size); +int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev); +int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, + const char *buf, + size_t size); +int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev); +void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 9d5a5a1f15df..7191b3928e8e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -470,9 +470,6 @@ bool is_support_cclk_dpm(struct amdgpu_device *adev) { struct smu_context *smu = &adev->smu; - if (!is_support_sw_smu(adev)) - return false; - if (!smu_feature_is_enabled(smu, SMU_FEATURE_CCLK_DPM_BIT)) return false; From 13f5dbd6e3d9a4ea0a8d061bb2a2f19bb21cdacc Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 22 Nov 2021 11:09:08 +0800 Subject: [PATCH 006/339] drm/amd/pm: do not expose power implementation details to display Display is another client of our power APIs. It's not proper to spike into power implementation details there. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +- .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 246 +++++++----------- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 218 ++++++++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 38 +++ 4 files changed, 344 insertions(+), 164 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index afadec2d1993..6692c8f75f23 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2179,12 +2179,8 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; int ret = 0; - if (!is_support_sw_smu(adev)) - return 0; - /* This interface is for dGPU Navi1x.Linux dc-pplib interface depends * on window driver dc implementation. * For Navi1x, clock settings of dcn watermarks are fixed. the settings @@ -2223,7 +2219,7 @@ static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev) return 0; } - ret = smu_write_watermarks_table(smu); + ret = amdgpu_dpm_write_watermarks_table(adev); if (ret) { DRM_ERROR("Failed to update WMTABLE!\n"); return ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index eba270121698..46550811da00 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -99,10 +99,7 @@ bool dm_pp_apply_display_requirements( adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1; } - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_configuration_change) - adev->powerplay.pp_funcs->display_configuration_change( - adev->powerplay.pp_handle, - &adev->pm.pm_display_cfg); + amdgpu_dpm_display_configuration_change(adev, &adev->pm.pm_display_cfg); amdgpu_pm_compute_clocks(adev); } @@ -298,31 +295,25 @@ bool dm_pp_get_clock_levels_by_type( struct dm_pp_clock_levels *dc_clks) { struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; struct amd_pp_clocks pp_clks = { 0 }; struct amd_pp_simple_clock_info validation_clks = { 0 }; uint32_t i; - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) { - if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, - dc_to_pp_clock_type(clk_type), &pp_clks)) { - /* Error in pplib. Provide default values. */ - get_default_clock_levels(clk_type, dc_clks); - return true; - } + if (amdgpu_dpm_get_clock_by_type(adev, + dc_to_pp_clock_type(clk_type), &pp_clks)) { + /* Error in pplib. Provide default values. */ + get_default_clock_levels(clk_type, dc_clks); + return true; } pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_display_mode_validation_clocks) { - if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks( - pp_handle, &validation_clks)) { - /* Error in pplib. Provide default values. */ - DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n"); - validation_clks.engine_max_clock = 72000; - validation_clks.memory_max_clock = 80000; - validation_clks.level = 0; - } + if (amdgpu_dpm_get_display_mode_validation_clks(adev, &validation_clks)) { + /* Error in pplib. Provide default values. */ + DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n"); + validation_clks.engine_max_clock = 72000; + validation_clks.memory_max_clock = 80000; + validation_clks.level = 0; } DRM_INFO("DM_PPLIB: Validation clocks:\n"); @@ -370,18 +361,14 @@ bool dm_pp_get_clock_levels_by_type_with_latency( struct dm_pp_clock_levels_with_latency *clk_level_info) { struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; struct pp_clock_levels_with_latency pp_clks = { 0 }; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int ret; - if (pp_funcs && pp_funcs->get_clock_by_type_with_latency) { - ret = pp_funcs->get_clock_by_type_with_latency(pp_handle, - dc_to_pp_clock_type(clk_type), - &pp_clks); - if (ret) - return false; - } + ret = amdgpu_dpm_get_clock_by_type_with_latency(adev, + dc_to_pp_clock_type(clk_type), + &pp_clks); + if (ret) + return false; pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type); @@ -394,18 +381,14 @@ bool dm_pp_get_clock_levels_by_type_with_voltage( struct dm_pp_clock_levels_with_voltage *clk_level_info) { struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; struct pp_clock_levels_with_voltage pp_clk_info = {0}; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int ret; - if (pp_funcs && pp_funcs->get_clock_by_type_with_voltage) { - ret = pp_funcs->get_clock_by_type_with_voltage(pp_handle, - dc_to_pp_clock_type(clk_type), - &pp_clk_info); - if (ret) - return false; - } + ret = amdgpu_dpm_get_clock_by_type_with_voltage(adev, + dc_to_pp_clock_type(clk_type), + &pp_clk_info); + if (ret) + return false; pp_to_dc_clock_levels_with_voltage(&pp_clk_info, clk_level_info, clk_type); @@ -417,19 +400,16 @@ bool dm_pp_notify_wm_clock_changes( struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges) { struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; /* * Limit this watermark setting for Polaris for now * TODO: expand this to other ASICs */ - if ((adev->asic_type >= CHIP_POLARIS10) && (adev->asic_type <= CHIP_VEGAM) - && pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges) { - if (!pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, + if ((adev->asic_type >= CHIP_POLARIS10) && + (adev->asic_type <= CHIP_VEGAM) && + !amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, (void *)wm_with_clock_ranges)) return true; - } return false; } @@ -456,12 +436,10 @@ bool dm_pp_apply_clock_for_voltage_request( if (!pp_clock_request.clock_type) return false; - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_clock_voltage_request) - ret = adev->powerplay.pp_funcs->display_clock_voltage_request( - adev->powerplay.pp_handle, - &pp_clock_request); - if (ret) + ret = amdgpu_dpm_display_clock_voltage_request(adev, &pp_clock_request); + if (ret && (ret != -EOPNOTSUPP)) return false; + return true; } @@ -471,15 +449,8 @@ bool dm_pp_get_static_clocks( { struct amdgpu_device *adev = ctx->driver_context; struct amd_pp_clock_info pp_clk_info = {0}; - int ret = 0; - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_current_clocks) - ret = adev->powerplay.pp_funcs->get_current_clocks( - adev->powerplay.pp_handle, - &pp_clk_info); - else - return false; - if (ret) + if (amdgpu_dpm_get_current_clocks(adev, &pp_clk_info)) return false; static_clk_info->max_clocks_state = pp_to_dc_powerlevel_state(pp_clk_info.max_clocks_state); @@ -494,8 +465,6 @@ static void pp_rv_set_wm_ranges(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges; struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = wm_with_clock_ranges.wm_dmif_clocks_ranges; struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = wm_with_clock_ranges.wm_mcif_clocks_ranges; @@ -536,72 +505,48 @@ static void pp_rv_set_wm_ranges(struct pp_smu *pp, ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000; } - if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges) - pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, - &wm_with_clock_ranges); + amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, + &wm_with_clock_ranges); } static void pp_rv_set_pme_wa_enable(struct pp_smu *pp) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (pp_funcs && pp_funcs->notify_smu_enable_pwe) - pp_funcs->notify_smu_enable_pwe(pp_handle); + amdgpu_dpm_notify_smu_enable_pwe(adev); } static void pp_rv_set_active_display_count(struct pp_smu *pp, int count) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (!pp_funcs || !pp_funcs->set_active_display_count) - return; - - pp_funcs->set_active_display_count(pp_handle, count); + amdgpu_dpm_set_active_display_count(adev, count); } static void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk) - return; - - pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock); + amdgpu_dpm_set_min_deep_sleep_dcefclk(adev, clock); } static void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq) - return; - - pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock); + amdgpu_dpm_set_hard_min_dcefclk_by_freq(adev, clock); } static void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq) - return; - - pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz); + amdgpu_dpm_set_hard_min_fclk_by_freq(adev, mhz); } static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp, @@ -609,11 +554,8 @@ static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges) - pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, ranges); + amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, ranges); return PP_SMU_RESULT_OK; } @@ -622,14 +564,13 @@ static enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - if (!pp_funcs || !pp_funcs->set_active_display_count) + ret = amdgpu_dpm_set_active_display_count(adev, count); + if (ret == -EOPNOTSUPP) return PP_SMU_RESULT_UNSUPPORTED; - - /* 0: successful or smu.ppt_funcs->set_display_count = NULL; 1: fail */ - if (pp_funcs->set_active_display_count(pp_handle, count)) + else if (ret) + /* 0: successful or smu.ppt_funcs->set_display_count = NULL; 1: fail */ return PP_SMU_RESULT_FAIL; return PP_SMU_RESULT_OK; @@ -640,14 +581,13 @@ pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - - if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk) - return PP_SMU_RESULT_UNSUPPORTED; + int ret = 0; /* 0: successful or smu.ppt_funcs->set_deep_sleep_dcefclk = NULL;1: fail */ - if (pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, mhz)) + ret = amdgpu_dpm_set_min_deep_sleep_dcefclk(adev, mhz); + if (ret == -EOPNOTSUPP) + return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) return PP_SMU_RESULT_FAIL; return PP_SMU_RESULT_OK; @@ -658,12 +598,8 @@ static enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq( { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_display_clock_request clock_req; - - if (!pp_funcs || !pp_funcs->display_clock_voltage_request) - return PP_SMU_RESULT_UNSUPPORTED; + int ret = 0; clock_req.clock_type = amd_pp_dcef_clock; clock_req.clock_freq_in_khz = mhz * 1000; @@ -671,7 +607,10 @@ static enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq( /* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL * 1: fail */ - if (pp_funcs->display_clock_voltage_request(pp_handle, &clock_req)) + ret = amdgpu_dpm_display_clock_voltage_request(adev, &clock_req); + if (ret == -EOPNOTSUPP) + return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) return PP_SMU_RESULT_FAIL; return PP_SMU_RESULT_OK; @@ -682,12 +621,8 @@ pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_display_clock_request clock_req; - - if (!pp_funcs || !pp_funcs->display_clock_voltage_request) - return PP_SMU_RESULT_UNSUPPORTED; + int ret = 0; clock_req.clock_type = amd_pp_mem_clock; clock_req.clock_freq_in_khz = mhz * 1000; @@ -695,7 +630,10 @@ pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) /* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL * 1: fail */ - if (pp_funcs->display_clock_voltage_request(pp_handle, &clock_req)) + ret = amdgpu_dpm_display_clock_voltage_request(adev, &clock_req); + if (ret == -EOPNOTSUPP) + return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) return PP_SMU_RESULT_FAIL; return PP_SMU_RESULT_OK; @@ -706,14 +644,10 @@ static enum pp_smu_status pp_nv_set_pstate_handshake_support( { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (pp_funcs && pp_funcs->display_disable_memory_clock_switch) { - if (pp_funcs->display_disable_memory_clock_switch(pp_handle, - !pstate_handshake_supported)) - return PP_SMU_RESULT_FAIL; - } + if (amdgpu_dpm_display_disable_memory_clock_switch(adev, + !pstate_handshake_supported)) + return PP_SMU_RESULT_FAIL; return PP_SMU_RESULT_OK; } @@ -723,12 +657,8 @@ static enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_display_clock_request clock_req; - - if (!pp_funcs || !pp_funcs->display_clock_voltage_request) - return PP_SMU_RESULT_UNSUPPORTED; + int ret = 0; switch (clock_id) { case PP_SMU_NV_DISPCLK: @@ -748,7 +678,10 @@ static enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp, /* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL * 1: fail */ - if (pp_funcs->display_clock_voltage_request(pp_handle, &clock_req)) + ret = amdgpu_dpm_display_clock_voltage_request(adev, &clock_req); + if (ret == -EOPNOTSUPP) + return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) return PP_SMU_RESULT_FAIL; return PP_SMU_RESULT_OK; @@ -759,16 +692,16 @@ static enum pp_smu_status pp_nv_get_maximum_sustainable_clocks( { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - if (!pp_funcs || !pp_funcs->get_max_sustainable_clocks_by_dc) + ret = amdgpu_dpm_get_max_sustainable_clocks_by_dc(adev, + max_clocks); + if (ret == -EOPNOTSUPP) return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) + return PP_SMU_RESULT_FAIL; - if (!pp_funcs->get_max_sustainable_clocks_by_dc(pp_handle, max_clocks)) - return PP_SMU_RESULT_OK; - - return PP_SMU_RESULT_FAIL; + return PP_SMU_RESULT_OK; } static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp, @@ -776,18 +709,17 @@ static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - if (!pp_funcs || !pp_funcs->get_uclk_dpm_states) + ret = amdgpu_dpm_get_uclk_dpm_states(adev, + clock_values_in_khz, + num_states); + if (ret == -EOPNOTSUPP) return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) + return PP_SMU_RESULT_FAIL; - if (!pp_funcs->get_uclk_dpm_states(pp_handle, - clock_values_in_khz, - num_states)) - return PP_SMU_RESULT_OK; - - return PP_SMU_RESULT_FAIL; + return PP_SMU_RESULT_OK; } static enum pp_smu_status pp_rn_get_dpm_clock_table( @@ -795,16 +727,15 @@ static enum pp_smu_status pp_rn_get_dpm_clock_table( { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - if (!pp_funcs || !pp_funcs->get_dpm_clock_table) + ret = amdgpu_dpm_get_dpm_clock_table(adev, clock_table); + if (ret == -EOPNOTSUPP) return PP_SMU_RESULT_UNSUPPORTED; + else if (ret) + return PP_SMU_RESULT_FAIL; - if (!pp_funcs->get_dpm_clock_table(pp_handle, clock_table)) - return PP_SMU_RESULT_OK; - - return PP_SMU_RESULT_FAIL; + return PP_SMU_RESULT_OK; } static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp, @@ -812,11 +743,8 @@ static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp, { const struct dc_context *ctx = pp->dm; struct amdgpu_device *adev = ctx->driver_context; - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges) - pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, ranges); + amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, ranges); return PP_SMU_RESULT_OK; } diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 494cf1459d0f..6adc174bb981 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1659,6 +1659,14 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, } } +int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) +{ + if (!is_support_sw_smu(adev)) + return 0; + + return smu_write_watermarks_table(&adev->smu); +} + int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, uint64_t event_arg) @@ -2163,3 +2171,213 @@ void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) amdgpu_smu_stb_debug_fs_init(adev); } + +int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, + const struct amd_pp_display_configuration *input) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->display_configuration_change) + return 0; + + return pp_funcs->display_configuration_change(adev->powerplay.pp_handle, + input); +} + +int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, + enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_clock_by_type) + return 0; + + return pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, + type, + clocks); +} + +int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, + struct amd_pp_simple_clock_info *clocks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_display_mode_validation_clocks) + return 0; + + return pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, + clocks); +} + +int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_clock_by_type_with_latency) + return 0; + + return pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, + type, + clocks); +} + +int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_clock_by_type_with_voltage) + return 0; + + return pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, + type, + clocks); +} + +int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, + void *clock_ranges) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_watermarks_for_clocks_ranges) + return -EOPNOTSUPP; + + return pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, + clock_ranges); +} + +int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, + struct pp_display_clock_request *clock) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->display_clock_voltage_request) + return -EOPNOTSUPP; + + return pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, + clock); +} + +int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, + struct amd_pp_clock_info *clocks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_current_clocks) + return -EOPNOTSUPP; + + return pp_funcs->get_current_clocks(adev->powerplay.pp_handle, + clocks); +} + +void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->notify_smu_enable_pwe) + return; + + pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); +} + +int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, + uint32_t count) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_active_display_count) + return -EOPNOTSUPP; + + return pp_funcs->set_active_display_count(adev->powerplay.pp_handle, + count); +} + +int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, + uint32_t clock) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_min_deep_sleep_dcefclk) + return -EOPNOTSUPP; + + return pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, + clock); +} + +void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, + uint32_t clock) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_hard_min_dcefclk_by_freq) + return; + + pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, + clock); +} + +void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, + uint32_t clock) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->set_hard_min_fclk_by_freq) + return; + + pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, + clock); +} + +int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, + bool disable_memory_clock_switch) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->display_disable_memory_clock_switch) + return 0; + + return pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, + disable_memory_clock_switch); +} + +int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, + struct pp_smu_nv_clock_table *max_clocks) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_max_sustainable_clocks_by_dc) + return -EOPNOTSUPP; + + return pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, + max_clocks); +} + +enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, + unsigned int *clock_values_in_khz, + unsigned int *num_states) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_uclk_dpm_states) + return -EOPNOTSUPP; + + return pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, + clock_values_in_khz, + num_states); +} + +int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, + struct dpm_clocks *clock_table) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + + if (!pp_funcs->get_dpm_clock_table) + return -EOPNOTSUPP; + + return pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, + clock_table); +} diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index ef0df75b4040..649041dadf52 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -508,6 +508,7 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t min, uint32_t max); +int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev); int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, uint64_t event_arg); int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); @@ -586,4 +587,41 @@ int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, size_t size); int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev); void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev); +int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, + const struct amd_pp_display_configuration *input); +int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, + enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks); +int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, + struct amd_pp_simple_clock_info *clocks); +int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks); +int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks); +int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, + void *clock_ranges); +int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, + struct pp_display_clock_request *clock); +int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, + struct amd_pp_clock_info *clocks); +void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev); +int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, + uint32_t count); +int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, + uint32_t clock); +void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, + uint32_t clock); +void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, + uint32_t clock); +int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, + bool disable_memory_clock_switch); +int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, + struct pp_smu_nv_clock_table *max_clocks); +enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, + unsigned int *clock_values_in_khz, + unsigned int *num_states); +int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, + struct dpm_clocks *clock_table); #endif From d448157665870bfbf9b6baa5991cd9d6bc98c7e6 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 11 Nov 2021 10:02:20 +0800 Subject: [PATCH 007/339] drm/amd/pm: do not expose those APIs used internally only in amdgpu_dpm.c Move them to amdgpu_dpm.c instead. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 25 +++++++++++++++++++++++-- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 23 ----------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 6adc174bb981..dce9b02460e6 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -34,6 +34,27 @@ #define WIDTH_4K 3840 +#define amdgpu_dpm_pre_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_post_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_display_configuration_changed(adev) \ + ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_print_power_state(adev, ps) \ + ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) + +#define amdgpu_dpm_vblank_too_short(adev) \ + ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_enable_bapm(adev, e) \ + ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) + +#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ + ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) + void amdgpu_dpm_print_class_info(u32 class, u32 class2) { const char *s; @@ -120,7 +141,7 @@ void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, pr_cont("\n"); } -void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) +static void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) { struct drm_device *ddev = adev_to_drm(adev); struct drm_crtc *crtc; @@ -168,7 +189,7 @@ u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) return vblank_time_us; } -u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) +static u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) { struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 649041dadf52..2897d395ff31 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -259,27 +259,6 @@ enum amdgpu_pcie_gen { AMDGPU_PCIE_GEN_INVALID = 0xffff }; -#define amdgpu_dpm_pre_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_post_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_display_configuration_changed(adev) \ - ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_print_power_state(adev, ps) \ - ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) - -#define amdgpu_dpm_vblank_too_short(adev) \ - ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_enable_bapm(adev, e) \ - ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) - -#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ - ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) - #define amdgpu_dpm_reset_power_profile_state(adev, request) \ ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ (adev)->powerplay.pp_handle, request)) @@ -420,8 +399,6 @@ void amdgpu_dpm_print_cap_info(u32 caps); void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, struct amdgpu_ps *rps); u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); -u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev); -void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev); int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, void *data, uint32_t *size); From a79110f2dc0194326d2e8c2cf83db6c784c37e97 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 11 Nov 2021 10:12:29 +0800 Subject: [PATCH 008/339] drm/amd/pm: do not expose those APIs used internally only in si_dpm.c Move them to si_dpm.c instead. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 25 ----- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 25 ----- drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 106 +++++++++++++++------- drivers/gpu/drm/amd/pm/powerplay/si_dpm.h | 15 ++- 4 files changed, 83 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index dce9b02460e6..c97e79862779 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -894,31 +894,6 @@ void amdgpu_add_thermal_controller(struct amdgpu_device *adev) } } -enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev, - u32 sys_mask, - enum amdgpu_pcie_gen asic_gen, - enum amdgpu_pcie_gen default_gen) -{ - switch (asic_gen) { - case AMDGPU_PCIE_GEN1: - return AMDGPU_PCIE_GEN1; - case AMDGPU_PCIE_GEN2: - return AMDGPU_PCIE_GEN2; - case AMDGPU_PCIE_GEN3: - return AMDGPU_PCIE_GEN3; - default: - if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) && - (default_gen == AMDGPU_PCIE_GEN3)) - return AMDGPU_PCIE_GEN3; - else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) && - (default_gen == AMDGPU_PCIE_GEN2)) - return AMDGPU_PCIE_GEN2; - else - return AMDGPU_PCIE_GEN1; - } - return AMDGPU_PCIE_GEN1; -} - struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx) { diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 2897d395ff31..108706ee8760 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -45,19 +45,6 @@ enum amdgpu_int_thermal_type { THERMAL_TYPE_KV, }; -enum amdgpu_dpm_auto_throttle_src { - AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, - AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL -}; - -enum amdgpu_dpm_event_src { - AMDGPU_DPM_EVENT_SRC_ANALOG = 0, - AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1, - AMDGPU_DPM_EVENT_SRC_DIGITAL = 2, - AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, - AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 -}; - struct amdgpu_ps { u32 caps; /* vbios flags */ u32 class; /* vbios flags */ @@ -252,13 +239,6 @@ struct amdgpu_dpm_fan { bool ucode_fan_control; }; -enum amdgpu_pcie_gen { - AMDGPU_PCIE_GEN1 = 0, - AMDGPU_PCIE_GEN2 = 1, - AMDGPU_PCIE_GEN3 = 2, - AMDGPU_PCIE_GEN_INVALID = 0xffff -}; - #define amdgpu_dpm_reset_power_profile_state(adev, request) \ ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ (adev)->powerplay.pp_handle, request)) @@ -411,11 +391,6 @@ void amdgpu_free_extended_power_table(struct amdgpu_device *adev); void amdgpu_add_thermal_controller(struct amdgpu_device *adev); -enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev, - u32 sys_mask, - enum amdgpu_pcie_gen asic_gen, - enum amdgpu_pcie_gen default_gen); - struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx); diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c index 81f82aa05ec2..2823376797d3 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -96,6 +96,19 @@ union pplib_clock_info { struct _ATOM_PPLIB_SI_CLOCK_INFO si; }; +enum si_dpm_auto_throttle_src { + SI_DPM_AUTO_THROTTLE_SRC_THERMAL, + SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL +}; + +enum si_dpm_event_src { + SI_DPM_EVENT_SRC_ANALOG = 0, + SI_DPM_EVENT_SRC_EXTERNAL = 1, + SI_DPM_EVENT_SRC_DIGITAL = 2, + SI_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, + SI_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 +}; + static const u32 r600_utc[R600_PM_NUMBER_OF_TC] = { R600_UTC_DFLT_00, @@ -3718,25 +3731,25 @@ static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources) { struct rv7xx_power_info *pi = rv770_get_pi(adev); bool want_thermal_protection; - enum amdgpu_dpm_event_src dpm_event_src; + enum si_dpm_event_src dpm_event_src; switch (sources) { case 0: default: want_thermal_protection = false; break; - case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL): + case (1 << SI_DPM_AUTO_THROTTLE_SRC_THERMAL): want_thermal_protection = true; - dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGITAL; + dpm_event_src = SI_DPM_EVENT_SRC_DIGITAL; break; - case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL): + case (1 << SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL): want_thermal_protection = true; - dpm_event_src = AMDGPU_DPM_EVENT_SRC_EXTERNAL; + dpm_event_src = SI_DPM_EVENT_SRC_EXTERNAL; break; - case ((1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL) | - (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL)): + case ((1 << SI_DPM_AUTO_THROTTLE_SRC_EXTERNAL) | + (1 << SI_DPM_AUTO_THROTTLE_SRC_THERMAL)): want_thermal_protection = true; - dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL; + dpm_event_src = SI_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL; break; } @@ -3750,7 +3763,7 @@ static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources) } static void si_enable_auto_throttle_source(struct amdgpu_device *adev, - enum amdgpu_dpm_auto_throttle_src source, + enum si_dpm_auto_throttle_src source, bool enable) { struct rv7xx_power_info *pi = rv770_get_pi(adev); @@ -4927,6 +4940,31 @@ static int si_populate_smc_initial_state(struct amdgpu_device *adev, return 0; } +static enum si_pcie_gen si_gen_pcie_gen_support(struct amdgpu_device *adev, + u32 sys_mask, + enum si_pcie_gen asic_gen, + enum si_pcie_gen default_gen) +{ + switch (asic_gen) { + case SI_PCIE_GEN1: + return SI_PCIE_GEN1; + case SI_PCIE_GEN2: + return SI_PCIE_GEN2; + case SI_PCIE_GEN3: + return SI_PCIE_GEN3; + default: + if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) && + (default_gen == SI_PCIE_GEN3)) + return SI_PCIE_GEN3; + else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) && + (default_gen == SI_PCIE_GEN2)) + return SI_PCIE_GEN2; + else + return SI_PCIE_GEN1; + } + return SI_PCIE_GEN1; +} + static int si_populate_smc_acpi_state(struct amdgpu_device *adev, SISLANDS_SMC_STATETABLE *table) { @@ -4989,10 +5027,10 @@ static int si_populate_smc_acpi_state(struct amdgpu_device *adev, &table->ACPIState.level.std_vddc); } table->ACPIState.level.gen2PCIE = - (u8)amdgpu_get_pcie_gen_support(adev, - si_pi->sys_pcie_mask, - si_pi->boot_pcie_gen, - AMDGPU_PCIE_GEN1); + (u8)si_gen_pcie_gen_support(adev, + si_pi->sys_pcie_mask, + si_pi->boot_pcie_gen, + SI_PCIE_GEN1); if (si_pi->vddc_phase_shed_control) si_populate_phase_shedding_value(adev, @@ -5430,7 +5468,7 @@ static int si_convert_power_level_to_smc(struct amdgpu_device *adev, bool gmc_pg = false; if (eg_pi->pcie_performance_request && - (si_pi->force_pcie_gen != AMDGPU_PCIE_GEN_INVALID)) + (si_pi->force_pcie_gen != SI_PCIE_GEN_INVALID)) level->gen2PCIE = (u8)si_pi->force_pcie_gen; else level->gen2PCIE = (u8)pl->pcie_gen; @@ -6147,8 +6185,8 @@ static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable) WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); } -static enum amdgpu_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state) +static enum si_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) { struct si_ps *state = si_get_ps(amdgpu_state); int i; @@ -6177,27 +6215,27 @@ static void si_request_link_speed_change_before_state_change(struct amdgpu_devic struct amdgpu_ps *amdgpu_current_state) { struct si_power_info *si_pi = si_get_pi(adev); - enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); - enum amdgpu_pcie_gen current_link_speed; + enum si_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); + enum si_pcie_gen current_link_speed; - if (si_pi->force_pcie_gen == AMDGPU_PCIE_GEN_INVALID) + if (si_pi->force_pcie_gen == SI_PCIE_GEN_INVALID) current_link_speed = si_get_maximum_link_speed(adev, amdgpu_current_state); else current_link_speed = si_pi->force_pcie_gen; - si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; + si_pi->force_pcie_gen = SI_PCIE_GEN_INVALID; si_pi->pspp_notify_required = false; if (target_link_speed > current_link_speed) { switch (target_link_speed) { #if defined(CONFIG_ACPI) - case AMDGPU_PCIE_GEN3: + case SI_PCIE_GEN3: if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0) break; - si_pi->force_pcie_gen = AMDGPU_PCIE_GEN2; - if (current_link_speed == AMDGPU_PCIE_GEN2) + si_pi->force_pcie_gen = SI_PCIE_GEN2; + if (current_link_speed == SI_PCIE_GEN2) break; fallthrough; - case AMDGPU_PCIE_GEN2: + case SI_PCIE_GEN2: if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) break; fallthrough; @@ -6217,13 +6255,13 @@ static void si_notify_link_speed_change_after_state_change(struct amdgpu_device struct amdgpu_ps *amdgpu_current_state) { struct si_power_info *si_pi = si_get_pi(adev); - enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); + enum si_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); u8 request; if (si_pi->pspp_notify_required) { - if (target_link_speed == AMDGPU_PCIE_GEN3) + if (target_link_speed == SI_PCIE_GEN3) request = PCIE_PERF_REQ_PECI_GEN3; - else if (target_link_speed == AMDGPU_PCIE_GEN2) + else if (target_link_speed == SI_PCIE_GEN2) request = PCIE_PERF_REQ_PECI_GEN2; else request = PCIE_PERF_REQ_PECI_GEN1; @@ -6864,7 +6902,7 @@ static int si_dpm_enable(struct amdgpu_device *adev) si_enable_sclk_control(adev, true); si_start_dpm(adev); - si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); + si_enable_auto_throttle_source(adev, SI_DPM_AUTO_THROTTLE_SRC_THERMAL, true); si_thermal_start_thermal_controller(adev); ni_update_current_ps(adev, boot_ps); @@ -6904,7 +6942,7 @@ static void si_dpm_disable(struct amdgpu_device *adev) si_enable_power_containment(adev, boot_ps, false); si_enable_smc_cac(adev, boot_ps, false); si_enable_spread_spectrum(adev, false); - si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, false); + si_enable_auto_throttle_source(adev, SI_DPM_AUTO_THROTTLE_SRC_THERMAL, false); si_stop_dpm(adev); si_reset_to_default(adev); si_dpm_stop_smc(adev); @@ -7148,10 +7186,10 @@ static void si_parse_pplib_clock_info(struct amdgpu_device *adev, pl->vddc = le16_to_cpu(clock_info->si.usVDDC); pl->vddci = le16_to_cpu(clock_info->si.usVDDCI); pl->flags = le32_to_cpu(clock_info->si.ulFlags); - pl->pcie_gen = amdgpu_get_pcie_gen_support(adev, - si_pi->sys_pcie_mask, - si_pi->boot_pcie_gen, - clock_info->si.ucPCIEGen); + pl->pcie_gen = si_gen_pcie_gen_support(adev, + si_pi->sys_pcie_mask, + si_pi->boot_pcie_gen, + clock_info->si.ucPCIEGen); /* patch up vddc if necessary */ ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, @@ -7318,7 +7356,7 @@ static int si_dpm_init(struct amdgpu_device *adev) si_pi->sys_pcie_mask = adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK; - si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; + si_pi->force_pcie_gen = SI_PCIE_GEN_INVALID; si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); si_set_max_cu_value(adev); diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h index bc0be6818e21..11cb7874a6bb 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h @@ -595,13 +595,20 @@ struct rv7xx_power_info { RV770_SMC_STATETABLE smc_statetable; }; +enum si_pcie_gen { + SI_PCIE_GEN1 = 0, + SI_PCIE_GEN2 = 1, + SI_PCIE_GEN3 = 2, + SI_PCIE_GEN_INVALID = 0xffff +}; + struct rv7xx_pl { u32 sclk; u32 mclk; u16 vddc; u16 vddci; /* eg+ only */ u32 flags; - enum amdgpu_pcie_gen pcie_gen; /* si+ only */ + enum si_pcie_gen pcie_gen; /* si+ only */ }; struct rv7xx_ps { @@ -967,9 +974,9 @@ struct si_power_info { struct si_ulv_param ulv; u32 max_cu; /* pcie gen */ - enum amdgpu_pcie_gen force_pcie_gen; - enum amdgpu_pcie_gen boot_pcie_gen; - enum amdgpu_pcie_gen acpi_pcie_gen; + enum si_pcie_gen force_pcie_gen; + enum si_pcie_gen boot_pcie_gen; + enum si_pcie_gen acpi_pcie_gen; u32 sys_pcie_mask; /* flags */ bool enable_dte; From 28a31774b050261371953401e8072ae15200c91e Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 11 Nov 2021 14:29:00 +0800 Subject: [PATCH 009/339] drm/amd/pm: do not expose the API used internally only in kv_dpm.c Move it to kv_dpm.c instead. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 23 --------------------- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 -- drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 25 ++++++++++++++++++++++- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index c97e79862779..9dfb57cceca5 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -209,29 +209,6 @@ static u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) return vrefresh; } -bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor) -{ - switch (sensor) { - case THERMAL_TYPE_RV6XX: - case THERMAL_TYPE_RV770: - case THERMAL_TYPE_EVERGREEN: - case THERMAL_TYPE_SUMO: - case THERMAL_TYPE_NI: - case THERMAL_TYPE_SI: - case THERMAL_TYPE_CI: - case THERMAL_TYPE_KV: - return true; - case THERMAL_TYPE_ADT7473_WITH_INTERNAL: - case THERMAL_TYPE_EMC2103_WITH_INTERNAL: - return false; /* need special handling */ - case THERMAL_TYPE_NONE: - case THERMAL_TYPE_EXTERNAL: - case THERMAL_TYPE_EXTERNAL_GPIO: - default: - return false; - } -} - union power_info { struct _ATOM_POWERPLAY_INFO info; struct _ATOM_POWERPLAY_INFO_V2 info_2; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 108706ee8760..ecababa562af 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -382,8 +382,6 @@ u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, void *data, uint32_t *size); -bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor); - int amdgpu_get_platform_caps(struct amdgpu_device *adev); int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c index bcae42cef374..380a5336c74f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c @@ -1256,6 +1256,29 @@ static void kv_dpm_enable_bapm(void *handle, bool enable) } } +static bool kv_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor) +{ + switch (sensor) { + case THERMAL_TYPE_RV6XX: + case THERMAL_TYPE_RV770: + case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_SUMO: + case THERMAL_TYPE_NI: + case THERMAL_TYPE_SI: + case THERMAL_TYPE_CI: + case THERMAL_TYPE_KV: + return true; + case THERMAL_TYPE_ADT7473_WITH_INTERNAL: + case THERMAL_TYPE_EMC2103_WITH_INTERNAL: + return false; /* need special handling */ + case THERMAL_TYPE_NONE: + case THERMAL_TYPE_EXTERNAL: + case THERMAL_TYPE_EXTERNAL_GPIO: + default: + return false; + } +} + static int kv_dpm_enable(struct amdgpu_device *adev) { struct kv_power_info *pi = kv_get_pi(adev); @@ -1352,7 +1375,7 @@ static int kv_dpm_enable(struct amdgpu_device *adev) } if (adev->irq.installed && - amdgpu_is_internal_thermal_sensor(adev->pm.int_thermal_type)) { + kv_is_internal_thermal_sensor(adev->pm.int_thermal_type)) { ret = kv_set_thermal_temperature_range(adev, KV_TEMP_RANGE_MIN, KV_TEMP_RANGE_MAX); if (ret) { DRM_ERROR("kv_set_thermal_temperature_range failed\n"); From 84176663e70d93836d30d2a480a4201c7f790b42 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 11 Nov 2021 14:19:33 +0800 Subject: [PATCH 010/339] drm/amd/pm: create a new holder for those APIs used only by legacy ASICs(si/kv) Those APIs are used only by legacy ASICs(si/kv). They cannot be shared by other ASICs. So, we create a new holder for them. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 2 +- .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 2 +- .../gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 1022 +--------------- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 17 +- drivers/gpu/drm/amd/pm/powerplay/Makefile | 2 +- drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 6 +- drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c | 1024 +++++++++++++++++ drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h | 37 + drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 6 +- 13 files changed, 1091 insertions(+), 1034 deletions(-) create mode 100644 drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index d1570a462a51..5d5205870861 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -2532,7 +2532,7 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) break; } /* adjust pm to dpms */ - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } static void dce_v10_0_crtc_prepare(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 18a7b3bd633b..4d812b22c54f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -2608,7 +2608,7 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) break; } /* adjust pm to dpms */ - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } static void dce_v11_0_crtc_prepare(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index c7803dc2b2d5..b90bc2adf778 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2424,7 +2424,7 @@ static void dce_v6_0_crtc_dpms(struct drm_crtc *crtc, int mode) break; } /* adjust pm to dpms */ - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } static void dce_v6_0_crtc_prepare(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 8318ee8339f1..7c1379b02f94 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -2433,7 +2433,7 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) break; } /* adjust pm to dpms */ - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } static void dce_v8_0_crtc_prepare(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 46550811da00..75284e2cec74 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -101,7 +101,7 @@ bool dm_pp_apply_display_requirements( amdgpu_dpm_display_configuration_change(adev, &adev->pm.pm_display_cfg); - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } return true; diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 2e295facd086..cdf724dcf832 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -404,6 +404,7 @@ struct amd_pm_funcs { int (*get_dpm_clock_table)(void *handle, struct dpm_clocks *clock_table); int (*get_smu_prv_buf_details)(void *handle, void **addr, size_t *size); + int (*change_power_state)(void *handle); }; struct metrics_table_header { diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 9dfb57cceca5..438c56df9f23 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -34,113 +34,9 @@ #define WIDTH_4K 3840 -#define amdgpu_dpm_pre_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_post_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_display_configuration_changed(adev) \ - ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_print_power_state(adev, ps) \ - ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) - -#define amdgpu_dpm_vblank_too_short(adev) \ - ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) - #define amdgpu_dpm_enable_bapm(adev, e) \ ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) -#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ - ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) - -void amdgpu_dpm_print_class_info(u32 class, u32 class2) -{ - const char *s; - - switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { - case ATOM_PPLIB_CLASSIFICATION_UI_NONE: - default: - s = "none"; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: - s = "battery"; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: - s = "balanced"; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: - s = "performance"; - break; - } - printk("\tui class: %s\n", s); - printk("\tinternal class:"); - if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && - (class2 == 0)) - pr_cont(" none"); - else { - if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) - pr_cont(" boot"); - if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) - pr_cont(" thermal"); - if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - pr_cont(" limited_pwr"); - if (class & ATOM_PPLIB_CLASSIFICATION_REST) - pr_cont(" rest"); - if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) - pr_cont(" forced"); - if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - pr_cont(" 3d_perf"); - if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) - pr_cont(" ovrdrv"); - if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) - pr_cont(" uvd"); - if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) - pr_cont(" 3d_low"); - if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) - pr_cont(" acpi"); - if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - pr_cont(" uvd_hd2"); - if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - pr_cont(" uvd_hd"); - if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - pr_cont(" uvd_sd"); - if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - pr_cont(" limited_pwr2"); - if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - pr_cont(" ulv"); - if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - pr_cont(" uvd_mvc"); - } - pr_cont("\n"); -} - -void amdgpu_dpm_print_cap_info(u32 caps) -{ - printk("\tcaps:"); - if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) - pr_cont(" single_disp"); - if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) - pr_cont(" video"); - if (caps & ATOM_PPLIB_DISALLOW_ON_DC) - pr_cont(" no_dc"); - pr_cont("\n"); -} - -void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - printk("\tstatus:"); - if (rps == adev->pm.dpm.current_ps) - pr_cont(" c"); - if (rps == adev->pm.dpm.requested_ps) - pr_cont(" r"); - if (rps == adev->pm.dpm.boot_ps) - pr_cont(" b"); - pr_cont("\n"); -} - static void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) { struct drm_device *ddev = adev_to_drm(adev); @@ -161,7 +57,6 @@ static void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) } } - u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) { struct drm_device *dev = adev_to_drm(adev); @@ -209,679 +104,6 @@ static u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) return vrefresh; } -union power_info { - struct _ATOM_POWERPLAY_INFO info; - struct _ATOM_POWERPLAY_INFO_V2 info_2; - struct _ATOM_POWERPLAY_INFO_V3 info_3; - struct _ATOM_PPLIB_POWERPLAYTABLE pplib; - struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; - struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; - struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; - struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; -}; - -union fan_info { - struct _ATOM_PPLIB_FANTABLE fan; - struct _ATOM_PPLIB_FANTABLE2 fan2; - struct _ATOM_PPLIB_FANTABLE3 fan3; -}; - -static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, - ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) -{ - u32 size = atom_table->ucNumEntries * - sizeof(struct amdgpu_clock_voltage_dependency_entry); - int i; - ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; - - amdgpu_table->entries = kzalloc(size, GFP_KERNEL); - if (!amdgpu_table->entries) - return -ENOMEM; - - entry = &atom_table->entries[0]; - for (i = 0; i < atom_table->ucNumEntries; i++) { - amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | - (entry->ucClockHigh << 16); - amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); - } - amdgpu_table->count = atom_table->ucNumEntries; - - return 0; -} - -int amdgpu_get_platform_caps(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - union power_info *power_info; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; - u8 frev, crev; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return -EINVAL; - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - - adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); - adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); - adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); - - return 0; -} - -/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 - -int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - union power_info *power_info; - union fan_info *fan_info; - ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; - u8 frev, crev; - int ret, i; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return -EINVAL; - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - - /* fan table */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { - if (power_info->pplib3.usFanTableOffset) { - fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib3.usFanTableOffset)); - adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; - adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); - adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); - adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); - adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); - adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); - adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); - if (fan_info->fan.ucFanTableFormat >= 2) - adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); - else - adev->pm.dpm.fan.t_max = 10900; - adev->pm.dpm.fan.cycle_delay = 100000; - if (fan_info->fan.ucFanTableFormat >= 3) { - adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; - adev->pm.dpm.fan.default_max_fan_pwm = - le16_to_cpu(fan_info->fan3.usFanPWMMax); - adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; - adev->pm.dpm.fan.fan_output_sensitivity = - le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); - } - adev->pm.dpm.fan.ucode_fan_control = true; - } - } - - /* clock dependancy tables, shedding tables */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { - if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { - ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = - (ATOM_PPLIB_Clock_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); - if (clk_v->ucNumEntries) { - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = - le16_to_cpu(clk_v->entries[0].usSclkLow) | - (clk_v->entries[0].ucSclkHigh << 16); - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = - le16_to_cpu(clk_v->entries[0].usMclkLow) | - (clk_v->entries[0].ucMclkHigh << 16); - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = - le16_to_cpu(clk_v->entries[0].usVddc); - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = - le16_to_cpu(clk_v->entries[0].usVddci); - } - } - if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { - ATOM_PPLIB_PhaseSheddingLimits_Table *psl = - (ATOM_PPLIB_PhaseSheddingLimits_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); - ATOM_PPLIB_PhaseSheddingLimits_Record *entry; - - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = - kcalloc(psl->ucNumEntries, - sizeof(struct amdgpu_phase_shedding_limits_entry), - GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - - entry = &psl->entries[0]; - for (i = 0; i < psl->ucNumEntries; i++) { - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = - le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = - le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); - } - adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = - psl->ucNumEntries; - } - } - - /* cac data */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { - adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); - adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); - adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; - adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); - if (adev->pm.dpm.tdp_od_limit) - adev->pm.dpm.power_control = true; - else - adev->pm.dpm.power_control = false; - adev->pm.dpm.tdp_adjustment = 0; - adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); - adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); - adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); - if (power_info->pplib5.usCACLeakageTableOffset) { - ATOM_PPLIB_CAC_Leakage_Table *cac_table = - (ATOM_PPLIB_CAC_Leakage_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); - ATOM_PPLIB_CAC_Leakage_Record *entry; - u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); - adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - entry = &cac_table->entries[0]; - for (i = 0; i < cac_table->ucNumEntries; i++) { - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = - le16_to_cpu(entry->usVddc1); - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = - le16_to_cpu(entry->usVddc2); - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = - le16_to_cpu(entry->usVddc3); - } else { - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = - le16_to_cpu(entry->usVddc); - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = - le32_to_cpu(entry->ulLeakageValue); - } - entry = (ATOM_PPLIB_CAC_Leakage_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); - } - adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; - } - } - - /* ext tables */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { - ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && - ext_hdr->usVCETableOffset) { - VCEClockInfoArray *array = (VCEClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usVCETableOffset) + 1); - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = - (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + - 1 + array->ucNumEntries * sizeof(VCEClockInfo)); - ATOM_PPLIB_VCE_State_Table *states = - (ATOM_PPLIB_VCE_State_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + - 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + - 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; - ATOM_PPLIB_VCE_State_Record *state_entry; - VCEClockInfo *vce_clk; - u32 size = limits->numEntries * - sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - state_entry = &states->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - vce_clk = (VCEClockInfo *) - ((u8 *)&array->entries[0] + - (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = - le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = - le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); - } - adev->pm.dpm.num_of_vce_states = - states->numEntries > AMD_MAX_VCE_LEVELS ? - AMD_MAX_VCE_LEVELS : states->numEntries; - for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { - vce_clk = (VCEClockInfo *) - ((u8 *)&array->entries[0] + - (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); - adev->pm.dpm.vce_states[i].evclk = - le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); - adev->pm.dpm.vce_states[i].ecclk = - le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); - adev->pm.dpm.vce_states[i].clk_idx = - state_entry->ucClockInfoIndex & 0x3f; - adev->pm.dpm.vce_states[i].pstate = - (state_entry->ucClockInfoIndex & 0xc0) >> 6; - state_entry = (ATOM_PPLIB_VCE_State_Record *) - ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && - ext_hdr->usUVDTableOffset) { - UVDClockInfoArray *array = (UVDClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = - (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + - 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; - u32 size = limits->numEntries * - sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - UVDClockInfo *uvd_clk = (UVDClockInfo *) - ((u8 *)&array->entries[0] + - (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = - le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = - le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && - ext_hdr->usSAMUTableOffset) { - ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = - (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); - ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; - u32 size = limits->numEntries * - sizeof(struct amdgpu_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = - le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && - ext_hdr->usPPMTableOffset) { - ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPPMTableOffset)); - adev->pm.dpm.dyn_state.ppm_table = - kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.ppm_table) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; - adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = - le16_to_cpu(ppm->usCpuCoreNumber); - adev->pm.dpm.dyn_state.ppm_table->platform_tdp = - le32_to_cpu(ppm->ulPlatformTDP); - adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = - le32_to_cpu(ppm->ulSmallACPlatformTDP); - adev->pm.dpm.dyn_state.ppm_table->platform_tdc = - le32_to_cpu(ppm->ulPlatformTDC); - adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = - le32_to_cpu(ppm->ulSmallACPlatformTDC); - adev->pm.dpm.dyn_state.ppm_table->apu_tdp = - le32_to_cpu(ppm->ulApuTDP); - adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = - le32_to_cpu(ppm->ulDGpuTDP); - adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = - le32_to_cpu(ppm->ulDGpuUlvPower); - adev->pm.dpm.dyn_state.ppm_table->tj_max = - le32_to_cpu(ppm->ulTjmax); - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && - ext_hdr->usACPTableOffset) { - ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = - (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usACPTableOffset) + 1); - ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; - u32 size = limits->numEntries * - sizeof(struct amdgpu_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = - le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && - ext_hdr->usPowerTuneTableOffset) { - u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); - ATOM_PowerTune_Table *pt; - adev->pm.dpm.dyn_state.cac_tdp_table = - kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.cac_tdp_table) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - if (rev > 0) { - ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); - adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = - ppt->usMaximumPowerDeliveryLimit; - pt = &ppt->power_tune_table; - } else { - ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); - adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; - pt = &ppt->power_tune_table; - } - adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); - adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = - le16_to_cpu(pt->usConfigurableTDP); - adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); - adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = - le16_to_cpu(pt->usBatteryPowerLimit); - adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = - le16_to_cpu(pt->usSmallPowerLimit); - adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = - le16_to_cpu(pt->usLowCACLeakage); - adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = - le16_to_cpu(pt->usHighCACLeakage); - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && - ext_hdr->usSclkVddgfxTableOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); - ret = amdgpu_parse_clk_voltage_dep_table( - &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, - dep_table); - if (ret) { - kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); - return ret; - } - } - } - - return 0; -} - -void amdgpu_free_extended_power_table(struct amdgpu_device *adev) -{ - struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; - - kfree(dyn_state->vddc_dependency_on_sclk.entries); - kfree(dyn_state->vddci_dependency_on_mclk.entries); - kfree(dyn_state->vddc_dependency_on_mclk.entries); - kfree(dyn_state->mvdd_dependency_on_mclk.entries); - kfree(dyn_state->cac_leakage_table.entries); - kfree(dyn_state->phase_shedding_limits_table.entries); - kfree(dyn_state->ppm_table); - kfree(dyn_state->cac_tdp_table); - kfree(dyn_state->vce_clock_voltage_dependency_table.entries); - kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); - kfree(dyn_state->samu_clock_voltage_dependency_table.entries); - kfree(dyn_state->acp_clock_voltage_dependency_table.entries); - kfree(dyn_state->vddgfx_dependency_on_sclk.entries); -} - -static const char *pp_lib_thermal_controller_names[] = { - "NONE", - "lm63", - "adm1032", - "adm1030", - "max6649", - "lm64", - "f75375", - "RV6xx", - "RV770", - "adt7473", - "NONE", - "External GPIO", - "Evergreen", - "emc2103", - "Sumo", - "Northern Islands", - "Southern Islands", - "lm96163", - "Sea Islands", - "Kaveri/Kabini", -}; - -void amdgpu_add_thermal_controller(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - ATOM_PPLIB_POWERPLAYTABLE *power_table; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - ATOM_PPLIB_THERMALCONTROLLER *controller; - struct amdgpu_i2c_bus_rec i2c_bus; - u16 data_offset; - u8 frev, crev; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return; - power_table = (ATOM_PPLIB_POWERPLAYTABLE *) - (mode_info->atom_context->bios + data_offset); - controller = &power_table->sThermalController; - - /* add the i2c bus for thermal/fan chip */ - if (controller->ucType > 0) { - if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) - adev->pm.no_fan = true; - adev->pm.fan_pulses_per_revolution = - controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - if (adev->pm.fan_pulses_per_revolution) { - adev->pm.fan_min_rpm = controller->ucFanMinRPM; - adev->pm.fan_max_rpm = controller->ucFanMaxRPM; - } - if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_RV770; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_NI; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_SI; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_CI; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_KV; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { - DRM_INFO("External GPIO thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; - } else if (controller->ucType == - ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { - DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; - } else if (controller->ucType == - ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { - DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; - } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { - DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", - pp_lib_thermal_controller_names[controller->ucType], - controller->ucI2cAddress >> 1, - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; - i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); - adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); - if (adev->pm.i2c_bus) { - struct i2c_board_info info = { }; - const char *name = pp_lib_thermal_controller_names[controller->ucType]; - info.addr = controller->ucI2cAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); - i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); - } - } else { - DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", - controller->ucType, - controller->ucI2cAddress >> 1, - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - } - } -} - -struct amd_vce_state* -amdgpu_get_vce_clock_state(void *handle, u32 idx) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (idx < adev->pm.dpm.num_of_vce_states) - return &adev->pm.dpm.vce_states[idx]; - - return NULL; -} - int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; @@ -1240,215 +462,10 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) adev->pm.dpm.state = dpm_state; mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } -static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, - enum amd_pm_state_type dpm_state) -{ - int i; - struct amdgpu_ps *ps; - u32 ui_class; - bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? - true : false; - - /* check if the vblank period is too short to adjust the mclk */ - if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { - if (amdgpu_dpm_vblank_too_short(adev)) - single_display = false; - } - - /* certain older asics have a separare 3D performance state, - * so try that first if the user selected performance - */ - if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) - dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; - /* balanced states don't exist at the moment */ - if (dpm_state == POWER_STATE_TYPE_BALANCED) - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - -restart_search: - /* Pick the best power state based on current conditions */ - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - ps = &adev->pm.dpm.ps[i]; - ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; - switch (dpm_state) { - /* user states */ - case POWER_STATE_TYPE_BATTERY: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_BALANCED: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_PERFORMANCE: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - /* internal states */ - case POWER_STATE_TYPE_INTERNAL_UVD: - if (adev->pm.dpm.uvd_ps) - return adev->pm.dpm.uvd_ps; - else - break; - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_BOOT: - return adev->pm.dpm.boot_ps; - case POWER_STATE_TYPE_INTERNAL_THERMAL: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ACPI: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ULV: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_3DPERF: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - return ps; - break; - default: - break; - } - } - /* use a fallback state if we didn't match */ - switch (dpm_state) { - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (adev->pm.dpm.uvd_ps) { - return adev->pm.dpm.uvd_ps; - } else { - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - } - case POWER_STATE_TYPE_INTERNAL_THERMAL: - dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_ACPI: - dpm_state = POWER_STATE_TYPE_BATTERY; - goto restart_search; - case POWER_STATE_TYPE_BATTERY: - case POWER_STATE_TYPE_BALANCED: - case POWER_STATE_TYPE_INTERNAL_3DPERF: - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - default: - break; - } - - return NULL; -} - -static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) -{ - struct amdgpu_ps *ps; - enum amd_pm_state_type dpm_state; - int ret; - bool equal = false; - - /* if dpm init failed */ - if (!adev->pm.dpm_enabled) - return; - - if (adev->pm.dpm.user_state != adev->pm.dpm.state) { - /* add other state override checks here */ - if ((!adev->pm.dpm.thermal_active) && - (!adev->pm.dpm.uvd_active)) - adev->pm.dpm.state = adev->pm.dpm.user_state; - } - dpm_state = adev->pm.dpm.state; - - ps = amdgpu_dpm_pick_power_state(adev, dpm_state); - if (ps) - adev->pm.dpm.requested_ps = ps; - else - return; - - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { - printk("switching from power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); - printk("switching to power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); - } - - /* update whether vce is active */ - ps->vce_active = adev->pm.dpm.vce_active; - if (adev->powerplay.pp_funcs->display_configuration_changed) - amdgpu_dpm_display_configuration_changed(adev); - - ret = amdgpu_dpm_pre_set_power_state(adev); - if (ret) - return; - - if (adev->powerplay.pp_funcs->check_state_equal) { - if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) - equal = false; - } - - if (equal) - return; - - if (adev->powerplay.pp_funcs->set_power_state) - adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); - - amdgpu_dpm_post_set_power_state(adev); - - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - - if (adev->powerplay.pp_funcs->force_performance_level) { - if (adev->pm.dpm.thermal_active) { - enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; - /* force low perf level for thermal */ - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); - /* save the user's level */ - adev->pm.dpm.forced_level = level; - } else { - /* otherwise, user selected level */ - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); - } - } -} - -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) +void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) { int i = 0; @@ -1464,7 +481,13 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) amdgpu_fence_wait_empty(ring); } - if (adev->powerplay.pp_funcs->dispatch_tasks) { + if ((adev->family == AMDGPU_FAMILY_SI) || + (adev->family == AMDGPU_FAMILY_KV)) { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + adev->powerplay.pp_funcs->change_power_state(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); + } else { if (!amdgpu_device_has_dc_support(adev)) { mutex_lock(&adev->pm.mutex); amdgpu_dpm_get_active_displays(adev); @@ -1483,11 +506,6 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) mutex_unlock(&adev->pm.mutex); } amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); - } else { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - amdgpu_dpm_change_power_state_locked(adev); - mutex_unlock(&adev->pm.mutex); } } @@ -1505,7 +523,7 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) } mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } else { ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); if (ret) @@ -1541,7 +559,7 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) } mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } else { ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); if (ret) @@ -1550,18 +568,6 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) } } -void amdgpu_pm_print_power_states(struct amdgpu_device *adev) -{ - int i; - - if (adev->powerplay.pp_funcs->print_power_state == NULL) - return; - - for (i = 0; i < adev->pm.dpm.num_ps; i++) - amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); - -} - void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) { int ret = 0; @@ -1727,7 +733,7 @@ void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, if (amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state) == -EOPNOTSUPP) - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) @@ -1902,7 +908,7 @@ int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) AMD_PP_TASK_READJUST_POWER_STATE, NULL) == -EOPNOTSUPP) { adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } return 0; @@ -1932,7 +938,7 @@ int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) AMD_PP_TASK_READJUST_POWER_STATE, NULL) == -EOPNOTSUPP) { adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } return 0; diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index ecababa562af..1958e0e488b0 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -374,24 +374,10 @@ enum amdgpu_display_gap AMDGPU_PM_DISPLAY_GAP_IGNORE = 3, }; -void amdgpu_dpm_print_class_info(u32 class, u32 class2); -void amdgpu_dpm_print_cap_info(u32 caps); -void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, - struct amdgpu_ps *rps); u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, void *data, uint32_t *size); -int amdgpu_get_platform_caps(struct amdgpu_device *adev); - -int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); -void amdgpu_free_extended_power_table(struct amdgpu_device *adev); - -void amdgpu_add_thermal_controller(struct amdgpu_device *adev); - -struct amd_vce_state* -amdgpu_get_vce_clock_state(void *handle, u32 idx); - int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate); @@ -442,11 +428,10 @@ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors senso void amdgpu_dpm_thermal_work_handler(struct work_struct *work); -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); +void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev); void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); -void amdgpu_pm_print_power_states(struct amdgpu_device *adev); int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable); int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size); diff --git a/drivers/gpu/drm/amd/pm/powerplay/Makefile b/drivers/gpu/drm/amd/pm/powerplay/Makefile index 0fb114adc79f..614d8b6a58ad 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/Makefile +++ b/drivers/gpu/drm/amd/pm/powerplay/Makefile @@ -28,7 +28,7 @@ AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/powerplay/ include $(AMD_POWERPLAY) -POWER_MGR-y = amd_powerplay.o +POWER_MGR-y = amd_powerplay.o legacy_dpm.o POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c index 380a5336c74f..eed89835231c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c @@ -36,6 +36,7 @@ #include "gca/gfx_7_2_d.h" #include "gca/gfx_7_2_sh_mask.h" +#include "legacy_dpm.h" #define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 #define KV_MINIMUM_ENGINE_CLOCK 800 @@ -3087,7 +3088,7 @@ static int kv_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); return ret; } @@ -3135,7 +3136,7 @@ static int kv_dpm_resume(void *handle) adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } return 0; } @@ -3389,6 +3390,7 @@ static const struct amd_pm_funcs kv_dpm_funcs = { .get_vce_clock_state = amdgpu_get_vce_clock_state, .check_state_equal = kv_check_state_equal, .read_sensor = &kv_dpm_read_sensor, + .change_power_state = amdgpu_dpm_change_power_state_locked, }; static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = { diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c new file mode 100644 index 000000000000..67c84b7ad8e7 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c @@ -0,0 +1,1024 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "amdgpu.h" +#include "amdgpu_i2c.h" +#include "amdgpu_atombios.h" +#include "atom.h" +#include "amd_pcie.h" +#include "legacy_dpm.h" + +#define amdgpu_dpm_pre_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_post_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_display_configuration_changed(adev) \ + ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_print_power_state(adev, ps) \ + ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) + +#define amdgpu_dpm_vblank_too_short(adev) \ + ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ + ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) + +void amdgpu_dpm_print_class_info(u32 class, u32 class2) +{ + const char *s; + + switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: + default: + s = "none"; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: + s = "battery"; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: + s = "balanced"; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: + s = "performance"; + break; + } + printk("\tui class: %s\n", s); + printk("\tinternal class:"); + if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && + (class2 == 0)) + pr_cont(" none"); + else { + if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) + pr_cont(" boot"); + if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + pr_cont(" thermal"); + if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + pr_cont(" limited_pwr"); + if (class & ATOM_PPLIB_CLASSIFICATION_REST) + pr_cont(" rest"); + if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) + pr_cont(" forced"); + if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + pr_cont(" 3d_perf"); + if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) + pr_cont(" ovrdrv"); + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + pr_cont(" uvd"); + if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) + pr_cont(" 3d_low"); + if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) + pr_cont(" acpi"); + if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + pr_cont(" uvd_hd2"); + if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + pr_cont(" uvd_hd"); + if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + pr_cont(" uvd_sd"); + if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + pr_cont(" limited_pwr2"); + if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + pr_cont(" ulv"); + if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + pr_cont(" uvd_mvc"); + } + pr_cont("\n"); +} + +void amdgpu_dpm_print_cap_info(u32 caps) +{ + printk("\tcaps:"); + if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) + pr_cont(" single_disp"); + if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) + pr_cont(" video"); + if (caps & ATOM_PPLIB_DISALLOW_ON_DC) + pr_cont(" no_dc"); + pr_cont("\n"); +} + +void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + printk("\tstatus:"); + if (rps == adev->pm.dpm.current_ps) + pr_cont(" c"); + if (rps == adev->pm.dpm.requested_ps) + pr_cont(" r"); + if (rps == adev->pm.dpm.boot_ps) + pr_cont(" b"); + pr_cont("\n"); +} + +void amdgpu_pm_print_power_states(struct amdgpu_device *adev) +{ + int i; + + if (adev->powerplay.pp_funcs->print_power_state == NULL) + return; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) + amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); + +} + +union power_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; + struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; + struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; +}; + +int amdgpu_get_platform_caps(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); + adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); + adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); + + return 0; +} + +union fan_info { + struct _ATOM_PPLIB_FANTABLE fan; + struct _ATOM_PPLIB_FANTABLE2 fan2; + struct _ATOM_PPLIB_FANTABLE3 fan3; +}; + +static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, + ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) +{ + u32 size = atom_table->ucNumEntries * + sizeof(struct amdgpu_clock_voltage_dependency_entry); + int i; + ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; + + amdgpu_table->entries = kzalloc(size, GFP_KERNEL); + if (!amdgpu_table->entries) + return -ENOMEM; + + entry = &atom_table->entries[0]; + for (i = 0; i < atom_table->ucNumEntries; i++) { + amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | + (entry->ucClockHigh << 16); + amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); + } + amdgpu_table->count = atom_table->ucNumEntries; + + return 0; +} + +/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 + +int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + union power_info *power_info; + union fan_info *fan_info; + ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + int ret, i; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + /* fan table */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { + if (power_info->pplib3.usFanTableOffset) { + fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib3.usFanTableOffset)); + adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; + adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); + adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); + adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); + adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); + adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); + adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); + if (fan_info->fan.ucFanTableFormat >= 2) + adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); + else + adev->pm.dpm.fan.t_max = 10900; + adev->pm.dpm.fan.cycle_delay = 100000; + if (fan_info->fan.ucFanTableFormat >= 3) { + adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; + adev->pm.dpm.fan.default_max_fan_pwm = + le16_to_cpu(fan_info->fan3.usFanPWMMax); + adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; + adev->pm.dpm.fan.fan_output_sensitivity = + le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); + } + adev->pm.dpm.fan.ucode_fan_control = true; + } + } + + /* clock dependancy tables, shedding tables */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { + if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { + ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = + (ATOM_PPLIB_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); + if (clk_v->ucNumEntries) { + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = + le16_to_cpu(clk_v->entries[0].usSclkLow) | + (clk_v->entries[0].ucSclkHigh << 16); + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = + le16_to_cpu(clk_v->entries[0].usMclkLow) | + (clk_v->entries[0].ucMclkHigh << 16); + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = + le16_to_cpu(clk_v->entries[0].usVddc); + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = + le16_to_cpu(clk_v->entries[0].usVddci); + } + } + if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { + ATOM_PPLIB_PhaseSheddingLimits_Table *psl = + (ATOM_PPLIB_PhaseSheddingLimits_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); + ATOM_PPLIB_PhaseSheddingLimits_Record *entry; + + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = + kcalloc(psl->ucNumEntries, + sizeof(struct amdgpu_phase_shedding_limits_entry), + GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + + entry = &psl->entries[0]; + for (i = 0; i < psl->ucNumEntries; i++) { + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = + le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = + le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); + } + adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = + psl->ucNumEntries; + } + } + + /* cac data */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { + adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); + adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); + adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; + adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); + if (adev->pm.dpm.tdp_od_limit) + adev->pm.dpm.power_control = true; + else + adev->pm.dpm.power_control = false; + adev->pm.dpm.tdp_adjustment = 0; + adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); + adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); + adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); + if (power_info->pplib5.usCACLeakageTableOffset) { + ATOM_PPLIB_CAC_Leakage_Table *cac_table = + (ATOM_PPLIB_CAC_Leakage_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); + ATOM_PPLIB_CAC_Leakage_Record *entry; + u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); + adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + entry = &cac_table->entries[0]; + for (i = 0; i < cac_table->ucNumEntries; i++) { + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = + le16_to_cpu(entry->usVddc1); + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = + le16_to_cpu(entry->usVddc2); + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = + le16_to_cpu(entry->usVddc3); + } else { + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = + le16_to_cpu(entry->usVddc); + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = + le32_to_cpu(entry->ulLeakageValue); + } + entry = (ATOM_PPLIB_CAC_Leakage_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); + } + adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; + } + } + + /* ext tables */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { + ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && + ext_hdr->usVCETableOffset) { + VCEClockInfoArray *array = (VCEClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1); + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = + (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + + 1 + array->ucNumEntries * sizeof(VCEClockInfo)); + ATOM_PPLIB_VCE_State_Table *states = + (ATOM_PPLIB_VCE_State_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + + 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + + 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; + ATOM_PPLIB_VCE_State_Record *state_entry; + VCEClockInfo *vce_clk; + u32 size = limits->numEntries * + sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + state_entry = &states->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + vce_clk = (VCEClockInfo *) + ((u8 *)&array->entries[0] + + (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); + } + adev->pm.dpm.num_of_vce_states = + states->numEntries > AMD_MAX_VCE_LEVELS ? + AMD_MAX_VCE_LEVELS : states->numEntries; + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { + vce_clk = (VCEClockInfo *) + ((u8 *)&array->entries[0] + + (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); + adev->pm.dpm.vce_states[i].evclk = + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); + adev->pm.dpm.vce_states[i].ecclk = + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); + adev->pm.dpm.vce_states[i].clk_idx = + state_entry->ucClockInfoIndex & 0x3f; + adev->pm.dpm.vce_states[i].pstate = + (state_entry->ucClockInfoIndex & 0xc0) >> 6; + state_entry = (ATOM_PPLIB_VCE_State_Record *) + ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && + ext_hdr->usUVDTableOffset) { + UVDClockInfoArray *array = (UVDClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = + (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + + 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; + u32 size = limits->numEntries * + sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + UVDClockInfo *uvd_clk = (UVDClockInfo *) + ((u8 *)&array->entries[0] + + (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = + le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = + le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && + ext_hdr->usSAMUTableOffset) { + ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = + (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); + ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; + u32 size = limits->numEntries * + sizeof(struct amdgpu_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = + le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && + ext_hdr->usPPMTableOffset) { + ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPPMTableOffset)); + adev->pm.dpm.dyn_state.ppm_table = + kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.ppm_table) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; + adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = + le16_to_cpu(ppm->usCpuCoreNumber); + adev->pm.dpm.dyn_state.ppm_table->platform_tdp = + le32_to_cpu(ppm->ulPlatformTDP); + adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = + le32_to_cpu(ppm->ulSmallACPlatformTDP); + adev->pm.dpm.dyn_state.ppm_table->platform_tdc = + le32_to_cpu(ppm->ulPlatformTDC); + adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = + le32_to_cpu(ppm->ulSmallACPlatformTDC); + adev->pm.dpm.dyn_state.ppm_table->apu_tdp = + le32_to_cpu(ppm->ulApuTDP); + adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = + le32_to_cpu(ppm->ulDGpuTDP); + adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = + le32_to_cpu(ppm->ulDGpuUlvPower); + adev->pm.dpm.dyn_state.ppm_table->tj_max = + le32_to_cpu(ppm->ulTjmax); + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && + ext_hdr->usACPTableOffset) { + ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = + (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usACPTableOffset) + 1); + ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; + u32 size = limits->numEntries * + sizeof(struct amdgpu_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = + le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && + ext_hdr->usPowerTuneTableOffset) { + u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + ATOM_PowerTune_Table *pt; + adev->pm.dpm.dyn_state.cac_tdp_table = + kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.cac_tdp_table) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + if (rev > 0) { + ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = + ppt->usMaximumPowerDeliveryLimit; + pt = &ppt->power_tune_table; + } else { + ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; + pt = &ppt->power_tune_table; + } + adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); + adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = + le16_to_cpu(pt->usConfigurableTDP); + adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); + adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = + le16_to_cpu(pt->usBatteryPowerLimit); + adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = + le16_to_cpu(pt->usSmallPowerLimit); + adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = + le16_to_cpu(pt->usLowCACLeakage); + adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = + le16_to_cpu(pt->usHighCACLeakage); + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && + ext_hdr->usSclkVddgfxTableOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); + ret = amdgpu_parse_clk_voltage_dep_table( + &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, + dep_table); + if (ret) { + kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); + return ret; + } + } + } + + return 0; +} + +void amdgpu_free_extended_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; + + kfree(dyn_state->vddc_dependency_on_sclk.entries); + kfree(dyn_state->vddci_dependency_on_mclk.entries); + kfree(dyn_state->vddc_dependency_on_mclk.entries); + kfree(dyn_state->mvdd_dependency_on_mclk.entries); + kfree(dyn_state->cac_leakage_table.entries); + kfree(dyn_state->phase_shedding_limits_table.entries); + kfree(dyn_state->ppm_table); + kfree(dyn_state->cac_tdp_table); + kfree(dyn_state->vce_clock_voltage_dependency_table.entries); + kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); + kfree(dyn_state->samu_clock_voltage_dependency_table.entries); + kfree(dyn_state->acp_clock_voltage_dependency_table.entries); + kfree(dyn_state->vddgfx_dependency_on_sclk.entries); +} + +static const char *pp_lib_thermal_controller_names[] = { + "NONE", + "lm63", + "adm1032", + "adm1030", + "max6649", + "lm64", + "f75375", + "RV6xx", + "RV770", + "adt7473", + "NONE", + "External GPIO", + "Evergreen", + "emc2103", + "Sumo", + "Northern Islands", + "Southern Islands", + "lm96163", + "Sea Islands", + "Kaveri/Kabini", +}; + +void amdgpu_add_thermal_controller(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + ATOM_PPLIB_POWERPLAYTABLE *power_table; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + ATOM_PPLIB_THERMALCONTROLLER *controller; + struct amdgpu_i2c_bus_rec i2c_bus; + u16 data_offset; + u8 frev, crev; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return; + power_table = (ATOM_PPLIB_POWERPLAYTABLE *) + (mode_info->atom_context->bios + data_offset); + controller = &power_table->sThermalController; + + /* add the i2c bus for thermal/fan chip */ + if (controller->ucType > 0) { + if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) + adev->pm.no_fan = true; + adev->pm.fan_pulses_per_revolution = + controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + if (adev->pm.fan_pulses_per_revolution) { + adev->pm.fan_min_rpm = controller->ucFanMinRPM; + adev->pm.fan_max_rpm = controller->ucFanMaxRPM; + } + if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_RV770; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_NI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_SI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_CI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_KV; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { + DRM_INFO("External GPIO thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { + DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { + DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; + } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", + pp_lib_thermal_controller_names[controller->ucType], + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; + i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); + adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); + if (adev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = pp_lib_thermal_controller_names[controller->ucType]; + info.addr = controller->ucI2cAddress >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); + } + } else { + DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", + controller->ucType, + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + } + } +} + +struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (idx < adev->pm.dpm.num_of_vce_states) + return &adev->pm.dpm.vce_states[idx]; + + return NULL; +} + +static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type dpm_state) +{ + int i; + struct amdgpu_ps *ps; + u32 ui_class; + bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? + true : false; + + /* check if the vblank period is too short to adjust the mclk */ + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { + if (amdgpu_dpm_vblank_too_short(adev)) + single_display = false; + } + + /* certain older asics have a separare 3D performance state, + * so try that first if the user selected performance + */ + if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) + dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; + /* balanced states don't exist at the moment */ + if (dpm_state == POWER_STATE_TYPE_BALANCED) + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + +restart_search: + /* Pick the best power state based on current conditions */ + for (i = 0; i < adev->pm.dpm.num_ps; i++) { + ps = &adev->pm.dpm.ps[i]; + ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; + switch (dpm_state) { + /* user states */ + case POWER_STATE_TYPE_BATTERY: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_BALANCED: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_PERFORMANCE: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + /* internal states */ + case POWER_STATE_TYPE_INTERNAL_UVD: + if (adev->pm.dpm.uvd_ps) + return adev->pm.dpm.uvd_ps; + else + break; + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_BOOT: + return adev->pm.dpm.boot_ps; + case POWER_STATE_TYPE_INTERNAL_THERMAL: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ACPI: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ULV: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_3DPERF: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + return ps; + break; + default: + break; + } + } + /* use a fallback state if we didn't match */ + switch (dpm_state) { + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (adev->pm.dpm.uvd_ps) { + return adev->pm.dpm.uvd_ps; + } else { + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + } + case POWER_STATE_TYPE_INTERNAL_THERMAL: + dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_ACPI: + dpm_state = POWER_STATE_TYPE_BATTERY; + goto restart_search; + case POWER_STATE_TYPE_BATTERY: + case POWER_STATE_TYPE_BALANCED: + case POWER_STATE_TYPE_INTERNAL_3DPERF: + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + default: + break; + } + + return NULL; +} + +int amdgpu_dpm_change_power_state_locked(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_ps *ps; + enum amd_pm_state_type dpm_state; + int ret; + bool equal = false; + + /* if dpm init failed */ + if (!adev->pm.dpm_enabled) + return 0; + + if (adev->pm.dpm.user_state != adev->pm.dpm.state) { + /* add other state override checks here */ + if ((!adev->pm.dpm.thermal_active) && + (!adev->pm.dpm.uvd_active)) + adev->pm.dpm.state = adev->pm.dpm.user_state; + } + dpm_state = adev->pm.dpm.state; + + ps = amdgpu_dpm_pick_power_state(adev, dpm_state); + if (ps) + adev->pm.dpm.requested_ps = ps; + else + return -EINVAL; + + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { + printk("switching from power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); + printk("switching to power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); + } + + /* update whether vce is active */ + ps->vce_active = adev->pm.dpm.vce_active; + if (adev->powerplay.pp_funcs->display_configuration_changed) + amdgpu_dpm_display_configuration_changed(adev); + + ret = amdgpu_dpm_pre_set_power_state(adev); + if (ret) + return ret; + + if (adev->powerplay.pp_funcs->check_state_equal) { + if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) + equal = false; + } + + if (equal) + return 0; + + if (adev->powerplay.pp_funcs->set_power_state) + adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); + + amdgpu_dpm_post_set_power_state(adev); + + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; + + if (adev->powerplay.pp_funcs->force_performance_level) { + if (adev->pm.dpm.thermal_active) { + enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; + /* force low perf level for thermal */ + amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); + /* save the user's level */ + adev->pm.dpm.forced_level = level; + } else { + /* otherwise, user selected level */ + amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); + } + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h new file mode 100644 index 000000000000..7ac30f1aed20 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h @@ -0,0 +1,37 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __LEGACY_DPM_H__ +#define __LEGACY_DPM_H__ + +void amdgpu_dpm_print_class_info(u32 class, u32 class2); +void amdgpu_dpm_print_cap_info(u32 caps); +void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, + struct amdgpu_ps *rps); +int amdgpu_get_platform_caps(struct amdgpu_device *adev); +int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); +void amdgpu_free_extended_power_table(struct amdgpu_device *adev); +void amdgpu_add_thermal_controller(struct amdgpu_device *adev); +struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx); +int amdgpu_dpm_change_power_state_locked(void *handle); +void amdgpu_pm_print_power_states(struct amdgpu_device *adev); +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c index 2823376797d3..7becb9e9275b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -37,6 +37,7 @@ #include #include #include +#include #define MC_CG_ARB_FREQ_F0 0x0a #define MC_CG_ARB_FREQ_F1 0x0b @@ -7800,7 +7801,7 @@ static int si_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); return ret; } @@ -7848,7 +7849,7 @@ static int si_dpm_resume(void *handle) adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) - amdgpu_pm_compute_clocks(adev); + amdgpu_dpm_compute_clocks(adev); } return 0; } @@ -8101,6 +8102,7 @@ static const struct amd_pm_funcs si_dpm_funcs = { .check_state_equal = &si_check_state_equal, .get_vce_clock_state = amdgpu_get_vce_clock_state, .read_sensor = &si_dpm_read_sensor, + .change_power_state = amdgpu_dpm_change_power_state_locked, }; static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { From d698a2c4859de2d4d42d2f3c3806d6dce821d663 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 15 Nov 2021 15:24:05 +0800 Subject: [PATCH 011/339] drm/amd/pm: move pp_force_state_enabled member to amdgpu_pm structure As it lables an internal pm state and amdgpu_pm structure is the more proper place than amdgpu_device structure for it. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/pm/amdgpu_pm.c | 6 +++--- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 182d673103ed..d6dff14e7a2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -949,7 +949,6 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; - bool pp_force_state_enabled; /* smu */ struct smu_context smu; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index b16bb67b93f1..cd32f4ed373e 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -469,7 +469,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - if (adev->pp_force_state_enabled) + if (adev->pm.pp_force_state_enabled) return amdgpu_get_pp_cur_state(dev, attr, buf); else return sysfs_emit(buf, "\n"); @@ -492,7 +492,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (adev->in_suspend && !adev->in_runpm) return -EPERM; - adev->pp_force_state_enabled = false; + adev->pm.pp_force_state_enabled = false; if (strlen(buf) == 1) return count; @@ -523,7 +523,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (ret) goto err_out; - adev->pp_force_state_enabled = true; + adev->pm.pp_force_state_enabled = true; } pm_runtime_mark_last_busy(ddev->dev); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 1958e0e488b0..7afff23305a5 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -343,6 +343,8 @@ struct amdgpu_pm { * 0 = disabled (default), otherwise enable corresponding debug mode */ uint32_t smu_debug_mask; + + bool pp_force_state_enabled; }; #define R600_SSTU_DFLT 0 From 6ddbd37f10749830e0a6ddf839ca4313a007d3f5 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 17 Nov 2021 10:46:24 +0800 Subject: [PATCH 012/339] drm/amd/pm: optimize the amdgpu_pm_compute_clocks() implementations Drop cross callings and multi-function APIs. Also avoid exposing internal implementations details. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/kgd_pp_interface.h | 2 +- drivers/gpu/drm/amd/pm/Makefile | 2 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 200 ++---------------- drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c | 94 ++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 2 - .../gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h | 32 +++ .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 39 +++- drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 6 +- drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c | 60 +++++- drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h | 3 +- drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 41 +++- 11 files changed, 288 insertions(+), 193 deletions(-) create mode 100644 drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c create mode 100644 drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index cdf724dcf832..7919e96e772b 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -404,7 +404,7 @@ struct amd_pm_funcs { int (*get_dpm_clock_table)(void *handle, struct dpm_clocks *clock_table); int (*get_smu_prv_buf_details)(void *handle, void **addr, size_t *size); - int (*change_power_state)(void *handle); + void (*pm_compute_clocks)(void *handle); }; struct metrics_table_header { diff --git a/drivers/gpu/drm/amd/pm/Makefile b/drivers/gpu/drm/amd/pm/Makefile index 8cf6eff1ea93..d35ffde387f1 100644 --- a/drivers/gpu/drm/amd/pm/Makefile +++ b/drivers/gpu/drm/amd/pm/Makefile @@ -40,7 +40,7 @@ AMD_PM = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/,$(PM_LIBS))) include $(AMD_PM) -PM_MGR = amdgpu_dpm.o amdgpu_pm.o +PM_MGR = amdgpu_dpm.o amdgpu_pm.o amdgpu_dpm_internal.o AMD_PM_POWER = $(addprefix $(AMD_PM_PATH)/,$(PM_MGR)) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 438c56df9f23..fd2a7a2edf7d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -37,73 +37,6 @@ #define amdgpu_dpm_enable_bapm(adev, e) \ ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) -static void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) -{ - struct drm_device *ddev = adev_to_drm(adev); - struct drm_crtc *crtc; - struct amdgpu_crtc *amdgpu_crtc; - - adev->pm.dpm.new_active_crtcs = 0; - adev->pm.dpm.new_active_crtc_count = 0; - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (amdgpu_crtc->enabled) { - adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); - adev->pm.dpm.new_active_crtc_count++; - } - } - } -} - -u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) -{ - struct drm_device *dev = adev_to_drm(adev); - struct drm_crtc *crtc; - struct amdgpu_crtc *amdgpu_crtc; - u32 vblank_in_pixels; - u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ - - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { - vblank_in_pixels = - amdgpu_crtc->hw_mode.crtc_htotal * - (amdgpu_crtc->hw_mode.crtc_vblank_end - - amdgpu_crtc->hw_mode.crtc_vdisplay + - (amdgpu_crtc->v_border * 2)); - - vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock; - break; - } - } - } - - return vblank_time_us; -} - -static u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) -{ - struct drm_device *dev = adev_to_drm(adev); - struct drm_crtc *crtc; - struct amdgpu_crtc *amdgpu_crtc; - u32 vrefresh = 0; - - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { - vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); - break; - } - } - } - - return vrefresh; -} - int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; @@ -432,115 +365,38 @@ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors senso return ret; } -void amdgpu_dpm_thermal_work_handler(struct work_struct *work) -{ - struct amdgpu_device *adev = - container_of(work, struct amdgpu_device, - pm.dpm.thermal.work); - /* switch to the thermal state */ - enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; - int temp, size = sizeof(temp); - - if (!adev->pm.dpm_enabled) - return; - - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, - (void *)&temp, &size)) { - if (temp < adev->pm.dpm.thermal.min_temp) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } else { - if (adev->pm.dpm.thermal.high_to_low) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } - mutex_lock(&adev->pm.mutex); - if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) - adev->pm.dpm.thermal_active = true; - else - adev->pm.dpm.thermal_active = false; - adev->pm.dpm.state = dpm_state; - mutex_unlock(&adev->pm.mutex); - - amdgpu_dpm_compute_clocks(adev); -} - void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) { - int i = 0; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; if (!adev->pm.dpm_enabled) return; - if (adev->mode_info.num_crtc) - amdgpu_display_bandwidth_update(adev); + if (!pp_funcs->pm_compute_clocks) + return; - for (i = 0; i < AMDGPU_MAX_RINGS; i++) { - struct amdgpu_ring *ring = adev->rings[i]; - if (ring && ring->sched.ready) - amdgpu_fence_wait_empty(ring); - } - - if ((adev->family == AMDGPU_FAMILY_SI) || - (adev->family == AMDGPU_FAMILY_KV)) { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - adev->powerplay.pp_funcs->change_power_state(adev->powerplay.pp_handle); - mutex_unlock(&adev->pm.mutex); - } else { - if (!amdgpu_device_has_dc_support(adev)) { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; - adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); - adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); - /* we have issues with mclk switching with - * refresh rates over 120 hz on the non-DC code. - */ - if (adev->pm.pm_display_cfg.vrefresh > 120) - adev->pm.pm_display_cfg.min_vblank_time = 0; - if (adev->powerplay.pp_funcs->display_configuration_change) - adev->powerplay.pp_funcs->display_configuration_change( - adev->powerplay.pp_handle, - &adev->pm.pm_display_cfg); - mutex_unlock(&adev->pm.mutex); - } - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); - } + pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); } void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) { int ret = 0; - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.uvd_active = true; - adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; - } else { - adev->pm.dpm.uvd_active = false; - } - mutex_unlock(&adev->pm.mutex); + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); + if (ret) + DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", + enable ? "enable" : "disable", ret); - amdgpu_dpm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); - if (ret) - DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", - enable ? "enable" : "disable", ret); + /* enable/disable Low Memory PState for UVD (4k videos) */ + if (adev->asic_type == CHIP_STONEY && + adev->uvd.decode_image_width >= WIDTH_4K) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - /* enable/disable Low Memory PState for UVD (4k videos) */ - if (adev->asic_type == CHIP_STONEY && - adev->uvd.decode_image_width >= WIDTH_4K) { - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (hwmgr && hwmgr->hwmgr_func && - hwmgr->hwmgr_func->update_nbdpm_pstate) - hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, - !enable, - true); - } + if (hwmgr && hwmgr->hwmgr_func && + hwmgr->hwmgr_func->update_nbdpm_pstate) + hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, + !enable, + true); } } @@ -548,24 +404,10 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) { int ret = 0; - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.vce_active = true; - /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; - } else { - adev->pm.dpm.vce_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_dpm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); - if (ret) - DRM_ERROR("Dpm %s vce failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - } + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); + if (ret) + DRM_ERROR("Dpm %s vce failed, ret = %d. \n", + enable ? "enable" : "disable", ret); } void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c new file mode 100644 index 000000000000..ba5f6413412d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c @@ -0,0 +1,94 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "amdgpu.h" +#include "amdgpu_display.h" +#include "hwmgr.h" +#include "amdgpu_smu.h" + +void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) +{ + struct drm_device *ddev = adev_to_drm(adev); + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + + adev->pm.dpm.new_active_crtcs = 0; + adev->pm.dpm.new_active_crtc_count = 0; + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (amdgpu_crtc->enabled) { + adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); + adev->pm.dpm.new_active_crtc_count++; + } + } + } +} + +u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev_to_drm(adev); + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + u32 vblank_in_pixels; + u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { + vblank_in_pixels = + amdgpu_crtc->hw_mode.crtc_htotal * + (amdgpu_crtc->hw_mode.crtc_vblank_end - + amdgpu_crtc->hw_mode.crtc_vdisplay + + (amdgpu_crtc->v_border * 2)); + + vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock; + break; + } + } + } + + return vblank_time_us; +} + +u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev_to_drm(adev); + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + u32 vrefresh = 0; + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { + vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); + break; + } + } + } + + return vrefresh; +} diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 7afff23305a5..63302b3aebe0 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -428,8 +428,6 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, void *data, uint32_t *size); -void amdgpu_dpm_thermal_work_handler(struct work_struct *work); - void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev); void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h new file mode 100644 index 000000000000..5c2a89f0d5d5 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm_internal.h @@ -0,0 +1,32 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __AMDGPU_DPM_INTERNAL_H__ +#define __AMDGPU_DPM_INTERNAL_H__ + +void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev); + +u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); + +u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 3ab67b232cd4..6a06a1f0b79b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -31,7 +31,8 @@ #include "power_state.h" #include "amdgpu.h" #include "hwmgr.h" - +#include "amdgpu_dpm_internal.h" +#include "amdgpu_display.h" static const struct amd_pm_funcs pp_dpm_funcs; @@ -1683,6 +1684,41 @@ static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size) return 0; } +static void pp_pm_compute_clocks(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + struct amdgpu_device *adev = hwmgr->adev; + int i = 0; + + if (adev->mode_info.num_crtc) + amdgpu_display_bandwidth_update(adev); + + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->sched.ready) + amdgpu_fence_wait_empty(ring); + } + + if (!amdgpu_device_has_dc_support(adev)) { + amdgpu_dpm_get_active_displays(adev); + adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; + adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); + adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we have issues with mclk switching with + * refresh rates over 120 hz on the non-DC code. + */ + if (adev->pm.pm_display_cfg.vrefresh > 120) + adev->pm.pm_display_cfg.min_vblank_time = 0; + + pp_display_configuration_change(handle, + &adev->pm.pm_display_cfg); + } + + pp_dpm_dispatch_tasks(handle, + AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, + NULL); +} + static const struct amd_pm_funcs pp_dpm_funcs = { .load_firmware = pp_dpm_load_fw, .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, @@ -1747,4 +1783,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .get_gpu_metrics = pp_get_gpu_metrics, .gfx_state_change_set = pp_gfx_state_change_set, .get_smu_prv_buf_details = pp_get_prv_buffer_details, + .pm_compute_clocks = pp_pm_compute_clocks, }; diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c index eed89835231c..72824ef61edd 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c @@ -3088,7 +3088,7 @@ static int kv_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - amdgpu_dpm_compute_clocks(adev); + amdgpu_legacy_dpm_compute_clocks(adev); return ret; } @@ -3136,7 +3136,7 @@ static int kv_dpm_resume(void *handle) adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) - amdgpu_dpm_compute_clocks(adev); + amdgpu_legacy_dpm_compute_clocks(adev); } return 0; } @@ -3390,7 +3390,7 @@ static const struct amd_pm_funcs kv_dpm_funcs = { .get_vce_clock_state = amdgpu_get_vce_clock_state, .check_state_equal = kv_check_state_equal, .read_sensor = &kv_dpm_read_sensor, - .change_power_state = amdgpu_dpm_change_power_state_locked, + .pm_compute_clocks = amdgpu_legacy_dpm_compute_clocks, }; static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = { diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c index 67c84b7ad8e7..3c6ee493e410 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c @@ -26,6 +26,8 @@ #include "atom.h" #include "amd_pcie.h" #include "legacy_dpm.h" +#include "amdgpu_dpm_internal.h" +#include "amdgpu_display.h" #define amdgpu_dpm_pre_set_power_state(adev) \ ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) @@ -949,9 +951,8 @@ restart_search: return NULL; } -int amdgpu_dpm_change_power_state_locked(void *handle) +static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) { - struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ps *ps; enum amd_pm_state_type dpm_state; int ret; @@ -1022,3 +1023,58 @@ int amdgpu_dpm_change_power_state_locked(void *handle) return 0; } + +void amdgpu_legacy_dpm_compute_clocks(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int i = 0; + + if (adev->mode_info.num_crtc) + amdgpu_display_bandwidth_update(adev); + + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->sched.ready) + amdgpu_fence_wait_empty(ring); + } + + amdgpu_dpm_get_active_displays(adev); + + amdgpu_dpm_change_power_state_locked(adev); +} + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work) +{ + struct amdgpu_device *adev = + container_of(work, struct amdgpu_device, + pm.dpm.thermal.work); + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + /* switch to the thermal state */ + enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; + int temp, size = sizeof(temp); + + if (!adev->pm.dpm_enabled) + return; + + if (!pp_funcs->read_sensor(adev->powerplay.pp_handle, + AMDGPU_PP_SENSOR_GPU_TEMP, + (void *)&temp, + &size)) { + if (temp < adev->pm.dpm.thermal.min_temp) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } else { + if (adev->pm.dpm.thermal.high_to_low) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } + + if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) + adev->pm.dpm.thermal_active = true; + else + adev->pm.dpm.thermal_active = false; + + adev->pm.dpm.state = dpm_state; + + amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle); +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h index 7ac30f1aed20..93bd3973330c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h +++ b/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h @@ -32,6 +32,7 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); void amdgpu_free_extended_power_table(struct amdgpu_device *adev); void amdgpu_add_thermal_controller(struct amdgpu_device *adev); struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx); -int amdgpu_dpm_change_power_state_locked(void *handle); void amdgpu_pm_print_power_states(struct amdgpu_device *adev); +void amdgpu_legacy_dpm_compute_clocks(void *handle); +void amdgpu_dpm_thermal_work_handler(struct work_struct *work); #endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c index 7becb9e9275b..9f8cc81cb7ca 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -3891,6 +3891,40 @@ static int si_set_boot_state(struct amdgpu_device *adev) } #endif +static int si_set_powergating_by_smu(void *handle, + uint32_t block_type, + bool gate) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + switch (block_type) { + case AMD_IP_BLOCK_TYPE_UVD: + if (!gate) { + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + } else { + adev->pm.dpm.uvd_active = false; + } + + amdgpu_legacy_dpm_compute_clocks(handle); + break; + case AMD_IP_BLOCK_TYPE_VCE: + if (!gate) { + adev->pm.dpm.vce_active = true; + /* XXX select vce level based on ring/task */ + adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; + } else { + adev->pm.dpm.vce_active = false; + } + + amdgpu_legacy_dpm_compute_clocks(handle); + break; + default: + break; + } + return 0; +} + static int si_set_sw_state(struct amdgpu_device *adev) { return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? @@ -7801,7 +7835,7 @@ static int si_dpm_hw_init(void *handle) else adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); - amdgpu_dpm_compute_clocks(adev); + amdgpu_legacy_dpm_compute_clocks(adev); return ret; } @@ -7849,7 +7883,7 @@ static int si_dpm_resume(void *handle) adev->pm.dpm_enabled = true; mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) - amdgpu_dpm_compute_clocks(adev); + amdgpu_legacy_dpm_compute_clocks(adev); } return 0; } @@ -8094,6 +8128,7 @@ static const struct amd_pm_funcs si_dpm_funcs = { .print_power_state = &si_dpm_print_power_state, .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, .force_performance_level = &si_dpm_force_performance_level, + .set_powergating_by_smu = &si_set_powergating_by_smu, .vblank_too_short = &si_dpm_vblank_too_short, .set_fan_control_mode = &si_dpm_set_fan_control_mode, .get_fan_control_mode = &si_dpm_get_fan_control_mode, @@ -8102,7 +8137,7 @@ static const struct amd_pm_funcs si_dpm_funcs = { .check_state_equal = &si_check_state_equal, .get_vce_clock_state = amdgpu_get_vce_clock_state, .read_sensor = &si_dpm_read_sensor, - .change_power_state = amdgpu_dpm_change_power_state_locked, + .pm_compute_clocks = amdgpu_legacy_dpm_compute_clocks, }; static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { From a627967e803e58c5525ac92a4af0d15379189a32 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 17 Nov 2021 11:29:05 +0800 Subject: [PATCH 013/339] drm/amd/pm: move those code piece used by Stoney only to smu8_hwmgr.c Instead of putting them in amdgpu_dpm.c. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 14 -------------- drivers/gpu/drm/amd/pm/inc/hwmgr.h | 3 --- .../gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c | 10 +++++++++- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index fd2a7a2edf7d..88909b7c40db 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -32,8 +32,6 @@ #include "hwmgr.h" #include -#define WIDTH_4K 3840 - #define amdgpu_dpm_enable_bapm(adev, e) \ ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) @@ -386,18 +384,6 @@ void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) if (ret) DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", enable ? "enable" : "disable", ret); - - /* enable/disable Low Memory PState for UVD (4k videos) */ - if (adev->asic_type == CHIP_STONEY && - adev->uvd.decode_image_width >= WIDTH_4K) { - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (hwmgr && hwmgr->hwmgr_func && - hwmgr->hwmgr_func->update_nbdpm_pstate) - hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, - !enable, - true); - } } void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h index 8ed01071fe5a..03226baea65e 100644 --- a/drivers/gpu/drm/amd/pm/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/inc/hwmgr.h @@ -331,9 +331,6 @@ struct pp_hwmgr_func { uint32_t mc_addr_low, uint32_t mc_addr_hi, uint32_t size); - int (*update_nbdpm_pstate)(struct pp_hwmgr *hwmgr, - bool enable, - bool lock); int (*get_thermal_temperature_range)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); int (*get_power_profile_mode)(struct pp_hwmgr *hwmgr, char *buf); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c index 03bf8f069222..b50fd4a4a3d1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c @@ -1950,9 +1950,12 @@ static void smu8_dpm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate) smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerON, NULL); } +#define WIDTH_4K 3840 + static void smu8_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) { struct smu8_hwmgr *data = hwmgr->backend; + struct amdgpu_device *adev = hwmgr->adev; data->uvd_power_gated = bgate; @@ -1976,6 +1979,12 @@ static void smu8_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) smu8_dpm_update_uvd_dpm(hwmgr, false); } + /* enable/disable Low Memory PState for UVD (4k videos) */ + if (adev->asic_type == CHIP_STONEY && + adev->uvd.decode_image_width >= WIDTH_4K) + smu8_nbdpm_pstate_enable_disable(hwmgr, + bgate, + true); } static void smu8_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) @@ -2037,7 +2046,6 @@ static const struct pp_hwmgr_func smu8_hwmgr_funcs = { .power_state_set = smu8_set_power_state_tasks, .dynamic_state_management_disable = smu8_disable_dpm_tasks, .notify_cac_buffer_info = smu8_notify_cac_buffer_info, - .update_nbdpm_pstate = smu8_nbdpm_pstate_enable_disable, .get_thermal_temperature_range = smu8_get_thermal_temperature_range, }; From 7689dab48259073ea13d64d32365b77860b84e7f Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 11 Nov 2021 12:03:14 +0800 Subject: [PATCH 014/339] drm/amd/pm: drop redundant or unused APIs and data structures Drop those unused APIs and data structures. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 49 ------------------------- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 4 ++ 2 files changed, 4 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 63302b3aebe0..ba857ca75392 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -88,19 +88,6 @@ struct amdgpu_dpm_thermal { struct amdgpu_irq_src irq; }; -enum amdgpu_clk_action -{ - AMDGPU_SCLK_UP = 1, - AMDGPU_SCLK_DOWN -}; - -struct amdgpu_blacklist_clocks -{ - u32 sclk; - u32 mclk; - enum amdgpu_clk_action action; -}; - struct amdgpu_clock_and_voltage_limits { u32 sclk; u32 mclk; @@ -239,10 +226,6 @@ struct amdgpu_dpm_fan { bool ucode_fan_control; }; -#define amdgpu_dpm_reset_power_profile_state(adev, request) \ - ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ - (adev)->powerplay.pp_handle, request)) - struct amdgpu_dpm { struct amdgpu_ps *ps; /* number of valid power states */ @@ -347,35 +330,6 @@ struct amdgpu_pm { bool pp_force_state_enabled; }; -#define R600_SSTU_DFLT 0 -#define R600_SST_DFLT 0x00C8 - -/* XXX are these ok? */ -#define R600_TEMP_RANGE_MIN (90 * 1000) -#define R600_TEMP_RANGE_MAX (120 * 1000) - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -enum amdgpu_td { - AMDGPU_TD_AUTO, - AMDGPU_TD_UP, - AMDGPU_TD_DOWN, -}; - -enum amdgpu_display_watermark { - AMDGPU_DISPLAY_WATERMARK_LOW = 0, - AMDGPU_DISPLAY_WATERMARK_HIGH = 1, -}; - -enum amdgpu_display_gap -{ - AMDGPU_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, - AMDGPU_PM_DISPLAY_GAP_VBLANK = 1, - AMDGPU_PM_DISPLAY_GAP_WATERMARK = 2, - AMDGPU_PM_DISPLAY_GAP_IGNORE = 3, -}; - u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, void *data, uint32_t *size); @@ -425,9 +379,6 @@ int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); -int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, - void *data, uint32_t *size); - void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev); void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index beea03810bca..67a25da79256 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -26,6 +26,10 @@ #include "amdgpu_smu.h" #if defined(SWSMU_CODE_LAYER_L2) || defined(SWSMU_CODE_LAYER_L3) || defined(SWSMU_CODE_LAYER_L4) + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + int smu_cmn_send_msg_without_waiting(struct smu_context *smu, uint16_t msg_index, uint32_t param); From ebfc253335af81db2e40e6e8ed17cd76edf9080f Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 22 Nov 2021 13:11:06 +0800 Subject: [PATCH 015/339] drm/amd/pm: do not expose the smu_context structure used internally in power This can cover the power implementation details. And as what did for powerplay framework, we hook the smu_context to adev->powerplay.pp_handle. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 --- .../gpu/drm/amd/include/kgd_pp_interface.h | 3 ++ drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 50 +++++++++++++------ drivers/gpu/drm/amd/pm/amdgpu_pm.c | 2 +- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 4 -- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 48 +++++++++++------- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 9 ++-- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 9 ++-- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 9 ++-- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 4 +- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 9 ++-- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 8 +-- 12 files changed, 94 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d6dff14e7a2d..f0132a5cc58d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -99,7 +99,6 @@ #include "amdgpu_gem.h" #include "amdgpu_doorbell.h" #include "amdgpu_amdkfd.h" -#include "amdgpu_smu.h" #include "amdgpu_discovery.h" #include "amdgpu_mes.h" #include "amdgpu_umc.h" @@ -949,11 +948,6 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; - - /* smu */ - struct smu_context smu; - - /* dpm */ struct amdgpu_pm pm; u32 cg_flags; u32 pg_flags; diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 7919e96e772b..a8eec91c0995 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -25,6 +25,9 @@ #define __KGD_PP_INTERFACE_H__ extern const struct amdgpu_ip_block_version pp_smu_ip_block; +extern const struct amdgpu_ip_block_version smu_v11_0_ip_block; +extern const struct amdgpu_ip_block_version smu_v12_0_ip_block; +extern const struct amdgpu_ip_block_version smu_v13_0_ip_block; enum smu_event_type { SMU_EVENT_RESET_COMPLETE = 0, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 88909b7c40db..2756f52b74c1 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -31,6 +31,7 @@ #include "amdgpu_display.h" #include "hwmgr.h" #include +#include "amdgpu_smu.h" #define amdgpu_dpm_enable_bapm(adev, e) \ ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) @@ -213,7 +214,7 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (is_support_sw_smu(adev)) return smu_mode1_reset_is_support(smu); @@ -223,7 +224,7 @@ bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (is_support_sw_smu(adev)) return smu_mode1_reset(smu); @@ -276,7 +277,7 @@ int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (is_support_sw_smu(adev)) return smu_allow_xgmi_power_down(smu, en); @@ -341,7 +342,7 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) mutex_unlock(&adev->pm.mutex); if (is_support_sw_smu(adev)) - smu_set_ac_dc(&adev->smu); + smu_set_ac_dc(adev->powerplay.pp_handle); } } @@ -426,12 +427,14 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) { - return smu_handle_passthrough_sbr(&adev->smu, enable); + return smu_handle_passthrough_sbr(adev->powerplay.pp_handle, enable); } int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) { - return smu_send_hbm_bad_pages_num(&adev->smu, size); + struct smu_context *smu = adev->powerplay.pp_handle; + + return smu_send_hbm_bad_pages_num(smu, size); } int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, @@ -444,7 +447,7 @@ int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, switch (type) { case PP_SCLK: - return smu_get_dpm_freq_range(&adev->smu, SMU_SCLK, min, max); + return smu_get_dpm_freq_range(adev->powerplay.pp_handle, SMU_SCLK, min, max); default: return -EINVAL; } @@ -455,12 +458,14 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, uint32_t min, uint32_t max) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; switch (type) { case PP_SCLK: - return smu_set_soft_freq_range(&adev->smu, SMU_SCLK, min, max); + return smu_set_soft_freq_range(smu, SMU_SCLK, min, max); default: return -EINVAL; } @@ -468,33 +473,41 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return 0; - return smu_write_watermarks_table(&adev->smu); + return smu_write_watermarks_table(smu); } int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, enum smu_event_type event, uint64_t event_arg) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_wait_for_event(&adev->smu, event, event_arg); + return smu_wait_for_event(smu, event, event_arg); } int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_get_status_gfxoff(&adev->smu, value); + return smu_get_status_gfxoff(smu, value); } uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) { - return atomic64_read(&adev->smu.throttle_int_counter); + struct smu_context *smu = adev->powerplay.pp_handle; + + return atomic64_read(&smu->throttle_int_counter); } /* amdgpu_dpm_gfx_state_change - Handle gfx power state change set @@ -516,10 +529,12 @@ void amdgpu_dpm_gfx_state_change(struct amdgpu_device *adev, int amdgpu_dpm_get_ecc_info(struct amdgpu_device *adev, void *umc_ecc) { + struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_get_ecc_info(&adev->smu, umc_ecc); + return smu_get_ecc_info(smu, umc_ecc); } struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, @@ -943,9 +958,10 @@ int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) { struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + struct smu_context *smu = adev->powerplay.pp_handle; - if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || - (is_support_sw_smu(adev) && adev->smu.is_apu) || + if ((is_support_sw_smu(adev) && smu->od_enabled) || + (is_support_sw_smu(adev) && smu->is_apu) || (!is_support_sw_smu(adev) && hwmgr->od_enabled)) return true; @@ -968,7 +984,9 @@ int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) { - return adev->smu.cpu_core_num; + struct smu_context *smu = adev->powerplay.pp_handle; + + return smu->cpu_core_num; } void amdgpu_dpm_stb_debug_fs_init(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index cd32f4ed373e..b14b004577e5 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2869,7 +2869,7 @@ static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, int limit_type = to_sensor_dev_attr(attr)->index; return sysfs_emit(buf, "%s\n", - limit_type == SMU_FAST_PPT_LIMIT ? "fastPPT" : "slowPPT"); + limit_type == PP_PWR_TYPE_FAST ? "fastPPT" : "slowPPT"); } static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index b90ed0ec9322..8a689baeaf82 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -1390,10 +1390,6 @@ int smu_mode1_reset(struct smu_context *smu); extern const struct amd_ip_funcs smu_ip_funcs; -extern const struct amdgpu_ip_block_version smu_v11_0_ip_block; -extern const struct amdgpu_ip_block_version smu_v12_0_ip_block; -extern const struct amdgpu_ip_block_version smu_v13_0_ip_block; - bool is_support_sw_smu(struct amdgpu_device *adev); bool is_support_cclk_dpm(struct amdgpu_device *adev); int smu_write_watermarks_table(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7191b3928e8e..c898ea67354a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -468,7 +468,7 @@ bool is_support_sw_smu(struct amdgpu_device *adev) bool is_support_cclk_dpm(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (!smu_feature_is_enabled(smu, SMU_FEATURE_CCLK_DPM_BIT)) return false; @@ -572,7 +572,7 @@ static int smu_get_driver_allowed_feature_mask(struct smu_context *smu) static int smu_set_funcs(struct amdgpu_device *adev) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (adev->pm.pp_feature & PP_OVERDRIVE_MASK) smu->od_enabled = true; @@ -624,7 +624,11 @@ static int smu_set_funcs(struct amdgpu_device *adev) static int smu_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu; + + smu = kzalloc(sizeof(struct smu_context), GFP_KERNEL); + if (!smu) + return -ENOMEM; smu->adev = adev; smu->pm_enabled = !!amdgpu_dpm; @@ -684,7 +688,7 @@ err0_out: static int smu_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret = 0; smu_set_fine_grain_gfx_freq_parameters(smu); @@ -730,7 +734,7 @@ static int smu_late_init(void *handle) smu_get_fan_parameters(smu); - smu_handle_task(&adev->smu, + smu_handle_task(smu, smu->smu_dpm.dpm_level, AMD_PP_TASK_COMPLETE_INIT, false); @@ -1020,7 +1024,7 @@ static void smu_interrupt_work_fn(struct work_struct *work) static int smu_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret; smu->pool_size = adev->pm.smu_prv_buffer_size; @@ -1095,7 +1099,7 @@ static int smu_sw_init(void *handle) static int smu_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret; ret = smu_smc_table_sw_fini(smu); @@ -1330,7 +1334,7 @@ static int smu_hw_init(void *handle) { int ret; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) { smu->pm_enabled = false; @@ -1346,7 +1350,7 @@ static int smu_hw_init(void *handle) if (smu->is_apu) { smu_dpm_set_vcn_enable(smu, true); smu_dpm_set_jpeg_enable(smu, true); - smu_set_gfx_cgpg(&adev->smu, true); + smu_set_gfx_cgpg(smu, true); } if (!smu->pm_enabled) @@ -1506,7 +1510,7 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) static int smu_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1525,6 +1529,14 @@ static int smu_hw_fini(void *handle) return smu_smc_hw_cleanup(smu); } +static void smu_late_fini(void *handle) +{ + struct amdgpu_device *adev = handle; + struct smu_context *smu = adev->powerplay.pp_handle; + + kfree(smu); +} + static int smu_reset(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -1552,7 +1564,7 @@ static int smu_reset(struct smu_context *smu) static int smu_suspend(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; int ret; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) @@ -1569,7 +1581,7 @@ static int smu_suspend(void *handle) smu->watermarks_bitmap &= ~(WATERMARKS_LOADED); - smu_set_gfx_cgpg(&adev->smu, false); + smu_set_gfx_cgpg(smu, false); return 0; } @@ -1578,7 +1590,7 @@ static int smu_resume(void *handle) { int ret; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1600,7 +1612,7 @@ static int smu_resume(void *handle) return ret; } - smu_set_gfx_cgpg(&adev->smu, true); + smu_set_gfx_cgpg(smu, true); smu->disable_uclk_switch = 0; @@ -2132,6 +2144,7 @@ const struct amd_ip_funcs smu_ip_funcs = { .sw_fini = smu_sw_fini, .hw_init = smu_hw_init, .hw_fini = smu_hw_fini, + .late_fini = smu_late_fini, .suspend = smu_suspend, .resume = smu_resume, .is_idle = NULL, @@ -3196,7 +3209,7 @@ int smu_stb_collect_info(struct smu_context *smu, void *buf, uint32_t size) static int smu_stb_debugfs_open(struct inode *inode, struct file *filp) { struct amdgpu_device *adev = filp->f_inode->i_private; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; unsigned char *buf; int r; @@ -3221,7 +3234,7 @@ static ssize_t smu_stb_debugfs_read(struct file *filp, char __user *buf, size_t loff_t *pos) { struct amdgpu_device *adev = filp->f_inode->i_private; - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (!filp->private_data) @@ -3262,7 +3275,7 @@ void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev) { #if defined(CONFIG_DEBUG_FS) - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; if (!smu->stb_context.stb_buf_size) return; @@ -3274,7 +3287,6 @@ void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev) &smu_stb_debugfs_fops, smu->stb_context.stb_buf_size); #endif - } int smu_send_hbm_bad_pages_num(struct smu_context *smu, uint32_t size) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 505d2fb94fd9..0a1547c27305 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2072,7 +2072,8 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -2118,9 +2119,9 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 2bb7816b245a..37e11716e919 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2779,7 +2779,8 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -2825,9 +2826,9 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index d8c57b780bca..efe6b2eff6a0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3459,7 +3459,8 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -3505,9 +3506,9 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 4e9e2cf39859..e176e6a74f44 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1372,7 +1372,7 @@ static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, unsigned tyep, enum amdgpu_interrupt_state state) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t low, high; uint32_t val = 0; @@ -1441,7 +1441,7 @@ static int smu_v11_0_irq_process(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t client_id = entry->client_id; uint32_t src_id = entry->src_id; /* diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 4885c4ae78b7..a4d46f7069bc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1475,7 +1475,8 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); - struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; int i, j, r, c; @@ -1521,9 +1522,9 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&adev->smu.mutex); - r = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&adev->smu.mutex); + mutex_lock(&smu->mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&smu->mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index b54790d3483e..f1d7b4900aa1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -1200,7 +1200,7 @@ static int smu_v13_0_set_irq_state(struct amdgpu_device *adev, unsigned tyep, enum amdgpu_interrupt_state state) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t low, high; uint32_t val = 0; @@ -1275,7 +1275,7 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - struct smu_context *smu = &adev->smu; + struct smu_context *smu = adev->powerplay.pp_handle; uint32_t client_id = entry->client_id; uint32_t src_id = entry->src_id; /* @@ -1321,11 +1321,11 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev, switch (ctxid) { case 0x3: dev_dbg(adev->dev, "Switched to AC mode!\n"); - smu_v13_0_ack_ac_dc_interrupt(&adev->smu); + smu_v13_0_ack_ac_dc_interrupt(smu); break; case 0x4: dev_dbg(adev->dev, "Switched to DC mode!\n"); - smu_v13_0_ack_ac_dc_interrupt(&adev->smu); + smu_v13_0_ack_ac_dc_interrupt(smu); break; case 0x7: /* From 837d542a09cd533055423dfca7e621a9c1d13c5b Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 16 Nov 2021 13:30:53 +0800 Subject: [PATCH 016/339] drm/amd/pm: relocate the power related headers Instead of centralizing all headers in the same folder. Separate them into different folders and place them among those source files those who really need them. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/Makefile | 11 ++++--- drivers/gpu/drm/amd/pm/legacy-dpm/Makefile | 32 +++++++++++++++++++ .../pm/{powerplay => legacy-dpm}/cik_dpm.h | 0 .../amd/pm/{powerplay => legacy-dpm}/kv_dpm.c | 0 .../amd/pm/{powerplay => legacy-dpm}/kv_dpm.h | 0 .../amd/pm/{powerplay => legacy-dpm}/kv_smc.c | 0 .../pm/{powerplay => legacy-dpm}/legacy_dpm.c | 0 .../pm/{powerplay => legacy-dpm}/legacy_dpm.h | 0 .../amd/pm/{powerplay => legacy-dpm}/ppsmc.h | 0 .../pm/{powerplay => legacy-dpm}/r600_dpm.h | 0 .../amd/pm/{powerplay => legacy-dpm}/si_dpm.c | 0 .../amd/pm/{powerplay => legacy-dpm}/si_dpm.h | 0 .../amd/pm/{powerplay => legacy-dpm}/si_smc.c | 0 .../{powerplay => legacy-dpm}/sislands_smc.h | 0 drivers/gpu/drm/amd/pm/powerplay/Makefile | 6 +--- .../pm/{ => powerplay}/inc/amd_powerplay.h | 0 .../drm/amd/pm/{ => powerplay}/inc/cz_ppsmc.h | 0 .../amd/pm/{ => powerplay}/inc/fiji_ppsmc.h | 0 .../pm/{ => powerplay}/inc/hardwaremanager.h | 0 .../drm/amd/pm/{ => powerplay}/inc/hwmgr.h | 0 .../{ => powerplay}/inc/polaris10_pwrvirus.h | 0 .../amd/pm/{ => powerplay}/inc/power_state.h | 0 .../drm/amd/pm/{ => powerplay}/inc/pp_debug.h | 0 .../amd/pm/{ => powerplay}/inc/pp_endian.h | 0 .../amd/pm/{ => powerplay}/inc/pp_thermal.h | 0 .../amd/pm/{ => powerplay}/inc/ppinterrupt.h | 0 .../drm/amd/pm/{ => powerplay}/inc/rv_ppsmc.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smu10.h | 0 .../pm/{ => powerplay}/inc/smu10_driver_if.h | 0 .../pm/{ => powerplay}/inc/smu11_driver_if.h | 0 .../gpu/drm/amd/pm/{ => powerplay}/inc/smu7.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smu71.h | 0 .../pm/{ => powerplay}/inc/smu71_discrete.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smu72.h | 0 .../pm/{ => powerplay}/inc/smu72_discrete.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smu73.h | 0 .../pm/{ => powerplay}/inc/smu73_discrete.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smu74.h | 0 .../pm/{ => powerplay}/inc/smu74_discrete.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smu75.h | 0 .../pm/{ => powerplay}/inc/smu75_discrete.h | 0 .../amd/pm/{ => powerplay}/inc/smu7_common.h | 0 .../pm/{ => powerplay}/inc/smu7_discrete.h | 0 .../amd/pm/{ => powerplay}/inc/smu7_fusion.h | 0 .../amd/pm/{ => powerplay}/inc/smu7_ppsmc.h | 0 .../gpu/drm/amd/pm/{ => powerplay}/inc/smu8.h | 0 .../amd/pm/{ => powerplay}/inc/smu8_fusion.h | 0 .../gpu/drm/amd/pm/{ => powerplay}/inc/smu9.h | 0 .../pm/{ => powerplay}/inc/smu9_driver_if.h | 0 .../{ => powerplay}/inc/smu_ucode_xfer_cz.h | 0 .../{ => powerplay}/inc/smu_ucode_xfer_vi.h | 0 .../drm/amd/pm/{ => powerplay}/inc/smumgr.h | 0 .../amd/pm/{ => powerplay}/inc/tonga_ppsmc.h | 0 .../amd/pm/{ => powerplay}/inc/vega10_ppsmc.h | 0 .../inc/vega12/smu9_driver_if.h | 0 .../amd/pm/{ => powerplay}/inc/vega12_ppsmc.h | 0 .../amd/pm/{ => powerplay}/inc/vega20_ppsmc.h | 0 .../drm/amd/pm/{ => swsmu}/inc/amdgpu_smu.h | 0 .../inc/pmfw_if}/aldebaran_ppsmc.h | 0 .../inc/pmfw_if}/arcturus_ppsmc.h | 0 .../inc/pmfw_if}/smu11_driver_if_arcturus.h | 0 .../pmfw_if}/smu11_driver_if_cyan_skillfish.h | 0 .../inc/pmfw_if}/smu11_driver_if_navi10.h | 0 .../pmfw_if}/smu11_driver_if_sienna_cichlid.h | 0 .../inc/pmfw_if}/smu11_driver_if_vangogh.h | 0 .../inc/pmfw_if}/smu12_driver_if.h | 0 .../inc/pmfw_if}/smu13_driver_if_aldebaran.h | 0 .../pmfw_if}/smu13_driver_if_yellow_carp.h | 0 .../inc/pmfw_if}/smu_v11_0_7_ppsmc.h | 0 .../inc/pmfw_if}/smu_v11_0_ppsmc.h | 0 .../inc/pmfw_if}/smu_v11_5_pmfw.h | 0 .../inc/pmfw_if}/smu_v11_5_ppsmc.h | 0 .../inc/pmfw_if}/smu_v11_8_pmfw.h | 0 .../inc/pmfw_if}/smu_v11_8_ppsmc.h | 0 .../inc/pmfw_if}/smu_v12_0_ppsmc.h | 0 .../inc/pmfw_if}/smu_v13_0_1_pmfw.h | 0 .../inc/pmfw_if}/smu_v13_0_1_ppsmc.h | 0 .../pm/{ => swsmu}/inc/smu_11_0_cdr_table.h | 0 .../drm/amd/pm/{ => swsmu}/inc/smu_types.h | 0 .../drm/amd/pm/{ => swsmu}/inc/smu_v11_0.h | 0 .../pm/{ => swsmu}/inc/smu_v11_0_7_pptable.h | 0 .../pm/{ => swsmu}/inc/smu_v11_0_pptable.h | 0 .../drm/amd/pm/{ => swsmu}/inc/smu_v12_0.h | 0 .../drm/amd/pm/{ => swsmu}/inc/smu_v13_0.h | 0 .../pm/{ => swsmu}/inc/smu_v13_0_pptable.h | 0 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 - .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 1 - 87 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 drivers/gpu/drm/amd/pm/legacy-dpm/Makefile rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/cik_dpm.h (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/kv_dpm.c (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/kv_dpm.h (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/kv_smc.c (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/legacy_dpm.c (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/legacy_dpm.h (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/r600_dpm.h (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/si_dpm.c (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/si_dpm.h (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/si_smc.c (100%) rename drivers/gpu/drm/amd/pm/{powerplay => legacy-dpm}/sislands_smc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/amd_powerplay.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/cz_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/fiji_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/hardwaremanager.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/hwmgr.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/polaris10_pwrvirus.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/power_state.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/pp_debug.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/pp_endian.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/pp_thermal.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/ppinterrupt.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/rv_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu10.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu10_driver_if.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu11_driver_if.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu7.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu71.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu71_discrete.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu72.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu72_discrete.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu73.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu73_discrete.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu74.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu74_discrete.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu75.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu75_discrete.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu7_common.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu7_discrete.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu7_fusion.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu7_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu8.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu8_fusion.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu9.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu9_driver_if.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu_ucode_xfer_cz.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smu_ucode_xfer_vi.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/smumgr.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/tonga_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/vega10_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/vega12/smu9_driver_if.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/vega12_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => powerplay}/inc/vega20_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/amdgpu_smu.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/aldebaran_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/arcturus_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu11_driver_if_arcturus.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu11_driver_if_cyan_skillfish.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu11_driver_if_navi10.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu11_driver_if_sienna_cichlid.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu11_driver_if_vangogh.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu12_driver_if.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu13_driver_if_aldebaran.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu13_driver_if_yellow_carp.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v11_0_7_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v11_0_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v11_5_pmfw.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v11_5_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v11_8_pmfw.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v11_8_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v12_0_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v13_0_1_pmfw.h (100%) rename drivers/gpu/drm/amd/pm/{inc => swsmu/inc/pmfw_if}/smu_v13_0_1_ppsmc.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_11_0_cdr_table.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_types.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_v11_0.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_v11_0_7_pptable.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_v11_0_pptable.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_v12_0.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_v13_0.h (100%) rename drivers/gpu/drm/amd/pm/{ => swsmu}/inc/smu_v13_0_pptable.h (100%) diff --git a/drivers/gpu/drm/amd/pm/Makefile b/drivers/gpu/drm/amd/pm/Makefile index d35ffde387f1..51751db436b0 100644 --- a/drivers/gpu/drm/amd/pm/Makefile +++ b/drivers/gpu/drm/amd/pm/Makefile @@ -21,20 +21,23 @@ # subdir-ccflags-y += \ - -I$(FULL_AMD_PATH)/pm/inc/ \ -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ + -I$(FULL_AMD_PATH)/pm/inc/ \ -I$(FULL_AMD_PATH)/pm/swsmu \ + -I$(FULL_AMD_PATH)/pm/swsmu/inc \ + -I$(FULL_AMD_PATH)/pm/swsmu/inc/pmfw_if \ -I$(FULL_AMD_PATH)/pm/swsmu/smu11 \ -I$(FULL_AMD_PATH)/pm/swsmu/smu12 \ -I$(FULL_AMD_PATH)/pm/swsmu/smu13 \ - -I$(FULL_AMD_PATH)/pm/powerplay \ + -I$(FULL_AMD_PATH)/pm/powerplay/inc \ -I$(FULL_AMD_PATH)/pm/powerplay/smumgr\ - -I$(FULL_AMD_PATH)/pm/powerplay/hwmgr + -I$(FULL_AMD_PATH)/pm/powerplay/hwmgr \ + -I$(FULL_AMD_PATH)/pm/legacy-dpm AMD_PM_PATH = ../pm -PM_LIBS = swsmu powerplay +PM_LIBS = swsmu powerplay legacy-dpm AMD_PM = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/,$(PM_LIBS))) diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/Makefile b/drivers/gpu/drm/amd/pm/legacy-dpm/Makefile new file mode 100644 index 000000000000..baa4265d1daa --- /dev/null +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/Makefile @@ -0,0 +1,32 @@ +# +# Copyright 2021 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +AMD_LEGACYDPM_PATH = ../pm/legacy-dpm + +LEGACYDPM_MGR-y = legacy_dpm.o + +LEGACYDPM_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o +LEGACYDPM_MGR-$(CONFIG_DRM_AMDGPU_SI)+= si_dpm.o si_smc.o + +AMD_LEGACYDPM_POWER = $(addprefix $(AMD_LEGACYDPM_PATH)/,$(LEGACYDPM_MGR-y)) + +AMD_POWERPLAY_FILES += $(AMD_LEGACYDPM_POWER) diff --git a/drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h b/drivers/gpu/drm/amd/pm/legacy-dpm/cik_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/cik_dpm.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c rename to drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_smc.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_smc.c similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/kv_smc.c rename to drivers/gpu/drm/amd/pm/legacy-dpm/kv_smc.c diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.c rename to drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c diff --git a/drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/legacy_dpm.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/ppsmc.h b/drivers/gpu/drm/amd/pm/legacy-dpm/ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/ppsmc.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h b/drivers/gpu/drm/amd/pm/legacy-dpm/r600_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/r600_dpm.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/si_dpm.c rename to drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/si_dpm.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_smc.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_smc.c similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/si_smc.c rename to drivers/gpu/drm/amd/pm/legacy-dpm/si_smc.c diff --git a/drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h b/drivers/gpu/drm/amd/pm/legacy-dpm/sislands_smc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h rename to drivers/gpu/drm/amd/pm/legacy-dpm/sislands_smc.h diff --git a/drivers/gpu/drm/amd/pm/powerplay/Makefile b/drivers/gpu/drm/amd/pm/powerplay/Makefile index 614d8b6a58ad..795a3624cbbf 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/Makefile +++ b/drivers/gpu/drm/amd/pm/powerplay/Makefile @@ -28,11 +28,7 @@ AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/powerplay/ include $(AMD_POWERPLAY) -POWER_MGR-y = amd_powerplay.o legacy_dpm.o - -POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o - -POWER_MGR-$(CONFIG_DRM_AMDGPU_SI)+= si_dpm.o si_smc.o +POWER_MGR-y = amd_powerplay.o AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR-y)) diff --git a/drivers/gpu/drm/amd/pm/inc/amd_powerplay.h b/drivers/gpu/drm/amd/pm/powerplay/inc/amd_powerplay.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/amd_powerplay.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/amd_powerplay.h diff --git a/drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/cz_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/cz_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/fiji_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/fiji_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/hardwaremanager.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/hardwaremanager.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/hardwaremanager.h diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/hwmgr.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h diff --git a/drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h b/drivers/gpu/drm/amd/pm/powerplay/inc/polaris10_pwrvirus.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/polaris10_pwrvirus.h diff --git a/drivers/gpu/drm/amd/pm/inc/power_state.h b/drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/power_state.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/power_state.h diff --git a/drivers/gpu/drm/amd/pm/inc/pp_debug.h b/drivers/gpu/drm/amd/pm/powerplay/inc/pp_debug.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/pp_debug.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/pp_debug.h diff --git a/drivers/gpu/drm/amd/pm/inc/pp_endian.h b/drivers/gpu/drm/amd/pm/powerplay/inc/pp_endian.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/pp_endian.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/pp_endian.h diff --git a/drivers/gpu/drm/amd/pm/inc/pp_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/inc/pp_thermal.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/pp_thermal.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/pp_thermal.h diff --git a/drivers/gpu/drm/amd/pm/inc/ppinterrupt.h b/drivers/gpu/drm/amd/pm/powerplay/inc/ppinterrupt.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/ppinterrupt.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/ppinterrupt.h diff --git a/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/rv_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/rv_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu10.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu10.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu10.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu10.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu10_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu10_driver_if.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu11_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu11_driver_if.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu7.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu7.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu7.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu7.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu71.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu71.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu71.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu71.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu71_discrete.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu71_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu71_discrete.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu71_discrete.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu72.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu72.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu72.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu72.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu72_discrete.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu72_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu72_discrete.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu72_discrete.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu73.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu73.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu73.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu73.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu73_discrete.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu73_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu73_discrete.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu73_discrete.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu74.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu74.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu74.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu74.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu74_discrete.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu74_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu74_discrete.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu74_discrete.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu75.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu75.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu75.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu75.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu75_discrete.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu75_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu75_discrete.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu75_discrete.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu7_common.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu7_common.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu7_common.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu7_common.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu7_discrete.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu7_discrete.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu7_discrete.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu7_discrete.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu7_fusion.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu7_fusion.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu7_fusion.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu7_fusion.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu7_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu7_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu8.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu8.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu8.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu8.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu8_fusion.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu8_fusion.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu8_fusion.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu8_fusion.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu9.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu9.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu9.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu9.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu9_driver_if.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu9_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu9_driver_if.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu9_driver_if.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_cz.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_vi.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_vi.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_vi.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_vi.h diff --git a/drivers/gpu/drm/amd/pm/inc/smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smumgr.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smumgr.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/smumgr.h diff --git a/drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/tonga_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/tonga_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/vega10_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/vega10_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h b/drivers/gpu/drm/amd/pm/powerplay/inc/vega12/smu9_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/vega12/smu9_driver_if.h diff --git a/drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/vega12_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/vega12_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/inc/vega20_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h rename to drivers/gpu/drm/amd/pm/powerplay/inc/vega20_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h diff --git a/drivers/gpu/drm/amd/pm/inc/aldebaran_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/aldebaran_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/aldebaran_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/arcturus_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/arcturus_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_arcturus.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_arcturus.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_cyan_skillfish.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_cyan_skillfish.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_navi10.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_navi10.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_vangogh.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_vangogh.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu11_driver_if_vangogh.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_vangogh.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu12_driver_if.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu12_driver_if.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu13_driver_if_aldebaran.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu13_driver_if_aldebaran.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_aldebaran.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu13_driver_if_yellow_carp.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu13_driver_if_yellow_carp.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_yellow_carp.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_0_7_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_0_7_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_0_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_0_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_5_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_5_pmfw.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_5_pmfw.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_5_pmfw.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_5_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_5_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_5_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_5_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_8_pmfw.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_8_pmfw.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_8_pmfw.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_8_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v11_8_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v12_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v12_0_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v12_0_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v12_0_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v13_0_1_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_1_pmfw.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v13_0_1_pmfw.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_1_pmfw.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v13_0_1_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_1_ppsmc.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v13_0_1_ppsmc.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_1_ppsmc.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_11_0_cdr_table.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_11_0_cdr_table.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_11_0_cdr_table.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_types.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_0.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_pptable.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_7_pptable.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v11_0_pptable.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0_pptable.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v12_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v12_0.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v13_0.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v13_0_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h similarity index 100% rename from drivers/gpu/drm/amd/pm/inc/smu_v13_0_pptable.h rename to drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_pptable.h diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 0a1547c27305..d3963bfe5c89 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -33,7 +33,6 @@ #include "smu11_driver_if_arcturus.h" #include "soc15_common.h" #include "atom.h" -#include "power_state.h" #include "arcturus_ppt.h" #include "smu_v11_0_pptable.h" #include "arcturus_ppsmc.h" diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index a4d46f7069bc..ac8ba5e0e697 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -33,7 +33,6 @@ #include "smu13_driver_if_aldebaran.h" #include "soc15_common.h" #include "atom.h" -#include "power_state.h" #include "aldebaran_ppt.h" #include "smu_v13_0_pptable.h" #include "aldebaran_ppsmc.h" From 3bce90bfbaa8de63bc500bc5a4dd262ed8e548ca Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 24 Nov 2021 11:12:31 +0800 Subject: [PATCH 017/339] drm/amd/pm: drop unnecessary gfxoff controls Those gfxoff controls added for some specific ASICs are unnecessary. The functionalities are not affected without them. Also to align with other ASICs, they should also be dropped. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4 --- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 25 +------------------ .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 7 ------ .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 7 ------ 4 files changed, 1 insertion(+), 42 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index c898ea67354a..8895b2b595a4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1542,8 +1542,6 @@ static int smu_reset(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret; - amdgpu_gfx_off_ctrl(smu->adev, false); - ret = smu_hw_fini(adev); if (ret) return ret; @@ -1556,8 +1554,6 @@ static int smu_reset(struct smu_context *smu) if (ret) return ret; - amdgpu_gfx_off_ctrl(smu->adev, true); - return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index efe6b2eff6a0..4e37cd8025ed 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1036,10 +1036,6 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, if (ret) goto print_clk_out; - /* no need to disable gfxoff when retrieving the current gfxclk */ - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, false); - ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); if (ret) goto print_clk_out; @@ -1168,25 +1164,18 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, } print_clk_out: - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, true); - return size; } static int sienna_cichlid_force_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t mask) { - struct amdgpu_device *adev = smu->adev; int ret = 0; uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; soft_min_level = mask ? (ffs(mask) - 1) : 0; soft_max_level = mask ? (fls(mask) - 1) : 0; - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, false); - switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: @@ -1220,9 +1209,6 @@ static int sienna_cichlid_force_clk_levels(struct smu_context *smu, } forec_level_out: - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, true); - return 0; } @@ -1865,16 +1851,7 @@ static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max) { - struct amdgpu_device *adev = smu->adev; - int ret; - - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, false); - ret = smu_v11_0_get_dpm_ultimate_freq(smu, clk_type, min, max); - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, true); - - return ret; + return smu_v11_0_get_dpm_ultimate_freq(smu, clk_type, min, max); } static void sienna_cichlid_dump_od_table(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index e176e6a74f44..9acf2c045a97 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1798,7 +1798,6 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, uint32_t min, uint32_t max) { - struct amdgpu_device *adev = smu->adev; int ret = 0, clk_id = 0; uint32_t param; @@ -1811,9 +1810,6 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, if (clk_id < 0) return clk_id; - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, false); - if (max > 0) { param = (uint32_t)((clk_id << 16) | (max & 0xffff)); ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq, @@ -1831,9 +1827,6 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, } out: - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, true); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index f1d7b4900aa1..f66d8b9135ca 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -1533,7 +1533,6 @@ int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu, uint32_t min, uint32_t max) { - struct amdgpu_device *adev = smu->adev; int ret = 0, clk_id = 0; uint32_t param; @@ -1546,9 +1545,6 @@ int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu, if (clk_id < 0) return clk_id; - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, false); - if (max > 0) { param = (uint32_t)((clk_id << 16) | (max & 0xffff)); ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq, @@ -1566,9 +1562,6 @@ int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu, } out: - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, true); - return ret; } From 61d7d0d5adc705f833d8a5dbb596253842486220 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 25 Nov 2021 11:15:46 +0800 Subject: [PATCH 018/339] drm/amd/pm: revise the performance level setting APIs Avoid cross callings which make lock protection enforcement on amdgpu_dpm_force_performance_level() impossible. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/amd_shared.h | 2 -- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 29 ++++++++++++++++--- .../gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c | 17 ++++++----- .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 12 -------- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 15 ---------- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - 6 files changed, 34 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index f57a1478f0fe..fb6ad56ad6f1 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -268,7 +268,6 @@ enum amd_dpm_forced_level; * @set_clockgating_state: enable/disable cg for the IP block * @set_powergating_state: enable/disable pg for the IP block * @get_clockgating_state: get current clockgating status - * @enable_umd_pstate: enable UMD powerstate * * These hooks provide an interface for controlling the operational state * of IP blocks. After acquiring a list of IP blocks for the GPU in use, @@ -299,7 +298,6 @@ struct amd_ip_funcs { int (*set_powergating_state)(void *handle, enum amd_powergating_state state); void (*get_clockgating_state)(void *handle, u32 *flags); - int (*enable_umd_pstate)(void *handle, enum amd_dpm_forced_level *level); }; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index b14b004577e5..d3eab245e0fe 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -300,6 +300,10 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level; enum amd_dpm_forced_level current_level; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; int ret = 0; if (amdgpu_in_reset(adev)) @@ -354,10 +358,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, } /* profile_exit setting is valid only when current mode is in profile mode */ - if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) && + if (!(current_level & profile_mode_mask) && (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { pr_err("Currently not in any profile mode!\n"); pm_runtime_mark_last_busy(ddev->dev); @@ -365,6 +366,26 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return -EINVAL; } + if (!(current_level & profile_mode_mask) && + (level & profile_mode_mask)) { + /* enter UMD Pstate */ + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } else if ((current_level & profile_mode_mask) && + !(level & profile_mode_mask)) { + /* exit UMD Pstate */ + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + if (amdgpu_dpm_force_performance_level(adev, level)) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c index 3c6ee493e410..9613c6181c17 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/legacy_dpm.c @@ -953,6 +953,7 @@ restart_search: static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) { + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct amdgpu_ps *ps; enum amd_pm_state_type dpm_state; int ret; @@ -976,7 +977,7 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) else return -EINVAL; - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { + if (amdgpu_dpm == 1 && pp_funcs->print_power_state) { printk("switching from power state:\n"); amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); printk("switching to power state:\n"); @@ -985,14 +986,14 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) /* update whether vce is active */ ps->vce_active = adev->pm.dpm.vce_active; - if (adev->powerplay.pp_funcs->display_configuration_changed) + if (pp_funcs->display_configuration_changed) amdgpu_dpm_display_configuration_changed(adev); ret = amdgpu_dpm_pre_set_power_state(adev); if (ret) return ret; - if (adev->powerplay.pp_funcs->check_state_equal) { + if (pp_funcs->check_state_equal) { if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) equal = false; } @@ -1000,24 +1001,24 @@ static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) if (equal) return 0; - if (adev->powerplay.pp_funcs->set_power_state) - adev->powerplay.pp_funcs->set_power_state(adev->powerplay.pp_handle); + if (pp_funcs->set_power_state) + pp_funcs->set_power_state(adev->powerplay.pp_handle); amdgpu_dpm_post_set_power_state(adev); adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - if (adev->powerplay.pp_funcs->force_performance_level) { + if (pp_funcs->force_performance_level) { if (adev->pm.dpm.thermal_active) { enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; /* force low perf level for thermal */ - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); + pp_funcs->force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); /* save the user's level */ adev->pm.dpm.forced_level = level; } else { /* otherwise, user selected level */ - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); + pp_funcs->force_performance_level(adev, adev->pm.dpm.forced_level); } } diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 6a06a1f0b79b..89341729744d 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -323,12 +323,6 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, if (*level & profile_mode_mask) { hwmgr->saved_dpm_level = hwmgr->dpm_level; hwmgr->en_umd_pstate = true; - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -336,12 +330,6 @@ static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = hwmgr->saved_dpm_level; hwmgr->en_umd_pstate = false; - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); } } } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8895b2b595a4..c374c3067496 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1677,14 +1677,7 @@ static int smu_enable_umd_pstate(void *handle, /* enter umd pstate, save current level, disable gfx cg*/ if (*level & profile_mode_mask) { smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level; - smu_dpm_ctx->enable_umd_pstate = true; smu_gpo_control(smu, false); - amdgpu_device_ip_set_powergating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); smu_gfx_ulv_control(smu, false); smu_deep_sleep_control(smu, false); amdgpu_asic_update_umd_stable_pstate(smu->adev, true); @@ -1694,16 +1687,9 @@ static int smu_enable_umd_pstate(void *handle, if (!(*level & profile_mode_mask)) { if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = smu_dpm_ctx->saved_dpm_level; - smu_dpm_ctx->enable_umd_pstate = false; amdgpu_asic_update_umd_stable_pstate(smu->adev, false); smu_deep_sleep_control(smu, true); smu_gfx_ulv_control(smu, true); - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); smu_gpo_control(smu, true); } } @@ -2149,7 +2135,6 @@ const struct amd_ip_funcs smu_ip_funcs = { .soft_reset = NULL, .set_clockgating_state = smu_set_clockgating_state, .set_powergating_state = smu_set_powergating_state, - .enable_umd_pstate = smu_enable_umd_pstate, }; const struct amdgpu_ip_block_version smu_v11_0_ip_block = diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 8a689baeaf82..3fdab6a44901 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -363,7 +363,6 @@ struct smu_dpm_context { uint32_t dpm_context_size; void *dpm_context; void *golden_dpm_context; - bool enable_umd_pstate; enum amd_dpm_forced_level dpm_level; enum amd_dpm_forced_level saved_dpm_level; enum amd_dpm_forced_level requested_dpm_level; From 3712e7a494596b26861f4dc9b81676d1d0272eaf Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 16 Nov 2021 14:30:20 +0800 Subject: [PATCH 019/339] drm/amd/pm: unified lock protections in amdgpu_dpm.c As the only entry point, it's now safe and reasonable to enforce the lock protections in amdgpu_dpm.c. And with this, we can drop other internal used power locks. Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 707 +++++++++++++++------ drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 16 +- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 16 +- 3 files changed, 526 insertions(+), 213 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 2756f52b74c1..68d2e80a673b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -39,15 +39,33 @@ int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - return pp_funcs->get_sclk((adev)->powerplay.pp_handle, (low)); + if (!pp_funcs->get_sclk) + return 0; + + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_sclk((adev)->powerplay.pp_handle, + low); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - return pp_funcs->get_mclk((adev)->powerplay.pp_handle, (low)); + if (!pp_funcs->get_mclk) + return 0; + + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_mclk((adev)->powerplay.pp_handle, + low); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate) @@ -62,52 +80,20 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block return 0; } + mutex_lock(&adev->pm.mutex); + switch (block_type) { case AMD_IP_BLOCK_TYPE_UVD: case AMD_IP_BLOCK_TYPE_VCE: - if (pp_funcs && pp_funcs->set_powergating_by_smu) { - /* - * TODO: need a better lock mechanism - * - * Here adev->pm.mutex lock protection is enforced on - * UVD and VCE cases only. Since for other cases, there - * may be already lock protection in amdgpu_pm.c. - * This is a quick fix for the deadlock issue below. - * NFO: task ocltst:2028 blocked for more than 120 seconds. - * Tainted: G OE 5.0.0-37-generic #40~18.04.1-Ubuntu - * echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. - * cltst D 0 2028 2026 0x00000000 - * all Trace: - * __schedule+0x2c0/0x870 - * schedule+0x2c/0x70 - * schedule_preempt_disabled+0xe/0x10 - * __mutex_lock.isra.9+0x26d/0x4e0 - * __mutex_lock_slowpath+0x13/0x20 - * ? __mutex_lock_slowpath+0x13/0x20 - * mutex_lock+0x2f/0x40 - * amdgpu_dpm_set_powergating_by_smu+0x64/0xe0 [amdgpu] - * gfx_v8_0_enable_gfx_static_mg_power_gating+0x3c/0x70 [amdgpu] - * gfx_v8_0_set_powergating_state+0x66/0x260 [amdgpu] - * amdgpu_device_ip_set_powergating_state+0x62/0xb0 [amdgpu] - * pp_dpm_force_performance_level+0xe7/0x100 [amdgpu] - * amdgpu_set_dpm_forced_performance_level+0x129/0x330 [amdgpu] - */ - mutex_lock(&adev->pm.mutex); - ret = (pp_funcs->set_powergating_by_smu( - (adev)->powerplay.pp_handle, block_type, gate)); - mutex_unlock(&adev->pm.mutex); - } - break; case AMD_IP_BLOCK_TYPE_GFX: case AMD_IP_BLOCK_TYPE_VCN: case AMD_IP_BLOCK_TYPE_SDMA: case AMD_IP_BLOCK_TYPE_JPEG: case AMD_IP_BLOCK_TYPE_GMC: case AMD_IP_BLOCK_TYPE_ACP: - if (pp_funcs && pp_funcs->set_powergating_by_smu) { + if (pp_funcs && pp_funcs->set_powergating_by_smu) ret = (pp_funcs->set_powergating_by_smu( (adev)->powerplay.pp_handle, block_type, gate)); - } break; default: break; @@ -116,6 +102,8 @@ int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block if (!ret) atomic_set(&adev->pm.pwr_state[block_type], pwr_state); + mutex_unlock(&adev->pm.mutex); + return ret; } @@ -128,9 +116,13 @@ int amdgpu_dpm_baco_enter(struct amdgpu_device *adev) if (!pp_funcs || !pp_funcs->set_asic_baco_state) return -ENOENT; + mutex_lock(&adev->pm.mutex); + /* enter BACO state */ ret = pp_funcs->set_asic_baco_state(pp_handle, 1); + mutex_unlock(&adev->pm.mutex); + return ret; } @@ -143,9 +135,13 @@ int amdgpu_dpm_baco_exit(struct amdgpu_device *adev) if (!pp_funcs || !pp_funcs->set_asic_baco_state) return -ENOENT; + mutex_lock(&adev->pm.mutex); + /* exit BACO state */ ret = pp_funcs->set_asic_baco_state(pp_handle, 0); + mutex_unlock(&adev->pm.mutex); + return ret; } @@ -156,9 +152,13 @@ int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; if (pp_funcs && pp_funcs->set_mp1_state) { + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_mp1_state( adev->powerplay.pp_handle, mp1_state); + + mutex_unlock(&adev->pm.mutex); } return ret; @@ -169,25 +169,37 @@ bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; void *pp_handle = adev->powerplay.pp_handle; bool baco_cap; + int ret = 0; if (!pp_funcs || !pp_funcs->get_asic_baco_capability) return false; - if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap)) - return false; + mutex_lock(&adev->pm.mutex); - return baco_cap; + ret = pp_funcs->get_asic_baco_capability(pp_handle, + &baco_cap); + + mutex_unlock(&adev->pm.mutex); + + return ret ? false : baco_cap; } int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; void *pp_handle = adev->powerplay.pp_handle; + int ret = 0; if (!pp_funcs || !pp_funcs->asic_reset_mode_2) return -ENOENT; - return pp_funcs->asic_reset_mode_2(pp_handle); + mutex_lock(&adev->pm.mutex); + + ret = pp_funcs->asic_reset_mode_2(pp_handle); + + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) @@ -199,37 +211,47 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) if (!pp_funcs || !pp_funcs->set_asic_baco_state) return -ENOENT; + mutex_lock(&adev->pm.mutex); + /* enter BACO state */ ret = pp_funcs->set_asic_baco_state(pp_handle, 1); if (ret) - return ret; + goto out; /* exit BACO state */ ret = pp_funcs->set_asic_baco_state(pp_handle, 0); - if (ret) - return ret; - return 0; +out: + mutex_unlock(&adev->pm.mutex); + return ret; } bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) { struct smu_context *smu = adev->powerplay.pp_handle; + bool support_mode1_reset = false; - if (is_support_sw_smu(adev)) - return smu_mode1_reset_is_support(smu); + if (is_support_sw_smu(adev)) { + mutex_lock(&adev->pm.mutex); + support_mode1_reset = smu_mode1_reset_is_support(smu); + mutex_unlock(&adev->pm.mutex); + } - return false; + return support_mode1_reset; } int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = -EOPNOTSUPP; - if (is_support_sw_smu(adev)) - return smu_mode1_reset(smu); + if (is_support_sw_smu(adev)) { + mutex_lock(&adev->pm.mutex); + ret = smu_mode1_reset(smu); + mutex_unlock(&adev->pm.mutex); + } - return -EOPNOTSUPP; + return ret; } int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, @@ -242,9 +264,12 @@ int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, if (amdgpu_sriov_vf(adev)) return 0; - if (pp_funcs && pp_funcs->switch_power_profile) + if (pp_funcs && pp_funcs->switch_power_profile) { + mutex_lock(&adev->pm.mutex); ret = pp_funcs->switch_power_profile( adev->powerplay.pp_handle, type, en); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -255,9 +280,12 @@ int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int ret = 0; - if (pp_funcs && pp_funcs->set_xgmi_pstate) + if (pp_funcs && pp_funcs->set_xgmi_pstate) { + mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, pstate); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -269,8 +297,11 @@ int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; void *pp_handle = adev->powerplay.pp_handle; - if (pp_funcs && pp_funcs->set_df_cstate) + if (pp_funcs && pp_funcs->set_df_cstate) { + mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_df_cstate(pp_handle, cstate); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -278,11 +309,15 @@ int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; - if (is_support_sw_smu(adev)) - return smu_allow_xgmi_power_down(smu, en); + if (is_support_sw_smu(adev)) { + mutex_lock(&adev->pm.mutex); + ret = smu_allow_xgmi_power_down(smu, en); + mutex_unlock(&adev->pm.mutex); + } - return 0; + return ret; } int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) @@ -292,8 +327,11 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) adev->powerplay.pp_funcs; int ret = 0; - if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) + if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) { + mutex_lock(&adev->pm.mutex); ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -306,9 +344,12 @@ int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, adev->powerplay.pp_funcs; int ret = 0; - if (pp_funcs && pp_funcs->set_clockgating_by_smu) + if (pp_funcs && pp_funcs->set_clockgating_by_smu) { + mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_clockgating_by_smu(pp_handle, msg_id); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -321,9 +362,12 @@ int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, adev->powerplay.pp_funcs; int ret = -EOPNOTSUPP; - if (pp_funcs && pp_funcs->smu_i2c_bus_access) + if (pp_funcs && pp_funcs->smu_i2c_bus_access) { + mutex_lock(&adev->pm.mutex); ret = pp_funcs->smu_i2c_bus_access(pp_handle, acquire); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -336,13 +380,15 @@ void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) adev->pm.ac_power = true; else adev->pm.ac_power = false; + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->enable_bapm) amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); - mutex_unlock(&adev->pm.mutex); if (is_support_sw_smu(adev)) smu_set_ac_dc(adev->powerplay.pp_handle); + + mutex_unlock(&adev->pm.mutex); } } @@ -350,16 +396,19 @@ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors senso void *data, uint32_t *size) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - int ret = 0; + int ret = -EINVAL; if (!data || !size) return -EINVAL; - if (pp_funcs && pp_funcs->read_sensor) - ret = pp_funcs->read_sensor((adev)->powerplay.pp_handle, - sensor, data, size); - else - ret = -EINVAL; + if (pp_funcs && pp_funcs->read_sensor) { + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->read_sensor(adev->powerplay.pp_handle, + sensor, + data, + size); + mutex_unlock(&adev->pm.mutex); + } return ret; } @@ -374,7 +423,9 @@ void amdgpu_dpm_compute_clocks(struct amdgpu_device *adev) if (!pp_funcs->pm_compute_clocks) return; + mutex_lock(&adev->pm.mutex); pp_funcs->pm_compute_clocks(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); } void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) @@ -409,32 +460,51 @@ void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) { - int r; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int r = 0; - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { - r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); - if (r) { - pr_err("smu firmware loading failed\n"); - return r; - } + if (!pp_funcs->load_firmware) + return 0; - if (smu_version) - *smu_version = adev->pm.fw_version; + mutex_lock(&adev->pm.mutex); + r = pp_funcs->load_firmware(adev->powerplay.pp_handle); + if (r) { + pr_err("smu firmware loading failed\n"); + goto out; } - return 0; + if (smu_version) + *smu_version = adev->pm.fw_version; + +out: + mutex_unlock(&adev->pm.mutex); + return r; } int amdgpu_dpm_handle_passthrough_sbr(struct amdgpu_device *adev, bool enable) { - return smu_handle_passthrough_sbr(adev->powerplay.pp_handle, enable); + int ret = 0; + + if (is_support_sw_smu(adev)) { + mutex_lock(&adev->pm.mutex); + ret = smu_handle_passthrough_sbr(adev->powerplay.pp_handle, + enable); + mutex_unlock(&adev->pm.mutex); + } + + return ret; } int amdgpu_dpm_send_hbm_bad_pages_num(struct amdgpu_device *adev, uint32_t size) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; - return smu_send_hbm_bad_pages_num(smu, size); + mutex_lock(&adev->pm.mutex); + ret = smu_send_hbm_bad_pages_num(smu, size); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, @@ -442,15 +512,22 @@ int amdgpu_dpm_get_dpm_freq_range(struct amdgpu_device *adev, uint32_t *min, uint32_t *max) { + int ret = 0; + + if (type != PP_SCLK) + return -EINVAL; + if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - switch (type) { - case PP_SCLK: - return smu_get_dpm_freq_range(adev->powerplay.pp_handle, SMU_SCLK, min, max); - default: - return -EINVAL; - } + mutex_lock(&adev->pm.mutex); + ret = smu_get_dpm_freq_range(adev->powerplay.pp_handle, + SMU_SCLK, + min, + max); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, @@ -459,26 +536,37 @@ int amdgpu_dpm_set_soft_freq_range(struct amdgpu_device *adev, uint32_t max) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; + + if (type != PP_SCLK) + return -EINVAL; if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - switch (type) { - case PP_SCLK: - return smu_set_soft_freq_range(smu, SMU_SCLK, min, max); - default: - return -EINVAL; - } + mutex_lock(&adev->pm.mutex); + ret = smu_set_soft_freq_range(smu, + SMU_SCLK, + min, + max); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_write_watermarks_table(struct amdgpu_device *adev) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; if (!is_support_sw_smu(adev)) return 0; - return smu_write_watermarks_table(smu); + mutex_lock(&adev->pm.mutex); + ret = smu_write_watermarks_table(smu); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, @@ -486,27 +574,40 @@ int amdgpu_dpm_wait_for_event(struct amdgpu_device *adev, uint64_t event_arg) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_wait_for_event(smu, event, event_arg); + mutex_lock(&adev->pm.mutex); + ret = smu_wait_for_event(smu, event, event_arg); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) { struct smu_context *smu = adev->powerplay.pp_handle; + int ret = 0; if (!is_support_sw_smu(adev)) return -EOPNOTSUPP; - return smu_get_status_gfxoff(smu, value); + mutex_lock(&adev->pm.mutex); + ret = smu_get_status_gfxoff(smu, value); + mutex_unlock(&adev->pm.mutex); + + return ret; } uint64_t amdgpu_dpm_get_thermal_throttling_counter(struct amdgpu_device *adev) { struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) + return 0; + return atomic64_read(&smu->throttle_int_counter); } @@ -541,12 +642,17 @@ struct amd_vce_state *amdgpu_dpm_get_vce_clock_state(struct amdgpu_device *adev, uint32_t idx) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + struct amd_vce_state *vstate = NULL; if (!pp_funcs->get_vce_clock_state) return NULL; - return pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, - idx); + mutex_lock(&adev->pm.mutex); + vstate = pp_funcs->get_vce_clock_state(adev->powerplay.pp_handle, + idx); + mutex_unlock(&adev->pm.mutex); + + return vstate; } void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, @@ -554,21 +660,28 @@ void amdgpu_dpm_get_current_power_state(struct amdgpu_device *adev, { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + mutex_lock(&adev->pm.mutex); + if (!pp_funcs->get_current_power_state) { *state = adev->pm.dpm.user_state; - return; + goto out; } *state = pp_funcs->get_current_power_state(adev->powerplay.pp_handle); if (*state < POWER_STATE_TYPE_DEFAULT || *state > POWER_STATE_TYPE_INTERNAL_3DPERF) *state = adev->pm.dpm.user_state; + +out: + mutex_unlock(&adev->pm.mutex); } void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, enum amd_pm_state_type state) { + mutex_lock(&adev->pm.mutex); adev->pm.dpm.user_state = state; + mutex_unlock(&adev->pm.mutex); if (is_support_sw_smu(adev)) return; @@ -584,10 +697,12 @@ enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_dpm_forced_level level; + mutex_lock(&adev->pm.mutex); if (pp_funcs->get_performance_level) level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); else level = adev->pm.dpm.forced_level; + mutex_unlock(&adev->pm.mutex); return level; } @@ -596,30 +711,46 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, enum amd_dpm_forced_level level) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; - if (pp_funcs->force_performance_level) { - if (adev->pm.dpm.thermal_active) - return -EINVAL; + if (!pp_funcs->force_performance_level) + return 0; - if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, - level)) - return -EINVAL; + mutex_lock(&adev->pm.mutex); - adev->pm.dpm.forced_level = level; + if (adev->pm.dpm.thermal_active) { + ret = -EINVAL; + goto out; } - return 0; + if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, + level)) + ret = -EINVAL; + + if (!ret) + adev->pm.dpm.forced_level = level; + +out: + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, struct pp_states_info *states) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_pp_num_states) return -EOPNOTSUPP; - return pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, states); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_pp_num_states(adev->powerplay.pp_handle, + states); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, @@ -627,21 +758,34 @@ int amdgpu_dpm_dispatch_task(struct amdgpu_device *adev, enum amd_pm_state_type *user_state) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->dispatch_tasks) return -EOPNOTSUPP; - return pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, task_id, user_state); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->dispatch_tasks(adev->powerplay.pp_handle, + task_id, + user_state); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_pp_table(struct amdgpu_device *adev, char **table) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_pp_table) return 0; - return pp_funcs->get_pp_table(adev->powerplay.pp_handle, table); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, + table); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, @@ -650,14 +794,19 @@ int amdgpu_dpm_set_fine_grain_clk_vol(struct amdgpu_device *adev, uint32_t size) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_fine_grain_clk_vol) return 0; - return pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, - type, - input, - size); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_fine_grain_clk_vol(adev->powerplay.pp_handle, + type, + input, + size); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, @@ -666,14 +815,19 @@ int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, uint32_t size) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->odn_edit_dpm_table) return 0; - return pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, - type, - input, - size); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->odn_edit_dpm_table(adev->powerplay.pp_handle, + type, + input, + size); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, @@ -681,36 +835,51 @@ int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, char *buf) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->print_clock_levels) return 0; - return pp_funcs->print_clock_levels(adev->powerplay.pp_handle, - type, - buf); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->print_clock_levels(adev->powerplay.pp_handle, + type, + buf); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, uint64_t ppfeature_masks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_ppfeature_status) return 0; - return pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, - ppfeature_masks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_ppfeature_status(adev->powerplay.pp_handle, + ppfeature_masks); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_ppfeature_status) return 0; - return pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, - buf); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_ppfeature_status(adev->powerplay.pp_handle, + buf); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, @@ -718,23 +887,33 @@ int amdgpu_dpm_force_clock_level(struct amdgpu_device *adev, uint32_t mask) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->force_clock_level) return 0; - return pp_funcs->force_clock_level(adev->powerplay.pp_handle, - type, - mask); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->force_clock_level(adev->powerplay.pp_handle, + type, + mask); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_sclk_od(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_sclk_od) return 0; - return pp_funcs->get_sclk_od(adev->powerplay.pp_handle); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_sclk_od(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) @@ -744,8 +923,10 @@ int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) if (is_support_sw_smu(adev)) return 0; + mutex_lock(&adev->pm.mutex); if (pp_funcs->set_sclk_od) pp_funcs->set_sclk_od(adev->powerplay.pp_handle, value); + mutex_unlock(&adev->pm.mutex); if (amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, @@ -760,11 +941,16 @@ int amdgpu_dpm_set_sclk_od(struct amdgpu_device *adev, uint32_t value) int amdgpu_dpm_get_mclk_od(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_mclk_od) return 0; - return pp_funcs->get_mclk_od(adev->powerplay.pp_handle); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_mclk_od(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) @@ -774,8 +960,10 @@ int amdgpu_dpm_set_mclk_od(struct amdgpu_device *adev, uint32_t value) if (is_support_sw_smu(adev)) return 0; + mutex_lock(&adev->pm.mutex); if (pp_funcs->set_mclk_od) pp_funcs->set_mclk_od(adev->powerplay.pp_handle, value); + mutex_unlock(&adev->pm.mutex); if (amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, @@ -791,35 +979,51 @@ int amdgpu_dpm_get_power_profile_mode(struct amdgpu_device *adev, char *buf) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_power_profile_mode) return -EOPNOTSUPP; - return pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, - buf); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_power_profile_mode(adev->powerplay.pp_handle, + buf); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_power_profile_mode(struct amdgpu_device *adev, long *input, uint32_t size) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_power_profile_mode) return 0; - return pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, - input, - size); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_power_profile_mode(adev->powerplay.pp_handle, + input, + size); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_gpu_metrics(struct amdgpu_device *adev, void **table) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_gpu_metrics) return 0; - return pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, table); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_gpu_metrics(adev->powerplay.pp_handle, + table); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, @@ -830,7 +1034,9 @@ int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, if (!pp_funcs->get_fan_control_mode) return -EOPNOTSUPP; + mutex_lock(&adev->pm.mutex); *fan_mode = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); return 0; } @@ -839,44 +1045,68 @@ int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, uint32_t speed) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_fan_speed_pwm) return -EINVAL; - return pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, speed); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, + speed); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, uint32_t *speed) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_fan_speed_pwm) return -EINVAL; - return pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, speed); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, + speed); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, uint32_t *speed) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_fan_speed_rpm) return -EINVAL; - return pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, speed); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, + speed); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, uint32_t speed) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_fan_speed_rpm) return -EINVAL; - return pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, speed); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, + speed); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, @@ -887,7 +1117,10 @@ int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, if (!pp_funcs->set_fan_control_mode) return -EOPNOTSUPP; - pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, mode); + mutex_lock(&adev->pm.mutex); + pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, + mode); + mutex_unlock(&adev->pm.mutex); return 0; } @@ -898,33 +1131,50 @@ int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, enum pp_power_type power_type) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_power_limit) return -ENODATA; - return pp_funcs->get_power_limit(adev->powerplay.pp_handle, - limit, - pp_limit_level, - power_type); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_power_limit(adev->powerplay.pp_handle, + limit, + pp_limit_level, + power_type); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_power_limit(struct amdgpu_device *adev, uint32_t limit) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_power_limit) return -EINVAL; - return pp_funcs->set_power_limit(adev->powerplay.pp_handle, limit); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_power_limit(adev->powerplay.pp_handle, + limit); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_is_cclk_dpm_supported(struct amdgpu_device *adev) { + bool cclk_dpm_supported = false; + if (!is_support_sw_smu(adev)) return false; - return is_support_cclk_dpm(adev); + mutex_lock(&adev->pm.mutex); + cclk_dpm_supported = is_support_cclk_dpm(adev); + mutex_unlock(&adev->pm.mutex); + + return (int)cclk_dpm_supported; } int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, @@ -935,8 +1185,10 @@ int amdgpu_dpm_debugfs_print_current_performance_level(struct amdgpu_device *ade if (!pp_funcs->debugfs_print_current_performance_level) return -EOPNOTSUPP; + mutex_lock(&adev->pm.mutex); pp_funcs->debugfs_print_current_performance_level(adev->powerplay.pp_handle, m); + mutex_unlock(&adev->pm.mutex); return 0; } @@ -946,13 +1198,18 @@ int amdgpu_dpm_get_smu_prv_buf_details(struct amdgpu_device *adev, size_t *size) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_smu_prv_buf_details) return -ENOSYS; - return pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, - addr, - size); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_smu_prv_buf_details(adev->powerplay.pp_handle, + addr, + size); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_is_overdrive_supported(struct amdgpu_device *adev) @@ -973,19 +1230,27 @@ int amdgpu_dpm_set_pp_table(struct amdgpu_device *adev, size_t size) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_pp_table) return -EOPNOTSUPP; - return pp_funcs->set_pp_table(adev->powerplay.pp_handle, - buf, - size); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_pp_table(adev->powerplay.pp_handle, + buf, + size); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_num_cpu_cores(struct amdgpu_device *adev) { struct smu_context *smu = adev->powerplay.pp_handle; + if (!is_support_sw_smu(adev)) + return INT_MAX; + return smu->cpu_core_num; } @@ -1001,12 +1266,17 @@ int amdgpu_dpm_display_configuration_change(struct amdgpu_device *adev, const struct amd_pp_display_configuration *input) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->display_configuration_change) return 0; - return pp_funcs->display_configuration_change(adev->powerplay.pp_handle, - input); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->display_configuration_change(adev->powerplay.pp_handle, + input); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, @@ -1014,25 +1284,35 @@ int amdgpu_dpm_get_clock_by_type(struct amdgpu_device *adev, struct amd_pp_clocks *clocks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_clock_by_type) return 0; - return pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, - type, - clocks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_clock_by_type(adev->powerplay.pp_handle, + type, + clocks); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_display_mode_validation_clks(struct amdgpu_device *adev, struct amd_pp_simple_clock_info *clocks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_display_mode_validation_clocks) return 0; - return pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, - clocks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_display_mode_validation_clocks(adev->powerplay.pp_handle, + clocks); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, @@ -1040,13 +1320,18 @@ int amdgpu_dpm_get_clock_by_type_with_latency(struct amdgpu_device *adev, struct pp_clock_levels_with_latency *clocks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_clock_by_type_with_latency) return 0; - return pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, - type, - clocks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_clock_by_type_with_latency(adev->powerplay.pp_handle, + type, + clocks); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, @@ -1054,49 +1339,69 @@ int amdgpu_dpm_get_clock_by_type_with_voltage(struct amdgpu_device *adev, struct pp_clock_levels_with_voltage *clocks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_clock_by_type_with_voltage) return 0; - return pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, - type, - clocks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_clock_by_type_with_voltage(adev->powerplay.pp_handle, + type, + clocks); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_watermarks_for_clocks_ranges(struct amdgpu_device *adev, void *clock_ranges) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_watermarks_for_clocks_ranges) return -EOPNOTSUPP; - return pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, - clock_ranges); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_watermarks_for_clocks_ranges(adev->powerplay.pp_handle, + clock_ranges); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_display_clock_voltage_request(struct amdgpu_device *adev, struct pp_display_clock_request *clock) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->display_clock_voltage_request) return -EOPNOTSUPP; - return pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, - clock); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->display_clock_voltage_request(adev->powerplay.pp_handle, + clock); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_current_clocks(struct amdgpu_device *adev, struct amd_pp_clock_info *clocks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_current_clocks) return -EOPNOTSUPP; - return pp_funcs->get_current_clocks(adev->powerplay.pp_handle, - clocks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_current_clocks(adev->powerplay.pp_handle, + clocks); + mutex_unlock(&adev->pm.mutex); + + return ret; } void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) @@ -1106,31 +1411,43 @@ void amdgpu_dpm_notify_smu_enable_pwe(struct amdgpu_device *adev) if (!pp_funcs->notify_smu_enable_pwe) return; + mutex_lock(&adev->pm.mutex); pp_funcs->notify_smu_enable_pwe(adev->powerplay.pp_handle); + mutex_unlock(&adev->pm.mutex); } int amdgpu_dpm_set_active_display_count(struct amdgpu_device *adev, uint32_t count) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_active_display_count) return -EOPNOTSUPP; - return pp_funcs->set_active_display_count(adev->powerplay.pp_handle, - count); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_active_display_count(adev->powerplay.pp_handle, + count); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_set_min_deep_sleep_dcefclk(struct amdgpu_device *adev, uint32_t clock) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_min_deep_sleep_dcefclk) return -EOPNOTSUPP; - return pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, - clock); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->set_min_deep_sleep_dcefclk(adev->powerplay.pp_handle, + clock); + mutex_unlock(&adev->pm.mutex); + + return ret; } void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, @@ -1141,8 +1458,10 @@ void amdgpu_dpm_set_hard_min_dcefclk_by_freq(struct amdgpu_device *adev, if (!pp_funcs->set_hard_min_dcefclk_by_freq) return; + mutex_lock(&adev->pm.mutex); pp_funcs->set_hard_min_dcefclk_by_freq(adev->powerplay.pp_handle, clock); + mutex_unlock(&adev->pm.mutex); } void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, @@ -1153,32 +1472,44 @@ void amdgpu_dpm_set_hard_min_fclk_by_freq(struct amdgpu_device *adev, if (!pp_funcs->set_hard_min_fclk_by_freq) return; + mutex_lock(&adev->pm.mutex); pp_funcs->set_hard_min_fclk_by_freq(adev->powerplay.pp_handle, clock); + mutex_unlock(&adev->pm.mutex); } int amdgpu_dpm_display_disable_memory_clock_switch(struct amdgpu_device *adev, bool disable_memory_clock_switch) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->display_disable_memory_clock_switch) return 0; - return pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, - disable_memory_clock_switch); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->display_disable_memory_clock_switch(adev->powerplay.pp_handle, + disable_memory_clock_switch); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_max_sustainable_clocks_by_dc(struct amdgpu_device *adev, struct pp_smu_nv_clock_table *max_clocks) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_max_sustainable_clocks_by_dc) return -EOPNOTSUPP; - return pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, - max_clocks); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_max_sustainable_clocks_by_dc(adev->powerplay.pp_handle, + max_clocks); + mutex_unlock(&adev->pm.mutex); + + return ret; } enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, @@ -1186,23 +1517,33 @@ enum pp_smu_status amdgpu_dpm_get_uclk_dpm_states(struct amdgpu_device *adev, unsigned int *num_states) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_uclk_dpm_states) return -EOPNOTSUPP; - return pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, - clock_values_in_khz, - num_states); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_uclk_dpm_states(adev->powerplay.pp_handle, + clock_values_in_khz, + num_states); + mutex_unlock(&adev->pm.mutex); + + return ret; } int amdgpu_dpm_get_dpm_clock_table(struct amdgpu_device *adev, struct dpm_clocks *clock_table) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_dpm_clock_table) return -EOPNOTSUPP; - return pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, - clock_table); + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->get_dpm_clock_table(adev->powerplay.pp_handle, + clock_table); + mutex_unlock(&adev->pm.mutex); + + return ret; } diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c index 72824ef61edd..b37662c4a413 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c @@ -3040,21 +3040,18 @@ static int kv_dpm_sw_init(void *handle) return 0; INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); - mutex_lock(&adev->pm.mutex); ret = kv_dpm_init(adev); if (ret) goto dpm_failed; adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; if (amdgpu_dpm == 1) amdgpu_pm_print_power_states(adev); - mutex_unlock(&adev->pm.mutex); DRM_INFO("amdgpu: dpm initialized\n"); return 0; dpm_failed: kv_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); DRM_ERROR("amdgpu: dpm initialization failed\n"); return ret; } @@ -3065,9 +3062,7 @@ static int kv_dpm_sw_fini(void *handle) flush_work(&adev->pm.dpm.thermal.work); - mutex_lock(&adev->pm.mutex); kv_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); return 0; } @@ -3080,14 +3075,12 @@ static int kv_dpm_hw_init(void *handle) if (!amdgpu_dpm) return 0; - mutex_lock(&adev->pm.mutex); kv_dpm_setup_asic(adev); ret = kv_dpm_enable(adev); if (ret) adev->pm.dpm_enabled = false; else adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); amdgpu_legacy_dpm_compute_clocks(adev); return ret; } @@ -3096,11 +3089,8 @@ static int kv_dpm_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); + if (adev->pm.dpm_enabled) kv_dpm_disable(adev); - mutex_unlock(&adev->pm.mutex); - } return 0; } @@ -3110,12 +3100,10 @@ static int kv_dpm_suspend(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); /* disable dpm */ kv_dpm_disable(adev); /* reset the power state */ adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; - mutex_unlock(&adev->pm.mutex); } return 0; } @@ -3127,14 +3115,12 @@ static int kv_dpm_resume(void *handle) if (adev->pm.dpm_enabled) { /* asic init will reset to the boot state */ - mutex_lock(&adev->pm.mutex); kv_dpm_setup_asic(adev); ret = kv_dpm_enable(adev); if (ret) adev->pm.dpm_enabled = false; else adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) amdgpu_legacy_dpm_compute_clocks(adev); } diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index 9f8cc81cb7ca..92b987fb31d4 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -7786,21 +7786,18 @@ static int si_dpm_sw_init(void *handle) return ret; INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); - mutex_lock(&adev->pm.mutex); ret = si_dpm_init(adev); if (ret) goto dpm_failed; adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; if (amdgpu_dpm == 1) amdgpu_pm_print_power_states(adev); - mutex_unlock(&adev->pm.mutex); DRM_INFO("amdgpu: dpm initialized\n"); return 0; dpm_failed: si_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); DRM_ERROR("amdgpu: dpm initialization failed\n"); return ret; } @@ -7811,9 +7808,7 @@ static int si_dpm_sw_fini(void *handle) flush_work(&adev->pm.dpm.thermal.work); - mutex_lock(&adev->pm.mutex); si_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); return 0; } @@ -7827,14 +7822,12 @@ static int si_dpm_hw_init(void *handle) if (!amdgpu_dpm) return 0; - mutex_lock(&adev->pm.mutex); si_dpm_setup_asic(adev); ret = si_dpm_enable(adev); if (ret) adev->pm.dpm_enabled = false; else adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); amdgpu_legacy_dpm_compute_clocks(adev); return ret; } @@ -7843,11 +7836,8 @@ static int si_dpm_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); + if (adev->pm.dpm_enabled) si_dpm_disable(adev); - mutex_unlock(&adev->pm.mutex); - } return 0; } @@ -7857,12 +7847,10 @@ static int si_dpm_suspend(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); /* disable dpm */ si_dpm_disable(adev); /* reset the power state */ adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; - mutex_unlock(&adev->pm.mutex); } return 0; } @@ -7874,14 +7862,12 @@ static int si_dpm_resume(void *handle) if (adev->pm.dpm_enabled) { /* asic init will reset to the boot state */ - mutex_lock(&adev->pm.mutex); si_dpm_setup_asic(adev); ret = si_dpm_enable(adev); if (ret) adev->pm.dpm_enabled = false; else adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); if (adev->pm.dpm_enabled) amdgpu_legacy_dpm_compute_clocks(adev); } From 1a408c710d9e273a22050b0b7b0c131f92847918 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 2 Dec 2021 09:50:34 +0800 Subject: [PATCH 020/339] drm/amdgpu: wrap those atombios APIs used by SI under CONFIG_DRM_AMDGPU_SI No need to compile them on CONFIG_DRM_AMDGPU_SI disabled. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h | 22 +++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 12a6b1c99c93..9ba4817a9148 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1083,6 +1083,7 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, return 0; } +#ifdef CONFIG_DRM_AMDGPU_SI int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev, u32 clock, bool strobe_mode, @@ -1503,6 +1504,7 @@ int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev, } return -EINVAL; } +#endif bool amdgpu_atombios_has_gpu_virtualization_table(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h index 27e74b1fc260..4153d520e2a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h @@ -160,6 +160,7 @@ int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, bool strobe_mode, struct atom_clock_dividers *dividers); +#ifdef CONFIG_DRM_AMDGPU_SI int amdgpu_atombios_get_memory_pll_dividers(struct amdgpu_device *adev, u32 clock, bool strobe_mode, @@ -179,6 +180,17 @@ int amdgpu_atombios_get_voltage_table(struct amdgpu_device *adev, int amdgpu_atombios_init_mc_reg_table(struct amdgpu_device *adev, u8 module_index, struct atom_mc_reg_table *reg_table); +int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, + u16 voltage_id, u16 *voltage); +int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, + u16 *voltage, + u16 leakage_idx); +void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, + u16 *vddc, u16 *vddci, u16 *mvdd); +int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, + u8 voltage_type, + u8 *svd_gpio_id, u8 *svc_gpio_id); +#endif bool amdgpu_atombios_has_gpu_virtualization_table(struct amdgpu_device *adev); @@ -190,21 +202,11 @@ void amdgpu_atombios_scratch_regs_set_backlight_level(struct amdgpu_device *adev bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev); void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); -int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type, - u16 voltage_id, u16 *voltage); -int amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(struct amdgpu_device *adev, - u16 *voltage, - u16 leakage_idx); -void amdgpu_atombios_get_default_voltages(struct amdgpu_device *adev, - u16 *vddc, u16 *vddci, u16 *mvdd); int amdgpu_atombios_get_clock_dividers(struct amdgpu_device *adev, u8 clock_type, u32 clock, bool strobe_mode, struct atom_clock_dividers *dividers); -int amdgpu_atombios_get_svi2_info(struct amdgpu_device *adev, - u8 voltage_type, - u8 *svd_gpio_id, u8 *svc_gpio_id); int amdgpu_atombios_get_data_table(struct amdgpu_device *adev, uint32_t table, From bcf19fdd507fb679bb6e1b8a119961f32b6cbb95 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 2 Dec 2021 10:13:23 +0800 Subject: [PATCH 021/339] drm/amd/pm: drop those unrealistic thermal_type checks As it's impossible the thermal sensor of KV is one of them. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c index b37662c4a413..8b23cc9f098a 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c @@ -1260,18 +1260,8 @@ static void kv_dpm_enable_bapm(void *handle, bool enable) static bool kv_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor) { switch (sensor) { - case THERMAL_TYPE_RV6XX: - case THERMAL_TYPE_RV770: - case THERMAL_TYPE_EVERGREEN: - case THERMAL_TYPE_SUMO: - case THERMAL_TYPE_NI: - case THERMAL_TYPE_SI: - case THERMAL_TYPE_CI: case THERMAL_TYPE_KV: return true; - case THERMAL_TYPE_ADT7473_WITH_INTERNAL: - case THERMAL_TYPE_EMC2103_WITH_INTERNAL: - return false; /* need special handling */ case THERMAL_TYPE_NONE: case THERMAL_TYPE_EXTERNAL: case THERMAL_TYPE_EXTERNAL_GPIO: From 54c73b51df2958f564b144ce86f15a85e227db90 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Jan 2022 18:14:22 -0500 Subject: [PATCH 022/339] drm/amdgpu/pm: move additional logic into amdgpu_dpm_force_performance_level This is part of the forced performance level. Move it from the sysfs handler into amdgpu_dpm_force_performance_level. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 61 ++++++++++++++++++++++++++++- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 50 ----------------------- 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 68d2e80a673b..728b6e10f302 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -692,16 +692,25 @@ void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, amdgpu_dpm_compute_clocks(adev); } -enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) +static enum amd_dpm_forced_level amdgpu_dpm_get_performance_level_locked(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_dpm_forced_level level; - mutex_lock(&adev->pm.mutex); if (pp_funcs->get_performance_level) level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); else level = adev->pm.dpm.forced_level; + + return level; +} + +enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) +{ + enum amd_dpm_forced_level level; + + mutex_lock(&adev->pm.mutex); + level = amdgpu_dpm_get_performance_level_locked(adev); mutex_unlock(&adev->pm.mutex); return level; @@ -711,6 +720,11 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, enum amd_dpm_forced_level level) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + enum amd_dpm_forced_level current_level; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; int ret = 0; if (!pp_funcs->force_performance_level) @@ -723,6 +737,49 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, goto out; } + current_level = amdgpu_dpm_get_performance_level_locked(adev); + if (current_level == level) { + ret = 0; + goto out; + } + + if (adev->asic_type == CHIP_RAVEN) { + if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { + if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && + level == AMD_DPM_FORCED_LEVEL_MANUAL) + amdgpu_gfx_off_ctrl(adev, false); + else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && + level != AMD_DPM_FORCED_LEVEL_MANUAL) + amdgpu_gfx_off_ctrl(adev, true); + } + } + + if (!(current_level & profile_mode_mask) && + (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { + ret = -EINVAL; + goto out; + } + + if (!(current_level & profile_mode_mask) && + (level & profile_mode_mask)) { + /* enter UMD Pstate */ + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } else if ((current_level & profile_mode_mask) && + !(level & profile_mode_mask)) { + /* exit UMD Pstate */ + amdgpu_device_ip_set_clockgating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, level)) ret = -EINVAL; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d3eab245e0fe..d2823aaeca09 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -299,11 +299,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level; - enum amd_dpm_forced_level current_level; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; int ret = 0; if (amdgpu_in_reset(adev)) @@ -341,51 +336,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } - current_level = amdgpu_dpm_get_performance_level(adev); - if (current_level == level) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return count; - } - - if (adev->asic_type == CHIP_RAVEN) { - if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { - if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && level == AMD_DPM_FORCED_LEVEL_MANUAL) - amdgpu_gfx_off_ctrl(adev, false); - else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && level != AMD_DPM_FORCED_LEVEL_MANUAL) - amdgpu_gfx_off_ctrl(adev, true); - } - } - - /* profile_exit setting is valid only when current mode is in profile mode */ - if (!(current_level & profile_mode_mask) && - (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { - pr_err("Currently not in any profile mode!\n"); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - - if (!(current_level & profile_mode_mask) && - (level & profile_mode_mask)) { - /* enter UMD Pstate */ - amdgpu_device_ip_set_powergating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } else if ((current_level & profile_mode_mask) && - !(level & profile_mode_mask)) { - /* exit UMD Pstate */ - amdgpu_device_ip_set_clockgating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); - } - if (amdgpu_dpm_force_performance_level(adev, level)) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); From 685fae24d94fd615b7058832fcb437eb588f4860 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 11 Jan 2022 15:02:19 +0800 Subject: [PATCH 023/339] drm/amd/pm: correct the checks for fan attributes support On functionality unsupported, -EOPNOTSUPP will be returned. And we rely on that to determine the fan attributes support. Fixes: 79c65f3fcbb128 ("drm/amd/pm: do not expose power implementation details to amdgpu_pm.c") Signed-off-by: Evan Quan Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/kgd_pp_interface.h | 4 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 21 +-- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 21 ++- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 19 ++- .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 71 ++++++---- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 133 ++++++++++-------- 6 files changed, 160 insertions(+), 109 deletions(-) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a8eec91c0995..387120099493 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -315,8 +315,8 @@ struct amd_pm_funcs { void *rps, bool *equal); /* export for sysfs */ - void (*set_fan_control_mode)(void *handle, u32 mode); - u32 (*get_fan_control_mode)(void *handle); + int (*set_fan_control_mode)(void *handle, u32 mode); + int (*get_fan_control_mode)(void *handle, u32 *fan_mode); int (*set_fan_speed_pwm)(void *handle, u32 speed); int (*get_fan_speed_pwm)(void *handle, u32 *speed); int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 728b6e10f302..f0daa66f5b3d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1087,15 +1087,17 @@ int amdgpu_dpm_get_fan_control_mode(struct amdgpu_device *adev, uint32_t *fan_mode) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->get_fan_control_mode) return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); - *fan_mode = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle); + ret = pp_funcs->get_fan_control_mode(adev->powerplay.pp_handle, + fan_mode); mutex_unlock(&adev->pm.mutex); - return 0; + return ret; } int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, @@ -1105,7 +1107,7 @@ int amdgpu_dpm_set_fan_speed_pwm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->set_fan_speed_pwm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_fan_speed_pwm(adev->powerplay.pp_handle, @@ -1122,7 +1124,7 @@ int amdgpu_dpm_get_fan_speed_pwm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->get_fan_speed_pwm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->get_fan_speed_pwm(adev->powerplay.pp_handle, @@ -1139,7 +1141,7 @@ int amdgpu_dpm_get_fan_speed_rpm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->get_fan_speed_rpm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->get_fan_speed_rpm(adev->powerplay.pp_handle, @@ -1156,7 +1158,7 @@ int amdgpu_dpm_set_fan_speed_rpm(struct amdgpu_device *adev, int ret = 0; if (!pp_funcs->set_fan_speed_rpm) - return -EINVAL; + return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); ret = pp_funcs->set_fan_speed_rpm(adev->powerplay.pp_handle, @@ -1170,16 +1172,17 @@ int amdgpu_dpm_set_fan_control_mode(struct amdgpu_device *adev, uint32_t mode) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; if (!pp_funcs->set_fan_control_mode) return -EOPNOTSUPP; mutex_lock(&adev->pm.mutex); - pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, - mode); + ret = pp_funcs->set_fan_control_mode(adev->powerplay.pp_handle, + mode); mutex_unlock(&adev->pm.mutex); - return 0; + return ret; } int amdgpu_dpm_get_power_limit(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d2823aaeca09..1b03ad7a21ad 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3147,7 +3147,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; - uint32_t speed = 0; /* under multi-vf mode, the hwmon attributes are all not supported */ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) @@ -3213,15 +3212,15 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* mask fan attributes if we have no bindings for this asic to expose */ - if (((amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && + if (((amdgpu_dpm_get_fan_speed_pwm(adev, NULL) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ - ((amdgpu_dpm_get_fan_control_mode(adev, &speed) == -EOPNOTSUPP) && + ((amdgpu_dpm_get_fan_control_mode(adev, NULL) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ effective_mode &= ~S_IRUGO; - if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && + if (((amdgpu_dpm_set_fan_speed_pwm(adev, U32_MAX) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ - ((amdgpu_dpm_set_fan_control_mode(adev, speed) == -EOPNOTSUPP) && + ((amdgpu_dpm_set_fan_control_mode(adev, U32_MAX) == -EOPNOTSUPP) && attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ effective_mode &= ~S_IWUSR; @@ -3241,16 +3240,16 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* hide max/min values if we can't both query and manage the fan */ - if (((amdgpu_dpm_set_fan_speed_pwm(adev, speed) == -EINVAL) && - (amdgpu_dpm_get_fan_speed_pwm(adev, &speed) == -EINVAL) && - (amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && - (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL)) && + if (((amdgpu_dpm_set_fan_speed_pwm(adev, U32_MAX) == -EOPNOTSUPP) && + (amdgpu_dpm_get_fan_speed_pwm(adev, NULL) == -EOPNOTSUPP) && + (amdgpu_dpm_set_fan_speed_rpm(adev, U32_MAX) == -EOPNOTSUPP) && + (amdgpu_dpm_get_fan_speed_rpm(adev, NULL) == -EOPNOTSUPP)) && (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; - if ((amdgpu_dpm_set_fan_speed_rpm(adev, speed) == -EINVAL) && - (amdgpu_dpm_get_fan_speed_rpm(adev, &speed) == -EINVAL) && + if ((amdgpu_dpm_set_fan_speed_rpm(adev, U32_MAX) == -EOPNOTSUPP) && + (amdgpu_dpm_get_fan_speed_rpm(adev, NULL) == -EOPNOTSUPP) && (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) return 0; diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index 92b987fb31d4..23ff0d812e4b 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -6619,6 +6619,9 @@ static int si_dpm_get_fan_speed_pwm(void *handle, u64 tmp64; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (!speed) + return -EINVAL; + if (adev->pm.no_fan) return -ENOENT; @@ -6669,10 +6672,13 @@ static int si_dpm_set_fan_speed_pwm(void *handle, return 0; } -static void si_dpm_set_fan_control_mode(void *handle, u32 mode) +static int si_dpm_set_fan_control_mode(void *handle, u32 mode) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (mode == U32_MAX) + return -EINVAL; + if (mode) { /* stop auto-manage */ if (adev->pm.dpm.fan.ucode_fan_control) @@ -6685,19 +6691,26 @@ static void si_dpm_set_fan_control_mode(void *handle, u32 mode) else si_fan_ctrl_set_default_mode(adev); } + + return 0; } -static u32 si_dpm_get_fan_control_mode(void *handle) +static int si_dpm_get_fan_control_mode(void *handle, u32 *fan_mode) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct si_power_info *si_pi = si_get_pi(adev); u32 tmp; + if (!fan_mode) + return -EINVAL; + if (si_pi->fan_is_controlled_by_smc) return 0; tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; - return (tmp >> FDO_PWM_MODE_SHIFT); + *fan_mode = (tmp >> FDO_PWM_MODE_SHIFT); + + return 0; } #if 0 diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 89341729744d..76c26ae368f9 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -488,38 +488,43 @@ static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) return pm_type; } -static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) +static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) { struct pp_hwmgr *hwmgr = handle; if (!hwmgr || !hwmgr->pm_en) - return; + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) + return -EOPNOTSUPP; + + if (mode == U32_MAX) + return -EINVAL; - if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); mutex_unlock(&hwmgr->smu_lock); + + return 0; } -static uint32_t pp_dpm_get_fan_control_mode(void *handle) +static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode) { struct pp_hwmgr *hwmgr = handle; - uint32_t mode = 0; if (!hwmgr || !hwmgr->pm_en) - return 0; + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) + return -EOPNOTSUPP; + + if (!fan_mode) + return -EINVAL; - if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } mutex_lock(&hwmgr->smu_lock); - mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); + *fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); mutex_unlock(&hwmgr->smu_lock); - return mode; + return 0; } static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed) @@ -528,12 +533,14 @@ static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed) int ret = 0; if (!hwmgr || !hwmgr->pm_en) + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL) + return -EOPNOTSUPP; + + if (speed == U32_MAX) return -EINVAL; - if (hwmgr->hwmgr_func->set_fan_speed_pwm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } mutex_lock(&hwmgr->smu_lock); ret = hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed); mutex_unlock(&hwmgr->smu_lock); @@ -546,12 +553,13 @@ static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed) int ret = 0; if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; + return -EOPNOTSUPP; - if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } + if (hwmgr->hwmgr_func->get_fan_speed_pwm == NULL) + return -EOPNOTSUPP; + + if (!speed) + return -EINVAL; mutex_lock(&hwmgr->smu_lock); ret = hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed); @@ -565,9 +573,12 @@ static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) int ret = 0; if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; + return -EOPNOTSUPP; if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL) + return -EOPNOTSUPP; + + if (!rpm) return -EINVAL; mutex_lock(&hwmgr->smu_lock); @@ -582,12 +593,14 @@ static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm) int ret = 0; if (!hwmgr || !hwmgr->pm_en) + return -EOPNOTSUPP; + + if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) + return -EOPNOTSUPP; + + if (rpm == U32_MAX) return -EINVAL; - if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } mutex_lock(&hwmgr->smu_lock); ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm); mutex_unlock(&hwmgr->smu_lock); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index c374c3067496..828cb932f6a9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -59,7 +59,7 @@ static int smu_handle_task(struct smu_context *smu, bool lock_needed); static int smu_reset(struct smu_context *smu); static int smu_set_fan_speed_pwm(void *handle, u32 speed); -static int smu_set_fan_control_mode(struct smu_context *smu, int value); +static int smu_set_fan_control_mode(void *handle, u32 value); static int smu_set_power_limit(void *handle, uint32_t limit); static int smu_set_fan_speed_rpm(void *handle, uint32_t speed); static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled); @@ -407,7 +407,7 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) if (smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_MANUAL || smu->user_dpm_profile.fan_mode == AMD_FAN_CTRL_NONE) { ret = smu_set_fan_control_mode(smu, smu->user_dpm_profile.fan_mode); - if (ret) { + if (ret != -EOPNOTSUPP) { smu->user_dpm_profile.fan_speed_pwm = 0; smu->user_dpm_profile.fan_speed_rpm = 0; smu->user_dpm_profile.fan_mode = AMD_FAN_CTRL_AUTO; @@ -416,13 +416,13 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) if (smu->user_dpm_profile.fan_speed_pwm) { ret = smu_set_fan_speed_pwm(smu, smu->user_dpm_profile.fan_speed_pwm); - if (ret) + if (ret != -EOPNOTSUPP) dev_err(smu->adev->dev, "Failed to set manual fan speed in pwm\n"); } if (smu->user_dpm_profile.fan_speed_rpm) { ret = smu_set_fan_speed_rpm(smu, smu->user_dpm_profile.fan_speed_rpm); - if (ret) + if (ret != -EOPNOTSUPP) dev_err(smu->adev->dev, "Failed to set manual fan speed in rpm\n"); } } @@ -2218,18 +2218,22 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->set_fan_speed_rpm) + return -EOPNOTSUPP; + + if (speed == U32_MAX) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_speed_rpm) { - ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); - if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { - smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_RPM; - smu->user_dpm_profile.fan_speed_rpm = speed; + ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_RPM; + smu->user_dpm_profile.fan_speed_rpm = speed; - /* Override custom PWM setting as they cannot co-exist */ - smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_PWM; - smu->user_dpm_profile.fan_speed_pwm = 0; - } + /* Override custom PWM setting as they cannot co-exist */ + smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_PWM; + smu->user_dpm_profile.fan_speed_pwm = 0; } mutex_unlock(&smu->mutex); @@ -2562,60 +2566,65 @@ static int smu_set_power_profile_mode(void *handle, } -static u32 smu_get_fan_control_mode(void *handle) +static int smu_get_fan_control_mode(void *handle, u32 *fan_mode) { struct smu_context *smu = handle; - u32 ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return AMD_FAN_CTRL_NONE; + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->get_fan_control_mode) + return -EOPNOTSUPP; + + if (!fan_mode) + return -EINVAL; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_control_mode) - ret = smu->ppt_funcs->get_fan_control_mode(smu); + *fan_mode = smu->ppt_funcs->get_fan_control_mode(smu); mutex_unlock(&smu->mutex); - return ret; + return 0; } -static int smu_set_fan_control_mode(struct smu_context *smu, int value) +static int smu_set_fan_control_mode(void *handle, u32 value) { + struct smu_context *smu = handle; int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->set_fan_control_mode) + return -EOPNOTSUPP; + + if (value == U32_MAX) + return -EINVAL; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_control_mode) { - ret = smu->ppt_funcs->set_fan_control_mode(smu, value); - if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) - smu->user_dpm_profile.fan_mode = value; + ret = smu->ppt_funcs->set_fan_control_mode(smu, value); + if (ret) + goto out; + + if (!(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.fan_mode = value; + + /* reset user dpm fan speed */ + if (value != AMD_FAN_CTRL_MANUAL) { + smu->user_dpm_profile.fan_speed_pwm = 0; + smu->user_dpm_profile.fan_speed_rpm = 0; + smu->user_dpm_profile.flags &= ~(SMU_CUSTOM_FAN_SPEED_RPM | SMU_CUSTOM_FAN_SPEED_PWM); + } } +out: mutex_unlock(&smu->mutex); - /* reset user dpm fan speed */ - if (!ret && value != AMD_FAN_CTRL_MANUAL && - !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { - smu->user_dpm_profile.fan_speed_pwm = 0; - smu->user_dpm_profile.fan_speed_rpm = 0; - smu->user_dpm_profile.flags &= ~(SMU_CUSTOM_FAN_SPEED_RPM | SMU_CUSTOM_FAN_SPEED_PWM); - } - return ret; } -static void smu_pp_set_fan_control_mode(void *handle, u32 value) -{ - struct smu_context *smu = handle; - - smu_set_fan_control_mode(smu, value); -} - - static int smu_get_fan_speed_pwm(void *handle, u32 *speed) { struct smu_context *smu = handle; @@ -2624,10 +2633,15 @@ static int smu_get_fan_speed_pwm(void *handle, u32 *speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->get_fan_speed_pwm) + return -EOPNOTSUPP; + + if (!speed) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_speed_pwm) - ret = smu->ppt_funcs->get_fan_speed_pwm(smu, speed); + ret = smu->ppt_funcs->get_fan_speed_pwm(smu, speed); mutex_unlock(&smu->mutex); @@ -2642,18 +2656,22 @@ static int smu_set_fan_speed_pwm(void *handle, u32 speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->set_fan_speed_pwm) + return -EOPNOTSUPP; + + if (speed == U32_MAX) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_speed_pwm) { - ret = smu->ppt_funcs->set_fan_speed_pwm(smu, speed); - if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { - smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_PWM; - smu->user_dpm_profile.fan_speed_pwm = speed; + ret = smu->ppt_funcs->set_fan_speed_pwm(smu, speed); + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { + smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_PWM; + smu->user_dpm_profile.fan_speed_pwm = speed; - /* Override custom RPM setting as they cannot co-exist */ - smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_RPM; - smu->user_dpm_profile.fan_speed_rpm = 0; - } + /* Override custom RPM setting as they cannot co-exist */ + smu->user_dpm_profile.flags &= ~SMU_CUSTOM_FAN_SPEED_RPM; + smu->user_dpm_profile.fan_speed_rpm = 0; } mutex_unlock(&smu->mutex); @@ -2669,10 +2687,15 @@ static int smu_get_fan_speed_rpm(void *handle, uint32_t *speed) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; + if (!smu->ppt_funcs->get_fan_speed_rpm) + return -EOPNOTSUPP; + + if (!speed) + return -EINVAL; + mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_speed_rpm) - ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); + ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); mutex_unlock(&smu->mutex); @@ -3101,7 +3124,7 @@ static int smu_get_prv_buffer_details(void *handle, void **addr, size_t *size) static const struct amd_pm_funcs swsmu_pm_funcs = { /* export for sysfs */ - .set_fan_control_mode = smu_pp_set_fan_control_mode, + .set_fan_control_mode = smu_set_fan_control_mode, .get_fan_control_mode = smu_get_fan_control_mode, .set_fan_speed_pwm = smu_set_fan_speed_pwm, .get_fan_speed_pwm = smu_get_fan_speed_pwm, From 6492e1b07c03397f85bd6dc0e230ea6cd9394635 Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 4 Jan 2022 13:35:37 +0800 Subject: [PATCH 024/339] drm/amdgpu: Unify ras block interface for each ras block 1. Define unified ops interface for each block. 2. Add ras_block_match function pointer in ops interface, each ras block can customize specail match function to identify itself. 3. Add amdgpu_ras_block_match_default new function. If a ras block doesn't define .ras_block_match, default execute amdgpu_ras_block_match_default to identify this ras block. 4. Define unified basic ras block data for each ras block. 5. Create dedicated amdgpu device ras block link list to manage all of the ras blocks. 6. Add amdgpu_ras_register_ras_block new function interface for each ras block to register itself to ras controlling block. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 46 ++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 28 +++++++++++++ 4 files changed, 78 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index f0132a5cc58d..c349337939dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1091,6 +1091,8 @@ struct amdgpu_device { uint32_t ip_versions[MAX_HWIP][HWIP_MAX_INSTANCE]; bool ram_is_direct_mapped; + + struct list_head ras_list; }; static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 596bb2fdb8a2..9230e4476d91 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3519,6 +3519,8 @@ int amdgpu_device_init(struct amdgpu_device *adev, INIT_LIST_HEAD(&adev->reset_list); + INIT_LIST_HEAD(&adev->ras_list); + INIT_DELAYED_WORK(&adev->delayed_init_work, amdgpu_device_delayed_init_work_handler); INIT_DELAYED_WORK(&adev->gfx.gfx_off_delay_work, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 4a9970423e7d..bf2983fe5d9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -866,6 +866,40 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev, } /* feature ctl end */ +int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object* block_obj, enum amdgpu_ras_block block) +{ + if(!block_obj) + return -EINVAL; + + if (block_obj->block == block) + return 0; + + return -EINVAL; +} + +static struct amdgpu_ras_block_object* amdgpu_ras_get_ras_block(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint32_t sub_block_index) +{ + struct amdgpu_ras_block_object *obj, *tmp; + + if (block >= AMDGPU_RAS_BLOCK__LAST) + return NULL; + + if (!amdgpu_ras_is_supported(adev, block)) + return NULL; + + list_for_each_entry_safe(obj, tmp, &adev->ras_list, node) { + if (obj->ras_block_match) { + if (obj->ras_block_match(obj, block, sub_block_index) == 0) + return obj; + } else { + if (amdgpu_ras_block_match_default(obj, block) == 0) + return obj; + } + } + + return NULL; +} static void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev, struct ras_common_if *ras_block, @@ -2776,3 +2810,15 @@ static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev) } } #endif +/* Register each ip ras block into amdgpu ras */ +int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, + struct amdgpu_ras_block_object* ras_block_obj) +{ + if (!adev || !ras_block_obj) + return -EINVAL; + + INIT_LIST_HEAD(&ras_block_obj->node); + list_add_tail(&ras_block_obj->node, &adev->ras_list); + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 1c708122d492..f66122fdf477 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -484,6 +484,33 @@ struct ras_debug_if { }; int op; }; + +struct amdgpu_ras_block_object { + /* block name */ + char name[32]; + + enum amdgpu_ras_block block; + + uint32_t sub_block_index; + + /* ras block link */ + struct list_head node; + + int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj, enum amdgpu_ras_block block, uint32_t sub_block_index); + int (*ras_late_init)(struct amdgpu_device *adev, void *ras_info); + void (*ras_fini)(struct amdgpu_device *adev); + const struct amdgpu_ras_block_hw_ops *hw_ops; +}; + +struct amdgpu_ras_block_hw_ops { + int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if); + void (*query_ras_error_count)(struct amdgpu_device *adev,void *ras_error_status); + void (*query_ras_error_status)(struct amdgpu_device *adev); + void (*query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status); + void (*reset_ras_error_count)(struct amdgpu_device *adev); + void (*reset_ras_error_status)(struct amdgpu_device *adev); +}; + /* work flow * vbios * 1: ras feature enable (enabled by default) @@ -667,4 +694,5 @@ const char *get_ras_block_str(struct ras_common_if *ras_block); bool amdgpu_ras_is_poison_mode_supported(struct amdgpu_device *adev); +int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object* ras_block_obj); #endif From 7cab2124058d2f5f048f435a4631e176dcd1430d Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 4 Jan 2022 13:39:15 +0800 Subject: [PATCH 025/339] drm/amdgpu: Modify the compilation failed problem when other ras blocks' .h include amdgpu_ras.h Modify the compilation failed problem when other ras blocks' .h include amdgpu_ras.h. v2: squash in forward declaration warning fix (Alex) Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 39 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 34 +++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 2 +- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index c349337939dd..445a0d077c1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -108,6 +108,7 @@ #include "amdgpu_smuio.h" #include "amdgpu_fdinfo.h" #include "amdgpu_mca.h" +#include "amdgpu_ras.h" #define MAX_GPU_INSTANCE 16 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index bf2983fe5d9d..5b3f4beb2149 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2810,6 +2810,45 @@ static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev) } } #endif + +struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev) +{ + if (!adev) + return NULL; + + return adev->psp.ras_context.ras; +} + +int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras* ras_con) +{ + if (!adev) + return -EINVAL;; + + adev->psp.ras_context.ras = ras_con; + return 0; +} + +/* check if ras is supported on block, say, sdma, gfx */ +int amdgpu_ras_is_supported(struct amdgpu_device *adev, + unsigned int block) +{ + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + + if (block >= AMDGPU_RAS_BLOCK_COUNT) + return 0; + return ras && (adev->ras_enabled & (1 << block)); +} + +int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) +{ + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + + if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0) + schedule_work(&ras->recovery_work); + return 0; +} + + /* Register each ip ras block into amdgpu ras */ int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object* ras_block_obj) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index f66122fdf477..7a4d82378205 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -26,11 +26,11 @@ #include #include -#include "amdgpu.h" -#include "amdgpu_psp.h" #include "ta_ras_if.h" #include "amdgpu_ras_eeprom.h" +struct amdgpu_iv_entry; + #define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0) enum amdgpu_ras_block { @@ -525,19 +525,6 @@ struct amdgpu_ras_block_hw_ops { * 8: feature disable */ -#define amdgpu_ras_get_context(adev) ((adev)->psp.ras_context.ras) -#define amdgpu_ras_set_context(adev, ras_con) ((adev)->psp.ras_context.ras = (ras_con)) - -/* check if ras is supported on block, say, sdma, gfx */ -static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev, - unsigned int block) -{ - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - - if (block >= AMDGPU_RAS_BLOCK_COUNT) - return 0; - return ras && (adev->ras_enabled & (1 << block)); -} int amdgpu_ras_recovery_init(struct amdgpu_device *adev); @@ -554,15 +541,6 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, int amdgpu_ras_save_bad_pages(struct amdgpu_device *adev); -static inline int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) -{ - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - - if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0) - schedule_work(&ras->recovery_work); - return 0; -} - static inline enum ta_ras_block amdgpu_ras_block_to_ta(enum amdgpu_ras_block block) { switch (block) { @@ -694,5 +672,13 @@ const char *get_ras_block_str(struct ras_common_if *ras_block); bool amdgpu_ras_is_poison_mode_supported(struct amdgpu_device *adev); +int amdgpu_ras_is_supported(struct amdgpu_device *adev, unsigned int block); + +int amdgpu_ras_reset_gpu(struct amdgpu_device *adev); + +struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev); + +int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras* ras_con); + int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object* ras_block_obj); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 25951b2d83b6..e81ce465ff3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -21,7 +21,7 @@ * */ -#include "amdgpu_ras.h" +#include "amdgpu.h" static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, void *ras_error_status, From 8b0fb0e967c1700bd729ae54b6f229501b8587ec Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 4 Jan 2022 13:52:46 +0800 Subject: [PATCH 026/339] drm/amdgpu: Modify gfx block to fit for the unified ras block data and ops 1.Modify gfx block to fit for the unified ras block data and ops. 2.Change amdgpu_gfx_ras_funcs to amdgpu_gfx_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of gfx ras variable so that gfx ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register gfx ras block into amdgpu device ras block link list. 5.Remove the redundant code about gfx in amdgpu_ras.c after using the unified ras block. 6.Fill unified ras block .name .block .ras_late_init and .ras_fini for all of gfx versions. If .ras_late_init and .ras_fini had been defined by the selected gfx version, the defined functions will take effect; if not defined, default fill with amdgpu_gfx_ras_late_init and amdgpu_gfx_ras_fini. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 8 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 17 ++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 63 ++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 65 ++++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c | 24 +++++---- drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c | 25 +++++----- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.h | 2 +- 8 files changed, 123 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 3d8f82dc8c97..43004822ec6f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -622,7 +622,7 @@ int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value) return r; } -int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev) +int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, void *ras_info) { int r; struct ras_fs_if fs_info = { @@ -695,9 +695,9 @@ int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev, */ if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) { kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->query_ras_error_count) - adev->gfx.ras_funcs->query_ras_error_count(adev, err_data); + if (adev->gfx.ras && adev->gfx.ras->ras_block.hw_ops && + adev->gfx.ras->ras_block.hw_ops->query_ras_error_count) + adev->gfx.ras->ras_block.hw_ops->query_ras_error_count(adev, err_data); amdgpu_ras_reset_gpu(adev); } return AMDGPU_RAS_SUCCESS; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index 776c886fd94a..f99eac544f6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -31,6 +31,7 @@ #include "amdgpu_ring.h" #include "amdgpu_rlc.h" #include "soc15.h" +#include "amdgpu_ras.h" /* GFX current status */ #define AMDGPU_GFX_NORMAL_MODE 0x00000000L @@ -198,16 +199,8 @@ struct amdgpu_cu_info { uint32_t bitmap[4][4]; }; -struct amdgpu_gfx_ras_funcs { - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); - int (*ras_error_inject)(struct amdgpu_device *adev, - void *inject_if); - int (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - void (*reset_ras_error_count)(struct amdgpu_device *adev); - void (*query_ras_error_status)(struct amdgpu_device *adev); - void (*reset_ras_error_status)(struct amdgpu_device *adev); +struct amdgpu_gfx_ras { + struct amdgpu_ras_block_object ras_block; void (*enable_watchdog_timer)(struct amdgpu_device *adev); }; @@ -331,7 +324,7 @@ struct amdgpu_gfx { /*ras */ struct ras_common_if *ras_if; - const struct amdgpu_gfx_ras_funcs *ras_funcs; + struct amdgpu_gfx_ras *ras; }; #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev)) @@ -393,7 +386,7 @@ bool amdgpu_gfx_is_me_queue_enabled(struct amdgpu_device *adev, int me, int pipe, int queue); void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable); int amdgpu_get_gfx_off_status(struct amdgpu_device *adev, uint32_t *value); -int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev); +int amdgpu_gfx_ras_late_init(struct amdgpu_device *adev, void *ras_info); void amdgpu_gfx_ras_fini(struct amdgpu_device *adev); int amdgpu_gfx_process_ras_data_cb(struct amdgpu_device *adev, void *err_data, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 5b3f4beb2149..a5812c21177e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -89,6 +89,8 @@ const char *get_ras_block_str(struct ras_common_if *ras_block) return ras_block_string[ras_block->block]; } +#define ras_block_str(_BLOCK_) (((_BLOCK_) < (sizeof(*ras_block_string)/sizeof(const char*))) ? ras_block_string[_BLOCK_] : "Out Of Range") + #define ras_err_str(i) (ras_error_string[ffs(i)]) #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) @@ -962,6 +964,7 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info) { + struct amdgpu_ras_block_object* block_obj = NULL; struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head); struct ras_err_data err_data = {0, 0, 0, NULL}; int i; @@ -969,6 +972,8 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, if (!obj) return -EINVAL; + block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0); + switch (info->head.block) { case AMDGPU_RAS_BLOCK__UMC: amdgpu_ras_get_ecc_info(adev, &err_data); @@ -981,13 +986,16 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, } break; case AMDGPU_RAS_BLOCK__GFX: - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->query_ras_error_count) - adev->gfx.ras_funcs->query_ras_error_count(adev, &err_data); + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", + get_ras_block_str(&info->head)); + return -EINVAL; + } + if (block_obj->hw_ops->query_ras_error_count) + block_obj->hw_ops->query_ras_error_count(adev, &err_data); - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->query_ras_error_status) - adev->gfx.ras_funcs->query_ras_error_status(adev); + if (block_obj->hw_ops->query_ras_error_status) + block_obj->hw_ops->query_ras_error_status(adev); break; case AMDGPU_RAS_BLOCK__MMHUB: if (adev->mmhub.ras_funcs && @@ -1074,18 +1082,23 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, enum amdgpu_ras_block block) { + struct amdgpu_ras_block_object* block_obj = amdgpu_ras_get_ras_block(adev, block, 0); + if (!amdgpu_ras_is_supported(adev, block)) return -EINVAL; switch (block) { case AMDGPU_RAS_BLOCK__GFX: - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->reset_ras_error_count) - adev->gfx.ras_funcs->reset_ras_error_count(adev); + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); + return -EINVAL; + } - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->reset_ras_error_status) - adev->gfx.ras_funcs->reset_ras_error_status(adev); + if (block_obj->hw_ops->reset_ras_error_count) + block_obj->hw_ops->reset_ras_error_count(adev); + + if (block_obj->hw_ops->reset_ras_error_status) + block_obj->hw_ops->reset_ras_error_status(adev); break; case AMDGPU_RAS_BLOCK__MMHUB: if (adev->mmhub.ras_funcs && @@ -1150,7 +1163,8 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, .address = info->address, .value = info->value, }; - int ret = 0; + int ret = -EINVAL; + struct amdgpu_ras_block_object* block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, info->head.sub_block_index); if (!obj) return -EINVAL; @@ -1164,11 +1178,13 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, switch (info->head.block) { case AMDGPU_RAS_BLOCK__GFX: - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->ras_error_inject) - ret = adev->gfx.ras_funcs->ras_error_inject(adev, info); - else - ret = -EINVAL; + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); + return -EINVAL; + } + + if (block_obj->hw_ops->ras_error_inject) + ret = block_obj->hw_ops->ras_error_inject(adev, info); break; case AMDGPU_RAS_BLOCK__UMC: case AMDGPU_RAS_BLOCK__SDMA: @@ -1800,15 +1816,20 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev) static void amdgpu_ras_error_status_query(struct amdgpu_device *adev, struct ras_query_if *info) { + struct amdgpu_ras_block_object* block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, info->head.sub_block_index); /* * Only two block need to query read/write * RspStatus at current state */ switch (info->head.block) { case AMDGPU_RAS_BLOCK__GFX: - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->query_ras_error_status) - adev->gfx.ras_funcs->query_ras_error_status(adev); + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); + return ; + } + + if (block_obj->hw_ops->query_ras_error_status) + block_obj->hw_ops->query_ras_error_status(adev); break; case AMDGPU_RAS_BLOCK__MMHUB: if (adev->mmhub.ras_funcs && diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 9189fb85a4dd..d36a6bc62560 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -882,7 +882,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev, static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev); static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring); static u64 gfx_v9_0_ring_get_rptr_compute(struct amdgpu_ring *ring); -static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, +static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status); static int gfx_v9_0_ras_error_inject(struct amdgpu_device *adev, void *inject_if); @@ -2197,12 +2197,16 @@ static const struct amdgpu_gfx_funcs gfx_v9_0_gfx_funcs = { .select_me_pipe_q = &gfx_v9_0_select_me_pipe_q, }; -static const struct amdgpu_gfx_ras_funcs gfx_v9_0_ras_funcs = { - .ras_late_init = amdgpu_gfx_ras_late_init, - .ras_fini = amdgpu_gfx_ras_fini, - .ras_error_inject = &gfx_v9_0_ras_error_inject, - .query_ras_error_count = &gfx_v9_0_query_ras_error_count, - .reset_ras_error_count = &gfx_v9_0_reset_ras_error_count, +const struct amdgpu_ras_block_hw_ops gfx_v9_0_ras_ops = { + .ras_error_inject = &gfx_v9_0_ras_error_inject, + .query_ras_error_count = &gfx_v9_0_query_ras_error_count, + .reset_ras_error_count = &gfx_v9_0_reset_ras_error_count, +}; + +static struct amdgpu_gfx_ras gfx_v9_0_ras = { + .ras_block = { + .hw_ops = &gfx_v9_0_ras_ops, + }, }; static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) @@ -2231,7 +2235,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) DRM_INFO("fix gfx.config for vega12\n"); break; case IP_VERSION(9, 4, 0): - adev->gfx.ras_funcs = &gfx_v9_0_ras_funcs; + adev->gfx.ras = &gfx_v9_0_ras; adev->gfx.config.max_hw_contexts = 8; adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; adev->gfx.config.sc_prim_fifo_size_backend = 0x100; @@ -2258,7 +2262,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) gb_addr_config = RAVEN_GB_ADDR_CONFIG_GOLDEN; break; case IP_VERSION(9, 4, 1): - adev->gfx.ras_funcs = &gfx_v9_4_ras_funcs; + adev->gfx.ras = &gfx_v9_4_ras; adev->gfx.config.max_hw_contexts = 8; adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; adev->gfx.config.sc_prim_fifo_size_backend = 0x100; @@ -2279,7 +2283,7 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) gb_addr_config |= 0x22010042; break; case IP_VERSION(9, 4, 2): - adev->gfx.ras_funcs = &gfx_v9_4_2_ras_funcs; + adev->gfx.ras = &gfx_v9_4_2_ras; adev->gfx.config.max_hw_contexts = 8; adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; adev->gfx.config.sc_prim_fifo_size_backend = 0x100; @@ -2298,6 +2302,25 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) break; } + if (adev->gfx.ras) { + err = amdgpu_ras_register_ras_block(adev, &adev->gfx.ras->ras_block); + if (err) { + DRM_ERROR("Failed to register gfx ras block!\n"); + return err; + } + + strcpy(adev->gfx.ras->ras_block.name,"gfx"); + adev->gfx.ras->ras_block.block = AMDGPU_RAS_BLOCK__GFX; + + /* If not define special ras_late_init function, use gfx default ras_late_init */ + if (!adev->gfx.ras->ras_block.ras_late_init) + adev->gfx.ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init; + + /* If not define special ras_fini function, use gfx default ras_fini */ + if (!adev->gfx.ras->ras_block.ras_fini) + adev->gfx.ras->ras_block.ras_fini = amdgpu_gfx_ras_fini; + } + adev->gfx.config.gb_addr_config = gb_addr_config; adev->gfx.config.gb_addr_config_fields.num_pipes = 1 << @@ -2513,9 +2536,8 @@ static int gfx_v9_0_sw_fini(void *handle) int i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->ras_fini) - adev->gfx.ras_funcs->ras_fini(adev); + if (adev->gfx.ras && adev->gfx.ras->ras_block.ras_fini) + adev->gfx.ras->ras_block.ras_fini(adev); for (i = 0; i < adev->gfx.num_gfx_rings; i++) amdgpu_ring_fini(&adev->gfx.gfx_ring[i]); @@ -4870,16 +4892,15 @@ static int gfx_v9_0_ecc_late_init(void *handle) if (r) return r; - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->ras_late_init) { - r = adev->gfx.ras_funcs->ras_late_init(adev); + if (adev->gfx.ras && adev->gfx.ras->ras_block.ras_late_init) { + r = adev->gfx.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } - if (adev->gfx.ras_funcs && - adev->gfx.ras_funcs->enable_watchdog_timer) - adev->gfx.ras_funcs->enable_watchdog_timer(adev); + if (adev->gfx.ras && + adev->gfx.ras->enable_watchdog_timer) + adev->gfx.ras->enable_watchdog_timer(adev); return 0; } @@ -6819,7 +6840,7 @@ static void gfx_v9_0_reset_ras_error_count(struct amdgpu_device *adev) WREG32_SOC15(GC, 0, mmATC_L2_CACHE_4K_EDC_INDEX, 255); } -static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, +static void gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; @@ -6828,7 +6849,7 @@ static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, uint32_t reg_value; if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) - return -EINVAL; + return; err_data->ue_count = 0; err_data->ce_count = 0; @@ -6857,8 +6878,6 @@ static int gfx_v9_0_query_ras_error_count(struct amdgpu_device *adev, mutex_unlock(&adev->grbm_idx_mutex); gfx_v9_0_query_utc_edc_status(adev, err_data); - - return 0; } static void gfx_v9_0_emit_mem_sync(struct amdgpu_ring *ring) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c index b4789dfc2bb9..c67e387a97f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c @@ -863,7 +863,7 @@ static int gfx_v9_4_ras_error_count(struct amdgpu_device *adev, return 0; } -static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev, +static void gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; @@ -872,7 +872,7 @@ static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev, uint32_t reg_value; if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) - return -EINVAL; + return; err_data->ue_count = 0; err_data->ce_count = 0; @@ -903,7 +903,6 @@ static int gfx_v9_4_query_ras_error_count(struct amdgpu_device *adev, gfx_v9_4_query_utc_edc_status(adev, err_data); - return 0; } static void gfx_v9_4_reset_ras_error_count(struct amdgpu_device *adev) @@ -1029,11 +1028,16 @@ static void gfx_v9_4_query_ras_error_status(struct amdgpu_device *adev) mutex_unlock(&adev->grbm_idx_mutex); } -const struct amdgpu_gfx_ras_funcs gfx_v9_4_ras_funcs = { - .ras_late_init = amdgpu_gfx_ras_late_init, - .ras_fini = amdgpu_gfx_ras_fini, - .ras_error_inject = &gfx_v9_4_ras_error_inject, - .query_ras_error_count = &gfx_v9_4_query_ras_error_count, - .reset_ras_error_count = &gfx_v9_4_reset_ras_error_count, - .query_ras_error_status = &gfx_v9_4_query_ras_error_status, + +const struct amdgpu_ras_block_hw_ops gfx_v9_4_ras_ops = { + .ras_error_inject = &gfx_v9_4_ras_error_inject, + .query_ras_error_count = &gfx_v9_4_query_ras_error_count, + .reset_ras_error_count = &gfx_v9_4_reset_ras_error_count, + .query_ras_error_status = &gfx_v9_4_query_ras_error_status, +}; + +struct amdgpu_gfx_ras gfx_v9_4_ras = { + .ras_block = { + .hw_ops = &gfx_v9_4_ras_ops, + }, }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h index bdd16b568021..ca520a767267 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.h @@ -24,6 +24,6 @@ #ifndef __GFX_V9_4_H__ #define __GFX_V9_4_H__ -extern const struct amdgpu_gfx_ras_funcs gfx_v9_4_ras_funcs; +extern struct amdgpu_gfx_ras gfx_v9_4_ras; #endif /* __GFX_V9_4_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c index c4f37a161875..7ec6243e015e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c @@ -1641,14 +1641,14 @@ static int gfx_v9_4_2_query_utc_edc_count(struct amdgpu_device *adev, return 0; } -static int gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev, +static void gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; uint32_t sec_count = 0, ded_count = 0; if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX)) - return -EINVAL; + return; err_data->ue_count = 0; err_data->ce_count = 0; @@ -1661,7 +1661,6 @@ static int gfx_v9_4_2_query_ras_error_count(struct amdgpu_device *adev, err_data->ce_count += sec_count; err_data->ue_count += ded_count; - return 0; } static void gfx_v9_4_2_reset_utc_err_status(struct amdgpu_device *adev) @@ -1931,13 +1930,17 @@ static void gfx_v9_4_2_reset_sq_timeout_status(struct amdgpu_device *adev) mutex_unlock(&adev->grbm_idx_mutex); } -const struct amdgpu_gfx_ras_funcs gfx_v9_4_2_ras_funcs = { - .ras_late_init = amdgpu_gfx_ras_late_init, - .ras_fini = amdgpu_gfx_ras_fini, - .ras_error_inject = &gfx_v9_4_2_ras_error_inject, - .query_ras_error_count = &gfx_v9_4_2_query_ras_error_count, - .reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count, - .query_ras_error_status = &gfx_v9_4_2_query_ras_error_status, - .reset_ras_error_status = &gfx_v9_4_2_reset_ras_error_status, +struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops ={ + .ras_error_inject = &gfx_v9_4_2_ras_error_inject, + .query_ras_error_count = &gfx_v9_4_2_query_ras_error_count, + .reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count, + .query_ras_error_status = &gfx_v9_4_2_query_ras_error_status, + .reset_ras_error_status = &gfx_v9_4_2_reset_ras_error_status, +}; + +struct amdgpu_gfx_ras gfx_v9_4_2_ras = { + .ras_block = { + .hw_ops = &gfx_v9_4_2_ras_ops, + }, .enable_watchdog_timer = &gfx_v9_4_2_enable_watchdog_timer, }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.h b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.h index 6db1f88509af..7584624b641c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.h +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.h @@ -31,6 +31,6 @@ void gfx_v9_4_2_init_golden_registers(struct amdgpu_device *adev, void gfx_v9_4_2_set_power_brake_sequence(struct amdgpu_device *adev); int gfx_v9_4_2_do_edc_gpr_workarounds(struct amdgpu_device *adev); -extern const struct amdgpu_gfx_ras_funcs gfx_v9_4_2_ras_funcs; +extern struct amdgpu_gfx_ras gfx_v9_4_2_ras; #endif /* __GFX_V9_4_2_H__ */ From 6c2453861f48e4e779cafa01c09e78ddc2c23c6b Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 4 Jan 2022 18:56:20 +0800 Subject: [PATCH 027/339] drm/amdgpu: Modify xgmi block to fit for the unified ras block data and ops 1.Modify gmc block to fit for the unified ras block data and ops. 2.Change amdgpu_xgmi_ras_funcs to amdgpu_xgmi_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of gmc ras variable so that gmc ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register gmc ras block into amdgpu device ras block link list. 5.Remove the redundant code about gmc in amdgpu_ras.c after using the unified ras block. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 16 +++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 11 ++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 10 ++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 26 +++++++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 4 ++-- 5 files changed, 37 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 2430d6223c2d..d86ee530e0a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -454,12 +454,13 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) return r; } - if (!adev->gmc.xgmi.connected_to_cpu) - adev->gmc.xgmi.ras_funcs = &xgmi_ras_funcs; + if (!adev->gmc.xgmi.connected_to_cpu) { + adev->gmc.xgmi.ras = &xgmi_ras; + amdgpu_ras_register_ras_block(adev, &adev->gmc.xgmi.ras->ras_block); + } - if (adev->gmc.xgmi.ras_funcs && - adev->gmc.xgmi.ras_funcs->ras_late_init) { - r = adev->gmc.xgmi.ras_funcs->ras_late_init(adev); + if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_late_init) { + r = adev->gmc.xgmi.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } @@ -505,9 +506,8 @@ void amdgpu_gmc_ras_fini(struct amdgpu_device *adev) adev->mmhub.ras_funcs->ras_fini) adev->mmhub.ras_funcs->ras_fini(adev); - if (adev->gmc.xgmi.ras_funcs && - adev->gmc.xgmi.ras_funcs->ras_fini) - adev->gmc.xgmi.ras_funcs->ras_fini(adev); + if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_fini) + adev->gmc.xgmi.ras->ras_block.ras_fini(adev); if (adev->hdp.ras_funcs && adev->hdp.ras_funcs->ras_fini) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 8458cebc6d5b..0001631cfedb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -29,6 +29,7 @@ #include #include "amdgpu_irq.h" +#include "amdgpu_ras.h" /* VA hole for 48bit addresses on Vega10 */ #define AMDGPU_GMC_HOLE_START 0x0000800000000000ULL @@ -135,12 +136,8 @@ struct amdgpu_gmc_funcs { unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev); }; -struct amdgpu_xgmi_ras_funcs { - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); - int (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - void (*reset_ras_error_count)(struct amdgpu_device *adev); +struct amdgpu_xgmi_ras { + struct amdgpu_ras_block_object ras_block; }; struct amdgpu_xgmi { @@ -159,7 +156,7 @@ struct amdgpu_xgmi { struct ras_common_if *ras_if; bool connected_to_cpu; bool pending_reset; - const struct amdgpu_xgmi_ras_funcs *ras_funcs; + struct amdgpu_xgmi_ras *ras; }; struct amdgpu_gmc { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index a5812c21177e..28997b7f7c95 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1012,9 +1012,13 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, adev->nbio.ras_funcs->query_ras_error_count(adev, &err_data); break; case AMDGPU_RAS_BLOCK__XGMI_WAFL: - if (adev->gmc.xgmi.ras_funcs && - adev->gmc.xgmi.ras_funcs->query_ras_error_count) - adev->gmc.xgmi.ras_funcs->query_ras_error_count(adev, &err_data); + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", + get_ras_block_str(&info->head)); + return -EINVAL; + } + if (block_obj->hw_ops->query_ras_error_count) + block_obj->hw_ops->query_ras_error_count(adev, &err_data); break; case AMDGPU_RAS_BLOCK__HDP: if (adev->hdp.ras_funcs && diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index e8b8f28c2f72..d29acd33eb11 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -732,7 +732,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) return psp_xgmi_terminate(&adev->psp); } -static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev) +static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, void *ras_info) { int r; struct ras_ih_if ih_info = { @@ -746,7 +746,7 @@ static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev) adev->gmc.xgmi.num_physical_nodes == 0) return 0; - adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev); + adev->gmc.xgmi.ras->ras_block.hw_ops->reset_ras_error_count(adev); if (!adev->gmc.xgmi.ras_if) { adev->gmc.xgmi.ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL); @@ -865,7 +865,7 @@ static int amdgpu_xgmi_query_pcs_error_status(struct amdgpu_device *adev, return 0; } -static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, +static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; @@ -874,7 +874,7 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, uint32_t ue_cnt = 0, ce_cnt = 0; if (!amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__XGMI_WAFL)) - return -EINVAL; + return ; err_data->ue_count = 0; err_data->ce_count = 0; @@ -940,17 +940,23 @@ static int amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, break; } - adev->gmc.xgmi.ras_funcs->reset_ras_error_count(adev); + adev->gmc.xgmi.ras->ras_block.hw_ops->reset_ras_error_count(adev); err_data->ue_count += ue_cnt; err_data->ce_count += ce_cnt; - - return 0; } -const struct amdgpu_xgmi_ras_funcs xgmi_ras_funcs = { - .ras_late_init = amdgpu_xgmi_ras_late_init, - .ras_fini = amdgpu_xgmi_ras_fini, +struct amdgpu_ras_block_hw_ops xgmi_ras_hw_ops = { .query_ras_error_count = amdgpu_xgmi_query_ras_error_count, .reset_ras_error_count = amdgpu_xgmi_reset_ras_error_count, }; + +struct amdgpu_xgmi_ras xgmi_ras = { + .ras_block = { + .name = "xgmi", + .block = AMDGPU_RAS_BLOCK__XGMI_WAFL, + .hw_ops = &xgmi_ras_hw_ops, + .ras_late_init = amdgpu_xgmi_ras_late_init, + .ras_fini = amdgpu_xgmi_ras_fini, + }, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index d2189bf7d428..0afca51c3c0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -24,7 +24,7 @@ #include #include "amdgpu_psp.h" - +#include "amdgpu_ras.h" struct amdgpu_hive_info { struct kobject kobj; @@ -50,7 +50,7 @@ struct amdgpu_pcs_ras_field { uint32_t pcs_err_shift; }; -extern const struct amdgpu_xgmi_ras_funcs xgmi_ras_funcs; +extern struct amdgpu_xgmi_ras xgmi_ras; struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive); int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); From 6d76e9049ad92be32704106668c34493c3e4c0d4 Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 4 Jan 2022 18:57:58 +0800 Subject: [PATCH 028/339] drm/amdgpu: Modify hdp block to fit for the unified ras block data and ops 1.Modify hdp block to fit for the unified ras block data and ops. 2.Change amdgpu_hdp_ras_funcs to amdgpu_hdp_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of hdp ras variable so that hdp ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register hdp ras block into amdgpu device ras block link list. 5.Remove the redundant code about hdp in amdgpu_ras.c after using the unified ras block. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 10 ++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h | 13 +++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 ++++++++-------- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 9 +++++---- drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c | 14 +++++++++++--- drivers/gpu/drm/amd/amdgpu/hdp_v4_0.h | 2 +- 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index d86ee530e0a4..58cc4dae1246 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -465,9 +465,8 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) return r; } - if (adev->hdp.ras_funcs && - adev->hdp.ras_funcs->ras_late_init) { - r = adev->hdp.ras_funcs->ras_late_init(adev); + if (adev->hdp.ras && adev->hdp.ras->ras_block.ras_late_init) { + r = adev->hdp.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } @@ -509,9 +508,8 @@ void amdgpu_gmc_ras_fini(struct amdgpu_device *adev) if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_fini) adev->gmc.xgmi.ras->ras_block.ras_fini(adev); - if (adev->hdp.ras_funcs && - adev->hdp.ras_funcs->ras_fini) - adev->hdp.ras_funcs->ras_fini(adev); + if (adev->hdp.ras && adev->hdp.ras->ras_block.ras_fini) + adev->hdp.ras->ras_block.ras_fini(adev); } /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c index a766e1aad2b9..518966a26130 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.c @@ -24,7 +24,7 @@ #include "amdgpu.h" #include "amdgpu_ras.h" -int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev) +int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev, void *ras_info) { int r; struct ras_ih_if ih_info = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h index 7ec99d591584..c94a4b3c8d6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h @@ -22,13 +22,10 @@ */ #ifndef __AMDGPU_HDP_H__ #define __AMDGPU_HDP_H__ +#include "amdgpu_ras.h" -struct amdgpu_hdp_ras_funcs { - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); - void (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - void (*reset_ras_error_count)(struct amdgpu_device *adev); +struct amdgpu_hdp_ras{ + struct amdgpu_ras_block_object ras_block; }; struct amdgpu_hdp_funcs { @@ -43,9 +40,9 @@ struct amdgpu_hdp_funcs { struct amdgpu_hdp { struct ras_common_if *ras_if; const struct amdgpu_hdp_funcs *funcs; - const struct amdgpu_hdp_ras_funcs *ras_funcs; + struct amdgpu_hdp_ras *ras; }; -int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev); +int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev, void *ras_info); void amdgpu_hdp_ras_fini(struct amdgpu_device *adev); #endif /* __AMDGPU_HDP_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 28997b7f7c95..c47a03252ec8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1012,6 +1012,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, adev->nbio.ras_funcs->query_ras_error_count(adev, &err_data); break; case AMDGPU_RAS_BLOCK__XGMI_WAFL: + case AMDGPU_RAS_BLOCK__HDP: if (!block_obj || !block_obj->hw_ops) { dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); @@ -1020,11 +1021,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, if (block_obj->hw_ops->query_ras_error_count) block_obj->hw_ops->query_ras_error_count(adev, &err_data); break; - case AMDGPU_RAS_BLOCK__HDP: - if (adev->hdp.ras_funcs && - adev->hdp.ras_funcs->query_ras_error_count) - adev->hdp.ras_funcs->query_ras_error_count(adev, &err_data); - break; case AMDGPU_RAS_BLOCK__MCA: amdgpu_ras_mca_query_error_status(adev, &info->head, &err_data); break; @@ -1118,9 +1114,13 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, adev->sdma.funcs->reset_ras_error_count(adev); break; case AMDGPU_RAS_BLOCK__HDP: - if (adev->hdp.ras_funcs && - adev->hdp.ras_funcs->reset_ras_error_count) - adev->hdp.ras_funcs->reset_ras_error_count(adev); + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); + return -EINVAL; + } + + if (block_obj->hw_ops->reset_ras_error_count) + block_obj->hw_ops->reset_ras_error_count(adev); break; default: break; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 88c1eb9ad068..16ab572219ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1269,7 +1269,8 @@ static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev) static void gmc_v9_0_set_hdp_ras_funcs(struct amdgpu_device *adev) { - adev->hdp.ras_funcs = &hdp_v4_0_ras_funcs; + adev->hdp.ras = &hdp_v4_0_ras; + amdgpu_ras_register_ras_block(adev, &adev->hdp.ras->ras_block); } static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev) @@ -1346,9 +1347,9 @@ static int gmc_v9_0_late_init(void *handle) adev->mmhub.ras_funcs->reset_ras_error_count) adev->mmhub.ras_funcs->reset_ras_error_count(adev); - if (adev->hdp.ras_funcs && - adev->hdp.ras_funcs->reset_ras_error_count) - adev->hdp.ras_funcs->reset_ras_error_count(adev); + if (adev->hdp.ras && adev->hdp.ras->ras_block.hw_ops && + adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count) + adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count(adev); } r = amdgpu_gmc_ras_late_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c index eecfb1545c1e..6b41fcbf4875 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c @@ -150,13 +150,21 @@ static void hdp_v4_0_init_registers(struct amdgpu_device *adev) WREG32_SOC15(HDP, 0, mmHDP_NONSURFACE_BASE_HI, (adev->gmc.vram_start >> 40)); } -const struct amdgpu_hdp_ras_funcs hdp_v4_0_ras_funcs = { - .ras_late_init = amdgpu_hdp_ras_late_init, - .ras_fini = amdgpu_hdp_ras_fini, +struct amdgpu_ras_block_hw_ops hdp_v4_0_ras_hw_ops = { .query_ras_error_count = hdp_v4_0_query_ras_error_count, .reset_ras_error_count = hdp_v4_0_reset_ras_error_count, }; +struct amdgpu_hdp_ras hdp_v4_0_ras = { + .ras_block = { + .name = "hdp", + .block = AMDGPU_RAS_BLOCK__HDP, + .hw_ops = &hdp_v4_0_ras_hw_ops, + .ras_late_init = amdgpu_hdp_ras_late_init, + .ras_fini = amdgpu_hdp_ras_fini, + }, +}; + const struct amdgpu_hdp_funcs hdp_v4_0_funcs = { .flush_hdp = hdp_v4_0_flush_hdp, .invalidate_hdp = hdp_v4_0_invalidate_hdp, diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.h b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.h index dc3a1b81dd62..c44eee9282ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.h +++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.h @@ -27,6 +27,6 @@ #include "soc15_common.h" extern const struct amdgpu_hdp_funcs hdp_v4_0_funcs; -extern const struct amdgpu_hdp_ras_funcs hdp_v4_0_ras_funcs; +extern struct amdgpu_hdp_ras hdp_v4_0_ras; #endif From 5e67bba301156c85251f49df19f5c695875814d1 Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 4 Jan 2022 19:04:41 +0800 Subject: [PATCH 029/339] drm/amdgpu: Modify mmhub block to fit for the unified ras block data and ops 1.Modify mmhub block to fit for the unified ras block data and ops. 2.Change amdgpu_mmhub_ras_funcs to amdgpu_mmhub_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of mmhub ras variable so that mmhub ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register mmhub ras block into amdgpu device ras block link list. 5.Remove the redundant code about mmhub in amdgpu_ras.c after using the unified ras block. 5.Remove the redundant code about mmhub in amdgpu_ras.c after using the unified ras block. 6.Fill unified ras block .name .block .ras_late_init and .ras_fini for all of mmhub versions. If .ras_late_init and .ras_fini had been defined by the selected mmhub version, the defined functions will take effect; if not defined, default fill them with amdgpu_mmhub_ras_late_init and amdgpu_mmhub_ras_fini. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 10 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h | 14 ++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 47 ++++++---------------- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 27 ++++++++++--- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 10 +++-- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c | 10 +++-- drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.h | 2 +- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 10 +++-- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h | 2 +- 12 files changed, 73 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 9230e4476d91..71b814fe15f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3307,9 +3307,9 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) if (adev->asic_reset_res) goto fail; - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->reset_ras_error_count) - adev->mmhub.ras_funcs->reset_ras_error_count(adev); + if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops && + adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count) + adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev); } else { task_barrier_full(&hive->tb); @@ -4656,9 +4656,9 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, if (!r && amdgpu_ras_intr_triggered()) { list_for_each_entry(tmp_adev, device_list_handle, reset_list) { - if (tmp_adev->mmhub.ras_funcs && - tmp_adev->mmhub.ras_funcs->reset_ras_error_count) - tmp_adev->mmhub.ras_funcs->reset_ras_error_count(tmp_adev); + if (tmp_adev->mmhub.ras && tmp_adev->mmhub.ras->ras_block.hw_ops && + tmp_adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count) + tmp_adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(tmp_adev); } amdgpu_ras_intr_cleared(); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 58cc4dae1246..acf806c87673 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -447,9 +447,8 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) return r; } - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->ras_late_init) { - r = adev->mmhub.ras_funcs->ras_late_init(adev); + if (adev->mmhub.ras && adev->mmhub.ras->ras_block.ras_late_init) { + r = adev->mmhub.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } @@ -501,9 +500,8 @@ void amdgpu_gmc_ras_fini(struct amdgpu_device *adev) adev->umc.ras_funcs->ras_fini) adev->umc.ras_funcs->ras_fini(adev); - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->ras_fini) - adev->mmhub.ras_funcs->ras_fini(adev); + if (adev->mmhub.ras && adev->mmhub.ras->ras_block.ras_fini) + adev->mmhub.ras->ras_block.ras_fini(adev); if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_fini) adev->gmc.xgmi.ras->ras_block.ras_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c index 24297dc51434..f9b5472a75d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.c @@ -24,7 +24,7 @@ #include "amdgpu.h" #include "amdgpu_ras.h" -int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev) +int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev, void *ras_info) { int r; struct ras_ih_if ih_info = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h index b27fcbccce2b..7deda9a3b81e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h @@ -21,14 +21,8 @@ #ifndef __AMDGPU_MMHUB_H__ #define __AMDGPU_MMHUB_H__ -struct amdgpu_mmhub_ras_funcs { - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); - void (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - void (*query_ras_error_status)(struct amdgpu_device *adev); - void (*reset_ras_error_count)(struct amdgpu_device *adev); - void (*reset_ras_error_status)(struct amdgpu_device *adev); +struct amdgpu_mmhub_ras { + struct amdgpu_ras_block_object ras_block; }; struct amdgpu_mmhub_funcs { @@ -50,10 +44,10 @@ struct amdgpu_mmhub_funcs { struct amdgpu_mmhub { struct ras_common_if *ras_if; const struct amdgpu_mmhub_funcs *funcs; - const struct amdgpu_mmhub_ras_funcs *ras_funcs; + struct amdgpu_mmhub_ras *ras; }; -int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev); +int amdgpu_mmhub_ras_late_init(struct amdgpu_device *adev, void *ras_info); void amdgpu_mmhub_ras_fini(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index c47a03252ec8..0ce26fd6abbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -986,6 +986,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, } break; case AMDGPU_RAS_BLOCK__GFX: + case AMDGPU_RAS_BLOCK__MMHUB: if (!block_obj || !block_obj->hw_ops) { dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); @@ -997,15 +998,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, if (block_obj->hw_ops->query_ras_error_status) block_obj->hw_ops->query_ras_error_status(adev); break; - case AMDGPU_RAS_BLOCK__MMHUB: - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->query_ras_error_count) - adev->mmhub.ras_funcs->query_ras_error_count(adev, &err_data); - - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->query_ras_error_status) - adev->mmhub.ras_funcs->query_ras_error_status(adev); - break; case AMDGPU_RAS_BLOCK__PCIE_BIF: if (adev->nbio.ras_funcs && adev->nbio.ras_funcs->query_ras_error_count) @@ -1089,6 +1081,7 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, switch (block) { case AMDGPU_RAS_BLOCK__GFX: + case AMDGPU_RAS_BLOCK__MMHUB: if (!block_obj || !block_obj->hw_ops) { dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); return -EINVAL; @@ -1100,15 +1093,6 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, if (block_obj->hw_ops->reset_ras_error_status) block_obj->hw_ops->reset_ras_error_status(adev); break; - case AMDGPU_RAS_BLOCK__MMHUB: - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->reset_ras_error_count) - adev->mmhub.ras_funcs->reset_ras_error_count(adev); - - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->reset_ras_error_status) - adev->mmhub.ras_funcs->reset_ras_error_status(adev); - break; case AMDGPU_RAS_BLOCK__SDMA: if (adev->sdma.funcs->reset_ras_error_count) adev->sdma.funcs->reset_ras_error_count(adev); @@ -1825,24 +1809,19 @@ static void amdgpu_ras_error_status_query(struct amdgpu_device *adev, * Only two block need to query read/write * RspStatus at current state */ - switch (info->head.block) { - case AMDGPU_RAS_BLOCK__GFX: - if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); - return ; - } + if ((info->head.block != AMDGPU_RAS_BLOCK__GFX) && + (info->head.block != AMDGPU_RAS_BLOCK__MMHUB)) + return ; - if (block_obj->hw_ops->query_ras_error_status) - block_obj->hw_ops->query_ras_error_status(adev); - break; - case AMDGPU_RAS_BLOCK__MMHUB: - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->query_ras_error_status) - adev->mmhub.ras_funcs->query_ras_error_status(adev); - break; - default: - break; + block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, info->head.sub_block_index); + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); + return ; } + + if (block_obj->hw_ops->query_ras_error_status) + block_obj->hw_ops->query_ras_error_status(adev); + } static void amdgpu_ras_query_err_status(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 16ab572219ed..7506e198e6e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1248,18 +1248,33 @@ static void gmc_v9_0_set_mmhub_ras_funcs(struct amdgpu_device *adev) { switch (adev->ip_versions[MMHUB_HWIP][0]) { case IP_VERSION(9, 4, 0): - adev->mmhub.ras_funcs = &mmhub_v1_0_ras_funcs; + adev->mmhub.ras = &mmhub_v1_0_ras; break; case IP_VERSION(9, 4, 1): - adev->mmhub.ras_funcs = &mmhub_v9_4_ras_funcs; + adev->mmhub.ras = &mmhub_v9_4_ras; break; case IP_VERSION(9, 4, 2): - adev->mmhub.ras_funcs = &mmhub_v1_7_ras_funcs; + adev->mmhub.ras = &mmhub_v1_7_ras; break; default: /* mmhub ras is not available */ break; } + + if (adev->mmhub.ras) { + amdgpu_ras_register_ras_block(adev, &adev->mmhub.ras->ras_block); + + strcpy(adev->mmhub.ras->ras_block.name,"mmhub"); + adev->mmhub.ras->ras_block.block = AMDGPU_RAS_BLOCK__MMHUB; + + /* If don't define special ras_late_init function, use default ras_late_init */ + if (!adev->mmhub.ras->ras_block.ras_late_init) + adev->mmhub.ras->ras_block.ras_late_init = amdgpu_mmhub_ras_late_init; + + /* If don't define special ras_fini function, use default ras_fini */ + if (!adev->mmhub.ras->ras_block.ras_fini) + adev->mmhub.ras->ras_block.ras_fini = amdgpu_mmhub_ras_fini; + } } static void gmc_v9_0_set_gfxhub_funcs(struct amdgpu_device *adev) @@ -1343,9 +1358,9 @@ static int gmc_v9_0_late_init(void *handle) } if (!amdgpu_persistent_edc_harvesting_supported(adev)) { - if (adev->mmhub.ras_funcs && - adev->mmhub.ras_funcs->reset_ras_error_count) - adev->mmhub.ras_funcs->reset_ras_error_count(adev); + if (adev->mmhub.ras && adev->mmhub.ras->ras_block.hw_ops && + adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count) + adev->mmhub.ras->ras_block.hw_ops->reset_ras_error_count(adev); if (adev->hdp.ras && adev->hdp.ras->ras_block.hw_ops && adev->hdp.ras->ras_block.hw_ops->reset_ras_error_count) diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 1da2ec692057..4c9f0c0f3116 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -774,13 +774,17 @@ static void mmhub_v1_0_reset_ras_error_count(struct amdgpu_device *adev) } } -const struct amdgpu_mmhub_ras_funcs mmhub_v1_0_ras_funcs = { - .ras_late_init = amdgpu_mmhub_ras_late_init, - .ras_fini = amdgpu_mmhub_ras_fini, +struct amdgpu_ras_block_hw_ops mmhub_v1_0_ras_hw_ops = { .query_ras_error_count = mmhub_v1_0_query_ras_error_count, .reset_ras_error_count = mmhub_v1_0_reset_ras_error_count, }; +struct amdgpu_mmhub_ras mmhub_v1_0_ras = { + .ras_block = { + .hw_ops = &mmhub_v1_0_ras_hw_ops, + }, +}; + const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = { .get_fb_location = mmhub_v1_0_get_fb_location, .init = mmhub_v1_0_init, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h index 4661b094e007..dae7ca48bd8b 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h @@ -24,6 +24,6 @@ #define __MMHUB_V1_0_H__ extern const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs; -extern const struct amdgpu_mmhub_ras_funcs mmhub_v1_0_ras_funcs; +extern struct amdgpu_mmhub_ras mmhub_v1_0_ras; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c index f5f7181f9af5..3b901f941627 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.c @@ -1321,15 +1321,19 @@ static void mmhub_v1_7_reset_ras_error_status(struct amdgpu_device *adev) } } -const struct amdgpu_mmhub_ras_funcs mmhub_v1_7_ras_funcs = { - .ras_late_init = amdgpu_mmhub_ras_late_init, - .ras_fini = amdgpu_mmhub_ras_fini, +struct amdgpu_ras_block_hw_ops mmhub_v1_7_ras_hw_ops = { .query_ras_error_count = mmhub_v1_7_query_ras_error_count, .reset_ras_error_count = mmhub_v1_7_reset_ras_error_count, .query_ras_error_status = mmhub_v1_7_query_ras_error_status, .reset_ras_error_status = mmhub_v1_7_reset_ras_error_status, }; +struct amdgpu_mmhub_ras mmhub_v1_7_ras = { + .ras_block = { + .hw_ops = &mmhub_v1_7_ras_hw_ops, + }, +}; + const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs = { .get_fb_location = mmhub_v1_7_get_fb_location, .init = mmhub_v1_7_init, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.h index a7f9dfc24697..629f49052137 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_7.h @@ -24,6 +24,6 @@ #define __MMHUB_V1_7_H__ extern const struct amdgpu_mmhub_funcs mmhub_v1_7_funcs; -extern const struct amdgpu_mmhub_ras_funcs mmhub_v1_7_ras_funcs; +extern struct amdgpu_mmhub_ras mmhub_v1_7_ras; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c index ff49eeaf7882..619106f7d23d 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c @@ -1655,14 +1655,18 @@ static void mmhub_v9_4_query_ras_error_status(struct amdgpu_device *adev) } } -const struct amdgpu_mmhub_ras_funcs mmhub_v9_4_ras_funcs = { - .ras_late_init = amdgpu_mmhub_ras_late_init, - .ras_fini = amdgpu_mmhub_ras_fini, +const struct amdgpu_ras_block_hw_ops mmhub_v9_4_ras_hw_ops = { .query_ras_error_count = mmhub_v9_4_query_ras_error_count, .reset_ras_error_count = mmhub_v9_4_reset_ras_error_count, .query_ras_error_status = mmhub_v9_4_query_ras_error_status, }; +struct amdgpu_mmhub_ras mmhub_v9_4_ras = { + .ras_block = { + .hw_ops = &mmhub_v9_4_ras_hw_ops, + }, +}; + const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = { .get_fb_location = mmhub_v9_4_get_fb_location, .init = mmhub_v9_4_init, diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h index 90436efa92ef..a48329d95f71 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h @@ -24,6 +24,6 @@ #define __MMHUB_V9_4_H__ extern const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs; -extern const struct amdgpu_mmhub_ras_funcs mmhub_v9_4_ras_funcs; +extern struct amdgpu_mmhub_ras mmhub_v9_4_ras; #endif From 2e54fe5d056e7dc82988ef64ded3dca0ef954f0a Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 5 Jan 2022 14:28:10 +0800 Subject: [PATCH 030/339] drm/amdgpu: Modify nbio block to fit for the unified ras block data and ops 1.Modify nbio block to fit for the unified ras block data and ops. 2.Change amdgpu_nbio_ras_funcs to amdgpu_nbio_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of mmhub ras variable so that nbio ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register nbio ras block into amdgpu device ras block link list. 5.Remove the redundant code about nbio in amdgpu_ras.c after using the unified ras block. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h | 11 ++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 22 ++++++++++------------ drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 17 +++++++++++++---- drivers/gpu/drm/amd/amdgpu/nbio_v7_4.h | 2 +- drivers/gpu/drm/amd/amdgpu/soc15.c | 18 ++++++++---------- 7 files changed, 43 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index f5cbc2747ac6..ea3e8c66211f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -199,13 +199,13 @@ static irqreturn_t amdgpu_irq_handler(int irq, void *arg) * ack the interrupt if it is there */ if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__PCIE_BIF)) { - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring) - adev->nbio.ras_funcs->handle_ras_controller_intr_no_bifring(adev); + if (adev->nbio.ras && + adev->nbio.ras->handle_ras_controller_intr_no_bifring) + adev->nbio.ras->handle_ras_controller_intr_no_bifring(adev); - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring) - adev->nbio.ras_funcs->handle_ras_err_event_athub_intr_no_bifring(adev); + if (adev->nbio.ras && + adev->nbio.ras->handle_ras_err_event_athub_intr_no_bifring) + adev->nbio.ras->handle_ras_err_event_athub_intr_no_bifring(adev); } return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c index 6afb02fef8cf..6ace2e390e77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.c @@ -22,7 +22,7 @@ #include "amdgpu.h" #include "amdgpu_ras.h" -int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev) +int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev, void *ras_info) { int r; struct ras_ih_if ih_info = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h index 843052205bd5..4afb76d3cd97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h @@ -47,15 +47,12 @@ struct nbio_hdp_flush_reg { u32 ref_and_mask_sdma7; }; -struct amdgpu_nbio_ras_funcs { +struct amdgpu_nbio_ras { + struct amdgpu_ras_block_object ras_block; void (*handle_ras_controller_intr_no_bifring)(struct amdgpu_device *adev); void (*handle_ras_err_event_athub_intr_no_bifring)(struct amdgpu_device *adev); int (*init_ras_controller_interrupt)(struct amdgpu_device *adev); int (*init_ras_err_event_athub_interrupt)(struct amdgpu_device *adev); - void (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); }; struct amdgpu_nbio_funcs { @@ -104,9 +101,9 @@ struct amdgpu_nbio { struct amdgpu_irq_src ras_err_event_athub_irq; struct ras_common_if *ras_if; const struct amdgpu_nbio_funcs *funcs; - const struct amdgpu_nbio_ras_funcs *ras_funcs; + struct amdgpu_nbio_ras *ras; }; -int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev); +int amdgpu_nbio_ras_late_init(struct amdgpu_device *adev, void *ras_info); void amdgpu_nbio_ras_fini(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 0ce26fd6abbd..6d1ca9e9795b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -999,10 +999,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, block_obj->hw_ops->query_ras_error_status(adev); break; case AMDGPU_RAS_BLOCK__PCIE_BIF: - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->query_ras_error_count) - adev->nbio.ras_funcs->query_ras_error_count(adev, &err_data); - break; case AMDGPU_RAS_BLOCK__XGMI_WAFL: case AMDGPU_RAS_BLOCK__HDP: if (!block_obj || !block_obj->hw_ops) { @@ -2385,24 +2381,26 @@ int amdgpu_ras_init(struct amdgpu_device *adev) case CHIP_VEGA20: case CHIP_ARCTURUS: case CHIP_ALDEBARAN: - if (!adev->gmc.xgmi.connected_to_cpu) - adev->nbio.ras_funcs = &nbio_v7_4_ras_funcs; + if (!adev->gmc.xgmi.connected_to_cpu) { + adev->nbio.ras = &nbio_v7_4_ras; + amdgpu_ras_register_ras_block(adev, &adev->nbio.ras->ras_block); + } break; default: /* nbio ras is not available */ break; } - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->init_ras_controller_interrupt) { - r = adev->nbio.ras_funcs->init_ras_controller_interrupt(adev); + if (adev->nbio.ras && + adev->nbio.ras->init_ras_controller_interrupt) { + r = adev->nbio.ras->init_ras_controller_interrupt(adev); if (r) goto release_con; } - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt) { - r = adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt(adev); + if (adev->nbio.ras && + adev->nbio.ras->init_ras_err_event_athub_interrupt) { + r = adev->nbio.ras->init_ras_err_event_athub_interrupt(adev); if (r) goto release_con; } diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index dc5e93756fea..39974b449341 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -658,16 +658,25 @@ static void nbio_v7_4_enable_doorbell_interrupt(struct amdgpu_device *adev, DOORBELL_INTERRUPT_DISABLE, enable ? 0 : 1); } -const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs = { +const struct amdgpu_ras_block_hw_ops nbio_v7_4_ras_hw_ops = { + .query_ras_error_count = nbio_v7_4_query_ras_error_count, +}; + +struct amdgpu_nbio_ras nbio_v7_4_ras = { + .ras_block = { + .name = "pcie_bif", + .block = AMDGPU_RAS_BLOCK__PCIE_BIF, + .hw_ops = &nbio_v7_4_ras_hw_ops, + .ras_late_init = amdgpu_nbio_ras_late_init, + .ras_fini = amdgpu_nbio_ras_fini, + }, .handle_ras_controller_intr_no_bifring = nbio_v7_4_handle_ras_controller_intr_no_bifring, .handle_ras_err_event_athub_intr_no_bifring = nbio_v7_4_handle_ras_err_event_athub_intr_no_bifring, .init_ras_controller_interrupt = nbio_v7_4_init_ras_controller_interrupt, .init_ras_err_event_athub_interrupt = nbio_v7_4_init_ras_err_event_athub_interrupt, - .query_ras_error_count = nbio_v7_4_query_ras_error_count, - .ras_late_init = amdgpu_nbio_ras_late_init, - .ras_fini = amdgpu_nbio_ras_fini, }; + static void nbio_v7_4_program_ltr(struct amdgpu_device *adev) { uint32_t def, data; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.h b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.h index cc5692db6f98..7490022d79d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.h +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.h @@ -29,6 +29,6 @@ extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg; extern const struct nbio_hdp_flush_reg nbio_v7_4_hdp_flush_reg_ald; extern const struct amdgpu_nbio_funcs nbio_v7_4_funcs; -extern const struct amdgpu_nbio_ras_funcs nbio_v7_4_ras_funcs; +extern struct amdgpu_nbio_ras nbio_v7_4_ras; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 0fc1747e4a70..6c8fcc4e29f4 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1224,9 +1224,8 @@ static int soc15_common_late_init(void *handle) if (amdgpu_sriov_vf(adev)) xgpu_ai_mailbox_get_irq(adev); - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->ras_late_init) - r = adev->nbio.ras_funcs->ras_late_init(adev); + if (adev->nbio.ras && adev->nbio.ras->ras_block.ras_late_init) + r = adev->nbio.ras->ras_block.ras_late_init(adev, NULL); return r; } @@ -1249,9 +1248,8 @@ static int soc15_common_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->ras_fini) - adev->nbio.ras_funcs->ras_fini(adev); + if (adev->nbio.ras && adev->nbio.ras->ras_block.ras_fini) + adev->nbio.ras->ras_block.ras_fini(adev); if (adev->df.funcs && adev->df.funcs->sw_fini) @@ -1318,11 +1316,11 @@ static int soc15_common_hw_fini(void *handle) if (adev->nbio.ras_if && amdgpu_ras_is_supported(adev, adev->nbio.ras_if->block)) { - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->init_ras_controller_interrupt) + if (adev->nbio.ras && + adev->nbio.ras->init_ras_controller_interrupt) amdgpu_irq_put(adev, &adev->nbio.ras_controller_irq, 0); - if (adev->nbio.ras_funcs && - adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt) + if (adev->nbio.ras && + adev->nbio.ras->init_ras_err_event_athub_interrupt) amdgpu_irq_put(adev, &adev->nbio.ras_err_event_athub_irq, 0); } From efe17d5a217e6b7dfd16c80dab522abcf2edf1bc Mon Sep 17 00:00:00 2001 From: yipechai Date: Thu, 6 Jan 2022 14:07:44 +0800 Subject: [PATCH 031/339] drm/amdgpu: Modify umc block to fit for the unified ras block data and ops 1.Modify umc block to fit for the unified ras block data and ops. 2.Change amdgpu_umc_ras_funcs to amdgpu_umc_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of umc ras variable so that umc ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register umc ras block into amdgpu device ras block link list. 5.Remove the redundant code about umc in amdgpu_ras.c after using the unified ras block. 6.Fill unified ras block .name .block .ras_late_init and .ras_fini for all of umc versions. If .ras_late_init and .ras_fini had been defined by the selected umc version, the defined functions will take effect; if not defined, default fill them with amdgpu_umc_ras_late_init and amdgpu_umc_ras_fini. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 10 ++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 30 +++++++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 32 ++++++++++++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 14 ++++------- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 16 ++++++++++++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 21 +++++++++++++--- drivers/gpu/drm/amd/amdgpu/umc_v6_1.c | 12 ++++++---- drivers/gpu/drm/amd/amdgpu/umc_v6_1.h | 2 +- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 10 +++++--- drivers/gpu/drm/amd/amdgpu/umc_v6_7.h | 2 +- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 12 ++++++---- drivers/gpu/drm/amd/amdgpu/umc_v8_7.h | 2 +- 12 files changed, 99 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index acf806c87673..de0ef21e1501 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -440,9 +440,8 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) { int r; - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->ras_late_init) { - r = adev->umc.ras_funcs->ras_late_init(adev); + if (adev->umc.ras && adev->umc.ras->ras_block.ras_late_init) { + r = adev->umc.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } @@ -496,9 +495,8 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) void amdgpu_gmc_ras_fini(struct amdgpu_device *adev) { - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->ras_fini) - adev->umc.ras_funcs->ras_fini(adev); + if (adev->umc.ras && adev->umc.ras->ras_block.ras_fini) + adev->umc.ras->ras_block.ras_fini(adev); if (adev->mmhub.ras && adev->mmhub.ras->ras_block.ras_fini) adev->mmhub.ras->ras_block.ras_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 6d1ca9e9795b..fba1c415a2a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -939,24 +939,24 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d */ ret = amdgpu_dpm_get_ecc_info(adev, (void *)&(ras->umc_ecc)); if (ret == -EOPNOTSUPP) { - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->query_ras_error_count) - adev->umc.ras_funcs->query_ras_error_count(adev, err_data); + if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops && + adev->umc.ras->ras_block.hw_ops->query_ras_error_count) + adev->umc.ras->ras_block.hw_ops->query_ras_error_count(adev, err_data); /* umc query_ras_error_address is also responsible for clearing * error status */ - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->query_ras_error_address) - adev->umc.ras_funcs->query_ras_error_address(adev, err_data); + if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops && + adev->umc.ras->ras_block.hw_ops->query_ras_error_address) + adev->umc.ras->ras_block.hw_ops->query_ras_error_address(adev, err_data); } else if (!ret) { - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->ecc_info_query_ras_error_count) - adev->umc.ras_funcs->ecc_info_query_ras_error_count(adev, err_data); + if (adev->umc.ras && + adev->umc.ras->ecc_info_query_ras_error_count) + adev->umc.ras->ecc_info_query_ras_error_count(adev, err_data); - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->ecc_info_query_ras_error_address) - adev->umc.ras_funcs->ecc_info_query_ras_error_address(adev, err_data); + if (adev->umc.ras && + adev->umc.ras->ecc_info_query_ras_error_address) + adev->umc.ras->ecc_info_query_ras_error_address(adev, err_data); } } @@ -2412,12 +2412,12 @@ int amdgpu_ras_init(struct amdgpu_device *adev) } else if (adev->df.funcs && adev->df.funcs->query_ras_poison_mode && - adev->umc.ras_funcs && - adev->umc.ras_funcs->query_ras_poison_mode) { + adev->umc.ras && + adev->umc.ras->query_ras_poison_mode) { df_poison = adev->df.funcs->query_ras_poison_mode(adev); umc_poison = - adev->umc.ras_funcs->query_ras_poison_mode(adev); + adev->umc.ras->query_ras_poison_mode(adev); /* Only poison is set in both DF and UMC, we can support it */ if (df_poison && umc_poison) con->poison_supported = true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index e81ce465ff3a..b4c68c09e071 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -35,12 +35,12 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); ret = amdgpu_dpm_get_ecc_info(adev, (void *)&(con->umc_ecc)); if (ret == -EOPNOTSUPP) { - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->query_ras_error_count) - adev->umc.ras_funcs->query_ras_error_count(adev, ras_error_status); + if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops && + adev->umc.ras->ras_block.hw_ops->query_ras_error_count) + adev->umc.ras->ras_block.hw_ops->query_ras_error_count(adev, ras_error_status); - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->query_ras_error_address && + if (adev->umc.ras && adev->umc.ras->ras_block.hw_ops && + adev->umc.ras->ras_block.hw_ops->query_ras_error_address && adev->umc.max_ras_err_cnt_per_query) { err_data->err_addr = kcalloc(adev->umc.max_ras_err_cnt_per_query, @@ -56,15 +56,15 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, /* umc query_ras_error_address is also responsible for clearing * error status */ - adev->umc.ras_funcs->query_ras_error_address(adev, ras_error_status); + adev->umc.ras->ras_block.hw_ops->query_ras_error_address(adev, ras_error_status); } } else if (!ret) { - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->ecc_info_query_ras_error_count) - adev->umc.ras_funcs->ecc_info_query_ras_error_count(adev, ras_error_status); + if (adev->umc.ras && + adev->umc.ras->ecc_info_query_ras_error_count) + adev->umc.ras->ecc_info_query_ras_error_count(adev, ras_error_status); - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->ecc_info_query_ras_error_address && + if (adev->umc.ras && + adev->umc.ras->ecc_info_query_ras_error_address && adev->umc.max_ras_err_cnt_per_query) { err_data->err_addr = kcalloc(adev->umc.max_ras_err_cnt_per_query, @@ -80,7 +80,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, /* umc query_ras_error_address is also responsible for clearing * error status */ - adev->umc.ras_funcs->ecc_info_query_ras_error_address(adev, ras_error_status); + adev->umc.ras->ecc_info_query_ras_error_address(adev, ras_error_status); } } @@ -136,7 +136,7 @@ static int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry, true); } -int amdgpu_umc_ras_late_init(struct amdgpu_device *adev) +int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, void *ras_info) { int r; struct ras_fs_if fs_info = { @@ -172,9 +172,9 @@ int amdgpu_umc_ras_late_init(struct amdgpu_device *adev) } /* ras init of specific umc version */ - if (adev->umc.ras_funcs && - adev->umc.ras_funcs->err_cnt_init) - adev->umc.ras_funcs->err_cnt_init(adev); + if (adev->umc.ras && + adev->umc.ras->err_cnt_init) + adev->umc.ras->err_cnt_init(adev); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index b72194e8bfe5..195740a6d97d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -20,6 +20,7 @@ */ #ifndef __AMDGPU_UMC_H__ #define __AMDGPU_UMC_H__ +#include "amdgpu_ras.h" /* * (addr / 256) * 4096, the higher 26 bits in ErrorAddr @@ -40,14 +41,9 @@ #define LOOP_UMC_CH_INST(ch_inst) for ((ch_inst) = 0; (ch_inst) < adev->umc.channel_inst_num; (ch_inst)++) #define LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) LOOP_UMC_INST((umc_inst)) LOOP_UMC_CH_INST((ch_inst)) -struct amdgpu_umc_ras_funcs { +struct amdgpu_umc_ras { + struct amdgpu_ras_block_object ras_block; void (*err_cnt_init)(struct amdgpu_device *adev); - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); - void (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - void (*query_ras_error_address)(struct amdgpu_device *adev, - void *ras_error_status); bool (*query_ras_poison_mode)(struct amdgpu_device *adev); void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status); @@ -73,10 +69,10 @@ struct amdgpu_umc { struct ras_common_if *ras_if; const struct amdgpu_umc_funcs *funcs; - const struct amdgpu_umc_ras_funcs *ras_funcs; + struct amdgpu_umc_ras *ras; }; -int amdgpu_umc_ras_late_init(struct amdgpu_device *adev); +int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, void *ras_info); void amdgpu_umc_ras_fini(struct amdgpu_device *adev); int amdgpu_umc_poison_handler(struct amdgpu_device *adev, void *ras_error_status, diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 38bb42727715..5ef4ad28ab26 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -664,11 +664,25 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev) adev->umc.umc_inst_num = UMC_V8_7_UMC_INSTANCE_NUM; adev->umc.channel_offs = UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA; adev->umc.channel_idx_tbl = &umc_v8_7_channel_idx_tbl[0][0]; - adev->umc.ras_funcs = &umc_v8_7_ras_funcs; + adev->umc.ras = &umc_v8_7_ras; break; default: break; } + if (adev->umc.ras) { + amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block); + + strcpy(adev->umc.ras->ras_block.name,"umc"); + adev->umc.ras->ras_block.block = AMDGPU_RAS_BLOCK__UMC; + + /* If don't define special ras_late_init function, use default ras_late_init */ + if (!adev->umc.ras->ras_block.ras_late_init) + adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init; + + /* If don't define special ras_fini function, use default ras_fini */ + if (!adev->umc.ras->ras_block.ras_fini) + adev->umc.ras->ras_block.ras_fini = amdgpu_umc_ras_fini; + } } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 7506e198e6e1..3965aae435f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1202,7 +1202,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM; adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_VG20; adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0]; - adev->umc.ras_funcs = &umc_v6_1_ras_funcs; + adev->umc.ras = &umc_v6_1_ras; break; case IP_VERSION(6, 1, 2): adev->umc.max_ras_err_cnt_per_query = UMC_V6_1_TOTAL_CHANNEL_NUM; @@ -1210,7 +1210,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) adev->umc.umc_inst_num = UMC_V6_1_UMC_INSTANCE_NUM; adev->umc.channel_offs = UMC_V6_1_PER_CHANNEL_OFFSET_ARCT; adev->umc.channel_idx_tbl = &umc_v6_1_channel_idx_tbl[0][0]; - adev->umc.ras_funcs = &umc_v6_1_ras_funcs; + adev->umc.ras = &umc_v6_1_ras; break; case IP_VERSION(6, 7, 0): adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM; @@ -1218,7 +1218,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM; adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET; if (!adev->gmc.xgmi.connected_to_cpu) - adev->umc.ras_funcs = &umc_v6_7_ras_funcs; + adev->umc.ras = &umc_v6_7_ras; if (1 & adev->smuio.funcs->get_die_id(adev)) adev->umc.channel_idx_tbl = &umc_v6_7_channel_idx_tbl_first[0][0]; else @@ -1227,6 +1227,21 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) default: break; } + + if (adev->umc.ras) { + amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block); + + strcpy(adev->umc.ras->ras_block.name,"umc"); + adev->umc.ras->ras_block.block = AMDGPU_RAS_BLOCK__UMC; + + /* If don't define special ras_late_init function, use default ras_late_init */ + if (!adev->umc.ras->ras_block.ras_late_init) + adev->umc.ras->ras_block.ras_late_init = amdgpu_umc_ras_late_init; + + /* If don't define special ras_fini function, use default ras_fini */ + if (!adev->umc.ras->ras_block.ras_fini) + adev->umc.ras->ras_block.ras_fini = amdgpu_umc_ras_fini; + } } static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c index 20b44983ac94..4776301972d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c @@ -465,10 +465,14 @@ static void umc_v6_1_err_cnt_init(struct amdgpu_device *adev) umc_v6_1_enable_umc_index_mode(adev); } -const struct amdgpu_umc_ras_funcs umc_v6_1_ras_funcs = { - .err_cnt_init = umc_v6_1_err_cnt_init, - .ras_late_init = amdgpu_umc_ras_late_init, - .ras_fini = amdgpu_umc_ras_fini, +const struct amdgpu_ras_block_hw_ops umc_v6_1_ras_hw_ops = { .query_ras_error_count = umc_v6_1_query_ras_error_count, .query_ras_error_address = umc_v6_1_query_ras_error_address, }; + +struct amdgpu_umc_ras umc_v6_1_ras = { + .ras_block = { + .hw_ops = &umc_v6_1_ras_hw_ops, + }, + .err_cnt_init = umc_v6_1_err_cnt_init, +}; \ No newline at end of file diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.h index 5dc36c730bb2..50c632eb4cc6 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.h @@ -45,7 +45,7 @@ /* umc ce count initial value */ #define UMC_V6_1_CE_CNT_INIT (UMC_V6_1_CE_CNT_MAX - UMC_V6_1_CE_INT_THRESHOLD) -extern const struct amdgpu_umc_ras_funcs umc_v6_1_ras_funcs; +extern struct amdgpu_umc_ras umc_v6_1_ras; extern const uint32_t umc_v6_1_channel_idx_tbl[UMC_V6_1_UMC_INSTANCE_NUM][UMC_V6_1_CHANNEL_INSTANCE_NUM]; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 6dd1e19e8d43..6953426f0bed 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -480,11 +480,15 @@ static bool umc_v6_7_query_ras_poison_mode(struct amdgpu_device *adev) return true; } -const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs = { - .ras_late_init = amdgpu_umc_ras_late_init, - .ras_fini = amdgpu_umc_ras_fini, +const struct amdgpu_ras_block_hw_ops umc_v6_7_ras_hw_ops = { .query_ras_error_count = umc_v6_7_query_ras_error_count, .query_ras_error_address = umc_v6_7_query_ras_error_address, +}; + +struct amdgpu_umc_ras umc_v6_7_ras = { + .ras_block = { + .hw_ops = &umc_v6_7_ras_hw_ops, + }, .query_ras_poison_mode = umc_v6_7_query_ras_poison_mode, .ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count, .ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address, diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h index 57f2557e7aca..1f2edf625370 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h @@ -43,7 +43,7 @@ #define UMC_V6_7_TOTAL_CHANNEL_NUM (UMC_V6_7_CHANNEL_INSTANCE_NUM * UMC_V6_7_UMC_INSTANCE_NUM) /* UMC regiser per channel offset */ #define UMC_V6_7_PER_CHANNEL_OFFSET 0x400 -extern const struct amdgpu_umc_ras_funcs umc_v6_7_ras_funcs; +extern struct amdgpu_umc_ras umc_v6_7_ras; extern const uint32_t umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; extern const uint32_t diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index af59a35788e3..ff9e1fac616d 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -324,10 +324,14 @@ static void umc_v8_7_err_cnt_init(struct amdgpu_device *adev) } } -const struct amdgpu_umc_ras_funcs umc_v8_7_ras_funcs = { - .err_cnt_init = umc_v8_7_err_cnt_init, - .ras_late_init = amdgpu_umc_ras_late_init, - .ras_fini = amdgpu_umc_ras_fini, +const struct amdgpu_ras_block_hw_ops umc_v8_7_ras_hw_ops = { .query_ras_error_count = umc_v8_7_query_ras_error_count, .query_ras_error_address = umc_v8_7_query_ras_error_address, }; + +struct amdgpu_umc_ras umc_v8_7_ras = { + .ras_block = { + .hw_ops = &umc_v8_7_ras_hw_ops, + }, + .err_cnt_init = umc_v8_7_err_cnt_init, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h index 37e6dc7c28e0..dd4993f5f78f 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.h @@ -44,7 +44,7 @@ /* umc ce count initial value */ #define UMC_V8_7_CE_CNT_INIT (UMC_V8_7_CE_CNT_MAX - UMC_V8_7_CE_INT_THRESHOLD) -extern const struct amdgpu_umc_ras_funcs umc_v8_7_ras_funcs; +extern struct amdgpu_umc_ras umc_v8_7_ras; extern const uint32_t umc_v8_7_channel_idx_tbl[UMC_V8_7_UMC_INSTANCE_NUM][UMC_V8_7_CHANNEL_INSTANCE_NUM]; From bdc4292bd3b4337985f716be789b08eef921f7a6 Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 5 Jan 2022 15:30:37 +0800 Subject: [PATCH 032/339] drm/amdgpu: Modify sdma block to fit for the unified ras block data and ops 1.Modify sdma block to fit for the unified ras block data and ops. 2.Change amdgpu_sdma_ras_funcs to amdgpu_sdma_ras, and the corresponding variable name remove _funcs suffix. 3.Remove the const flag of sdma ras variable so that sdma ras block can be able to be inserted into amdgpu device ras block link list. 4.Invoke amdgpu_ras_register_ras_block function to register sdma ras block into amdgpu device ras block link list. 5.Remove the redundant code about sdma in amdgpu_ras.c after using the unified ras block. 6.Fill unified ras block .name .block .ras_late_init and .ras_fini for all of sdma versions. If .ras_late_init and .ras_fini had been defined by the selected sdma version, the defined functions will take effect; if not defined, default fill them with amdgpu_sdma_ras_late_init and amdgpu_sdma_ras_fini. v2: squash in warning fix (Alex) Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 10 ---- drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h | 12 ++--- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 58 ++++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c | 25 ++++++++-- drivers/gpu/drm/amd/amdgpu/sdma_v4_4.h | 2 +- 5 files changed, 71 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index fba1c415a2a8..7c21eab95fc8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -967,7 +967,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct amdgpu_ras_block_object* block_obj = NULL; struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head); struct ras_err_data err_data = {0, 0, 0, NULL}; - int i; if (!obj) return -EINVAL; @@ -979,12 +978,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, amdgpu_ras_get_ecc_info(adev, &err_data); break; case AMDGPU_RAS_BLOCK__SDMA: - if (adev->sdma.funcs->query_ras_error_count) { - for (i = 0; i < adev->sdma.num_instances; i++) - adev->sdma.funcs->query_ras_error_count(adev, i, - &err_data); - } - break; case AMDGPU_RAS_BLOCK__GFX: case AMDGPU_RAS_BLOCK__MMHUB: if (!block_obj || !block_obj->hw_ops) { @@ -1090,9 +1083,6 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, block_obj->hw_ops->reset_ras_error_status(adev); break; case AMDGPU_RAS_BLOCK__SDMA: - if (adev->sdma.funcs->reset_ras_error_count) - adev->sdma.funcs->reset_ras_error_count(adev); - break; case AMDGPU_RAS_BLOCK__HDP: if (!block_obj || !block_obj->hw_ops) { dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h index f8fb755e3aa6..eaee12ab6518 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h @@ -23,6 +23,7 @@ #ifndef __AMDGPU_SDMA_H__ #define __AMDGPU_SDMA_H__ +#include "amdgpu_ras.h" /* max number of IP instances */ #define AMDGPU_MAX_SDMA_INSTANCES 8 @@ -50,13 +51,8 @@ struct amdgpu_sdma_instance { bool burst_nop; }; -struct amdgpu_sdma_ras_funcs { - int (*ras_late_init)(struct amdgpu_device *adev, - void *ras_ih_info); - void (*ras_fini)(struct amdgpu_device *adev); - int (*query_ras_error_count)(struct amdgpu_device *adev, - uint32_t instance, void *ras_error_status); - void (*reset_ras_error_count)(struct amdgpu_device *adev); +struct amdgpu_sdma_ras { + struct amdgpu_ras_block_object ras_block; }; struct amdgpu_sdma { @@ -73,7 +69,7 @@ struct amdgpu_sdma { uint32_t srbm_soft_reset; bool has_page_queue; struct ras_common_if *ras_if; - const struct amdgpu_sdma_ras_funcs *funcs; + struct amdgpu_sdma_ras *ras; }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index e8e4749e9c79..3c1483dc113e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -1892,13 +1892,13 @@ static int sdma_v4_0_late_init(void *handle) sdma_v4_0_setup_ulv(adev); if (!amdgpu_persistent_edc_harvesting_supported(adev)) { - if (adev->sdma.funcs && - adev->sdma.funcs->reset_ras_error_count) - adev->sdma.funcs->reset_ras_error_count(adev); + if (adev->sdma.ras && adev->sdma.ras->ras_block.hw_ops && + adev->sdma.ras->ras_block.hw_ops->reset_ras_error_count) + adev->sdma.ras->ras_block.hw_ops->reset_ras_error_count(adev); } - if (adev->sdma.funcs && adev->sdma.funcs->ras_late_init) - return adev->sdma.funcs->ras_late_init(adev, &ih_info); + if (adev->sdma.ras && adev->sdma.ras->ras_block.ras_late_init) + return adev->sdma.ras->ras_block.ras_late_init(adev, &ih_info); else return 0; } @@ -2001,8 +2001,9 @@ static int sdma_v4_0_sw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int i; - if (adev->sdma.funcs && adev->sdma.funcs->ras_fini) - adev->sdma.funcs->ras_fini(adev); + if (adev->sdma.ras && adev->sdma.ras->ras_block.hw_ops && + adev->sdma.ras->ras_block.ras_fini) + adev->sdma.ras->ras_block.ras_fini(adev); for (i = 0; i < adev->sdma.num_instances; i++) { amdgpu_ring_fini(&adev->sdma.instance[i].ring); @@ -2740,7 +2741,7 @@ static void sdma_v4_0_get_ras_error_count(uint32_t value, } } -static int sdma_v4_0_query_ras_error_count(struct amdgpu_device *adev, +static int sdma_v4_0_query_ras_error_count_by_instance(struct amdgpu_device *adev, uint32_t instance, void *ras_error_status) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; @@ -2762,6 +2763,18 @@ static int sdma_v4_0_query_ras_error_count(struct amdgpu_device *adev, return 0; }; +static void sdma_v4_0_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) +{ + int i = 0; + for (i = 0; i < adev->sdma.num_instances; i++) { + if (sdma_v4_0_query_ras_error_count_by_instance(adev, i, ras_error_status)) + { + dev_err(adev->dev, "Query ras error count failed in SDMA%d \n", i); + return; + } + } +} + static void sdma_v4_0_reset_ras_error_count(struct amdgpu_device *adev) { int i; @@ -2773,26 +2786,45 @@ static void sdma_v4_0_reset_ras_error_count(struct amdgpu_device *adev) } } -static const struct amdgpu_sdma_ras_funcs sdma_v4_0_ras_funcs = { - .ras_late_init = amdgpu_sdma_ras_late_init, - .ras_fini = amdgpu_sdma_ras_fini, +const struct amdgpu_ras_block_hw_ops sdma_v4_0_ras_hw_ops = { .query_ras_error_count = sdma_v4_0_query_ras_error_count, .reset_ras_error_count = sdma_v4_0_reset_ras_error_count, }; +static struct amdgpu_sdma_ras sdma_v4_0_ras = { + .ras_block = { + .hw_ops = &sdma_v4_0_ras_hw_ops, + }, +}; + static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev) { switch (adev->ip_versions[SDMA0_HWIP][0]) { case IP_VERSION(4, 2, 0): case IP_VERSION(4, 2, 2): - adev->sdma.funcs = &sdma_v4_0_ras_funcs; + adev->sdma.ras = &sdma_v4_0_ras; break; case IP_VERSION(4, 4, 0): - adev->sdma.funcs = &sdma_v4_4_ras_funcs; + adev->sdma.ras = &sdma_v4_4_ras; break; default: break; } + + if (adev->sdma.ras) { + amdgpu_ras_register_ras_block(adev, &adev->sdma.ras->ras_block); + + strcpy(adev->sdma.ras->ras_block.name,"sdma"); + adev->sdma.ras->ras_block.block = AMDGPU_RAS_BLOCK__SDMA; + + /* If don't define special ras_late_init function, use default ras_late_init */ + if (!adev->sdma.ras->ras_block.ras_late_init) + adev->sdma.ras->ras_block.ras_late_init = amdgpu_sdma_ras_late_init; + + /* If don't define special ras_fini function, use default ras_fini */ + if (!adev->sdma.ras->ras_block.ras_fini) + adev->sdma.ras->ras_block.ras_fini = amdgpu_sdma_ras_fini; + } } const struct amdgpu_ip_block_version sdma_v4_0_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c index bf95007f0843..5c1ba1116e5c 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c @@ -188,7 +188,7 @@ static void sdma_v4_4_get_ras_error_count(struct amdgpu_device *adev, } } -static int sdma_v4_4_query_ras_error_count(struct amdgpu_device *adev, +static int sdma_v4_4_query_ras_error_count_by_instance(struct amdgpu_device *adev, uint32_t instance, void *ras_error_status) { @@ -245,9 +245,26 @@ static void sdma_v4_4_reset_ras_error_count(struct amdgpu_device *adev) } } -const struct amdgpu_sdma_ras_funcs sdma_v4_4_ras_funcs = { - .ras_late_init = amdgpu_sdma_ras_late_init, - .ras_fini = amdgpu_sdma_ras_fini, +static void sdma_v4_4_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) +{ + int i = 0; + for (i = 0; i < adev->sdma.num_instances; i++) { + if (sdma_v4_4_query_ras_error_count_by_instance(adev, i, ras_error_status)) + { + dev_err(adev->dev, "Query ras error count failed in SDMA%d \n", i); + return; + } + } + +} + +const struct amdgpu_ras_block_hw_ops sdma_v4_4_ras_hw_ops = { .query_ras_error_count = sdma_v4_4_query_ras_error_count, .reset_ras_error_count = sdma_v4_4_reset_ras_error_count, }; + +struct amdgpu_sdma_ras sdma_v4_4_ras = { + .ras_block = { + .hw_ops = &sdma_v4_4_ras_hw_ops, + }, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.h b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.h index 74a6e5b5e949..a9f0c68359e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.h +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.h @@ -23,6 +23,6 @@ #ifndef __SDMA_V4_4_H__ #define __SDMA_V4_4_H__ -extern const struct amdgpu_sdma_ras_funcs sdma_v4_4_ras_funcs; +extern struct amdgpu_sdma_ras sdma_v4_4_ras; #endif From b0e2062dc8978869c1dd96d92027f74b361d5eb7 Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 5 Jan 2022 15:39:13 +0800 Subject: [PATCH 033/339] drm/amdgpu: Modify mca block to fit for the unified ras block data and ops 1.Modify mca block to fit for the unified ras block data and ops. 2.Define special .ras_block_match function for mca block to identify itself. 3.Change amdgpu_mca_ras_funcs to amdgpu_mca_ras_block(amdgpu_mca_ras had been used), and the corresponding variable name remove _funcs suffix. 4.Remove the const flag of cma ras variable so that cma ras block can be able to be inserted into amdgpu device ras block link list. 5.Invoke amdgpu_ras_register_ras_block function to register cma ras block into amdgpu device ras block link list. 6.Remove the redundant code about cma in amdgpu_ras.c after using the unified ras block. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 15 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c | 11 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h | 14 +--- drivers/gpu/drm/amd/amdgpu/mca_v3_0.c | 85 ++++++++++++++++++------- 4 files changed, 77 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index de0ef21e1501..a0a9abd23a7b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -469,23 +469,20 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) return r; } - if (adev->mca.mp0.ras_funcs && - adev->mca.mp0.ras_funcs->ras_late_init) { - r = adev->mca.mp0.ras_funcs->ras_late_init(adev); + if (adev->mca.mp0.ras && adev->mca.mp0.ras->ras_block.ras_late_init) { + r = adev->mca.mp0.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } - if (adev->mca.mp1.ras_funcs && - adev->mca.mp1.ras_funcs->ras_late_init) { - r = adev->mca.mp1.ras_funcs->ras_late_init(adev); + if (adev->mca.mp1.ras && adev->mca.mp1.ras->ras_block.ras_late_init) { + r = adev->mca.mp1.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } - if (adev->mca.mpio.ras_funcs && - adev->mca.mpio.ras_funcs->ras_late_init) { - r = adev->mca.mpio.ras_funcs->ras_late_init(adev); + if (adev->mca.mpio.ras && adev->mca.mpio.ras->ras_block.ras_late_init) { + r = adev->mca.mpio.ras->ras_block.ras_late_init(adev, NULL); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c index ce538f4819f9..52a60c2316a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c @@ -74,20 +74,23 @@ void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev, int amdgpu_mca_ras_late_init(struct amdgpu_device *adev, struct amdgpu_mca_ras *mca_dev) { + char sysfs_name[32] = {0}; int r; struct ras_ih_if ih_info = { .cb = NULL, }; - struct ras_fs_if fs_info = { - .sysfs_name = mca_dev->ras_funcs->sysfs_name, + struct ras_fs_if fs_info= { + .sysfs_name = sysfs_name, }; + snprintf(sysfs_name, sizeof(sysfs_name), "%s_err_count", mca_dev->ras->ras_block.name); + if (!mca_dev->ras_if) { mca_dev->ras_if = kmalloc(sizeof(struct ras_common_if), GFP_KERNEL); if (!mca_dev->ras_if) return -ENOMEM; - mca_dev->ras_if->block = mca_dev->ras_funcs->ras_block; - mca_dev->ras_if->sub_block_index = mca_dev->ras_funcs->ras_sub_block; + mca_dev->ras_if->block = mca_dev->ras->ras_block.block; + mca_dev->ras_if->sub_block_index = mca_dev->ras->ras_block.sub_block_index; mca_dev->ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; } ih_info.head = fs_info.head = *mca_dev->ras_if; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h index c74bc7177066..be030c4031d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h @@ -21,21 +21,13 @@ #ifndef __AMDGPU_MCA_H__ #define __AMDGPU_MCA_H__ -struct amdgpu_mca_ras_funcs { - int (*ras_late_init)(struct amdgpu_device *adev); - void (*ras_fini)(struct amdgpu_device *adev); - void (*query_ras_error_count)(struct amdgpu_device *adev, - void *ras_error_status); - void (*query_ras_error_address)(struct amdgpu_device *adev, - void *ras_error_status); - uint32_t ras_block; - uint32_t ras_sub_block; - const char* sysfs_name; +struct amdgpu_mca_ras_block { + struct amdgpu_ras_block_object ras_block; }; struct amdgpu_mca_ras { struct ras_common_if *ras_if; - const struct amdgpu_mca_ras_funcs *ras_funcs; + struct amdgpu_mca_ras_block *ras; }; struct amdgpu_mca_funcs { diff --git a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c index 8f7107d392af..f51092041edc 100644 --- a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c @@ -37,7 +37,7 @@ static void mca_v3_0_mp0_query_ras_error_count(struct amdgpu_device *adev, ras_error_status); } -static int mca_v3_0_mp0_ras_late_init(struct amdgpu_device *adev) +static int mca_v3_0_mp0_ras_late_init(struct amdgpu_device *adev, void *ras_info) { return amdgpu_mca_ras_late_init(adev, &adev->mca.mp0); } @@ -47,14 +47,34 @@ static void mca_v3_0_mp0_ras_fini(struct amdgpu_device *adev) amdgpu_mca_ras_fini(adev, &adev->mca.mp0); } -const struct amdgpu_mca_ras_funcs mca_v3_0_mp0_ras_funcs = { - .ras_late_init = mca_v3_0_mp0_ras_late_init, - .ras_fini = mca_v3_0_mp0_ras_fini, +static int mca_v3_0_ras_block_match(struct amdgpu_ras_block_object* block_obj, enum amdgpu_ras_block block, uint32_t sub_block_index) +{ + if(!block_obj) + return -EINVAL; + + if( (block_obj->block == block) && + (block_obj->sub_block_index == sub_block_index)) { + return 0; + } + + return -EINVAL; +} + +const struct amdgpu_ras_block_hw_ops mca_v3_0_mp0_hw_ops = { .query_ras_error_count = mca_v3_0_mp0_query_ras_error_count, .query_ras_error_address = NULL, - .ras_block = AMDGPU_RAS_BLOCK__MCA, - .ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MP0, - .sysfs_name = "mp0_err_count", +}; + +struct amdgpu_mca_ras_block mca_v3_0_mp0_ras = { + .ras_block = { + .block = AMDGPU_RAS_BLOCK__MCA, + .sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP0, + .name = "mp0", + .hw_ops = &mca_v3_0_mp0_hw_ops, + .ras_block_match = mca_v3_0_ras_block_match, + .ras_late_init = mca_v3_0_mp0_ras_late_init, + .ras_fini = mca_v3_0_mp0_ras_fini, + }, }; static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev, @@ -65,7 +85,7 @@ static void mca_v3_0_mp1_query_ras_error_count(struct amdgpu_device *adev, ras_error_status); } -static int mca_v3_0_mp1_ras_late_init(struct amdgpu_device *adev) +static int mca_v3_0_mp1_ras_late_init(struct amdgpu_device *adev, void *ras_info) { return amdgpu_mca_ras_late_init(adev, &adev->mca.mp1); } @@ -75,14 +95,21 @@ static void mca_v3_0_mp1_ras_fini(struct amdgpu_device *adev) amdgpu_mca_ras_fini(adev, &adev->mca.mp1); } -const struct amdgpu_mca_ras_funcs mca_v3_0_mp1_ras_funcs = { - .ras_late_init = mca_v3_0_mp1_ras_late_init, - .ras_fini = mca_v3_0_mp1_ras_fini, +const struct amdgpu_ras_block_hw_ops mca_v3_0_mp1_hw_ops = { .query_ras_error_count = mca_v3_0_mp1_query_ras_error_count, .query_ras_error_address = NULL, - .ras_block = AMDGPU_RAS_BLOCK__MCA, - .ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MP1, - .sysfs_name = "mp1_err_count", +}; + +struct amdgpu_mca_ras_block mca_v3_0_mp1_ras = { + .ras_block = { + .block = AMDGPU_RAS_BLOCK__MCA, + .sub_block_index = AMDGPU_RAS_MCA_BLOCK__MP1, + .name = "mp1", + .hw_ops = &mca_v3_0_mp1_hw_ops, + .ras_block_match = mca_v3_0_ras_block_match, + .ras_late_init = mca_v3_0_mp1_ras_late_init, + .ras_fini = mca_v3_0_mp1_ras_fini, + }, }; static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev, @@ -93,7 +120,7 @@ static void mca_v3_0_mpio_query_ras_error_count(struct amdgpu_device *adev, ras_error_status); } -static int mca_v3_0_mpio_ras_late_init(struct amdgpu_device *adev) +static int mca_v3_0_mpio_ras_late_init(struct amdgpu_device *adev, void *ras_info) { return amdgpu_mca_ras_late_init(adev, &adev->mca.mpio); } @@ -103,14 +130,21 @@ static void mca_v3_0_mpio_ras_fini(struct amdgpu_device *adev) amdgpu_mca_ras_fini(adev, &adev->mca.mpio); } -const struct amdgpu_mca_ras_funcs mca_v3_0_mpio_ras_funcs = { - .ras_late_init = mca_v3_0_mpio_ras_late_init, - .ras_fini = mca_v3_0_mpio_ras_fini, +const struct amdgpu_ras_block_hw_ops mca_v3_0_mpio_hw_ops = { .query_ras_error_count = mca_v3_0_mpio_query_ras_error_count, .query_ras_error_address = NULL, - .ras_block = AMDGPU_RAS_BLOCK__MCA, - .ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MPIO, - .sysfs_name = "mpio_err_count", +}; + +struct amdgpu_mca_ras_block mca_v3_0_mpio_ras = { + .ras_block = { + .block = AMDGPU_RAS_BLOCK__MCA, + .sub_block_index = AMDGPU_RAS_MCA_BLOCK__MPIO, + .name = "mpio", + .hw_ops = &mca_v3_0_mpio_hw_ops, + .ras_block_match = mca_v3_0_ras_block_match, + .ras_late_init = mca_v3_0_mpio_ras_late_init, + .ras_fini = mca_v3_0_mpio_ras_fini, + }, }; @@ -118,9 +152,12 @@ static void mca_v3_0_init(struct amdgpu_device *adev) { struct amdgpu_mca *mca = &adev->mca; - mca->mp0.ras_funcs = &mca_v3_0_mp0_ras_funcs; - mca->mp1.ras_funcs = &mca_v3_0_mp1_ras_funcs; - mca->mpio.ras_funcs = &mca_v3_0_mpio_ras_funcs; + mca->mp0.ras = &mca_v3_0_mp0_ras; + mca->mp1.ras = &mca_v3_0_mp1_ras; + mca->mpio.ras = &mca_v3_0_mpio_ras; + amdgpu_ras_register_ras_block(adev, &mca->mp0.ras->ras_block); + amdgpu_ras_register_ras_block(adev, &mca->mp1.ras->ras_block); + amdgpu_ras_register_ras_block(adev, &mca->mpio.ras->ras_block); } const struct amdgpu_mca_funcs mca_v3_0_funcs = { From 22d4ba53b1c10de6832e588f01d916e24306f6a1 Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 5 Jan 2022 15:40:26 +0800 Subject: [PATCH 034/339] drm/amdgpu: Adjust error inject function code style in amdgpu_ras.c 1. Move xgmi special error inject function from amdgpu_ras.c to xgmi block. 2. Support to use psp_ras_trigger_error as default error inject function in amdgpu_ras.c. If .ras_error_inject isn't defined in ras block, default error inject function will take effect. v2: squash in warning fix (Alex) Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 89 ++++-------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 27 +++++++ 2 files changed, 40 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 7c21eab95fc8..bcd33e5350f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -903,31 +903,6 @@ static struct amdgpu_ras_block_object* amdgpu_ras_get_ras_block(struct amdgpu_de return NULL; } -static void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev, - struct ras_common_if *ras_block, - struct ras_err_data *err_data) -{ - switch (ras_block->sub_block_index) { - case AMDGPU_RAS_MCA_BLOCK__MP0: - if (adev->mca.mp0.ras_funcs && - adev->mca.mp0.ras_funcs->query_ras_error_count) - adev->mca.mp0.ras_funcs->query_ras_error_count(adev, &err_data); - break; - case AMDGPU_RAS_MCA_BLOCK__MP1: - if (adev->mca.mp1.ras_funcs && - adev->mca.mp1.ras_funcs->query_ras_error_count) - adev->mca.mp1.ras_funcs->query_ras_error_count(adev, &err_data); - break; - case AMDGPU_RAS_MCA_BLOCK__MPIO: - if (adev->mca.mpio.ras_funcs && - adev->mca.mpio.ras_funcs->query_ras_error_count) - adev->mca.mpio.ras_funcs->query_ras_error_count(adev, &err_data); - break; - default: - break; - } -} - static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_data *err_data) { struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); @@ -994,6 +969,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, case AMDGPU_RAS_BLOCK__PCIE_BIF: case AMDGPU_RAS_BLOCK__XGMI_WAFL: case AMDGPU_RAS_BLOCK__HDP: + case AMDGPU_RAS_BLOCK__MCA: if (!block_obj || !block_obj->hw_ops) { dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); @@ -1002,9 +978,6 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, if (block_obj->hw_ops->query_ras_error_count) block_obj->hw_ops->query_ras_error_count(adev, &err_data); break; - case AMDGPU_RAS_BLOCK__MCA: - amdgpu_ras_mca_query_error_status(adev, &info->head, &err_data); - break; default: break; } @@ -1099,32 +1072,6 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, return 0; } -/* Trigger XGMI/WAFL error */ -static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, - struct ta_ras_trigger_error_input *block_info) -{ - int ret; - - if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW)) - dev_warn(adev->dev, "Failed to disallow df cstate"); - - if (amdgpu_dpm_allow_xgmi_power_down(adev, false)) - dev_warn(adev->dev, "Failed to disallow XGMI power down"); - - ret = psp_ras_trigger_error(&adev->psp, block_info); - - if (amdgpu_ras_intr_triggered()) - return ret; - - if (amdgpu_dpm_allow_xgmi_power_down(adev, true)) - dev_warn(adev->dev, "Failed to allow XGMI power down"); - - if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW)) - dev_warn(adev->dev, "Failed to allow df cstate"); - - return ret; -} - /* wrapper of psp_ras_trigger_error */ int amdgpu_ras_error_inject(struct amdgpu_device *adev, struct ras_inject_if *info) @@ -1143,6 +1090,11 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, if (!obj) return -EINVAL; + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); + return -EINVAL; + } + /* Calculate XGMI relative offset */ if (adev->gmc.xgmi.num_physical_nodes > 1) { block_info.address = @@ -1150,30 +1102,15 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, block_info.address); } - switch (info->head.block) { - case AMDGPU_RAS_BLOCK__GFX: - if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); - return -EINVAL; - } - + if (info->head.block == AMDGPU_RAS_BLOCK__GFX) { if (block_obj->hw_ops->ras_error_inject) ret = block_obj->hw_ops->ras_error_inject(adev, info); - break; - case AMDGPU_RAS_BLOCK__UMC: - case AMDGPU_RAS_BLOCK__SDMA: - case AMDGPU_RAS_BLOCK__MMHUB: - case AMDGPU_RAS_BLOCK__PCIE_BIF: - case AMDGPU_RAS_BLOCK__MCA: - ret = psp_ras_trigger_error(&adev->psp, &block_info); - break; - case AMDGPU_RAS_BLOCK__XGMI_WAFL: - ret = amdgpu_ras_error_inject_xgmi(adev, &block_info); - break; - default: - dev_info(adev->dev, "%s error injection is not supported yet\n", - get_ras_block_str(&info->head)); - ret = -EINVAL; + } else { + /* If defined special ras_error_inject(e.g: xgmi), implement special ras_error_inject */ + if (block_obj->hw_ops->ras_error_inject) + ret = block_obj->hw_ops->ras_error_inject(adev, &block_info); + else /*If not defined .ras_error_inject, use default ras_error_inject*/ + ret = psp_ras_trigger_error(&adev->psp, &block_info); } if (ret) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index d29acd33eb11..478457637d29 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -946,9 +946,36 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, err_data->ce_count += ce_cnt; } +/* Trigger XGMI/WAFL error */ +static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, void *inject_if) +{ + int ret = 0; + struct ta_ras_trigger_error_input *block_info = (struct ta_ras_trigger_error_input *)inject_if; + + if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW)) + dev_warn(adev->dev, "Failed to disallow df cstate"); + + if (amdgpu_dpm_allow_xgmi_power_down(adev, false)) + dev_warn(adev->dev, "Failed to disallow XGMI power down"); + + ret = psp_ras_trigger_error(&adev->psp, block_info); + + if (amdgpu_ras_intr_triggered()) + return ret; + + if (amdgpu_dpm_allow_xgmi_power_down(adev, true)) + dev_warn(adev->dev, "Failed to allow XGMI power down"); + + if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_ALLOW)) + dev_warn(adev->dev, "Failed to allow df cstate"); + + return ret; +} + struct amdgpu_ras_block_hw_ops xgmi_ras_hw_ops = { .query_ras_error_count = amdgpu_xgmi_query_ras_error_count, .reset_ras_error_count = amdgpu_xgmi_reset_ras_error_count, + .ras_error_inject = amdgpu_ras_error_inject_xgmi, }; struct amdgpu_xgmi_ras xgmi_ras = { From 7389a5b837cde5e5cd771619e9f006ae102f5d7d Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 5 Jan 2022 15:48:21 +0800 Subject: [PATCH 035/339] drm/amdgpu: Removed redundant ras code Removed redundant ras code. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: John Clements Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 67 +++++++------------------ 1 file changed, 19 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index bcd33e5350f8..517650d286a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -946,40 +946,25 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, if (!obj) return -EINVAL; - block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0); - - switch (info->head.block) { - case AMDGPU_RAS_BLOCK__UMC: + if (info->head.block == AMDGPU_RAS_BLOCK__UMC) { amdgpu_ras_get_ecc_info(adev, &err_data); - break; - case AMDGPU_RAS_BLOCK__SDMA: - case AMDGPU_RAS_BLOCK__GFX: - case AMDGPU_RAS_BLOCK__MMHUB: + } else { + block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0); if (!block_obj || !block_obj->hw_ops) { dev_info(adev->dev, "%s doesn't config ras function \n", - get_ras_block_str(&info->head)); + get_ras_block_str(&info->head)); return -EINVAL; } + if (block_obj->hw_ops->query_ras_error_count) block_obj->hw_ops->query_ras_error_count(adev, &err_data); - if (block_obj->hw_ops->query_ras_error_status) - block_obj->hw_ops->query_ras_error_status(adev); - break; - case AMDGPU_RAS_BLOCK__PCIE_BIF: - case AMDGPU_RAS_BLOCK__XGMI_WAFL: - case AMDGPU_RAS_BLOCK__HDP: - case AMDGPU_RAS_BLOCK__MCA: - if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", - get_ras_block_str(&info->head)); - return -EINVAL; - } - if (block_obj->hw_ops->query_ras_error_count) - block_obj->hw_ops->query_ras_error_count(adev, &err_data); - break; - default: - break; + if ((info->head.block == AMDGPU_RAS_BLOCK__SDMA) || + (info->head.block == AMDGPU_RAS_BLOCK__GFX) || + (info->head.block == AMDGPU_RAS_BLOCK__MMHUB)) { + if (block_obj->hw_ops->query_ras_error_status) + block_obj->hw_ops->query_ras_error_status(adev); + } } obj->err_data.ue_count += err_data.ue_count; @@ -1041,32 +1026,18 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, if (!amdgpu_ras_is_supported(adev, block)) return -EINVAL; - switch (block) { - case AMDGPU_RAS_BLOCK__GFX: - case AMDGPU_RAS_BLOCK__MMHUB: - if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); - return -EINVAL; - } + if (!block_obj || !block_obj->hw_ops) { + dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); + return -EINVAL; + } - if (block_obj->hw_ops->reset_ras_error_count) - block_obj->hw_ops->reset_ras_error_count(adev); + if (block_obj->hw_ops->reset_ras_error_count) + block_obj->hw_ops->reset_ras_error_count(adev); + if ((block == AMDGPU_RAS_BLOCK__GFX) || + (block == AMDGPU_RAS_BLOCK__MMHUB)) { if (block_obj->hw_ops->reset_ras_error_status) block_obj->hw_ops->reset_ras_error_status(adev); - break; - case AMDGPU_RAS_BLOCK__SDMA: - case AMDGPU_RAS_BLOCK__HDP: - if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); - return -EINVAL; - } - - if (block_obj->hw_ops->reset_ras_error_count) - block_obj->hw_ops->reset_ras_error_count(adev); - break; - default: - break; } return 0; From cb5cc4f573e18deb7d9143de0ccb62c08181bc85 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Thu, 9 Dec 2021 16:48:56 -0500 Subject: [PATCH 036/339] drm/amdgpu: improve debug VRAM access performance using sdma For better performance during VRAM access for debugged processes, do read/write copies over SDMA. In order to fulfill post mortem debugging on a broken device, fallback to stable MMIO access when gpu recovery is disabled or when job submission time outs are set to max. Failed SDMA access should automatically fall back to MMIO access. Use a pre-allocated GTT bounce buffer pre-mapped into GART to avoid page-table updates and TLB flushes on access. Signed-off-by: Jonathan Kim Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 78 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 4 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 5c3f24069f2a..953d68b26f0b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -50,6 +50,7 @@ #include #include +#include #include "amdgpu.h" #include "amdgpu_object.h" @@ -1433,6 +1434,70 @@ static void amdgpu_ttm_vram_mm_access(struct amdgpu_device *adev, loff_t pos, } } +static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, + unsigned long offset, void *buf, int len, int write) +{ + struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); + struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); + struct amdgpu_job *job; + struct dma_fence *fence; + uint64_t src_addr, dst_addr; + unsigned int num_dw; + int r, idx; + + if (len != PAGE_SIZE) + return -EINVAL; + + if (!adev->mman.sdma_access_ptr) + return -EACCES; + + r = drm_dev_enter(adev_to_drm(adev), &idx); + if (r) + return r; + + if (write) + memcpy(adev->mman.sdma_access_ptr, buf, len); + + num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); + r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, AMDGPU_IB_POOL_DELAYED, &job); + if (r) + goto out; + + src_addr = write ? amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo) : + amdgpu_bo_gpu_offset(abo); + dst_addr = write ? amdgpu_bo_gpu_offset(abo) : + amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo); + amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, PAGE_SIZE, false); + + amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]); + WARN_ON(job->ibs[0].length_dw > num_dw); + + r = amdgpu_job_submit(job, &adev->mman.entity, AMDGPU_FENCE_OWNER_UNDEFINED, &fence); + if (r) { + amdgpu_job_free(job); + goto out; + } + + if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout)) + r = -ETIMEDOUT; + dma_fence_put(fence); + + if (!(r || write)) + memcpy(buf, adev->mman.sdma_access_ptr, len); +out: + drm_dev_exit(idx); + return r; +} + +static inline bool amdgpu_ttm_allow_post_mortem_debug(struct amdgpu_device *adev) +{ + return amdgpu_gpu_recovery == 0 || + adev->gfx_timeout == MAX_SCHEDULE_TIMEOUT || + adev->compute_timeout == MAX_SCHEDULE_TIMEOUT || + adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || + adev->video_timeout == MAX_SCHEDULE_TIMEOUT; +} + /** * amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object. * @@ -1457,6 +1522,10 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, if (bo->resource->mem_type != TTM_PL_VRAM) return -EIO; + if (!amdgpu_ttm_allow_post_mortem_debug(adev) && + !amdgpu_ttm_access_memory_sdma(bo, offset, buf, len, write)) + return len; + amdgpu_res_first(bo->resource, offset, len, &cursor); while (cursor.remaining) { size_t count, size = cursor.size; @@ -1797,6 +1866,12 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) return r; } + if (amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_GTT, + &adev->mman.sdma_access_bo, NULL, + adev->mman.sdma_access_ptr)) + DRM_WARN("Debug VRAM access will use slowpath MM access\n"); + return 0; } @@ -1837,6 +1912,9 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_OA); ttm_device_fini(&adev->mman.bdev); adev->mman.initialized = false; + if (adev->mman.sdma_access_ptr) + amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL, + &adev->mman.sdma_access_ptr); DRM_INFO("amdgpu: ttm finalized\n"); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index f8f48be16d80..f06fd19b4895 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -98,6 +98,10 @@ struct amdgpu_mman { u64 fw_vram_usage_size; struct amdgpu_bo *fw_vram_usage_reserved_bo; void *fw_vram_usage_va; + + /* PAGE_SIZE'd BO for process memory r/w over SDMA. */ + struct amdgpu_bo *sdma_access_bo; + void *sdma_access_ptr; }; struct amdgpu_copy_mem { From 400ef298f400854544e062023671e927965bc9b0 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Wed, 12 Jan 2022 10:27:56 -0500 Subject: [PATCH 037/339] drm/amdgpu: cleanup ttm debug sdma vram access function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some suggested cleanups to declutter ttm when doing debug VRAM access over SDMA. Signed-off-by: Jonathan Kim Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 23 +++++++---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 445a0d077c1f..8ddddf12e1ef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1446,6 +1446,15 @@ int amdgpu_device_set_cg_state(struct amdgpu_device *adev, int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_powergating_state state); +static inline bool amdgpu_device_has_timeouts_enabled(struct amdgpu_device *adev) +{ + return amdgpu_gpu_recovery != 0 && + adev->gfx_timeout != MAX_SCHEDULE_TIMEOUT && + adev->compute_timeout != MAX_SCHEDULE_TIMEOUT && + adev->sdma_timeout != MAX_SCHEDULE_TIMEOUT && + adev->video_timeout != MAX_SCHEDULE_TIMEOUT; +} + #include "amdgpu_object.h" static inline bool amdgpu_is_tmz(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 953d68b26f0b..1e012b45f663 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1463,10 +1463,11 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, if (r) goto out; - src_addr = write ? amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo) : - amdgpu_bo_gpu_offset(abo); - dst_addr = write ? amdgpu_bo_gpu_offset(abo) : - amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo); + src_addr = amdgpu_bo_gpu_offset(abo); + dst_addr = amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo); + if (write) + swap(src_addr, dst_addr); + amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, PAGE_SIZE, false); amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]); @@ -1489,15 +1490,6 @@ out: return r; } -static inline bool amdgpu_ttm_allow_post_mortem_debug(struct amdgpu_device *adev) -{ - return amdgpu_gpu_recovery == 0 || - adev->gfx_timeout == MAX_SCHEDULE_TIMEOUT || - adev->compute_timeout == MAX_SCHEDULE_TIMEOUT || - adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || - adev->video_timeout == MAX_SCHEDULE_TIMEOUT; -} - /** * amdgpu_ttm_access_memory - Read or Write memory that backs a buffer object. * @@ -1522,7 +1514,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, if (bo->resource->mem_type != TTM_PL_VRAM) return -EIO; - if (!amdgpu_ttm_allow_post_mortem_debug(adev) && + if (amdgpu_device_has_timeouts_enabled(adev) && !amdgpu_ttm_access_memory_sdma(bo, offset, buf, len, write)) return len; @@ -1912,8 +1904,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_OA); ttm_device_fini(&adev->mman.bdev); adev->mman.initialized = false; - if (adev->mman.sdma_access_ptr) - amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL, + amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL, &adev->mman.sdma_access_ptr); DRM_INFO("amdgpu: ttm finalized\n"); } From 20c5e425d36a59529f2e6a77ba21d009cdfa8ffa Mon Sep 17 00:00:00 2001 From: Graham Sider Date: Tue, 11 Jan 2022 15:07:10 -0500 Subject: [PATCH 038/339] drm/amdkfd: Fix indentation on switch statement Cases should be same indentation as switch. Also fix string spanning across multiple lines. Signed-off-by: Graham Sider Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 55 ++++++++++++------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 2b65d0acae2c..5a47f437b455 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -64,34 +64,33 @@ static void kfd_device_info_set_sdma_queue_num(struct kfd_dev *kfd) uint32_t sdma_version = kfd->adev->ip_versions[SDMA0_HWIP][0]; switch (sdma_version) { - case IP_VERSION(4, 0, 0):/* VEGA10 */ - case IP_VERSION(4, 0, 1):/* VEGA12 */ - case IP_VERSION(4, 1, 0):/* RAVEN */ - case IP_VERSION(4, 1, 1):/* RAVEN */ - case IP_VERSION(4, 1, 2):/* RENOIR */ - case IP_VERSION(5, 2, 1):/* VANGOGH */ - case IP_VERSION(5, 2, 3):/* YELLOW_CARP */ - kfd->device_info.num_sdma_queues_per_engine = 2; - break; - case IP_VERSION(4, 2, 0):/* VEGA20 */ - case IP_VERSION(4, 2, 2):/* ARCTURUS */ - case IP_VERSION(4, 4, 0):/* ALDEBARAN */ - case IP_VERSION(5, 0, 0):/* NAVI10 */ - case IP_VERSION(5, 0, 1):/* CYAN_SKILLFISH */ - case IP_VERSION(5, 0, 2):/* NAVI14 */ - case IP_VERSION(5, 0, 5):/* NAVI12 */ - case IP_VERSION(5, 2, 0):/* SIENNA_CICHLID */ - case IP_VERSION(5, 2, 2):/* NAVY_FLOUNDER */ - case IP_VERSION(5, 2, 4):/* DIMGREY_CAVEFISH */ - case IP_VERSION(5, 2, 5):/* BEIGE_GOBY */ - kfd->device_info.num_sdma_queues_per_engine = 8; - break; - default: - dev_warn(kfd_device, - "Default sdma queue per engine(8) is set due to " - "mismatch of sdma ip block(SDMA_HWIP:0x%x).\n", - sdma_version); - kfd->device_info.num_sdma_queues_per_engine = 8; + case IP_VERSION(4, 0, 0):/* VEGA10 */ + case IP_VERSION(4, 0, 1):/* VEGA12 */ + case IP_VERSION(4, 1, 0):/* RAVEN */ + case IP_VERSION(4, 1, 1):/* RAVEN */ + case IP_VERSION(4, 1, 2):/* RENOIR */ + case IP_VERSION(5, 2, 1):/* VANGOGH */ + case IP_VERSION(5, 2, 3):/* YELLOW_CARP */ + kfd->device_info.num_sdma_queues_per_engine = 2; + break; + case IP_VERSION(4, 2, 0):/* VEGA20 */ + case IP_VERSION(4, 2, 2):/* ARCTURUS */ + case IP_VERSION(4, 4, 0):/* ALDEBARAN */ + case IP_VERSION(5, 0, 0):/* NAVI10 */ + case IP_VERSION(5, 0, 1):/* CYAN_SKILLFISH */ + case IP_VERSION(5, 0, 2):/* NAVI14 */ + case IP_VERSION(5, 0, 5):/* NAVI12 */ + case IP_VERSION(5, 2, 0):/* SIENNA_CICHLID */ + case IP_VERSION(5, 2, 2):/* NAVY_FLOUNDER */ + case IP_VERSION(5, 2, 4):/* DIMGREY_CAVEFISH */ + case IP_VERSION(5, 2, 5):/* BEIGE_GOBY */ + kfd->device_info.num_sdma_queues_per_engine = 8; + break; + default: + dev_warn(kfd_device, + "Default sdma queue per engine(8) is set due to mismatch of sdma ip block(SDMA_HWIP:0x%x).\n", + sdma_version); + kfd->device_info.num_sdma_queues_per_engine = 8; } } From c4381d0ee81930097e94e55d1c23f85798ffd093 Mon Sep 17 00:00:00 2001 From: Bokun Zhang Date: Wed, 12 Jan 2022 10:34:11 -0500 Subject: [PATCH 039/339] drm/amdgpu: Add interface to load SRIOV cap FW - Add interface to load SRIOV cap FW. If the FW does not exist, simply skip this FW loading routine. This FW will only be loaded under SRIOV. Other driver configuration will not be affected. By adding this interface, it will make us easier to prepare SRIOV Linux guest driver for different users. - Update sysfs interface to read cap FW version. - Refactor PSP FW loading routine under SRIOV to use a unified SWITCH statement instead of using IF statement - Remove redundant amdgpu_sriov_vf() check in FW loading routine Acked-by: Monk Liu Acked-by: Guchun Chen Signed-off-by: Bokun Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 14 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 108 +++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 9 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 + drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h | 1 + drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/psp_v3_1.c | 1 + include/uapi/drm/amdgpu_drm.h | 2 + 8 files changed, 125 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 289521aafb79..85f06396d184 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -400,6 +400,10 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->ver = adev->psp.toc.fw_version; fw_info->feature = adev->psp.toc.feature_version; break; + case AMDGPU_INFO_FW_CAP: + fw_info->ver = adev->psp.cap_fw_version; + fw_info->feature = adev->psp.cap_feature_version; + break; default: return -EINVAL; } @@ -1617,6 +1621,16 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused) seq_printf(m, "TOC feature version: %u, firmware version: 0x%08x\n", fw_info.feature, fw_info.ver); + /* CAP */ + if (adev->psp.cap_fw) { + query_fw.fw_type = AMDGPU_INFO_FW_CAP; + ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); + if (ret) + return ret; + seq_printf(m, "CAP feature version: %u, firmware version: 0x%08x\n", + fw_info.feature, fw_info.ver); + } + seq_printf(m, "VBIOS version: %s\n", ctx->vbios_version); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index dee17a0e1187..c984b5a34679 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -259,6 +259,32 @@ static bool psp_get_runtime_db_entry(struct amdgpu_device *adev, return ret; } +static int psp_init_sriov_microcode(struct psp_context *psp) +{ + struct amdgpu_device *adev = psp->adev; + int ret = 0; + + switch (adev->ip_versions[MP0_HWIP][0]) { + case IP_VERSION(9, 0, 0): + ret = psp_init_cap_microcode(psp, "vega10"); + break; + case IP_VERSION(11, 0, 9): + ret = psp_init_cap_microcode(psp, "navi12"); + break; + case IP_VERSION(11, 0, 7): + ret = psp_init_cap_microcode(psp, "sienna_cichlid"); + break; + case IP_VERSION(13, 0, 2): + ret = psp_init_ta_microcode(psp, "aldebaran"); + break; + default: + BUG(); + break; + } + + return ret; +} + static int psp_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -273,19 +299,13 @@ static int psp_sw_init(void *handle) ret = -ENOMEM; } - if (!amdgpu_sriov_vf(adev)) { + if (amdgpu_sriov_vf(adev)) + ret = psp_init_sriov_microcode(psp); + else ret = psp_init_microcode(psp); - if (ret) { - DRM_ERROR("Failed to load psp firmware!\n"); - return ret; - } - } else if (amdgpu_sriov_vf(adev) && - adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2)) { - ret = psp_init_ta_microcode(psp, "aldebaran"); - if (ret) { - DRM_ERROR("Failed to initialize ta microcode!\n"); - return ret; - } + if (ret) { + DRM_ERROR("Failed to load psp firmware!\n"); + return ret; } memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry)); @@ -353,6 +373,10 @@ static int psp_sw_fini(void *handle) release_firmware(psp->ta_fw); psp->ta_fw = NULL; } + if (adev->psp.cap_fw) { + release_firmware(psp->cap_fw); + psp->cap_fw = NULL; + } if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) || adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7)) @@ -491,7 +515,10 @@ psp_cmd_submit_buf(struct psp_context *psp, DRM_WARN("psp gfx command %s(0x%X) failed and response status is (0x%X)\n", psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id, psp->cmd_buf_mem->resp.status); - if (!timeout) { + /* If we load CAP FW, PSP must return 0 under SRIOV + * also return failure in case of timeout + */ + if ((ucode && (ucode->ucode_id == AMDGPU_UCODE_ID_CAP)) || !timeout) { ret = -EINVAL; goto exit; } @@ -2051,6 +2078,9 @@ static int psp_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) { switch (ucode->ucode_id) { + case AMDGPU_UCODE_ID_CAP: + *type = GFX_FW_TYPE_CAP; + break; case AMDGPU_UCODE_ID_SDMA0: *type = GFX_FW_TYPE_SDMA0; break; @@ -3217,6 +3247,58 @@ out: return err; } +int psp_init_cap_microcode(struct psp_context *psp, + const char *chip_name) +{ + struct amdgpu_device *adev = psp->adev; + char fw_name[PSP_FW_NAME_LEN]; + const struct psp_firmware_header_v1_0 *cap_hdr_v1_0; + struct amdgpu_firmware_info *info = NULL; + int err = 0; + + if (!chip_name) { + dev_err(adev->dev, "invalid chip name for cap microcode\n"); + return -EINVAL; + } + + if (!amdgpu_sriov_vf(adev)) { + dev_err(adev->dev, "cap microcode should only be loaded under SRIOV\n"); + return -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name); + err = request_firmware(&adev->psp.cap_fw, fw_name, adev->dev); + if (err) { + dev_warn(adev->dev, "cap microcode does not exist, skip\n"); + err = 0; + goto out; + } + + err = amdgpu_ucode_validate(adev->psp.cap_fw); + if (err) { + dev_err(adev->dev, "fail to initialize cap microcode\n"); + goto out; + } + + info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP]; + info->ucode_id = AMDGPU_UCODE_ID_CAP; + info->fw = adev->psp.cap_fw; + cap_hdr_v1_0 = (const struct psp_firmware_header_v1_0 *) + adev->psp.cap_fw->data; + adev->firmware.fw_size += ALIGN( + le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes), PAGE_SIZE); + adev->psp.cap_fw_version = le32_to_cpu(cap_hdr_v1_0->header.ucode_version); + adev->psp.cap_feature_version = le32_to_cpu(cap_hdr_v1_0->sos.fw_version); + adev->psp.cap_ucode_size = le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes); + + return 0; + +out: + release_firmware(adev->psp.cap_fw); + adev->psp.cap_fw = NULL; + return err; +} + static int psp_set_clockgating_state(void *handle, enum amd_clockgating_state state) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index f29afabbff1f..ff7d533eb746 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -306,6 +306,9 @@ struct psp_context /* toc firmware */ const struct firmware *toc_fw; + /* cap firmware */ + const struct firmware *cap_fw; + /* fence buffer */ struct amdgpu_bo *fence_buf_bo; uint64_t fence_buf_mc_addr; @@ -327,6 +330,10 @@ struct psp_context const struct firmware *ta_fw; uint32_t ta_fw_version; + uint32_t cap_fw_version; + uint32_t cap_feature_version; + uint32_t cap_ucode_size; + struct ta_context asd_context; struct psp_xgmi_context xgmi_context; struct psp_ras_context ras_context; @@ -440,6 +447,8 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name); int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name); +int psp_init_cap_microcode(struct psp_context *psp, + const char *chip_name); int psp_get_fw_attestation_records_addr(struct psp_context *psp, uint64_t *output_ptr); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 7c2538db3cd5..428f4df184d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -378,6 +378,7 @@ enum AMDGPU_UCODE_ID { AMDGPU_UCODE_ID_VCN0_RAM, AMDGPU_UCODE_ID_VCN1_RAM, AMDGPU_UCODE_ID_DMCUB, + AMDGPU_UCODE_ID_CAP, AMDGPU_UCODE_ID_MAXIMUM, }; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h index dd0dce254901..1f276ddd26e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h +++ b/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h @@ -258,6 +258,7 @@ enum psp_gfx_fw_type { GFX_FW_TYPE_SDMA6 = 56, /* SDMA6 MI */ GFX_FW_TYPE_SDMA7 = 57, /* SDMA7 MI */ GFX_FW_TYPE_VCN1 = 58, /* VCN1 MI */ + GFX_FW_TYPE_CAP = 62, /* CAP_FW */ GFX_FW_TYPE_REG_LIST = 67, /* REG_LIST MI */ GFX_FW_TYPE_MAX }; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index d0e76b36d4ab..9518b4394a6e 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -53,11 +53,13 @@ MODULE_FIRMWARE("amdgpu/navi14_ta.bin"); MODULE_FIRMWARE("amdgpu/navi12_sos.bin"); MODULE_FIRMWARE("amdgpu/navi12_asd.bin"); MODULE_FIRMWARE("amdgpu/navi12_ta.bin"); +MODULE_FIRMWARE("amdgpu/navi12_cap.bin"); MODULE_FIRMWARE("amdgpu/arcturus_sos.bin"); MODULE_FIRMWARE("amdgpu/arcturus_asd.bin"); MODULE_FIRMWARE("amdgpu/arcturus_ta.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_sos.bin"); MODULE_FIRMWARE("amdgpu/sienna_cichlid_ta.bin"); +MODULE_FIRMWARE("amdgpu/sienna_cichlid_cap.bin"); MODULE_FIRMWARE("amdgpu/navy_flounder_sos.bin"); MODULE_FIRMWARE("amdgpu/navy_flounder_ta.bin"); MODULE_FIRMWARE("amdgpu/vangogh_asd.bin"); @@ -177,8 +179,6 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) err = psp_init_asd_microcode(psp, chip_name); if (err) return err; - if (amdgpu_sriov_vf(adev)) - break; snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); if (err) { diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index 1ed357cb0f49..01f3bcc62a6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -44,6 +44,7 @@ MODULE_FIRMWARE("amdgpu/vega10_sos.bin"); MODULE_FIRMWARE("amdgpu/vega10_asd.bin"); +MODULE_FIRMWARE("amdgpu/vega10_cap.bin"); MODULE_FIRMWARE("amdgpu/vega12_sos.bin"); MODULE_FIRMWARE("amdgpu/vega12_asd.bin"); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 0b94ec7b73e7..be4f9111f478 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -728,6 +728,8 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_FW_DMCUB 0x14 /* Subquery id: Query TOC firmware version */ #define AMDGPU_INFO_FW_TOC 0x15 + /* Subquery id: Query CAP firmware version */ + #define AMDGPU_INFO_FW_CAP 0x16 /* number of bytes moved for TTM migration */ #define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f From df01fe73ee98daf00c94189967550bd2d2098912 Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 11 Jan 2022 16:45:19 +0800 Subject: [PATCH 040/339] drm/amdgpu: Add ras supported check for register_ras_block Add ras supported check for register_ras_block. Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 517650d286a7..a1b4623ab1dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2756,6 +2756,9 @@ int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, if (!adev || !ras_block_obj) return -EINVAL; + if (!amdgpu_ras_asic_supported(adev)) + return 0; + INIT_LIST_HEAD(&ras_block_obj->node); list_add_tail(&ras_block_obj->node, &adev->ras_list); From df4f0041c6ef497e598a67e367db835489162754 Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 12 Jan 2022 10:19:07 +0800 Subject: [PATCH 041/339] drm/amdgpu: No longer insert ras blocks into ras_list if it already exists in ras_list No longer insert ras blocks into ras_list if it already exists in ras_list. Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index a1b4623ab1dd..23f4290b2fde 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2753,12 +2753,20 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object* ras_block_obj) { + struct amdgpu_ras_block_object *obj, *tmp; if (!adev || !ras_block_obj) return -EINVAL; if (!amdgpu_ras_asic_supported(adev)) return 0; + /* If the ras object is in ras_list, don't add it again */ + list_for_each_entry_safe(obj, tmp, &adev->ras_list, node) { + if (obj == ras_block_obj) { + return 0; + } + } + INIT_LIST_HEAD(&ras_block_obj->node); list_add_tail(&ras_block_obj->node, &adev->ras_list); From 69f91d32c6632e09f0954e690d61ac4921dacbd3 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Thu, 13 Jan 2022 15:11:31 +0800 Subject: [PATCH 042/339] drm/amdgpu: remove unneeded semicolon Eliminate the following coccicheck warning: ./drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:2725:16-17: Unneeded semicolon Reported-by: Abaci Robot Reviewed-by: Guchun Chen Signed-off-by: Yang Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 23f4290b2fde..64eed01d740c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2722,7 +2722,7 @@ struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev) int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras* ras_con) { if (!adev) - return -EINVAL;; + return -EINVAL; adev->psp.ras_context.ras = ras_con; return 0; From ab3b9de65bfeded1d4646c9f66897c163e89abd8 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Thu, 13 Jan 2022 15:11:32 +0800 Subject: [PATCH 043/339] drm/amdgpu: clean up some inconsistent indenting Eliminate the follow smatch warnings: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:3504 amdgpu_device_init() warn: inconsistent indenting drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1716 amdgpu_ras_error_status_query() warn: if statement not indented drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1058 amdgpu_ras_error_inject() warn: inconsistent indenting Reported-by: Abaci Robot Reviewed-by: Guchun Chen Signed-off-by: Yang Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 71b814fe15f9..7dd7ef76c720 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3498,7 +3498,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); - amdgpu_device_init_apu_flags(adev); + amdgpu_device_init_apu_flags(adev); r = amdgpu_device_check_arguments(adev); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 64eed01d740c..d37b09b2d33a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1055,8 +1055,10 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, .address = info->address, .value = info->value, }; - int ret = -EINVAL; - struct amdgpu_ras_block_object* block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, info->head.sub_block_index); + int ret = -EINVAL; + struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, + info->head.block, + info->head.sub_block_index); if (!obj) return -EINVAL; @@ -1714,7 +1716,7 @@ static void amdgpu_ras_error_status_query(struct amdgpu_device *adev, } if (block_obj->hw_ops->query_ras_error_status) - block_obj->hw_ops->query_ras_error_status(adev); + block_obj->hw_ops->query_ras_error_status(adev); } From 954ea6aa1545a13036851327b4ed251fa7ab2f22 Mon Sep 17 00:00:00 2001 From: yipechai Date: Thu, 13 Jan 2022 11:01:17 +0800 Subject: [PATCH 044/339] drm/amdgpu: Use ARRAY_SIZE to get array length Use ARRAY_SIZE to get array length. Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d37b09b2d33a..9864f730b958 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -89,7 +89,8 @@ const char *get_ras_block_str(struct ras_common_if *ras_block) return ras_block_string[ras_block->block]; } -#define ras_block_str(_BLOCK_) (((_BLOCK_) < (sizeof(*ras_block_string)/sizeof(const char*))) ? ras_block_string[_BLOCK_] : "Out Of Range") +#define ras_block_str(_BLOCK_) \ + (((_BLOCK_) < ARRAY_SIZE(ras_block_string)) ? ras_block_string[_BLOCK_] : "Out Of Range") #define ras_err_str(i) (ras_error_string[ffs(i)]) From e3d833f41c46b8c59c4af53897a6619bf667ebe5 Mon Sep 17 00:00:00 2001 From: yipechai Date: Thu, 13 Jan 2022 11:29:55 +0800 Subject: [PATCH 045/339] drm/amdgpu: fix compile warning for ras_block_match_default fix compile warning for ras_block_match_default Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 9864f730b958..0bb6b5354802 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -869,7 +869,8 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev, } /* feature ctl end */ -int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object* block_obj, enum amdgpu_ras_block block) +static int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object *block_obj, + enum amdgpu_ras_block block) { if(!block_obj) return -EINVAL; From 1613f346f86b25121aceb941d03ca927e57af20c Mon Sep 17 00:00:00 2001 From: Flora Cui Date: Thu, 13 Jan 2022 14:55:24 +0800 Subject: [PATCH 046/339] drm/amd/pm: fix null ptr access check null ptr first before access its element v2: check adev->pm.dpm_enabled early in amdgpu_debugfs_pm_init() Signed-off-by: Flora Cui Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index f0daa66f5b3d..5fc33893a68c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -463,7 +463,7 @@ int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_versio const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; int r = 0; - if (!pp_funcs->load_firmware) + if (!pp_funcs || !pp_funcs->load_firmware) return 0; mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 1b03ad7a21ad..49a9c6375343 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3583,6 +3583,9 @@ void amdgpu_debugfs_pm_init(struct amdgpu_device *adev) struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; + if (!adev->pm.dpm_enabled) + return; + debugfs_create_file("amdgpu_pm_info", 0444, root, adev, &amdgpu_debugfs_pm_info_fops); From a85d70a8b4813a955d45b062440fedb9be701421 Mon Sep 17 00:00:00 2001 From: Changcheng Deng Date: Fri, 14 Jan 2022 09:20:36 +0000 Subject: [PATCH 047/339] drm/amd/pm: Replace one-element array with flexible-array member There is a regular need in the kernel to provide a way to declare having a dynamically sized set of trailing elements in a structure. Kernel code should always use "flexible array members" for these cases. The older style of one-element or zero-length arrays should no longer be used. Reference: https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays Reported-by: Zeal Robot Signed-off-by: Changcheng Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h index eb0f79f9c876..701aae598b58 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/smu_ucode_xfer_cz.h @@ -121,7 +121,7 @@ typedef struct SMU_Task SMU_Task; struct TOC { uint8_t JobList[NUM_JOBLIST_ENTRIES]; - SMU_Task tasks[1]; + SMU_Task tasks[]; }; // META DATA COMMAND Definitions From fb825b651de98cafef13e07673eb72d5e2ceb4a9 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Fri, 14 Jan 2022 18:43:52 +0800 Subject: [PATCH 048/339] drm/amd/display: Remove redundant initialization of dpg_width dpg_width is being initialized to width but this is never read as dpg_width is overwritten later on. Remove the redundant initialization. Cleans up the following clang-analyzer warning: drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:6020:8: warning: Value stored to 'dpg_width' during its initialization is never read [clang-analyzer-deadcode.DeadStores]. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 05e216524370..cb2f96690b4a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -6011,7 +6011,7 @@ static void set_crtc_test_pattern(struct dc_link *link, else if (link->dc->hwss.set_disp_pattern_generator) { struct pipe_ctx *odm_pipe; int opp_cnt = 1; - int dpg_width = width; + int dpg_width; for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) opp_cnt++; From 31425abeda7130e66e61dbd8468502061413631f Mon Sep 17 00:00:00 2001 From: CHANDAN VURDIGERE NATARAJ Date: Tue, 11 Jan 2022 19:02:26 +0530 Subject: [PATCH 049/339] drm/amdgpu: Enable recovery on yellow carp Add yellow carp to devices which support recovery Signed-off-by: CHANDAN VURDIGERE NATARAJ Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7dd7ef76c720..26debfd3bfb2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4476,6 +4476,7 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) case CHIP_BEIGE_GOBY: case CHIP_VANGOGH: case CHIP_ALDEBARAN: + case CHIP_YELLOW_CARP: break; default: goto disabled; From b3523c457380c23cf28d4ee1ef60da337a0a45c0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Jan 2022 17:41:44 -0500 Subject: [PATCH 050/339] drm/amdgpu: invert the logic in amdgpu_device_should_recover_gpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than opting into GPU recovery support, default to on, and opt out if it's not working on a particular GPU. This avoids the need to add new asics to this list since this is a core feature. Reviewed-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 44 +++++++++------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 26debfd3bfb2..d363ae2da5c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4452,34 +4452,24 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) if (amdgpu_gpu_recovery == -1) { switch (adev->asic_type) { - case CHIP_BONAIRE: - case CHIP_HAWAII: - case CHIP_TOPAZ: - case CHIP_TONGA: - case CHIP_FIJI: - case CHIP_POLARIS10: - case CHIP_POLARIS11: - case CHIP_POLARIS12: - case CHIP_VEGAM: - case CHIP_VEGA20: - case CHIP_VEGA10: - case CHIP_VEGA12: - case CHIP_RAVEN: - case CHIP_ARCTURUS: - case CHIP_RENOIR: - case CHIP_NAVI10: - case CHIP_NAVI14: - case CHIP_NAVI12: - case CHIP_SIENNA_CICHLID: - case CHIP_NAVY_FLOUNDER: - case CHIP_DIMGREY_CAVEFISH: - case CHIP_BEIGE_GOBY: - case CHIP_VANGOGH: - case CHIP_ALDEBARAN: - case CHIP_YELLOW_CARP: - break; - default: +#ifdef CONFIG_DRM_AMDGPU_SI + case CHIP_VERDE: + case CHIP_TAHITI: + case CHIP_PITCAIRN: + case CHIP_OLAND: + case CHIP_HAINAN: +#endif +#ifdef CONFIG_DRM_AMDGPU_CIK + case CHIP_KAVERI: + case CHIP_KABINI: + case CHIP_MULLINS: +#endif + case CHIP_CARRIZO: + case CHIP_STONEY: + case CHIP_CYAN_SKILLFISH: goto disabled; + default: + break; } } From 06cf9bd61a7452df375f212881d9bb6b3c52c3ec Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 12 Jan 2022 22:38:51 -0500 Subject: [PATCH 051/339] drm/amdgpu: don't do resets on APUs which don't support it It can cause a hang. This is normally not enabled for GPU hangs on these asics, but was recently enabled for handling aborted suspends. This causes hangs on some platforms on suspend. Fixes: daf8de0874ab5b ("drm/amdgpu: always reset the asic in suspend (v2)") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1858 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik.c | 4 ++++ drivers/gpu/drm/amd/amdgpu/vi.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 54f28c075f21..f10ce740a29c 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1428,6 +1428,10 @@ static int cik_asic_reset(struct amdgpu_device *adev) { int r; + /* APUs don't have full asic reset */ + if (adev->flags & AMD_IS_APU) + return 0; + if (cik_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { dev_info(adev->dev, "BACO reset\n"); r = amdgpu_dpm_baco_reset(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index fe9a7cc8d9eb..6645ebbd2696 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -956,6 +956,10 @@ static int vi_asic_reset(struct amdgpu_device *adev) { int r; + /* APUs don't have full asic reset */ + if (adev->flags & AMD_IS_APU) + return 0; + if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { dev_info(adev->dev, "BACO reset\n"); r = amdgpu_dpm_baco_reset(adev); From 5f0754ab2751d1935818459e8e71a8fe26f6403c Mon Sep 17 00:00:00 2001 From: Lukas Fink Date: Fri, 14 Jan 2022 07:51:41 +0100 Subject: [PATCH 052/339] drm/amdgpu: Fix rejecting Tahiti GPUs eb4fd29afd4a ("drm/amdgpu: bind to any 0x1002 PCI diplay class device") added generic bindings to amdgpu so that that it binds to all display class devices with VID 0x1002 and then rejects those in amdgpu_pci_probe. Unfortunately it reuses a driver_data value of 0 to detect those new bindings, which is already used to denote CHIP_TAHITI ASICs. The driver_data value given to those new bindings was changed in dd0761fd24ea1 ("drm/amdgpu: set CHIP_IP_DISCOVERY as the asic type by default") to CHIP_IP_DISCOVERY (=36), but it seems that the check in amdgpu_pci_probe was forgotten to be changed. Therefore, it still rejects Tahiti GPUs. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1860 Fixes: eb4fd29afd4a ("drm/amdgpu: bind to any 0x1002 PCI diplay class device") Signed-off-by: Lukas Fink Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 10e01928ffad..6d4eb1b72951 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1880,7 +1880,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, return -ENODEV; } - if (flags == 0) { + if (flags == CHIP_IP_DISCOVERY) { DRM_INFO("Unsupported asic. Remove me when IP discovery init is in place.\n"); return -ENODEV; } From a8e6398ffe171c84b1c03a17eb6d432dc5f703a4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 14 Jan 2022 09:59:29 -0500 Subject: [PATCH 053/339] drm/amdgpu: drop flags check for CHIP_IP_DISCOVERY Support for IP based discovery is in place now so this check is no longer required. Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6d4eb1b72951..cc6585193236 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1880,11 +1880,6 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, return -ENODEV; } - if (flags == CHIP_IP_DISCOVERY) { - DRM_INFO("Unsupported asic. Remove me when IP discovery init is in place.\n"); - return -ENODEV; - } - if (amdgpu_virtual_display || amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK)) supports_atomic = true; From e8521d0cd984897b4fa58e7837afebd04e44f0b3 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 7 Jan 2022 10:44:17 -0600 Subject: [PATCH 054/339] drm/amd/display: Revert W/A for hard hangs on DCN20/DCN21 The WA from commit 2a50edbf10c8 ("drm/amd/display: Apply w/a for hard hang on HPD") and commit 1bd3bc745e7f ("drm/amd/display: Extend w/a for hard hang on HPD to dcn20") causes a regression in s0ix where the system will fail to resume properly on many laptops. Pull the workarounds out to avoid that s0ix regression in the common case. This HPD hang happens with an external device in special circumstances and a new W/A will need to be developed for this in the future. Cc: Qingqing Zhuo Reported-by: Scott Bruce Reported-by: Chris Hixon Reported-by: spasswolf@web.de Link: https://bugzilla.kernel.org/show_bug.cgi?id=215436 Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1821 Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1852 Fixes: 2a50edbf10c8 ("drm/amd/display: Apply w/a for hard hang on HPD") Fixes: 1bd3bc745e7f ("drm/amd/display: Extend w/a for hard hang on HPD to dcn20") Reviewed-by: Nicholas Kazlauskas Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 11 +------- .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 11 +------- .../display/dc/irq/dcn20/irq_service_dcn20.c | 25 ------------------- .../display/dc/irq/dcn20/irq_service_dcn20.h | 2 -- .../display/dc/irq/dcn21/irq_service_dcn21.c | 25 ------------------- .../display/dc/irq/dcn21/irq_service_dcn21.h | 2 -- .../gpu/drm/amd/display/dc/irq/irq_service.c | 2 +- .../gpu/drm/amd/display/dc/irq/irq_service.h | 4 --- 8 files changed, 3 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 9f35f2e8f971..cac80ba69072 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -38,7 +38,6 @@ #include "clk/clk_11_0_0_offset.h" #include "clk/clk_11_0_0_sh_mask.h" -#include "irq/dcn20/irq_service_dcn20.h" #undef FN #define FN(reg_name, field_name) \ @@ -223,8 +222,6 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, bool force_reset = false; bool p_state_change_support; int total_plane_count; - int irq_src; - uint32_t hpd_state; if (dc->work_arounds.skip_clock_update) return; @@ -242,13 +239,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, if (dc->res_pool->pp_smu) pp_smu = &dc->res_pool->pp_smu->nv_funcs; - for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD6; irq_src++) { - hpd_state = dc_get_hpd_state_dcn20(dc->res_pool->irqs, irq_src); - if (hpd_state) - break; - } - - if (display_count == 0 && !hpd_state) + if (display_count == 0) enter_display_off = true; if (enter_display_off == safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index fbda42313bfe..f4dee0e48a67 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -42,7 +42,6 @@ #include "clk/clk_10_0_2_sh_mask.h" #include "renoir_ip_offset.h" -#include "irq/dcn21/irq_service_dcn21.h" /* Constants */ @@ -129,11 +128,9 @@ static void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; struct dc *dc = clk_mgr_base->ctx->dc; int display_count; - int irq_src; bool update_dppclk = false; bool update_dispclk = false; bool dpp_clock_lowered = false; - uint32_t hpd_state; struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu; @@ -150,14 +147,8 @@ static void rn_update_clocks(struct clk_mgr *clk_mgr_base, display_count = rn_get_active_display_cnt_wa(dc, context); - for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD5; irq_src++) { - hpd_state = dc_get_hpd_state_dcn21(dc->res_pool->irqs, irq_src); - if (hpd_state) - break; - } - /* if we can go lower, go lower */ - if (display_count == 0 && !hpd_state) { + if (display_count == 0) { rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); /* update power state */ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c index 9ccafe007b23..c4b067d01895 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c @@ -132,31 +132,6 @@ enum dc_irq_source to_dal_irq_source_dcn20( } } -uint32_t dc_get_hpd_state_dcn20(struct irq_service *irq_service, enum dc_irq_source source) -{ - const struct irq_source_info *info; - uint32_t addr; - uint32_t value; - uint32_t current_status; - - info = find_irq_source_info(irq_service, source); - if (!info) - return 0; - - addr = info->status_reg; - if (!addr) - return 0; - - value = dm_read_reg(irq_service->ctx, addr); - current_status = - get_reg_field_value( - value, - HPD0_DC_HPD_INT_STATUS, - DC_HPD_SENSE); - - return current_status; -} - static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h index 4d69ab24ca25..aee4b37999f1 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h @@ -31,6 +31,4 @@ struct irq_service *dal_irq_service_dcn20_create( struct irq_service_init_data *init_data); -uint32_t dc_get_hpd_state_dcn20(struct irq_service *irq_service, enum dc_irq_source source); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index 235294534c43..0f15bcada4e9 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -134,31 +134,6 @@ static enum dc_irq_source to_dal_irq_source_dcn21(struct irq_service *irq_servic return DC_IRQ_SOURCE_INVALID; } -uint32_t dc_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source) -{ - const struct irq_source_info *info; - uint32_t addr; - uint32_t value; - uint32_t current_status; - - info = find_irq_source_info(irq_service, source); - if (!info) - return 0; - - addr = info->status_reg; - if (!addr) - return 0; - - value = dm_read_reg(irq_service->ctx, addr); - current_status = - get_reg_field_value( - value, - HPD0_DC_HPD_INT_STATUS, - DC_HPD_SENSE); - - return current_status; -} - static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h index 616470e32380..da2bd0e93d7a 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h @@ -31,6 +31,4 @@ struct irq_service *dal_irq_service_dcn21_create( struct irq_service_init_data *init_data); -uint32_t dc_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source); - #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index 4db1133e4466..a2a4fbeb83f8 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -79,7 +79,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service) *irq_service = NULL; } -const struct irq_source_info *find_irq_source_info( +static const struct irq_source_info *find_irq_source_info( struct irq_service *irq_service, enum dc_irq_source source) { diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h index e60b82480093..dbfcb096eedd 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -69,10 +69,6 @@ struct irq_service { const struct irq_service_funcs *funcs; }; -const struct irq_source_info *find_irq_source_info( - struct irq_service *irq_service, - enum dc_irq_source source); - void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data); From 83f2726cd9c3b92589f850cd4935ebbc35eee840 Mon Sep 17 00:00:00 2001 From: mziya Date: Tue, 11 Jan 2022 15:08:35 +0800 Subject: [PATCH 055/339] drm/amd/pm: Update smu driver interface for sienna cichlid update smu driver if version to 0x40 V2: Interface version append with sienna_cichlid V3: Aligned with latest driver interface. Reviewed-by: Lijo Lazar Signed-off-by: mziya Signed-off-by: Alex Deucher --- .../pmfw_if/smu11_driver_if_sienna_cichlid.h | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h index 63b8701fd466..b253be602cc2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x3B +#define SMU11_DRIVER_IF_VERSION 0x40 #define PPTABLE_Sienna_Cichlid_SMU_VERSION 7 @@ -172,6 +172,7 @@ typedef enum { #define DPM_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00001000 #define DPM_OVERRIDE_DISABLE_VCN_PG 0x00002000 #define DPM_OVERRIDE_DISABLE_FMAX_VMAX 0x00004000 +#define DPM_OVERRIDE_ENABLE_eGPU_USB_WA 0x00008000 // VR Mapping Bit Defines #define VR_MAPPING_VR_SELECT_MASK 0x01 @@ -263,7 +264,22 @@ typedef enum { #define LED_DISPLAY_ERROR_BIT 2 //RLC Pace Table total number of levels -#define RLC_PACE_TABLE_NUM_LEVELS 16 +#define RLC_PACE_TABLE_NUM_LEVELS 16 +#define SIENNA_CICHLID_UMC_CHANNEL_NUM 16 + +typedef struct { + uint64_t mca_umc_status; + uint64_t mca_umc_addr; + + uint16_t ce_count_lo_chip; + uint16_t ce_count_hi_chip; + + uint32_t eccPadding; +} EccInfo_t; + +typedef struct { + EccInfo_t EccInfo[SIENNA_CICHLID_UMC_CHANNEL_NUM]; +} EccInfoTable_t; typedef enum { DRAM_BIT_WIDTH_DISABLED = 0, @@ -283,6 +299,7 @@ typedef enum { #define MAX_SW_I2C_COMMANDS 24 + typedef enum { I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 @@ -1672,7 +1689,8 @@ typedef struct { #define TABLE_OVERDRIVE 8 #define TABLE_I2C_COMMANDS 9 #define TABLE_PACE 10 -#define TABLE_COUNT 11 +#define TABLE_ECCINFO 11 +#define TABLE_COUNT 12 typedef struct { float FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; From c34242eea16f7d973501267142dd340cad3caeec Mon Sep 17 00:00:00 2001 From: mziya Date: Sat, 15 Jan 2022 15:21:54 +0800 Subject: [PATCH 056/339] drm/amdgpu: add new query interface for umc_v8_7 block add smu message query error information interface, function name align with IP version number V2: Removed unused err cnt entry Signed-off-by: mziya Acked-by: Evan Quan Reviewed-by: Stanley.Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 160 +++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index ff9e1fac616d..291b37f6db4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -40,13 +40,161 @@ const uint32_t {9, 0}, {15, 6} }; -static inline uint32_t get_umc_8_reg_offset(struct amdgpu_device *adev, +static inline uint32_t get_umc_v8_7_reg_offset(struct amdgpu_device *adev, uint32_t umc_inst, uint32_t ch_inst) { return adev->umc.channel_offs*ch_inst + UMC_8_INST_DIST*umc_inst; } +static inline uint32_t get_umc_v8_7_channel_index(struct amdgpu_device *adev, + uint32_t umc_inst, + uint32_t ch_inst) +{ + return adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; +} + +static void umc_v8_7_ecc_info_query_correctable_error_count(struct amdgpu_device *adev, + uint32_t channel_index, + unsigned long *error_count) +{ + uint64_t mc_umc_status; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + /* check for SRAM correctable error + * MCUMC_STATUS is a 64 bit register + */ + mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) + *error_count += 1; +} + +static void umc_v8_7_ecc_info_querry_uncorrectable_error_count(struct amdgpu_device *adev, + uint32_t channel_index, + unsigned long *error_count) +{ + uint64_t mc_umc_status; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + + /* check the MCUMC_STATUS */ + mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, PCC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, TCC) == 1)) + *error_count += 1; +} + +static void umc_v8_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, + void *ras_error_status) +{ + struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; + + uint32_t umc_inst = 0; + uint32_t ch_inst = 0; + uint32_t umc_reg_offset = 0; + uint32_t channel_index = 0; + + /* TODO: driver needs to toggle DF Cstate to ensure + * safe access of UMC registers. Will add the protection + */ + LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { + umc_reg_offset = get_umc_v8_7_reg_offset(adev, + umc_inst, + ch_inst); + channel_index = get_umc_v8_7_channel_index(adev, + umc_inst, + ch_inst); + umc_v8_7_ecc_info_query_correctable_error_count(adev, + channel_index, + &(err_data->ce_count)); + umc_v8_7_ecc_info_querry_uncorrectable_error_count(adev, + channel_index, + &(err_data->ue_count)); + } +} + +static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, + struct ras_err_data *err_data, + uint32_t umc_reg_offset, + uint32_t ch_inst, + uint32_t umc_inst) +{ + uint64_t mc_umc_status, err_addr, retired_page; + struct eeprom_table_record *err_rec; + uint32_t channel_index; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + + channel_index = + adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; + + mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + + if (mc_umc_status == 0) + return; + + if (!err_data->err_addr) + return; + + err_rec = &err_data->err_addr[err_data->err_addr_cnt]; + + /* calculate error address if ue/ce error is detected */ + if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && + (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || + REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) { + + err_addr = ras->umc_ecc.ecc[channel_index].mca_umc_addr; + err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); + + /* translate umc channel address to soc pa, 3 parts are included */ + retired_page = ADDR_OF_4KB_BLOCK(err_addr) | + ADDR_OF_256B_BLOCK(channel_index) | + OFFSET_IN_256B_BLOCK(err_addr); + + /* we only save ue error information currently, ce is skipped */ + if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) + == 1) { + err_rec->address = err_addr; + /* page frame address is saved */ + err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; + err_rec->ts = (uint64_t)ktime_get_real_seconds(); + err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; + err_rec->cu = 0; + err_rec->mem_channel = channel_index; + err_rec->mcumc_id = umc_inst; + + err_data->err_addr_cnt++; + } + } +} + +static void umc_v8_7_ecc_info_query_ras_error_address(struct amdgpu_device *adev, + void *ras_error_status) +{ + struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; + + uint32_t umc_inst = 0; + uint32_t ch_inst = 0; + uint32_t umc_reg_offset = 0; + + /* TODO: driver needs to toggle DF Cstate to ensure + * safe access of UMC resgisters. Will add the protection + * when firmware interface is ready + */ + LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { + umc_reg_offset = get_umc_v8_7_reg_offset(adev, + umc_inst, + ch_inst); + umc_v8_7_ecc_info_query_error_address(adev, + err_data, + umc_reg_offset, + ch_inst, + umc_inst); + } +} + static void umc_v8_7_clear_error_count_per_channel(struct amdgpu_device *adev, uint32_t umc_reg_offset) { @@ -92,7 +240,7 @@ static void umc_v8_7_clear_error_count(struct amdgpu_device *adev) uint32_t umc_reg_offset = 0; LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_8_reg_offset(adev, + umc_reg_offset = get_umc_v8_7_reg_offset(adev, umc_inst, ch_inst); @@ -178,7 +326,7 @@ static void umc_v8_7_query_ras_error_count(struct amdgpu_device *adev, uint32_t umc_reg_offset = 0; LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_8_reg_offset(adev, + umc_reg_offset = get_umc_v8_7_reg_offset(adev, umc_inst, ch_inst); @@ -268,7 +416,7 @@ static void umc_v8_7_query_ras_error_address(struct amdgpu_device *adev, uint32_t umc_reg_offset = 0; LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_8_reg_offset(adev, + umc_reg_offset = get_umc_v8_7_reg_offset(adev, umc_inst, ch_inst); @@ -316,7 +464,7 @@ static void umc_v8_7_err_cnt_init(struct amdgpu_device *adev) uint32_t umc_reg_offset = 0; LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_8_reg_offset(adev, + umc_reg_offset = get_umc_v8_7_reg_offset(adev, umc_inst, ch_inst); @@ -334,4 +482,6 @@ struct amdgpu_umc_ras umc_v8_7_ras = { .hw_ops = &umc_v8_7_ras_hw_ops, }, .err_cnt_init = umc_v8_7_err_cnt_init, + .ecc_info_query_ras_error_count = umc_v8_7_ecc_info_query_ras_error_count, + .ecc_info_query_ras_error_address = umc_v8_7_ecc_info_query_ras_error_address, }; From 3ddd0c90bafd9f2ae1ac9f1e67581537273dfed6 Mon Sep 17 00:00:00 2001 From: mziya Date: Tue, 11 Jan 2022 15:15:13 +0800 Subject: [PATCH 057/339] drm/amd/pm: add message smu to get ecc_table support ECC TABLE message, this table include umc ras error count and error address V2: Return after smu version check fail V3: Return -EOPNOTSUPP, if fail to get smc ver. V4: ECCTABLE typo corrected and sentence rephrased. Signed-off-by: mziya Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 69 +++++++++++++++++++ .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 2 + 2 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 4e37cd8025ed..eb47d490ee9d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -46,6 +46,7 @@ #include "mp/mp_11_0_sh_mask.h" #include "asic_reg/mp/mp_11_0_sh_mask.h" +#include "amdgpu_ras.h" #include "smu_cmn.h" /* @@ -83,6 +84,12 @@ /* STB FIFO depth is in 64bit units */ #define SIENNA_CICHLID_STB_DEPTH_UNIT_BYTES 8 +/* + * SMU support ECCTABLE since version 58.70.0, + * use this to check whether ECCTABLE feature is supported. + */ +#define SUPPORT_ECCTABLE_SMU_VERSION 0x003a4600 + static int get_table_size(struct smu_context *smu) { if (smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 13)) @@ -225,6 +232,7 @@ static struct cmn2asic_mapping sienna_cichlid_table_map[SMU_TABLE_COUNT] = { TAB_MAP(OVERDRIVE), TAB_MAP(I2C_COMMANDS), TAB_MAP(PACE), + TAB_MAP(ECCINFO), }; static struct cmn2asic_mapping sienna_cichlid_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { @@ -466,6 +474,8 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); if (!smu_table->metrics_table) @@ -481,6 +491,10 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) if (!smu_table->watermarks_table) goto err2_out; + smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); + if (!smu_table->ecc_table) + return -ENOMEM; + return 0; err2_out: @@ -3672,6 +3686,60 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_3); } +static int sienna_cichlid_check_ecc_table_support(struct smu_context *smu) +{ + uint32_t if_version = 0xff, smu_version = 0xff; + int ret = 0; + + ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); + if (ret) + return -EOPNOTSUPP; + + if (smu_version < SUPPORT_ECCTABLE_SMU_VERSION) + ret = -EOPNOTSUPP; + + return ret; +} + +static ssize_t sienna_cichlid_get_ecc_info(struct smu_context *smu, + void *table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + EccInfoTable_t *ecc_table = NULL; + struct ecc_info_per_ch *ecc_info_per_channel = NULL; + int i, ret = 0; + struct umc_ecc_info *eccinfo = (struct umc_ecc_info *)table; + + ret = sienna_cichlid_check_ecc_table_support(smu); + if (ret) + return ret; + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ECCINFO, + 0, + smu_table->ecc_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU ecc table!\n"); + return ret; + } + + ecc_table = (EccInfoTable_t *)smu_table->ecc_table; + + for (i = 0; i < SIENNA_CICHLID_UMC_CHANNEL_NUM; i++) { + ecc_info_per_channel = &(eccinfo->ecc[i]); + ecc_info_per_channel->ce_count_lo_chip = + ecc_table->EccInfo[i].ce_count_lo_chip; + ecc_info_per_channel->ce_count_hi_chip = + ecc_table->EccInfo[i].ce_count_hi_chip; + ecc_info_per_channel->mca_umc_status = + ecc_table->EccInfo[i].mca_umc_status; + ecc_info_per_channel->mca_umc_addr = + ecc_table->EccInfo[i].mca_umc_addr; + } + + return ret; +} static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) { struct smu_table_context *table_context = &smu->smu_table; @@ -3923,6 +3991,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .gpo_control = sienna_cichlid_gpo_control, .set_mp1_state = sienna_cichlid_set_mp1_state, .stb_collect_info = sienna_cichlid_stb_get_data_direct, + .get_ecc_info = sienna_cichlid_get_ecc_info, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 9acf2c045a97..7029e5deb6b3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -473,8 +473,10 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu) kfree(smu_table->hardcode_pptable); smu_table->hardcode_pptable = NULL; + kfree(smu_table->ecc_table); kfree(smu_table->metrics_table); kfree(smu_table->watermarks_table); + smu_table->ecc_table = NULL; smu_table->metrics_table = NULL; smu_table->watermarks_table = NULL; smu_table->metrics_time = 0; From 79c0462159a1fa3810ae1869a5fc9fd7782b6b70 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Tue, 11 Jan 2022 14:14:50 +0800 Subject: [PATCH 058/339] drm/amdgpu: handle denied inject error into critical regions v2 Changed from v1: remove unused brace Signed-off-by: Stanley.Yang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 9 ++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- drivers/gpu/drm/amd/amdgpu/ta_ras_if.h | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index c984b5a34679..5c9b67ab168f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1335,6 +1335,11 @@ static void psp_ras_ta_check_status(struct psp_context *psp) break; case TA_RAS_STATUS__SUCCESS: break; + case TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED: + if (ras_cmd->cmd_id == TA_RAS_COMMAND__TRIGGER_ERROR) + dev_warn(psp->adev->dev, + "RAS WARNING: Inject error to critical region is not allowed\n"); + break; default: dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); @@ -1547,7 +1552,9 @@ int psp_ras_trigger_error(struct psp_context *psp, if (amdgpu_ras_intr_triggered()) return 0; - if (ras_cmd->ras_status) + if (ras_cmd->ras_status == TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED) + return -EACCES; + else if (ras_cmd->ras_status) return -EINVAL; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 0bb6b5354802..3538032e40d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -455,7 +455,7 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, } if (ret) - return -EINVAL; + return ret; return size; } diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h index 5093826a43d1..509d8a1945eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h +++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h @@ -64,7 +64,8 @@ enum ta_ras_status { TA_RAS_STATUS__ERROR_PCS_STATE_ERROR = 0xA016, TA_RAS_STATUS__ERROR_PCS_STATE_HANG = 0xA017, TA_RAS_STATUS__ERROR_PCS_STATE_UNKNOWN = 0xA018, - TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ = 0xA019 + TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ = 0xA019, + TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED = 0xA01A }; enum ta_ras_block { From e475986f182156496fa2991012ca51956fe90bf7 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 14 Jan 2022 13:28:16 +0800 Subject: [PATCH 059/339] drm/amdgpu: drop redundant check of ip discovery_bin Early check in amdgpu_discovery_reg_base_init promises this. Signed-off-by: Guchun Chen Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index be45650250fa..b0bf69611fbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1195,11 +1195,6 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) return -EINVAL; amdgpu_discovery_harvest_ip(adev); - - if (!adev->mman.discovery_bin) { - DRM_ERROR("ip discovery uninitialized\n"); - return -EINVAL; - } break; } From 03f6fb84bd0e98a7b929aef5f308b8e3f2f24a0d Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 14 Jan 2022 13:49:13 +0800 Subject: [PATCH 060/339] drm/amdgpu: apply vcn harvest quirk This is a following patch to apply the workaround only on those boards with a bad harvest table in ip discovery. Signed-off-by: Guchun Chen Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index b0bf69611fbd..e6a26b554254 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -243,6 +243,30 @@ static inline bool amdgpu_discovery_verify_binary_signature(uint8_t *binary) return (le32_to_cpu(bhdr->binary_signature) == BINARY_SIGNATURE); } +static void amdgpu_discovery_harvest_config_quirk(struct amdgpu_device *adev) +{ + /* + * So far, apply this quirk only on those Navy Flounder boards which + * have a bad harvest table of VCN config. + */ + if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) && + (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2))) { + switch (adev->pdev->revision) { + case 0xC1: + case 0xC2: + case 0xC3: + case 0xC5: + case 0xC7: + case 0xCF: + case 0xDF: + adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1; + break; + default: + break; + } + } +} + static int amdgpu_discovery_init(struct amdgpu_device *adev) { struct table_info *info; @@ -548,11 +572,9 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev) break; } } - /* some IP discovery tables on Navy Flounder don't have this set correctly */ - if ((adev->ip_versions[UVD_HWIP][1] == IP_VERSION(3, 0, 1)) && - (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 2)) && - (adev->pdev->revision != 0xFF)) - adev->vcn.harvest_config |= AMDGPU_VCN_HARVEST_VCN1; + + amdgpu_discovery_harvest_config_quirk(adev); + if (vcn_harvest_count == adev->vcn.num_vcn_inst) { adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK; adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK; From b6efdb02d23ef615464cd0077c211b40a1faca26 Mon Sep 17 00:00:00 2001 From: yipechai Date: Fri, 14 Jan 2022 10:24:30 +0800 Subject: [PATCH 061/339] drm/amdgpu: Fix the code style warnings in amdgpu_ras MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the code style warnings in amdgpu_ras: 1. ERROR: space required before the open parenthesis '('. 2. WARNING: line length of xxx exceeds 100 columns. 3. ERROR: "foo* bar" should be "foo *bar". 4. WARNING: unnecessary whitespace before a quoted newline. 5. WARNING: space prohibited before semicolon. 6. WARNING: suspect code indent for conditional statements. 7. WARNING: braces {} are not necessary for single statement blocks. Signed-off-by: yipechai Reviewed-by: Tao Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 41 +++++++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 10 +++--- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 3538032e40d5..7a1d2bac698e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -872,7 +872,7 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev, static int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object *block_obj, enum amdgpu_ras_block block) { - if(!block_obj) + if (!block_obj) return -EINVAL; if (block_obj->block == block) @@ -881,7 +881,7 @@ static int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object *block_ return -EINVAL; } -static struct amdgpu_ras_block_object* amdgpu_ras_get_ras_block(struct amdgpu_device *adev, +static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_device *adev, enum amdgpu_ras_block block, uint32_t sub_block_index) { struct amdgpu_ras_block_object *obj, *tmp; @@ -941,7 +941,7 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info) { - struct amdgpu_ras_block_object* block_obj = NULL; + struct amdgpu_ras_block_object *block_obj = NULL; struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head); struct ras_err_data err_data = {0, 0, 0, NULL}; @@ -953,7 +953,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, } else { block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0); if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", + dev_info(adev->dev, "%s doesn't config ras function.\n", get_ras_block_str(&info->head)); return -EINVAL; } @@ -1023,13 +1023,14 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, enum amdgpu_ras_block block) { - struct amdgpu_ras_block_object* block_obj = amdgpu_ras_get_ras_block(adev, block, 0); + struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, block, 0); if (!amdgpu_ras_is_supported(adev, block)) return -EINVAL; if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", ras_block_str(block)); + dev_info(adev->dev, "%s doesn't config ras function.\n", + ras_block_str(block)); return -EINVAL; } @@ -1066,7 +1067,8 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, return -EINVAL; if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); + dev_info(adev->dev, "%s doesn't config ras function.\n", + get_ras_block_str(&info->head)); return -EINVAL; } @@ -1702,19 +1704,25 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev) static void amdgpu_ras_error_status_query(struct amdgpu_device *adev, struct ras_query_if *info) { - struct amdgpu_ras_block_object* block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, info->head.sub_block_index); + struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, + info->head.block, + info->head.sub_block_index); /* * Only two block need to query read/write * RspStatus at current state */ if ((info->head.block != AMDGPU_RAS_BLOCK__GFX) && (info->head.block != AMDGPU_RAS_BLOCK__MMHUB)) - return ; + return; + + block_obj = amdgpu_ras_get_ras_block(adev, + info->head.block, + info->head.sub_block_index); - block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, info->head.sub_block_index); if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function \n", get_ras_block_str(&info->head)); - return ; + dev_info(adev->dev, "%s doesn't config ras function.\n", + get_ras_block_str(&info->head)); + return; } if (block_obj->hw_ops->query_ras_error_status) @@ -2715,7 +2723,7 @@ static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev) } #endif -struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev) +struct amdgpu_ras *amdgpu_ras_get_context(struct amdgpu_device *adev) { if (!adev) return NULL; @@ -2723,7 +2731,7 @@ struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev) return adev->psp.ras_context.ras; } -int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras* ras_con) +int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_con) { if (!adev) return -EINVAL; @@ -2755,7 +2763,7 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) /* Register each ip ras block into amdgpu ras */ int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, - struct amdgpu_ras_block_object* ras_block_obj) + struct amdgpu_ras_block_object *ras_block_obj) { struct amdgpu_ras_block_object *obj, *tmp; if (!adev || !ras_block_obj) @@ -2766,9 +2774,8 @@ int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, /* If the ras object is in ras_list, don't add it again */ list_for_each_entry_safe(obj, tmp, &adev->ras_list, node) { - if (obj == ras_block_obj) { + if (obj == ras_block_obj) return 0; - } } INIT_LIST_HEAD(&ras_block_obj->node); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 7a4d82378205..a51a281bd91a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -496,7 +496,8 @@ struct amdgpu_ras_block_object { /* ras block link */ struct list_head node; - int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj, enum amdgpu_ras_block block, uint32_t sub_block_index); + int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj, + enum amdgpu_ras_block block, uint32_t sub_block_index); int (*ras_late_init)(struct amdgpu_device *adev, void *ras_info); void (*ras_fini)(struct amdgpu_device *adev); const struct amdgpu_ras_block_hw_ops *hw_ops; @@ -504,7 +505,7 @@ struct amdgpu_ras_block_object { struct amdgpu_ras_block_hw_ops { int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if); - void (*query_ras_error_count)(struct amdgpu_device *adev,void *ras_error_status); + void (*query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status); void (*query_ras_error_status)(struct amdgpu_device *adev); void (*query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count)(struct amdgpu_device *adev); @@ -678,7 +679,8 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev); struct amdgpu_ras* amdgpu_ras_get_context(struct amdgpu_device *adev); -int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras* ras_con); +int amdgpu_ras_set_context(struct amdgpu_device *adev, struct amdgpu_ras *ras_con); -int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object* ras_block_obj); +int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, + struct amdgpu_ras_block_object *ras_block_obj); #endif From 4f64ccf4f27c89089f3206446e2158833bda4795 Mon Sep 17 00:00:00 2001 From: yipechai Date: Fri, 14 Jan 2022 10:30:27 +0800 Subject: [PATCH 062/339] drm/amdgpu: Fix the code style warnings in gfx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the code style warnings in gfx: 1. WARNING: suspect code indent for conditional statements. 2. ERROR: spaces required around that '=' (ctx:WxV). Signed-off-by: yipechai Reviewed-by: Tao Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index d36a6bc62560..e12f9f5c3beb 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2314,11 +2314,11 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev) /* If not define special ras_late_init function, use gfx default ras_late_init */ if (!adev->gfx.ras->ras_block.ras_late_init) - adev->gfx.ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init; + adev->gfx.ras->ras_block.ras_late_init = amdgpu_gfx_ras_late_init; /* If not define special ras_fini function, use gfx default ras_fini */ if (!adev->gfx.ras->ras_block.ras_fini) - adev->gfx.ras->ras_block.ras_fini = amdgpu_gfx_ras_fini; + adev->gfx.ras->ras_block.ras_fini = amdgpu_gfx_ras_fini; } adev->gfx.config.gb_addr_config = gb_addr_config; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c index 7ec6243e015e..7653ebd0e67b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c @@ -1930,7 +1930,7 @@ static void gfx_v9_4_2_reset_sq_timeout_status(struct amdgpu_device *adev) mutex_unlock(&adev->grbm_idx_mutex); } -struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops ={ +struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops = { .ras_error_inject = &gfx_v9_4_2_ras_error_inject, .query_ras_error_count = &gfx_v9_4_2_query_ras_error_count, .reset_ras_error_count = &gfx_v9_4_2_reset_ras_error_count, From d622c094f8fe7a77fda613964ffdd9a248d2550a Mon Sep 17 00:00:00 2001 From: yipechai Date: Fri, 14 Jan 2022 10:31:49 +0800 Subject: [PATCH 063/339] drm/amdgpu: Fix the code style warnings in gmc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the code style warnings in gmc: ERROR: space required after that ',' (ctx:VxV). Signed-off-by: yipechai Reviewed-by: Tao Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 5ef4ad28ab26..4f8d356f8432 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -672,7 +672,7 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev) if (adev->umc.ras) { amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block); - strcpy(adev->umc.ras->ras_block.name,"umc"); + strcpy(adev->umc.ras->ras_block.name, "umc"); adev->umc.ras->ras_block.block = AMDGPU_RAS_BLOCK__UMC; /* If don't define special ras_late_init function, use default ras_late_init */ diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 3965aae435f8..c76ffd1a70cd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1231,7 +1231,7 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) if (adev->umc.ras) { amdgpu_ras_register_ras_block(adev, &adev->umc.ras->ras_block); - strcpy(adev->umc.ras->ras_block.name,"umc"); + strcpy(adev->umc.ras->ras_block.name, "umc"); adev->umc.ras->ras_block.block = AMDGPU_RAS_BLOCK__UMC; /* If don't define special ras_late_init function, use default ras_late_init */ From 8697a19ee955e32fe298b00feb0c61fc75cb5261 Mon Sep 17 00:00:00 2001 From: yipechai Date: Fri, 14 Jan 2022 10:33:09 +0800 Subject: [PATCH 064/339] drm/amdgpu: Fix the code style warnings in sdma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the code style warnings in sdma: 1. WARNING: Missing a blank line after declarations. 2. ERROR: that open brace { should be on the previous line. 3. WARNING: unnecessary whitespace before a quoted newline. 4. ERROR: space required after that ',' (ctx:VxV). Signed-off-by: yipechai Reviewed-by: Tao Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 8 ++++---- drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 3c1483dc113e..06a7ceda4c87 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2766,10 +2766,10 @@ static int sdma_v4_0_query_ras_error_count_by_instance(struct amdgpu_device *ade static void sdma_v4_0_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { int i = 0; + for (i = 0; i < adev->sdma.num_instances; i++) { - if (sdma_v4_0_query_ras_error_count_by_instance(adev, i, ras_error_status)) - { - dev_err(adev->dev, "Query ras error count failed in SDMA%d \n", i); + if (sdma_v4_0_query_ras_error_count_by_instance(adev, i, ras_error_status)) { + dev_err(adev->dev, "Query ras error count failed in SDMA%d\n", i); return; } } @@ -2814,7 +2814,7 @@ static void sdma_v4_0_set_ras_funcs(struct amdgpu_device *adev) if (adev->sdma.ras) { amdgpu_ras_register_ras_block(adev, &adev->sdma.ras->ras_block); - strcpy(adev->sdma.ras->ras_block.name,"sdma"); + strcpy(adev->sdma.ras->ras_block.name, "sdma"); adev->sdma.ras->ras_block.block = AMDGPU_RAS_BLOCK__SDMA; /* If don't define special ras_late_init function, use default ras_late_init */ diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c index 5c1ba1116e5c..6f9895cdddb1 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4.c @@ -248,10 +248,10 @@ static void sdma_v4_4_reset_ras_error_count(struct amdgpu_device *adev) static void sdma_v4_4_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { int i = 0; + for (i = 0; i < adev->sdma.num_instances; i++) { - if (sdma_v4_4_query_ras_error_count_by_instance(adev, i, ras_error_status)) - { - dev_err(adev->dev, "Query ras error count failed in SDMA%d \n", i); + if (sdma_v4_4_query_ras_error_count_by_instance(adev, i, ras_error_status)) { + dev_err(adev->dev, "Query ras error count failed in SDMA%d\n", i); return; } } From 71b6c4a277dbb2594c260ccedcafaef5154b0da0 Mon Sep 17 00:00:00 2001 From: yipechai Date: Fri, 14 Jan 2022 10:40:15 +0800 Subject: [PATCH 065/339] drm/amdgpu: Fix the code style warnings in hdp xgmi mca and umc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm/amdgpu: Fix the code style warnings in hdp xgmi mca and umc: 1. WARNING: missing space after struct definition. 2. WARNING: please, no space before tabs. 3. WARNING: line length of xxx exceeds 100 columns. 4. ERROR: "foo* bar" should be "foo *bar". 5. ERROR: space required before the open parenthesis '('. 6. ERROR: space prohibited after that open parenthesis '('. Signed-off-by: yipechai Reviewed-by: Tao Zhou Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 3 ++- drivers/gpu/drm/amd/amdgpu/mca_v3_0.c | 7 ++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h index c94a4b3c8d6d..4af2c2a322e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hdp.h @@ -24,7 +24,7 @@ #define __AMDGPU_HDP_H__ #include "amdgpu_ras.h" -struct amdgpu_hdp_ras{ +struct amdgpu_hdp_ras { struct amdgpu_ras_block_object ras_block; }; @@ -40,7 +40,7 @@ struct amdgpu_hdp_funcs { struct amdgpu_hdp { struct ras_common_if *ras_if; const struct amdgpu_hdp_funcs *funcs; - struct amdgpu_hdp_ras *ras; + struct amdgpu_hdp_ras *ras; }; int amdgpu_hdp_ras_late_init(struct amdgpu_device *adev, void *ras_info); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 478457637d29..5929d6f528c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -950,7 +950,8 @@ static void amdgpu_xgmi_query_ras_error_count(struct amdgpu_device *adev, static int amdgpu_ras_error_inject_xgmi(struct amdgpu_device *adev, void *inject_if) { int ret = 0; - struct ta_ras_trigger_error_input *block_info = (struct ta_ras_trigger_error_input *)inject_if; + struct ta_ras_trigger_error_input *block_info = + (struct ta_ras_trigger_error_input *)inject_if; if (amdgpu_dpm_set_df_cstate(adev, DF_CSTATE_DISALLOW)) dev_warn(adev->dev, "Failed to disallow df cstate"); diff --git a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c index f51092041edc..68565262af9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c @@ -47,12 +47,13 @@ static void mca_v3_0_mp0_ras_fini(struct amdgpu_device *adev) amdgpu_mca_ras_fini(adev, &adev->mca.mp0); } -static int mca_v3_0_ras_block_match(struct amdgpu_ras_block_object* block_obj, enum amdgpu_ras_block block, uint32_t sub_block_index) +static int mca_v3_0_ras_block_match(struct amdgpu_ras_block_object *block_obj, + enum amdgpu_ras_block block, uint32_t sub_block_index) { - if(!block_obj) + if (!block_obj) return -EINVAL; - if( (block_obj->block == block) && + if ((block_obj->block == block) && (block_obj->sub_block_index == sub_block_index)) { return 0; } From 22c16d251a79c3156d17627810557878e600dc6a Mon Sep 17 00:00:00 2001 From: Jingwen Chen Date: Thu, 13 Jan 2022 19:06:59 +0800 Subject: [PATCH 066/339] drm/amd/amdgpu: fixing read wrong pf2vf data in SRIOV [Why] This fixes 892deb48269c ("drm/amdgpu: Separate vf2pf work item init from virt data exchange"). we should read pf2vf data based at mman.fw_vram_usage_va after gmc sw_init. commit 892deb48269c breaks this logic. [How] calling amdgpu_virt_exchange_data in amdgpu_virt_init_data_exchange to set the right base in the right sequence. v2: call amdgpu_virt_init_data_exchange after gmc sw_init to make data exchange workqueue run v3: clean up the code logic v4: add some comment and make the code more readable Fixes: 892deb48269c ("drm/amdgpu: Separate vf2pf work item init from virt data exchange") Signed-off-by: Jingwen Chen Reviewed-by: Horace Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d363ae2da5c5..f0c07523b04d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2354,7 +2354,7 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) } if (amdgpu_sriov_vf(adev)) - amdgpu_virt_exchange_data(adev); + amdgpu_virt_init_data_exchange(adev); r = amdgpu_ib_pool_init(adev); if (r) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 894444ab0032..07bc0f504713 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -625,20 +625,20 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) adev->virt.fw_reserve.p_vf2pf = NULL; adev->virt.vf2pf_update_interval_ms = 0; - if (adev->bios != NULL) { - adev->virt.vf2pf_update_interval_ms = 2000; + if (adev->mman.fw_vram_usage_va != NULL) { + /* go through this logic in ip_init and reset to init workqueue*/ + amdgpu_virt_exchange_data(adev); + INIT_DELAYED_WORK(&adev->virt.vf2pf_work, amdgpu_virt_update_vf2pf_work_item); + schedule_delayed_work(&(adev->virt.vf2pf_work), msecs_to_jiffies(adev->virt.vf2pf_update_interval_ms)); + } else if (adev->bios != NULL) { + /* got through this logic in early init stage to get necessary flags, e.g. rlcg_acc related*/ adev->virt.fw_reserve.p_pf2vf = (struct amd_sriov_msg_pf2vf_info_header *) (adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10)); amdgpu_virt_read_pf2vf_data(adev); } - - if (adev->virt.vf2pf_update_interval_ms != 0) { - INIT_DELAYED_WORK(&adev->virt.vf2pf_work, amdgpu_virt_update_vf2pf_work_item); - schedule_delayed_work(&(adev->virt.vf2pf_work), msecs_to_jiffies(adev->virt.vf2pf_update_interval_ms)); - } } @@ -674,12 +674,6 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev) if (adev->virt.ras_init_done) amdgpu_virt_add_bad_page(adev, bp_block_offset, bp_block_size); } - } else if (adev->bios != NULL) { - adev->virt.fw_reserve.p_pf2vf = - (struct amd_sriov_msg_pf2vf_info_header *) - (adev->bios + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10)); - - amdgpu_virt_read_pf2vf_data(adev); } } From f3527a6483fbccbf569f91d9ee9c561b14d86a9f Mon Sep 17 00:00:00 2001 From: Marina Nikolic Date: Fri, 14 Jan 2022 00:46:33 +0800 Subject: [PATCH 067/339] drm/amd/pm: Enable sysfs required by rocm-smi tool for One VF mode Enable power level, power limit and fan speed information retrieval in one VF mode. This is required so that tool ROCM-SMI can provide this information to users. Signed-off-by: Marina Nikolic Acked-by: Evan Quan Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 17 ++--------------- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 49a9c6375343..837a31a46596 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1903,8 +1903,8 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_sclk_od, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_mclk_od, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_power_profile_mode, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), @@ -3152,19 +3152,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return 0; - /* there is no fan under pp one vf mode */ - if (amdgpu_sriov_is_pp_one_vf(adev) && - (attr == &sensor_dev_attr_pwm1.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_input.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_target.dev_attr.attr || - attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) - return 0; - /* Skip fan attributes if fan is not present */ if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index eb47d490ee9d..c29353e05fd2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -141,7 +141,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), - MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), From 47f29ac1cbae6e18329f0066f7c8d5d2346a5bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 17 Jan 2022 10:31:26 +0100 Subject: [PATCH 068/339] drm/radeon: fix error handling in radeon_driver_open_kms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return value was never initialized so the cleanup code executed when it isn't even necessary. Just add proper error handling. Fixes: ab50cb9df889 ("drm/radeon/radeon_kms: Fix a NULL pointer dereference in radeon_driver_open_kms()") Signed-off-by: Christian König Tested-by: Jan Stancek Tested-by: Borislav Petkov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index e2488559cc9f..11ad210919c8 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -666,18 +666,18 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL); if (unlikely(!fpriv)) { r = -ENOMEM; - goto out_suspend; + goto err_suspend; } if (rdev->accel_working) { vm = &fpriv->vm; r = radeon_vm_init(rdev, vm); if (r) - goto out_fpriv; + goto err_fpriv; r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); if (r) - goto out_vm_fini; + goto err_vm_fini; /* map the ib pool buffer read only into * virtual address space */ @@ -685,7 +685,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) rdev->ring_tmp_bo.bo); if (!vm->ib_bo_va) { r = -ENOMEM; - goto out_vm_fini; + goto err_vm_fini; } r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va, @@ -693,19 +693,21 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) RADEON_VM_PAGE_READABLE | RADEON_VM_PAGE_SNOOPED); if (r) - goto out_vm_fini; + goto err_vm_fini; } file_priv->driver_priv = fpriv; } - if (!r) - goto out_suspend; + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); + return 0; -out_vm_fini: +err_vm_fini: radeon_vm_fini(rdev, vm); -out_fpriv: +err_fpriv: kfree(fpriv); -out_suspend: + +err_suspend: pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); return r; From 7aba117ac9e01dc58afe29490f50025add9d388b Mon Sep 17 00:00:00 2001 From: Jarif Aftab Date: Tue, 16 Nov 2021 18:24:06 -0500 Subject: [PATCH 069/339] drm/amd/display: Disabled seamless boots on DP and renamed power_down_display_on_boot [WHY] - We only ever want seamless boots on eDPs - The naming and logic did not match the context [HOW] - Removed unnecessary if statements - Renamed power_down_display_on_boot to seamless_boot_edp_requested and swapped the logic Reviewed-by: Martin Leung Acked-by: Rodrigo Siqueira Signed-off-by: Jarif Aftab Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 12 ------------ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 5 ++--- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 7 +++---- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 5 ++--- 6 files changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6692c8f75f23..8a46b8430f1e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1496,10 +1496,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_data.flags.allow_lttpr_non_transparent_mode.bits.DP2_0 = true; #endif - init_data.flags.power_down_display_on_boot = true; + init_data.flags.seamless_boot_edp_requested = false; if (check_seamless_boot_capability(adev)) { - init_data.flags.power_down_display_on_boot = false; + init_data.flags.seamless_boot_edp_requested = true; init_data.flags.allow_seamless_boot_optimization = true; DRM_INFO("Seamless boot condition check passed\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index b5e570d33ca9..0c64dea4fdd8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1019,18 +1019,6 @@ static bool dc_link_detect_helper(struct dc_link *link, link->type != dc_connection_mst_branch) dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); - - // For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified. - if (reason == DETECT_REASON_BOOT && - !dc_ctx->dc->config.power_down_display_on_boot && - link->link_status.link_active) - perform_dp_seamless_boot = true; - - if (perform_dp_seamless_boot) { - read_current_link_settings_on_detect(link); - link->verified_link_cap = link->reported_link_cap; - } - break; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 288e7b01f561..263f7edd42a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -322,7 +322,7 @@ struct dc_config { bool fbc_support; bool disable_fractional_pwm; bool allow_seamless_boot_optimization; - bool power_down_display_on_boot; + bool seamless_boot_edp_requested; bool edp_not_connected; bool edp_no_power_sequencing; bool force_enum_edp; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 530a72e3eefe..915eecb40788 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1505,8 +1505,7 @@ void dcn10_init_hw(struct dc *dc) dmub_enable_outbox_notification(dc); /* we want to turn off all dp displays before doing detection */ - if (dc->config.power_down_display_on_boot) - dc_link_blank_all_dp_displays(dc); + dc_link_blank_all_dp_displays(dc); /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which @@ -1514,7 +1513,7 @@ void dcn10_init_hw(struct dc *dc) * Otherwise, if taking control is not possible, we need to power * everything down. */ - if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) { + if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) { if (!is_optimized_init_done) { hws->funcs.init_pipes(dc, dc->current_state); if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 1db1ca19411d..ed0a0e5fd805 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -545,8 +545,7 @@ void dcn30_init_hw(struct dc *dc) hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false); /* we want to turn off all dp displays before doing detection */ - if (dc->config.power_down_display_on_boot) - dc_link_blank_all_dp_displays(dc); + dc_link_blank_all_dp_displays(dc); /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which @@ -554,7 +553,7 @@ void dcn30_init_hw(struct dc *dc) * Otherwise, if taking control is not possible, we need to power * everything down. */ - if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) { + if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) { hws->funcs.init_pipes(dc, dc->current_state); if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, @@ -566,7 +565,7 @@ void dcn30_init_hw(struct dc *dc) * To avoid this, power down hardware on boot * if DIG is turned on and seamless boot not enabled */ - if (dc->config.power_down_display_on_boot) { + if (!dc->config.seamless_boot_edp_requested) { struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 4206ce5bf9a9..b2cfd277b913 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -197,8 +197,7 @@ void dcn31_init_hw(struct dc *dc) dmub_enable_outbox_notification(dc); /* we want to turn off all dp displays before doing detection */ - if (dc->config.power_down_display_on_boot) - dc_link_blank_all_dp_displays(dc); + dc_link_blank_all_dp_displays(dc); /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which @@ -206,7 +205,7 @@ void dcn31_init_hw(struct dc *dc) * Otherwise, if taking control is not possible, we need to power * everything down. */ - if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) { + if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) { hws->funcs.init_pipes(dc, dc->current_state); if (dc->res_pool->hubbub->funcs->allow_self_refresh_control) dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, From fd9048dd4425a9dc252153c8b72369f1969a35b3 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Fri, 10 Dec 2021 12:28:57 -0500 Subject: [PATCH 070/339] drm/amd/display: adjust bit comparison to be more type safe Might potentially have truncation problem with the implicit casting Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Eric Yang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index fa0569174aec..82c651535628 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -441,7 +441,7 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti bool dmub_dcn31_should_detect(struct dmub_srv *dmub) { uint32_t fw_boot_status = REG_READ(DMCUB_SCRATCH0); - bool should_detect = fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED; + bool should_detect = (fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED) != 0; return should_detect; } From b4c55e525461a9a091421e952d1e052127d558a8 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 15 Dec 2021 17:09:05 -0500 Subject: [PATCH 071/339] drm/amd/display: support new PMFW interface to disable Z9 only [Why] Need to disable Z9 on configurations that only support Z10 [How] Support new PMFW interface to disable Z9 Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Eric Yang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 6 +++--- .../drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c | 15 ++++++++++----- .../drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.h | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 8 +++++++- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 4162ce40089b..66bd0261ead6 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -139,9 +139,9 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, * also if safe to lower is false, we just go in the higher state */ if (safe_to_lower) { - if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_ALLOW && + if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW && new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { - dcn31_smu_set_Z9_support(clk_mgr, true); + dcn31_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support); dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true); clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; } @@ -167,7 +167,7 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, } else { if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { - dcn31_smu_set_Z9_support(clk_mgr, false); + dcn31_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW); dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false); clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c index a1011f3273f3..1c0415366216 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c @@ -306,23 +306,28 @@ void dcn31_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr) VBIOSSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS); } -void dcn31_smu_set_Z9_support(struct clk_mgr_internal *clk_mgr, bool support) +void dcn31_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support) { //TODO: Work with smu team to define optimization options. - unsigned int msg_id; + unsigned int msg_id, param; if (!clk_mgr->smu_present) return; - if (support) - msg_id = VBIOSSMC_MSG_AllowZstatesEntry; + if (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY) + param = 1; else + param = 0; + + if (support == DCN_ZSTATE_SUPPORT_DISALLOW) msg_id = VBIOSSMC_MSG_DisallowZstatesEntry; + else + msg_id = VBIOSSMC_MSG_AllowZstatesEntry; dcn31_smu_send_msg_with_param( clk_mgr, msg_id, - 0); + param); } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.h index cd0b7e1e685f..dfa25a76a6d1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.h @@ -265,7 +265,7 @@ void dcn31_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr void dcn31_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr); void dcn31_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); -void dcn31_smu_set_Z9_support(struct clk_mgr_internal *clk_mgr, bool support); +void dcn31_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support); void dcn31_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable); #endif /* DAL_DC_31_SMU_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 263f7edd42a4..b5e15da29017 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -396,6 +396,7 @@ enum dcn_pwr_state { enum dcn_zstate_support_state { DCN_ZSTATE_SUPPORT_UNKNOWN, DCN_ZSTATE_SUPPORT_ALLOW, + DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY, DCN_ZSTATE_SUPPORT_DISALLOW, }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 2bc93df023ad..d0a5c7afa265 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3093,8 +3093,14 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { struct dc_link *link = context->streams[0]->sink->link; - if (link->link_index == 0 && context->bw_ctx.dml.vba.StutterPeriod > 5000.0) + /* zstate only supported on PWRSEQ0 */ + if (link->link_index != 0) + return DCN_ZSTATE_SUPPORT_DISALLOW; + + if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0) return DCN_ZSTATE_SUPPORT_ALLOW; + else if (link->psr_settings.psr_feature_enabled) + return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; else return DCN_ZSTATE_SUPPORT_DISALLOW; } else From 82dcd8eb357caf4b16e6a201f6578b6e8795e541 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 3 Jan 2022 23:51:57 -0500 Subject: [PATCH 072/339] drm/amd/display: 3.2.168 This version brings improvements in the following: - Drop unnecessary DCN guards - Improve Z9 interface Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b5e15da29017..1c6728cf2d49 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.167" +#define DC_VER "3.2.168" #define MAX_SURFACES 3 #define MAX_PLANES 6 From f369e4eba89a6fc1cac619db86c00a964d1fc0a2 Mon Sep 17 00:00:00 2001 From: Jasdeep Dhillon Date: Wed, 5 Jan 2022 15:59:04 -0500 Subject: [PATCH 073/339] drm/amd/display: move FPU associated DCN302 code to DML folder (#2266) [Why & How] As part of the FPU isolation work documented in https://patchwork.freedesktop.org/series/93042/, isolate code that uses FPU in DCN302 to DML, where all FPU code should locate. Co-authored-by: Jasdeep Dhillon Reviewed-by: Rodrigo Siqueira Acked-by: Wayne Lin Signed-off-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn302/Makefile | 12 - .../amd/display/dc/dcn302/dcn302_resource.c | 316 +--------------- .../amd/display/dc/dcn302/dcn302_resource.h | 3 + drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 + .../amd/display/dc/dml/dcn302/dcn302_fpu.c | 357 ++++++++++++++++++ .../amd/display/dc/dml/dcn302/dcn302_fpu.h | 32 ++ 6 files changed, 404 insertions(+), 318 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile index 101620a8867a..f9561d7f97a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn302/Makefile @@ -1,11 +1,6 @@ # # (c) Copyright 2020 Advanced Micro Devices, Inc. All the rights reserved # -# All rights reserved. This notice is intended as a precaution against -# inadvertent publication and does not imply publication or any waiver -# of confidentiality. The year included in the foregoing notice is the -# year of creation of the work. -# # Authors: AMD # # Makefile for dcn302. @@ -20,13 +15,6 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o := -mhard-float -maltivec endif -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -CFLAGS_$(AMDDALPATH)/dc/dcn302/dcn302_resource.o += -mhard-float -endif - ifdef CONFIG_X86 ifdef IS_OLD_GCC # Stack alignment mismatch, proceed with caution. diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 2e9cbfa7663b..e512ae6d00d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -61,6 +61,8 @@ #include "resource.h" #include "vm_helper.h" +#include "dml/dcn302/dcn302_fpu.h" + #include "dimgrey_cavefish_ip_offset.h" #include "dcn/dcn_3_0_2_offset.h" #include "dcn/dcn_3_0_2_sh_mask.h" @@ -71,140 +73,6 @@ #define DC_LOGGER_INIT(logger) -struct _vcs_dpi_ip_params_st dcn3_02_ip = { - .use_min_dcfclk = 0, - .clamp_min_dcfclk = 0, - .odm_capable = 1, - .gpuvm_enable = 1, - .hostvm_enable = 0, - .gpuvm_max_page_table_levels = 4, - .hostvm_max_page_table_levels = 4, - .hostvm_cached_page_table_levels = 0, - .pte_group_size_bytes = 2048, - .num_dsc = 5, - .rob_buffer_size_kbytes = 184, - .det_buffer_size_kbytes = 184, - .dpte_buffer_size_in_pte_reqs_luma = 64, - .dpte_buffer_size_in_pte_reqs_chroma = 34, - .pde_proc_buffer_size_64k_reqs = 48, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .pte_enable = 1, - .max_page_table_levels = 2, - .pte_chunk_size_kbytes = 2, // ? - .meta_chunk_size_kbytes = 2, - .writeback_chunk_size_kbytes = 8, - .line_buffer_size_bits = 789504, - .is_line_buffer_bpp_fixed = 0, // ? - .line_buffer_fixed_bpp = 0, // ? - .dcc_supported = true, - .writeback_interface_buffer_size_kbytes = 90, - .writeback_line_buffer_buffer_size = 0, - .max_line_buffer_lines = 12, - .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 - .writeback_chroma_buffer_size_kbytes = 8, - .writeback_chroma_line_buffer_width_pixels = 4, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_taps = 1, - .writeback_max_vscl_taps = 1, - .writeback_line_buffer_luma_buffer_size = 0, - .writeback_line_buffer_chroma_buffer_size = 14643, - .cursor_buffer_size = 8, - .cursor_chunk_size = 2, - .max_num_otg = 5, - .max_num_dpp = 5, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 6, - .max_vscl_ratio = 6, - .hscl_mults = 4, - .vscl_mults = 4, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dispclk_ramp_margin_percent = 1, - .underscan_factor = 1.11, - .min_vblank_lines = 32, - .dppclk_delay_subtotal = 46, - .dynamic_metadata_vm_enabled = true, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_scl = 50, - .dppclk_delay_cnvc_formatter = 27, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 119, - .dcfclk_cstate_latency = 5.2, // SRExitTime - .max_inter_dcn_tile_repeaters = 8, - .max_num_hdmi_frl_outputs = 1, - .odm_combine_4to1_supported = true, - - .xfc_supported = false, - .xfc_fill_bw_overhead_percent = 10.0, - .xfc_fill_constant_bytes = 0, - .gfx7_compat_tiling_supported = 0, - .number_of_cursors = 1, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc = { - .clock_limits = { - { - .state = 0, - .dispclk_mhz = 562.0, - .dppclk_mhz = 300.0, - .phyclk_mhz = 300.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 405.6, - }, - }, - - .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ - .num_states = 1, - .sr_exit_time_us = 26.5, - .sr_enter_plus_exit_time_us = 31, - .urgent_latency_us = 4.0, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 40.0, - .writeback_latency_us = 12.0, - .max_request_size_bytes = 256, - .fabric_datapath_to_dcn_data_return_bytes = 64, - .dcn_downspread_percent = 0.5, - .downspread_percent = 0.38, - .dram_page_open_time_ns = 50.0, - .dram_rw_turnaround_time_ns = 17.5, - .dram_return_buffer_per_channel_bytes = 8192, - .round_trip_ping_latency_dcfclk_cycles = 156, - .urgent_out_of_order_return_per_channel_bytes = 4096, - .channel_interleave_bytes = 256, - .num_banks = 8, - .gpuvm_min_page_size_bytes = 4096, - .hostvm_min_page_size_bytes = 4096, - .dram_clock_change_latency_us = 404, - .dummy_pstate_latency_us = 5, - .writeback_dram_clock_change_latency_us = 23.0, - .return_bus_width_bytes = 64, - .dispclk_dppclk_vco_speed_mhz = 3650, - .xfc_bus_transport_time_us = 20, // ? - .xfc_xbuf_latency_tolerance_us = 4, // ? - .use_urgent_burst_bw = 1, // ? - .do_urgent_latency_adjustment = true, - .urgent_latency_adjustment_fabric_clock_component_us = 1.0, - .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000, -}; - static const struct dc_debug_options debug_defaults_drv = { .disable_dmcu = true, .force_abm_enable = false, @@ -1105,24 +973,19 @@ static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) loaded_ip->max_num_otg = pool->pipe_count; loaded_ip->max_num_dpp = pool->pipe_count; loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; + DC_FP_START(); dcn20_patch_bounding_box(dc, loaded_bb); + DC_FP_END(); if (dc->ctx->dc_bios->funcs->get_soc_bb_info) { struct bp_soc_bb_info bb_info = { 0 }; if (dc->ctx->dc_bios->funcs->get_soc_bb_info( dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) { - if (bb_info.dram_clock_change_latency_100ns > 0) - dcn3_02_soc.dram_clock_change_latency_us = - bb_info.dram_clock_change_latency_100ns * 10; - if (bb_info.dram_sr_enter_exit_latency_100ns > 0) - dcn3_02_soc.sr_enter_plus_exit_time_us = - bb_info.dram_sr_enter_exit_latency_100ns * 10; - - if (bb_info.dram_sr_exit_latency_100ns > 0) - dcn3_02_soc.sr_exit_time_us = - bb_info.dram_sr_exit_latency_100ns * 10; + DC_FP_START(); + dcn302_fpu_init_soc_bounding_box(bb_info); + DC_FP_END(); } } @@ -1257,170 +1120,11 @@ static void dcn302_destroy_resource_pool(struct resource_pool **pool) *pool = NULL; } -static void dcn302_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, - unsigned int *optimal_dcfclk, - unsigned int *optimal_fclk) -{ - double bw_from_dram, bw_from_dram1, bw_from_dram2; - - bw_from_dram1 = uclk_mts * dcn3_02_soc.num_chans * - dcn3_02_soc.dram_channel_width_bytes * (dcn3_02_soc.max_avg_dram_bw_use_normal_percent / 100); - bw_from_dram2 = uclk_mts * dcn3_02_soc.num_chans * - dcn3_02_soc.dram_channel_width_bytes * (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100); - - bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2; - - if (optimal_fclk) - *optimal_fclk = bw_from_dram / - (dcn3_02_soc.fabric_datapath_to_dcn_data_return_bytes * (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100)); - - if (optimal_dcfclk) - *optimal_dcfclk = bw_from_dram / - (dcn3_02_soc.return_bus_width_bytes * (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100)); -} - void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { - unsigned int i, j; - unsigned int num_states = 0; - - unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0}; - unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0}; - unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0}; - unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0}; - - unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200}; - unsigned int num_dcfclk_sta_targets = 4; - unsigned int num_uclk_states; - - - if (dc->ctx->dc_bios->vram_info.num_chans) - dcn3_02_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; - - if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) - dcn3_02_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; - - dcn3_02_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; - dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; - - if (bw_params->clk_table.entries[0].memclk_mhz) { - int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0; - - for (i = 0; i < MAX_NUM_DPM_LVL; i++) { - if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz) - max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; - if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz) - max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; - if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz) - max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; - if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz) - max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; - } - if (!max_dcfclk_mhz) - max_dcfclk_mhz = dcn3_02_soc.clock_limits[0].dcfclk_mhz; - if (!max_dispclk_mhz) - max_dispclk_mhz = dcn3_02_soc.clock_limits[0].dispclk_mhz; - if (!max_dppclk_mhz) - max_dppclk_mhz = dcn3_02_soc.clock_limits[0].dppclk_mhz; - if (!max_phyclk_mhz) - max_phyclk_mhz = dcn3_02_soc.clock_limits[0].phyclk_mhz; - - if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { - /* If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array */ - dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz; - num_dcfclk_sta_targets++; - } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { - /* If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates */ - for (i = 0; i < num_dcfclk_sta_targets; i++) { - if (dcfclk_sta_targets[i] > max_dcfclk_mhz) { - dcfclk_sta_targets[i] = max_dcfclk_mhz; - break; - } - } - /* Update size of array since we "removed" duplicates */ - num_dcfclk_sta_targets = i + 1; - } - - num_uclk_states = bw_params->clk_table.num_entries; - - /* Calculate optimal dcfclk for each uclk */ - for (i = 0; i < num_uclk_states; i++) { - dcn302_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16, - &optimal_dcfclk_for_uclk[i], NULL); - if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) { - optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz; - } - } - - /* Calculate optimal uclk for each dcfclk sta target */ - for (i = 0; i < num_dcfclk_sta_targets; i++) { - for (j = 0; j < num_uclk_states; j++) { - if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) { - optimal_uclk_for_dcfclk_sta_targets[i] = - bw_params->clk_table.entries[j].memclk_mhz * 16; - break; - } - } - } - - i = 0; - j = 0; - /* create the final dcfclk and uclk table */ - while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) { - if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) { - dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; - dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; - } else { - if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { - dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; - dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; - } else { - j = num_uclk_states; - } - } - } - - while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) { - dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; - dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; - } - - while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES && - optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { - dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; - dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; - } - - dcn3_02_soc.num_states = num_states; - for (i = 0; i < dcn3_02_soc.num_states; i++) { - dcn3_02_soc.clock_limits[i].state = i; - dcn3_02_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i]; - dcn3_02_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i]; - dcn3_02_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i]; - - /* Fill all states with max values of all other clocks */ - dcn3_02_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz; - dcn3_02_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz; - dcn3_02_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz; - /* Populate from bw_params for DTBCLK, SOCCLK */ - if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0) - dcn3_02_soc.clock_limits[i].dtbclk_mhz = dcn3_02_soc.clock_limits[i-1].dtbclk_mhz; - else - dcn3_02_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz; - if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0) - dcn3_02_soc.clock_limits[i].socclk_mhz = dcn3_02_soc.clock_limits[i-1].socclk_mhz; - else - dcn3_02_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz; - /* These clocks cannot come from bw_params, always fill from dcn3_02_soc[1] */ - /* FCLK, PHYCLK_D18, DSCCLK */ - dcn3_02_soc.clock_limits[i].phyclk_d18_mhz = dcn3_02_soc.clock_limits[0].phyclk_d18_mhz; - dcn3_02_soc.clock_limits[i].dscclk_mhz = dcn3_02_soc.clock_limits[0].dscclk_mhz; - } - /* re-init DML with updated bb */ - dml_init_instance(&dc->dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30); - if (dc->current_state) - dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30); - } + DC_FP_START(); + dcn302_fpu_update_bw_bounding_box(dc, bw_params); + DC_FP_END(); } static struct resource_funcs dcn302_res_pool_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h index 42d2c73e30bc..9f24e73b92b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.h @@ -28,6 +28,9 @@ #include "core_types.h" +extern struct _vcs_dpi_ip_params_st dcn3_02_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc; + struct resource_pool *dcn302_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index eee6672bd32d..06910b1f5965 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -71,6 +71,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) @@ -104,6 +105,7 @@ DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o DML += dcn301/dcn301_fpu.o +DML += dcn302/dcn302_fpu.o DML += dsc/rc_calc_fpu.o endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.c new file mode 100644 index 000000000000..e2bcd205aa93 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.c @@ -0,0 +1,357 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "resource.h" +#include "clk_mgr.h" +#include "dcn20/dcn20_resource.h" +#include "dcn302/dcn302_resource.h" + +#include "dml/dcn20/dcn20_fpu.h" +#include "dcn302_fpu.h" + +struct _vcs_dpi_ip_params_st dcn3_02_ip = { + .use_min_dcfclk = 0, + .clamp_min_dcfclk = 0, + .odm_capable = 1, + .gpuvm_enable = 1, + .hostvm_enable = 0, + .gpuvm_max_page_table_levels = 4, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 0, + .pte_group_size_bytes = 2048, + .num_dsc = 5, + .rob_buffer_size_kbytes = 184, + .det_buffer_size_kbytes = 184, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .pde_proc_buffer_size_64k_reqs = 48, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_enable = 1, + .max_page_table_levels = 2, + .pte_chunk_size_kbytes = 2, // ? + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 8, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, // ? + .line_buffer_fixed_bpp = 0, // ? + .dcc_supported = true, + .writeback_interface_buffer_size_kbytes = 90, + .writeback_line_buffer_buffer_size = 0, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 14643, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 5, + .max_num_dpp = 5, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.11, + .min_vblank_lines = 32, + .dppclk_delay_subtotal = 46, + .dynamic_metadata_vm_enabled = true, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dcfclk_cstate_latency = 5.2, // SRExitTime + .max_inter_dcn_tile_repeaters = 8, + .max_num_hdmi_frl_outputs = 1, + .odm_combine_4to1_supported = true, + + .xfc_supported = false, + .xfc_fill_bw_overhead_percent = 10.0, + .xfc_fill_constant_bytes = 0, + .gfx7_compat_tiling_supported = 0, + .number_of_cursors = 1, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc = { + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 562.0, + .dppclk_mhz = 300.0, + .phyclk_mhz = 300.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 405.6, + }, + }, + + .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ + .num_states = 1, + .sr_exit_time_us = 26.5, + .sr_enter_plus_exit_time_us = 31, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 40.0, + .writeback_latency_us = 12.0, + .max_request_size_bytes = 256, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 156, + .urgent_out_of_order_return_per_channel_bytes = 4096, + .channel_interleave_bytes = 256, + .num_banks = 8, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .dram_clock_change_latency_us = 404, + .dummy_pstate_latency_us = 5, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3650, + .xfc_bus_transport_time_us = 20, // ? + .xfc_xbuf_latency_tolerance_us = 4, // ? + .use_urgent_burst_bw = 1, // ? + .do_urgent_latency_adjustment = true, + .urgent_latency_adjustment_fabric_clock_component_us = 1.0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000, +}; + +static void dcn302_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, + unsigned int *optimal_dcfclk, + unsigned int *optimal_fclk) +{ + + double bw_from_dram, bw_from_dram1, bw_from_dram2; + + bw_from_dram1 = uclk_mts * dcn3_02_soc.num_chans * + dcn3_02_soc.dram_channel_width_bytes * + (dcn3_02_soc.max_avg_dram_bw_use_normal_percent / 100); + bw_from_dram2 = uclk_mts * dcn3_02_soc.num_chans * + dcn3_02_soc.dram_channel_width_bytes * + (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100); + + bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2; + + if (optimal_fclk) + *optimal_fclk = bw_from_dram / + (dcn3_02_soc.fabric_datapath_to_dcn_data_return_bytes * + (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100)); + + if (optimal_dcfclk) + *optimal_dcfclk = bw_from_dram / + (dcn3_02_soc.return_bus_width_bytes * + (dcn3_02_soc.max_avg_sdp_bw_use_normal_percent / 100)); +} + +void dcn302_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + unsigned int i, j; + unsigned int num_states = 0; + + unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0}; + unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0}; + + unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200}; + unsigned int num_dcfclk_sta_targets = 4; + unsigned int num_uclk_states; + + dc_assert_fp_enabled(); + + if (dc->ctx->dc_bios->vram_info.num_chans) + dcn3_02_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + + if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) + dcn3_02_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; + + dcn3_02_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + + if (bw_params->clk_table.entries[0].memclk_mhz) { + int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0; + + for (i = 0; i < MAX_NUM_DPM_LVL; i++) { + if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz) + max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; + if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; + if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; + if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz) + max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; + } + if (!max_dcfclk_mhz) + max_dcfclk_mhz = dcn3_02_soc.clock_limits[0].dcfclk_mhz; + if (!max_dispclk_mhz) + max_dispclk_mhz = dcn3_02_soc.clock_limits[0].dispclk_mhz; + if (!max_dppclk_mhz) + max_dppclk_mhz = dcn3_02_soc.clock_limits[0].dppclk_mhz; + if (!max_phyclk_mhz) + max_phyclk_mhz = dcn3_02_soc.clock_limits[0].phyclk_mhz; + + if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + /* If max DCFCLK is greater than the max DCFCLK STA target, insert into the DCFCLK STA target array */ + dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz; + num_dcfclk_sta_targets++; + } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + /* If max DCFCLK is less than the max DCFCLK STA target, cap values and remove duplicates */ + for (i = 0; i < num_dcfclk_sta_targets; i++) { + if (dcfclk_sta_targets[i] > max_dcfclk_mhz) { + dcfclk_sta_targets[i] = max_dcfclk_mhz; + break; + } + } + /* Update size of array since we "removed" duplicates */ + num_dcfclk_sta_targets = i + 1; + } + + num_uclk_states = bw_params->clk_table.num_entries; + + /* Calculate optimal dcfclk for each uclk */ + for (i = 0; i < num_uclk_states; i++) { + dcn302_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16, + &optimal_dcfclk_for_uclk[i], NULL); + if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) + optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz; + } + + /* Calculate optimal uclk for each dcfclk sta target */ + for (i = 0; i < num_dcfclk_sta_targets; i++) { + for (j = 0; j < num_uclk_states; j++) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) { + optimal_uclk_for_dcfclk_sta_targets[i] = + bw_params->clk_table.entries[j].memclk_mhz * 16; + break; + } + } + } + + i = 0; + j = 0; + /* create the final dcfclk and uclk table */ + while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } else { + if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; + } else { + j = num_uclk_states; + } + } + } + + while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } + + while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES && + optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; + } + + dcn3_02_soc.num_states = num_states; + for (i = 0; i < dcn3_02_soc.num_states; i++) { + dcn3_02_soc.clock_limits[i].state = i; + dcn3_02_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i]; + dcn3_02_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i]; + dcn3_02_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i]; + + /* Fill all states with max values of all other clocks */ + dcn3_02_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz; + dcn3_02_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz; + dcn3_02_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz; + /* Populate from bw_params for DTBCLK, SOCCLK */ + if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0) + dcn3_02_soc.clock_limits[i].dtbclk_mhz = dcn3_02_soc.clock_limits[i-1].dtbclk_mhz; + else + dcn3_02_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz; + if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0) + dcn3_02_soc.clock_limits[i].socclk_mhz = dcn3_02_soc.clock_limits[i-1].socclk_mhz; + else + dcn3_02_soc.clock_limits[i].socclk_mhz = bw_params->clk_table.entries[i].socclk_mhz; + /* These clocks cannot come from bw_params, always fill from dcn3_02_soc[1] */ + /* FCLK, PHYCLK_D18, DSCCLK */ + dcn3_02_soc.clock_limits[i].phyclk_d18_mhz = dcn3_02_soc.clock_limits[0].phyclk_d18_mhz; + dcn3_02_soc.clock_limits[i].dscclk_mhz = dcn3_02_soc.clock_limits[0].dscclk_mhz; + } + /* re-init DML with updated bb */ + dml_init_instance(&dc->dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30); + if (dc->current_state) + dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_02_soc, &dcn3_02_ip, DML_PROJECT_DCN30); + } +} + +void dcn302_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info) +{ + + dc_assert_fp_enabled(); + + if (bb_info.dram_clock_change_latency_100ns > 0) + dcn3_02_soc.dram_clock_change_latency_us = + bb_info.dram_clock_change_latency_100ns * 10; + + if (bb_info.dram_sr_enter_exit_latency_100ns > 0) + dcn3_02_soc.sr_enter_plus_exit_time_us = + bb_info.dram_sr_enter_exit_latency_100ns * 10; + + if (bb_info.dram_sr_exit_latency_100ns > 0) + dcn3_02_soc.sr_exit_time_us = + bb_info.dram_sr_exit_latency_100ns * 10; +} + + diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.h new file mode 100644 index 000000000000..548305d96cee --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn302/dcn302_fpu.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019-2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef __DCN302_FPU_H__ +#define __DCN302_FPU_H__ + +void dcn302_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info); +void dcn302_fpu_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +#endif /* __DCN302_FPU_H__*/ From c1a20f707ac33b1fec1d78bab74e07656c237801 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Tue, 21 Dec 2021 11:17:30 +0800 Subject: [PATCH 074/339] drm/amd/display: modify SMU_TIMEOUT macro. [WHY] If some SMU features are not enabled, SMU will return fail to that message. [HOW] SMU_TIMEOUT macro will treat "return fail" as timeout also. Correct the macro to only report timeout case. Reviewed-by: Jun Lei Acked-by: Wayne Lin Signed-off-by: Ian Chen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 7f94e3f70d7f..a5497ba89f15 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -170,9 +170,9 @@ bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enabl void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us); -// 0x1 = Result_OK, 0xFE = Result_UnkmownCmd +// 0x1 = Result_OK, 0xFE = Result_UnkmownCmd, 0x0 = Status_Busy #define IS_SMU_TIMEOUT(result) \ - (!(result == 0x1 || result == 0xFE)) + (result == 0x0) int dm_helper_dmub_aux_transfer_sync( struct dc_context *ctx, From 6421c49567d55b1ba8d9389e5832297398a51a1c Mon Sep 17 00:00:00 2001 From: Chris Park Date: Wed, 5 Jan 2022 23:39:56 -0500 Subject: [PATCH 075/339] drm/amd/display: DCEFCLK DS on CLK init [Why] On HG APU + dGPU scenario with no display to dGPU, DS stays disabled due to no display present. This problem can be worked around by DAL calling DCEFCLK DS message to SMU on clk init. [How] Call DCEFCLK DS message to SMU on clk init. Reviewed-by: Jun Lei Acked-by: Wayne Lin Signed-off-by: Chris Park Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index f977f29907df..0602bde78e6c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -184,6 +184,7 @@ void dcn3_init_clocks(struct clk_mgr *clk_mgr_base) dcn3_init_single_clock(clk_mgr, PPCLK_DCEFCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, &num_levels); + dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, 0); /* DTBCLK */ dcn3_init_single_clock(clk_mgr, PPCLK_DTBCLK, From 58c69b53aee24f47741b150e309567d9b38ecd6c Mon Sep 17 00:00:00 2001 From: Felipe Clark Date: Thu, 6 Jan 2022 15:30:33 -0500 Subject: [PATCH 076/339] drm/amd/display: Fix black screen issue on memory clock switch en [WHY] With some monitors when multi plane overlay is enabled the memory clock switching mechanism has to change and, due to an error in the initialization sequence, it may cause a black screen. [HOW] Change the firmware assisted memory clock switch initialization and tear-down sequence utilizing the prepare_bandwidth and optimize_bandwidth contexts. Reviewed-by: Aric Cyr Acked-by: Wayne Lin Signed-off-by: Felipe Clark Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 5 +++++ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h | 3 +++ drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index ed0a0e5fd805..dec8604a0612 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -355,6 +355,11 @@ void dcn30_prepare_bandwidth(struct dc *dc, dcn20_prepare_bandwidth(dc, context); } +void dcn30_optimize_bandwidth(struct dc *dc, struct dc_state *context) +{ + dcn20_optimize_bandwidth(dc, context); +} + void dcn30_disable_writeback( struct dc *dc, unsigned int dwb_pipe_inst) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h index 73e7b690e82c..357ee14711ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h @@ -50,6 +50,9 @@ void dcn30_disable_writeback( void dcn30_prepare_bandwidth(struct dc *dc, struct dc_state *context); +void dcn30_optimize_bandwidth(struct dc *dc, + struct dc_state *context); + bool dcn30_mmhubbub_warmup( struct dc *dc, unsigned int num_dwb, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index bb347319de83..73a416cba563 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -60,7 +60,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .interdependent_update_lock = dcn10_lock_all_pipes, .cursor_lock = dcn10_cursor_lock, .prepare_bandwidth = dcn20_prepare_bandwidth, - .optimize_bandwidth = dcn20_optimize_bandwidth, + .optimize_bandwidth = dcn30_optimize_bandwidth, .update_bandwidth = dcn20_update_bandwidth, .set_drr = dcn10_set_drr, .get_position = dcn10_get_position, From 9338cb719f0f0b43ee1ab39d17214f9b388c7fbf Mon Sep 17 00:00:00 2001 From: Charlene Liu Date: Fri, 7 Jan 2022 04:46:36 -0500 Subject: [PATCH 077/339] drm/amd/display: update dml to rev.99 and smu clk_table w/a [why] 1. update dml to rev.99 2. add smu clk table w/a: smu gives 1 dtm level with mismatch votage table which causes multiple issues. Reviewed-by: Nicholas Kazlauskas Acked-by: Wayne Lin Signed-off-by: Charlene Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../dc/dml/dcn31/display_mode_vba_31.c | 29 +++++++++++++++++-- .../drm/amd/display/dc/dml/display_mode_vba.h | 2 ++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index 6feb23432f8d..e4b9fd31223c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -64,6 +64,8 @@ typedef struct { double DCFCLKDeepSleep; unsigned int DPPPerPlane; bool ScalerEnabled; + double VRatio; + double VRatioChroma; enum scan_direction_class SourceScan; unsigned int BlockWidth256BytesY; unsigned int BlockHeight256BytesY; @@ -942,6 +944,7 @@ static bool CalculatePrefetchSchedule( double dst_y_prefetch_equ; double Tsw_oto; double prefetch_bw_oto; + double prefetch_bw_pr; double Tvm_oto; double Tr0_oto; double Tvm_oto_lines; @@ -971,6 +974,7 @@ static bool CalculatePrefetchSchedule( double min_Lsw; double Tsw_est1 = 0; double Tsw_est3 = 0; + double max_Tsw = 0; if (GPUVMEnable == true && HostVMEnable == true) { HostVMDynamicLevelsTrips = HostVMMaxNonCachedPageTableLevels; @@ -1111,11 +1115,14 @@ static bool CalculatePrefetchSchedule( bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC / 4; else bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC; - + /*rev 99*/ + prefetch_bw_pr = dml_min(1, bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane); + max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime; prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC; prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerPlane, prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime)); + prefetch_bw_oto = dml_max(prefetch_bw_pr, prefetch_sw_bytes / max_Tsw); - min_Lsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / max_vratio_pre; + min_Lsw = dml_max(1, dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / max_vratio_pre); Lsw_oto = dml_ceil(4 * dml_max(prefetch_sw_bytes / prefetch_bw_oto / LineTime, min_Lsw), 1) / 4; Tsw_oto = Lsw_oto * LineTime; @@ -1389,7 +1396,7 @@ static bool CalculatePrefetchSchedule( dml_print("DML::%s: SwathHeightC = %d\n", __func__, SwathHeightC); dml_print("DML::%s: VInitPreFillC = %f\n", __func__, VInitPreFillC); #endif - if ((SwathHeightC > 4)) { + if ((SwathHeightC > 4) || VInitPreFillC > 3) { if (LinesToRequestPrefetchPixelData > (VInitPreFillC - 3.0) / 2.0) { *VRatioPrefetchC = dml_max( *VRatioPrefetchC, @@ -2663,6 +2670,8 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman myPipe.DCFCLKDeepSleep = v->DCFCLKDeepSleep; myPipe.DPPPerPlane = v->DPPPerPlane[k]; myPipe.ScalerEnabled = v->ScalerEnabled[k]; + myPipe.VRatio = v->VRatio[k]; + myPipe.VRatioChroma = v->VRatioChroma[k]; myPipe.SourceScan = v->SourceScan[k]; myPipe.BlockWidth256BytesY = v->BlockWidth256BytesY[k]; myPipe.BlockHeight256BytesY = v->BlockHeight256BytesY[k]; @@ -3911,6 +3920,9 @@ static noinline void CalculatePrefetchSchedulePerPlane( myPipe.DCFCLKDeepSleep = v->ProjectedDCFCLKDeepSleep[i][j]; myPipe.DPPPerPlane = v->NoOfDPP[i][j][k]; myPipe.ScalerEnabled = v->ScalerEnabled[k]; + myPipe.VRatio = mode_lib->vba.VRatio[k]; + myPipe.VRatioChroma = mode_lib->vba.VRatioChroma[k]; + myPipe.SourceScan = v->SourceScan[k]; myPipe.BlockWidth256BytesY = v->Read256BlockWidthY[k]; myPipe.BlockHeight256BytesY = v->Read256BlockHeightY[k]; @@ -4987,6 +4999,17 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l &v->meta_row_bandwidth[i][j][k], &v->dpte_row_bandwidth[i][j][k]); } + /*DCCMetaBufferSizeSupport(i, j) = True + For k = 0 To NumberOfActivePlanes - 1 + If MetaRowBytes(i, j, k) > 24064 Then + DCCMetaBufferSizeSupport(i, j) = False + End If + Next k*/ + v->DCCMetaBufferSizeSupport[i][j] = true; + for (k = 0; k < v->NumberOfActivePlanes; ++k) { + if (v->MetaRowBytes[i][j][k] > 24064) + v->DCCMetaBufferSizeSupport[i][j] = false; + } v->UrgLatency[i] = CalculateUrgentLatency( v->UrgentLatencyPixelDataOnly, v->UrgentLatencyPixelMixedWithVMData, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 90e87961fe3e..8fe74a3b39a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -544,6 +544,8 @@ struct vba_vars_st { bool DTBCLKRequiredMoreThanSupported[DC__VOLTAGE_STATES]; double UrgentRoundTripAndOutOfOrderLatencyPerState[DC__VOLTAGE_STATES]; bool ROBSupport[DC__VOLTAGE_STATES][2]; + //based on rev 99: Dim DCCMetaBufferSizeSupport(NumberOfStates, 1) As Boolean + bool DCCMetaBufferSizeSupport[DC__VOLTAGE_STATES][2]; bool PTEBufferSizeNotExceeded[DC__VOLTAGE_STATES][2]; bool TotalVerticalActiveBandwidthSupport[DC__VOLTAGE_STATES][2]; double MaxTotalVerticalActiveAvailableBandwidth[DC__VOLTAGE_STATES][2]; From 047db281c026de5971cedb5bb486aa29bd16a39d Mon Sep 17 00:00:00 2001 From: Dale Zhao Date: Tue, 28 Dec 2021 16:50:28 +0800 Subject: [PATCH 078/339] drm/amd/display: Add signal type check when verify stream backends same [Why] For allow eDP hot-plug feature, the stream signal may change to VIRTUAL when plug-out and back to eDP when plug-in. OS will still setPathMode with same timing for each plugging, but eDP gets no stream update as we don't check signal type changing back as keeping it VIRTUAL. It's also unsafe for future cases that stream signal is switched with same timing. [How] Check stream signal type change include previous HDMI signal case. Reviewed-by: Aric Cyr Acked-by: Wayne Lin Signed-off-by: Dale Zhao Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b3912ff9dc91..b34bf59cf54b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1640,6 +1640,9 @@ static bool are_stream_backends_same( if (is_timing_changed(stream_a, stream_b)) return false; + if (stream_a->signal != stream_b->signal) + return false; + if (stream_a->dpms_off != stream_b->dpms_off) return false; From 56ca49cf6004ff328458954dd3d0fcf0189a96a4 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 8 Jan 2022 19:25:16 -0500 Subject: [PATCH 079/339] drm/amd/display: [FW Promotion] Release 0.0.100.0 Reviewed-by: Aric Cyr Acked-by: Wayne Lin Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 873ecd04e01d..e13d50abc281 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xbaf06b95 +#define DMUB_FW_VERSION_GIT_HASH 0x56a29f36 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 98 +#define DMUB_FW_VERSION_REVISION 100 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From ce0bdc62e80d40caa346ac4840a20769d5bd1ae6 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 10 Jan 2022 11:06:09 -0500 Subject: [PATCH 080/339] drm/amd/display: 3.2.169 This version brings along following fixes: - Organize FPU associated code to DML - Modify SMU_TIMEOUT macro - Organize dcn201 code - Address DS stays disabled problem under specific scenario - Fix black screen issue - Update DML to rev.99 - Address problem of eDP hot-plug feature Acked-by: Wayne Lin Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1c6728cf2d49..235e33f73913 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.168" +#define DC_VER "3.2.169" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 552b7cb0eed12c184b3bdfcc262e96a954a2bc86 Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Fri, 7 Jan 2022 18:33:36 -0300 Subject: [PATCH 081/339] drm/amd/display: move calcs folder into DML The calcs folder has FPU code on it, which should be isolated inside the DML folder as per https://patchwork.freedesktop.org/series/93042/. This commit aims single-handedly to correct the location of such FPU code and does not refactor any functions. Changes since v2: - Corrected problems to compile when DCN was disabled. Reviewed-by: Rodrigo Siqueira Signed-off-by: Isabella Basso Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/Makefile | 4 +- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 68 ------------------- drivers/gpu/drm/amd/display/dc/dml/Makefile | 10 ++- .../amd/display/dc/{ => dml}/calcs/bw_fixed.c | 0 .../display/dc/{ => dml}/calcs/calcs_logger.h | 0 .../display/dc/{ => dml}/calcs/custom_float.c | 0 .../display/dc/{ => dml}/calcs/dce_calcs.c | 0 .../dc/{ => dml}/calcs/dcn_calc_auto.c | 0 .../dc/{ => dml}/calcs/dcn_calc_auto.h | 0 .../dc/{ => dml}/calcs/dcn_calc_math.c | 0 .../display/dc/{ => dml}/calcs/dcn_calcs.c | 0 11 files changed, 11 insertions(+), 71 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/calcs/Makefile rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/bw_fixed.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/calcs_logger.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/custom_float.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dce_calcs.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calc_auto.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calc_auto.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calc_math.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calcs.c (100%) diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index b1f0d6260226..a4ef8f314307 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -23,12 +23,12 @@ # Makefile for Display Core (dc) component. # -DC_LIBS = basics bios calcs clk_mgr dce gpio irq virtual +DC_LIBS = basics bios clk_mgr dce dml gpio irq virtual ifdef CONFIG_DRM_AMD_DC_DCN DC_LIBS += dcn20 DC_LIBS += dsc -DC_LIBS += dcn10 dml +DC_LIBS += dcn10 DC_LIBS += dcn21 DC_LIBS += dcn201 DC_LIBS += dcn30 diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile deleted file mode 100644 index f3c00f479e1c..000000000000 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright 2017 Advanced Micro Devices, Inc. -# Copyright 2019 Raptor Engineering, LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -# -# Makefile for the 'calcs' sub-component of DAL. -# It calculates Bandwidth and Watermarks values for HW programming -# - -ifdef CONFIG_X86 -calcs_ccflags := -mhard-float -msse -endif - -ifdef CONFIG_PPC64 -calcs_ccflags := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -endif - -ifdef CONFIG_X86 -ifdef IS_OLD_GCC -# Stack alignment mismatch, proceed with caution. -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 -# (8B stack alignment). -calcs_ccflags += -mpreferred-stack-boundary=4 -else -calcs_ccflags += -msse2 -endif -endif - -CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_ccflags) -CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_ccflags) -CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare -CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_rcflags) -CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_rcflags) - -BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o - -ifdef CONFIG_DRM_AMD_DC_DCN -BW_CALCS += dcn_calcs.o dcn_calc_math.o dcn_calc_auto.o -endif - -AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS)) - -AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS) diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 06910b1f5965..b16c492593e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -74,6 +74,9 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_ccflags) -Wno-tautological-compare CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags) @@ -94,10 +97,14 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_rcflags) -DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ +DML = calcs/dce_calcs.o calcs/custom_float.o calcs/bw_fixed.o ifdef CONFIG_DRM_AMD_DC_DCN +DML += display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o DML += dcn20/dcn20_fpu.o DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o @@ -107,6 +114,7 @@ DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o DML += dcn301/dcn301_fpu.o DML += dcn302/dcn302_fpu.o DML += dsc/rc_calc_fpu.o +DML += calcs/dcn_calcs.o calcs/dcn_calc_math.o calcs/dcn_calc_auto.o endif AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c rename to drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c diff --git a/drivers/gpu/drm/amd/display/dc/calcs/calcs_logger.h b/drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/calcs_logger.h rename to drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/custom_float.c rename to drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.h similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.h diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c From 4bd8dd0d61f961e6c13cc118d4ebbdba57f8561f Mon Sep 17 00:00:00 2001 From: Yongzhi Liu Date: Tue, 18 Jan 2022 15:11:51 -0500 Subject: [PATCH 082/339] drm/amdgpu: Add missing pm_runtime_put_autosuspend pm_runtime_get_sync() increments the runtime PM usage counter even when it returns an error code, thus a matching decrement is needed on the error handling path to keep the counter balanced. Signed-off-by: Yongzhi Liu Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 9aea1cc5b27e..4b950de9bf66 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1120,8 +1120,10 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, return -EINVAL; r = pm_runtime_get_sync(adev_to_drm(adev)->dev); - if (r < 0) + if (r < 0) { + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; + } while (size) { uint32_t value; From dfd6879b98999867ac860a51348b00b5c0c2cafd Mon Sep 17 00:00:00 2001 From: Qiang Ma Date: Mon, 17 Jan 2022 15:47:31 +0800 Subject: [PATCH 083/339] drm/radeon: fix UVD suspend error I met a bug recently and the kernel log: [ 330.171875] radeon 0000:03:00.0: couldn't schedule ib [ 330.175781] [drm:radeon_uvd_suspend [radeon]] *ERROR* Error destroying UVD (-22)! In radeon drivers, using UVD suspend is as follows: if (rdev->has_uvd) { uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); } In radeon_ib_schedule function, we check the 'ring->ready' state, but in uvd_v1_0_fini funciton, we've cleared the ready state. So, just modify the suspend code flow to fix error. Reviewed-by: Leo Liu Signed-off-by: Qiang Ma Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 2 +- drivers/gpu/drm/radeon/evergreen.c | 2 +- drivers/gpu/drm/radeon/ni.c | 2 +- drivers/gpu/drm/radeon/r600.c | 2 +- drivers/gpu/drm/radeon/rv770.c | 2 +- drivers/gpu/drm/radeon/si.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 81b4de7be9f2..5819737c21c6 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -8517,8 +8517,8 @@ int cik_suspend(struct radeon_device *rdev) cik_cp_enable(rdev, false); cik_sdma_enable(rdev, false); if (rdev->has_uvd) { - uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); + uvd_v1_0_fini(rdev); } if (rdev->has_vce) radeon_vce_suspend(rdev); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index eeb590d2dec2..455f8036aa54 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -5156,8 +5156,8 @@ int evergreen_suspend(struct radeon_device *rdev) radeon_pm_suspend(rdev); radeon_audio_fini(rdev); if (rdev->has_uvd) { - uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); + uvd_v1_0_fini(rdev); } r700_cp_stop(rdev); r600_dma_stop(rdev); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 4a364ca7a1be..927e5f42e97d 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -2323,8 +2323,8 @@ int cayman_suspend(struct radeon_device *rdev) cayman_cp_enable(rdev, false); cayman_dma_stop(rdev); if (rdev->has_uvd) { - uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); + uvd_v1_0_fini(rdev); } evergreen_irq_suspend(rdev); radeon_wb_disable(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index ca3fcae2adb5..dd78fc499402 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3232,8 +3232,8 @@ int r600_suspend(struct radeon_device *rdev) radeon_audio_fini(rdev); r600_cp_stop(rdev); if (rdev->has_uvd) { - uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); + uvd_v1_0_fini(rdev); } r600_irq_suspend(rdev); radeon_wb_disable(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index e592e57be1bb..38796af4fadd 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1894,8 +1894,8 @@ int rv770_suspend(struct radeon_device *rdev) radeon_pm_suspend(rdev); radeon_audio_fini(rdev); if (rdev->has_uvd) { - uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); + uvd_v1_0_fini(rdev); } r700_cp_stop(rdev); r600_dma_stop(rdev); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 013e44ed0f39..8d5e4b25609d 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6800,8 +6800,8 @@ int si_suspend(struct radeon_device *rdev) si_cp_enable(rdev, false); cayman_dma_stop(rdev); if (rdev->has_uvd) { - uvd_v1_0_fini(rdev); radeon_uvd_suspend(rdev); + uvd_v1_0_fini(rdev); } if (rdev->has_vce) radeon_vce_suspend(rdev); From a5e7ffa11974d90d36f818ee34fc170722ec3098 Mon Sep 17 00:00:00 2001 From: Minghao Chi Date: Tue, 18 Jan 2022 07:57:02 +0000 Subject: [PATCH 084/339] amdgpu/amdgpu_psp: remove unneeded ret variable Return value from amdgpu_bo_create_kernel() directly instead of taking this in another redundant variable. Reported-by: Zeal Robot Signed-off-by: Minghao Chi Signed-off-by: CGEL ZTE Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 5c9b67ab168f..f2806959736a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -941,19 +941,15 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, static int psp_ta_init_shared_buf(struct psp_context *psp, struct ta_mem_context *mem_ctx) { - int ret; - /* * Allocate 16k memory aligned to 4k from Frame Buffer (local * physical) for ta to host memory */ - ret = amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size, + return amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &mem_ctx->shared_bo, &mem_ctx->shared_mc_addr, &mem_ctx->shared_buf); - - return ret; } static void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx) From 479e3b02b73a2de2b19df2950863149c59d57bfe Mon Sep 17 00:00:00 2001 From: Xiaojian Du Date: Mon, 17 Jan 2022 12:44:51 +0800 Subject: [PATCH 085/339] drm/amdgpu: add vram check function for GMC This patch will add vram check function for GMC block. It will write pattern data to the vram and then read back from the vram, so that to verify the work status of vram. This patch will cover gmc v6/7/8/9/10. Signed-off-by: Xiaojian Du Reviewed-by: Huang Rui Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 46 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 6 ++++ drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 5 ++- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 5 ++- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 5 ++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 11 ++++-- 7 files changed, 74 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index a0a9abd23a7b..cbe30ccf6162 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -822,3 +822,49 @@ void amdgpu_gmc_get_reserved_allocation(struct amdgpu_device *adev) break; } } + +int amdgpu_gmc_vram_checking(struct amdgpu_device *adev) +{ + struct amdgpu_bo *vram_bo; + uint64_t vram_gpu; + void *vram_ptr; + + int ret, size = 0x100000; + uint8_t cptr[10]; + + ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &vram_bo, + &vram_gpu, + &vram_ptr); + if (ret) + return ret; + + memset(vram_ptr, 0x86, size); + memset(cptr, 0x86, 10); + + /** + * Check the start, the mid, and the end of the memory if the content of + * each byte is the pattern "0x86". If yes, we suppose the vram bo is + * workable. + * + * Note: If check the each byte of whole 1M bo, it will cost too many + * seconds, so here, we just pick up three parts for emulation. + */ + ret = memcmp(vram_ptr, cptr, 10); + if (ret) + return ret; + + ret = memcmp(vram_ptr + (size / 2), cptr, 10); + if (ret) + return ret; + + ret = memcmp(vram_ptr + size - 10, cptr, 10); + if (ret) + return ret; + + amdgpu_bo_free_kernel(&vram_bo, &vram_gpu, + &vram_ptr); + + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 0001631cfedb..a5e8e0e08970 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -336,4 +336,5 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev); uint64_t amdgpu_gmc_vram_mc2pa(struct amdgpu_device *adev, uint64_t mc_addr); uint64_t amdgpu_gmc_vram_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo); uint64_t amdgpu_gmc_vram_cpu_pa(struct amdgpu_device *adev, struct amdgpu_bo *bo); +int amdgpu_gmc_vram_checking(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 4f8d356f8432..bb9a11bc644b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -1057,6 +1057,12 @@ static int gmc_v10_0_hw_init(void *handle) if (r) return r; + if (amdgpu_emu_mode == 1) { + r = amdgpu_gmc_vram_checking(adev); + if (r) + return r; + } + if (adev->umc.funcs && adev->umc.funcs->init_registers) adev->umc.funcs->init_registers(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index cd6c38e083d0..84f0debe8264 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -922,7 +922,10 @@ static int gmc_v6_0_hw_init(void *handle) if (r) return r; - return r; + if (amdgpu_emu_mode == 1) + return amdgpu_gmc_vram_checking(adev); + else + return r; } static int gmc_v6_0_hw_fini(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index ab8adbff9e2d..8800a18b0cf6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1111,7 +1111,10 @@ static int gmc_v7_0_hw_init(void *handle) if (r) return r; - return r; + if (amdgpu_emu_mode == 1) + return amdgpu_gmc_vram_checking(adev); + else + return r; } static int gmc_v7_0_hw_fini(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 054733838292..1c10fa5d0db7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1242,7 +1242,10 @@ static int gmc_v8_0_hw_init(void *handle) if (r) return r; - return r; + if (amdgpu_emu_mode == 1) + return amdgpu_gmc_vram_checking(adev); + else + return r; } static int gmc_v8_0_hw_fini(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c76ffd1a70cd..6866e0311b49 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1815,7 +1815,7 @@ static int gmc_v9_0_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; bool value; - int i; + int i, r; /* The sequence of these two function calls matters.*/ gmc_v9_0_init_golden_registers(adev); @@ -1850,7 +1850,14 @@ static int gmc_v9_0_hw_init(void *handle) if (adev->umc.funcs && adev->umc.funcs->init_registers) adev->umc.funcs->init_registers(adev); - return gmc_v9_0_gart_enable(adev); + r = gmc_v9_0_gart_enable(adev); + if (r) + return r; + + if (amdgpu_emu_mode == 1) + return amdgpu_gmc_vram_checking(adev); + else + return r; } /** From 86700a402694db56030a74481d09f35520332736 Mon Sep 17 00:00:00 2001 From: Xiaojian Du Date: Tue, 18 Jan 2022 17:18:13 +0800 Subject: [PATCH 086/339] drm/amdgpu: modify a pair of functions for the pcie port wreg/rreg This patch will modify a pair of functions for pcie port wreg/rreg. AMD GPU have had an independent NBIO block from SOC15 arch. If the dirver wants to read/write the address space of the pcie devices, it has to go through the NBIO block. This patch will move the pcie port wreg/rreg functions to "amdgpu_device.c", so that to reuse the functions on the future GPU ASICs. Signed-off-by: Xiaojian Du Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 4 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 33 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/nv.c | 34 ++-------------------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 8ddddf12e1ef..8658312764bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1315,6 +1315,10 @@ void amdgpu_device_invalidate_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring); void amdgpu_device_halt(struct amdgpu_device *adev); +u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev, + u32 reg); +void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, + u32 reg, u32 v); /* atpx handler */ #if defined(CONFIG_VGA_SWITCHEROO) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index f0c07523b04d..fcde99c69c47 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -5728,3 +5728,36 @@ void amdgpu_device_halt(struct amdgpu_device *adev) pci_disable_device(pdev); pci_wait_for_pending_transaction(pdev); } + +u32 amdgpu_device_pcie_port_rreg(struct amdgpu_device *adev, + u32 reg) +{ + unsigned long flags, address, data; + u32 r; + + address = adev->nbio.funcs->get_pcie_port_index_offset(adev); + data = adev->nbio.funcs->get_pcie_port_data_offset(adev); + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(address, reg * 4); + (void)RREG32(address); + r = RREG32(data); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); + return r; +} + +void amdgpu_device_pcie_port_wreg(struct amdgpu_device *adev, + u32 reg, u32 v) +{ + unsigned long flags, address, data; + + address = adev->nbio.funcs->get_pcie_port_index_offset(adev); + data = adev->nbio.funcs->get_pcie_port_data_offset(adev); + + spin_lock_irqsave(&adev->pcie_idx_lock, flags); + WREG32(address, reg * 4); + (void)RREG32(address); + WREG32(data, v); + (void)RREG32(data); + spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); +} diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 2ec1ffb36b1f..8f0c92cbdc4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -258,21 +258,6 @@ static u64 nv_pcie_rreg64(struct amdgpu_device *adev, u32 reg) return amdgpu_device_indirect_rreg64(adev, address, data, reg); } -static u32 nv_pcie_port_rreg(struct amdgpu_device *adev, u32 reg) -{ - unsigned long flags, address, data; - u32 r; - address = adev->nbio.funcs->get_pcie_port_index_offset(adev); - data = adev->nbio.funcs->get_pcie_port_data_offset(adev); - - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(address, reg * 4); - (void)RREG32(address); - r = RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); - return r; -} - static void nv_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v) { unsigned long address, data; @@ -283,21 +268,6 @@ static void nv_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v) amdgpu_device_indirect_wreg64(adev, address, data, reg, v); } -static void nv_pcie_port_wreg(struct amdgpu_device *adev, u32 reg, u32 v) -{ - unsigned long flags, address, data; - - address = adev->nbio.funcs->get_pcie_port_index_offset(adev); - data = adev->nbio.funcs->get_pcie_port_data_offset(adev); - - spin_lock_irqsave(&adev->pcie_idx_lock, flags); - WREG32(address, reg * 4); - (void)RREG32(address); - WREG32(data, v); - (void)RREG32(data); - spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); -} - static u32 nv_didt_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; @@ -742,8 +712,8 @@ static int nv_common_early_init(void *handle) adev->pcie_wreg = &nv_pcie_wreg; adev->pcie_rreg64 = &nv_pcie_rreg64; adev->pcie_wreg64 = &nv_pcie_wreg64; - adev->pciep_rreg = &nv_pcie_port_rreg; - adev->pciep_wreg = &nv_pcie_port_wreg; + adev->pciep_rreg = amdgpu_device_pcie_port_rreg; + adev->pciep_wreg = amdgpu_device_pcie_port_wreg; /* TODO: will add them during VCN v2 implementation */ adev->uvd_ctx_rreg = NULL; From 8eb53bb2aa8afa170ba40f9460f2de4d4d138764 Mon Sep 17 00:00:00 2001 From: yipechai Date: Mon, 17 Jan 2022 11:23:59 +0800 Subject: [PATCH 087/339] drm/amdgpu: Remove repeated calls Remove repeated calls. Signed-off-by: yipechai Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 7a1d2bac698e..4992bc554c0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1704,9 +1704,7 @@ static void amdgpu_ras_log_on_err_counter(struct amdgpu_device *adev) static void amdgpu_ras_error_status_query(struct amdgpu_device *adev, struct ras_query_if *info) { - struct amdgpu_ras_block_object *block_obj = amdgpu_ras_get_ras_block(adev, - info->head.block, - info->head.sub_block_index); + struct amdgpu_ras_block_object *block_obj; /* * Only two block need to query read/write * RspStatus at current state From 33cd016e600ac3417aff7c85f59b9a4b70a947e9 Mon Sep 17 00:00:00 2001 From: mziya Date: Wed, 19 Jan 2022 13:01:11 +0800 Subject: [PATCH 088/339] drm/amdgpu: remove unused variable Remove set but unused variable. warning: variable 'umc_reg_offset' set but not used Signed-off-by: mziya Reported-by: kernel test robot Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index 291b37f6db4e..05f79eea307c 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -94,16 +94,12 @@ static void umc_v8_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, uint32_t umc_inst = 0; uint32_t ch_inst = 0; - uint32_t umc_reg_offset = 0; uint32_t channel_index = 0; /* TODO: driver needs to toggle DF Cstate to ensure * safe access of UMC registers. Will add the protection */ LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_v8_7_reg_offset(adev, - umc_inst, - ch_inst); channel_index = get_umc_v8_7_channel_index(adev, umc_inst, ch_inst); From 5904e4135f3b3e6cc7bed46bda71118d55a56681 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Wed, 19 Jan 2022 16:09:40 +0800 Subject: [PATCH 089/339] drm/amdgpu: remove unused variable warning Signed-off-by: Stanley.Yang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 23 ----------------------- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 6 ------ 2 files changed, 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 6953426f0bed..526de1ca9b8d 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -61,22 +61,9 @@ static void umc_v6_7_ecc_info_query_correctable_error_count(struct amdgpu_device uint32_t channel_index, unsigned long *error_count) { - uint32_t ecc_err_cnt; uint64_t mc_umc_status; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - /* - * select the lower chip and check the error count - * skip add error count, calc error counter only from mca_umc_status - */ - ecc_err_cnt = ras->umc_ecc.ecc[channel_index].ce_count_lo_chip; - - /* - * select the higher chip and check the err counter - * skip add error count, calc error counter only from mca_umc_status - */ - ecc_err_cnt = ras->umc_ecc.ecc[channel_index].ce_count_hi_chip; - /* check for SRAM correctable error MCUMC_STATUS is a 64 bit register */ mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; @@ -110,15 +97,11 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, uint32_t umc_inst = 0; uint32_t ch_inst = 0; - uint32_t umc_reg_offset = 0; uint32_t channel_index = 0; /*TODO: driver needs to toggle DF Cstate to ensure * safe access of UMC registers. Will add the protection */ LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_v6_7_reg_offset(adev, - umc_inst, - ch_inst); channel_index = get_umc_v6_7_channel_index(adev, umc_inst, ch_inst); @@ -133,7 +116,6 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, struct ras_err_data *err_data, - uint32_t umc_reg_offset, uint32_t ch_inst, uint32_t umc_inst) { @@ -192,18 +174,13 @@ static void umc_v6_7_ecc_info_query_ras_error_address(struct amdgpu_device *adev uint32_t umc_inst = 0; uint32_t ch_inst = 0; - uint32_t umc_reg_offset = 0; /*TODO: driver needs to toggle DF Cstate to ensure * safe access of UMC resgisters. Will add the protection * when firmware interface is ready */ LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_v6_7_reg_offset(adev, - umc_inst, - ch_inst); umc_v6_7_ecc_info_query_error_address(adev, err_data, - umc_reg_offset, ch_inst, umc_inst); } diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index 05f79eea307c..cd57f39df7d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -114,7 +114,6 @@ static void umc_v8_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, struct ras_err_data *err_data, - uint32_t umc_reg_offset, uint32_t ch_inst, uint32_t umc_inst) { @@ -173,19 +172,14 @@ static void umc_v8_7_ecc_info_query_ras_error_address(struct amdgpu_device *adev uint32_t umc_inst = 0; uint32_t ch_inst = 0; - uint32_t umc_reg_offset = 0; /* TODO: driver needs to toggle DF Cstate to ensure * safe access of UMC resgisters. Will add the protection * when firmware interface is ready */ LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_v8_7_reg_offset(adev, - umc_inst, - ch_inst); umc_v8_7_ecc_info_query_error_address(adev, err_data, - umc_reg_offset, ch_inst, umc_inst); } From 1b08dfb889b2c584b444538c9500af24ba0a6dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 18 Jan 2022 12:53:11 +0100 Subject: [PATCH 090/339] drm/amdgpu: remove gart.ready flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That's just a leftover from old radeon days and was preventing CS and GART bindings before the hardware was initialized. But nowdays that is perfectly valid. The only thing we need to warn about are GART binding before the table is even allocated. Signed-off-by: Christian König Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 35 +++------- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h | 15 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 9 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 77 ++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 11 +-- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 8 +-- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 8 +-- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 10 +-- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 5 +- 11 files changed, 52 insertions(+), 137 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 645950a653a0..53cc844346f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -150,7 +150,7 @@ void amdgpu_gart_table_vram_free(struct amdgpu_device *adev) * replaces them with the dummy page (all asics). * Returns 0 for success, -EINVAL for failure. */ -int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, +void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, int pages) { unsigned t; @@ -161,13 +161,11 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, uint64_t flags = 0; int idx; - if (!adev->gart.ready) { - WARN(1, "trying to unbind memory from uninitialized GART !\n"); - return -EINVAL; - } + if (WARN_ON(!adev->gart.ptr)) + return; if (!drm_dev_enter(adev_to_drm(adev), &idx)) - return 0; + return; t = offset / AMDGPU_GPU_PAGE_SIZE; p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE; @@ -188,7 +186,6 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0); drm_dev_exit(idx); - return 0; } /** @@ -204,7 +201,7 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, * Map the dma_addresses into GART entries (all asics). * Returns 0 for success, -EINVAL for failure. */ -int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, +void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, int pages, dma_addr_t *dma_addr, uint64_t flags, void *dst) { @@ -212,13 +209,8 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, unsigned i, j, t; int idx; - if (!adev->gart.ready) { - WARN(1, "trying to bind memory to uninitialized GART !\n"); - return -EINVAL; - } - if (!drm_dev_enter(adev_to_drm(adev), &idx)) - return 0; + return; t = offset / AMDGPU_GPU_PAGE_SIZE; @@ -230,7 +222,6 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, } } drm_dev_exit(idx); - return 0; } /** @@ -246,20 +237,14 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, * (all asics). * Returns 0 for success, -EINVAL for failure. */ -int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, +void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, int pages, dma_addr_t *dma_addr, uint64_t flags) { - if (!adev->gart.ready) { - WARN(1, "trying to bind memory to uninitialized GART !\n"); - return -EINVAL; - } + if (WARN_ON(!adev->gart.ptr)) + return; - if (!adev->gart.ptr) - return 0; - - return amdgpu_gart_map(adev, offset, pages, dma_addr, flags, - adev->gart.ptr); + amdgpu_gart_map(adev, offset, pages, dma_addr, flags, adev->gart.ptr); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h index 78895413cf9f..8fea3e04e411 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.h @@ -46,7 +46,6 @@ struct amdgpu_gart { unsigned num_gpu_pages; unsigned num_cpu_pages; unsigned table_size; - bool ready; /* Asic default pte flags */ uint64_t gart_pte_flags; @@ -58,12 +57,12 @@ int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev); void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev); int amdgpu_gart_init(struct amdgpu_device *adev); void amdgpu_gart_dummy_page_fini(struct amdgpu_device *adev); -int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, - int pages); -int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, - int pages, dma_addr_t *dma_addr, uint64_t flags, - void *dst); -int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, - int pages, dma_addr_t *dma_addr, uint64_t flags); +void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, + int pages); +void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, + int pages, dma_addr_t *dma_addr, uint64_t flags, + void *dst); +void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, + int pages, dma_addr_t *dma_addr, uint64_t flags); void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 72022df264f6..c5263908caec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -220,26 +220,21 @@ uint64_t amdgpu_gtt_mgr_usage(struct amdgpu_gtt_mgr *mgr) * * Re-init the gart for each known BO in the GTT. */ -int amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) +void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) { struct amdgpu_gtt_node *node; struct drm_mm_node *mm_node; struct amdgpu_device *adev; - int r = 0; adev = container_of(mgr, typeof(*adev), mman.gtt_mgr); spin_lock(&mgr->lock); drm_mm_for_each_node(mm_node, &mgr->mm) { node = container_of(mm_node, typeof(*node), base.mm_nodes[0]); - r = amdgpu_ttm_recover_gart(node->tbo); - if (r) - break; + amdgpu_ttm_recover_gart(node->tbo); } spin_unlock(&mgr->lock); amdgpu_gart_invalidate_tlb(adev); - - return r; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 1e012b45f663..f0cd52b157f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -242,10 +242,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, dma_addr_t *dma_addr; dma_addr = &bo->ttm->dma_address[mm_cur->start >> PAGE_SHIFT]; - r = amdgpu_gart_map(adev, 0, num_pages, dma_addr, flags, - cpu_addr); - if (r) - goto error_free; + amdgpu_gart_map(adev, 0, num_pages, dma_addr, flags, cpu_addr); } else { dma_addr_t dma_address; @@ -253,11 +250,8 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, dma_address += adev->vm_manager.vram_base_offset; for (i = 0; i < num_pages; ++i) { - r = amdgpu_gart_map(adev, i << PAGE_SHIFT, 1, - &dma_address, flags, cpu_addr); - if (r) - goto error_free; - + amdgpu_gart_map(adev, i << PAGE_SHIFT, 1, &dma_address, + flags, cpu_addr); dma_address += PAGE_SIZE; } } @@ -822,14 +816,13 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_device *bdev, #endif } -static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, - struct ttm_buffer_object *tbo, - uint64_t flags) +static void amdgpu_ttm_gart_bind(struct amdgpu_device *adev, + struct ttm_buffer_object *tbo, + uint64_t flags) { struct amdgpu_bo *abo = ttm_to_amdgpu_bo(tbo); struct ttm_tt *ttm = tbo->ttm; struct amdgpu_ttm_tt *gtt = (void *)ttm; - int r; if (amdgpu_bo_encrypted(abo)) flags |= AMDGPU_PTE_TMZ; @@ -837,10 +830,8 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, if (abo->flags & AMDGPU_GEM_CREATE_CP_MQD_GFX9) { uint64_t page_idx = 1; - r = amdgpu_gart_bind(adev, gtt->offset, page_idx, - gtt->ttm.dma_address, flags); - if (r) - goto gart_bind_fail; + amdgpu_gart_bind(adev, gtt->offset, page_idx, + gtt->ttm.dma_address, flags); /* The memory type of the first page defaults to UC. Now * modify the memory type to NC from the second page of @@ -849,21 +840,13 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, flags &= ~AMDGPU_PTE_MTYPE_VG10_MASK; flags |= AMDGPU_PTE_MTYPE_VG10(AMDGPU_MTYPE_NC); - r = amdgpu_gart_bind(adev, - gtt->offset + (page_idx << PAGE_SHIFT), - ttm->num_pages - page_idx, - &(gtt->ttm.dma_address[page_idx]), flags); + amdgpu_gart_bind(adev, gtt->offset + (page_idx << PAGE_SHIFT), + ttm->num_pages - page_idx, + &(gtt->ttm.dma_address[page_idx]), flags); } else { - r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, - gtt->ttm.dma_address, flags); + amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, + gtt->ttm.dma_address, flags); } - -gart_bind_fail: - if (r) - DRM_ERROR("failed to bind %u pages at 0x%08llX\n", - ttm->num_pages, gtt->offset); - - return r; } /* @@ -879,7 +862,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev, struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void*)ttm; uint64_t flags; - int r = 0; + int r; if (!bo_mem) return -EINVAL; @@ -926,14 +909,10 @@ static int amdgpu_ttm_backend_bind(struct ttm_device *bdev, /* bind pages into GART page tables */ gtt->offset = (u64)bo_mem->start << PAGE_SHIFT; - r = amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, - gtt->ttm.dma_address, flags); - - if (r) - DRM_ERROR("failed to bind %u pages at 0x%08llX\n", - ttm->num_pages, gtt->offset); + amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages, + gtt->ttm.dma_address, flags); gtt->bound = true; - return r; + return 0; } /* @@ -983,12 +962,7 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) /* Bind pages */ gtt->offset = (u64)tmp->start << PAGE_SHIFT; - r = amdgpu_ttm_gart_bind(adev, bo, flags); - if (unlikely(r)) { - ttm_resource_free(bo, &tmp); - return r; - } - + amdgpu_ttm_gart_bind(adev, bo, flags); amdgpu_gart_invalidate_tlb(adev); ttm_resource_free(bo, &bo->resource); ttm_bo_assign_mem(bo, tmp); @@ -1002,19 +976,16 @@ int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo) * Called by amdgpu_gtt_mgr_recover() from amdgpu_device_reset() to * rebind GTT pages during a GPU reset. */ -int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) +void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo) { struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); uint64_t flags; - int r; if (!tbo->ttm) - return 0; + return; flags = amdgpu_ttm_tt_pte_flags(adev, tbo->ttm, tbo->resource); - r = amdgpu_ttm_gart_bind(adev, tbo, flags); - - return r; + amdgpu_ttm_gart_bind(adev, tbo, flags); } /* @@ -1028,7 +999,6 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev, { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); struct amdgpu_ttm_tt *gtt = (void *)ttm; - int r; /* if the pages have userptr pinning then clear that first */ if (gtt->userptr) { @@ -1048,10 +1018,7 @@ static void amdgpu_ttm_backend_unbind(struct ttm_device *bdev, return; /* unbind shouldn't be done for GDS/GWS/OA in ttm_bo_clean_mm */ - r = amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages); - if (r) - DRM_ERROR("failed to unbind %u pages at 0x%08llX\n", - gtt->ttm.num_pages, gtt->offset); + amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages); gtt->bound = false; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index f06fd19b4895..0efc31e3a457 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -119,7 +119,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev); bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_resource *mem); uint64_t amdgpu_gtt_mgr_usage(struct amdgpu_gtt_mgr *mgr); -int amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr); +void amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr); uint64_t amdgpu_preempt_mgr_usage(struct ttm_resource_manager *man); @@ -162,7 +162,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, struct dma_fence **fence); int amdgpu_ttm_alloc_gart(struct ttm_buffer_object *bo); -int amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); +void amdgpu_ttm_recover_gart(struct ttm_buffer_object *tbo); uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type); #if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index bb9a11bc644b..5e88655cdfa5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -1000,14 +1000,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) return -EINVAL; } - if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) - goto skip_pin_bo; - - r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); - if (r) - return r; - -skip_pin_bo: + amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); r = adev->gfxhub.funcs->gart_enable(adev); if (r) return r; @@ -1033,8 +1026,6 @@ skip_pin_bo: (unsigned)(adev->gmc.gart_size >> 20), (unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo)); - adev->gart.ready = true; - return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 84f0debe8264..ec291d28edff 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -469,16 +469,14 @@ static void gmc_v6_0_set_prt(struct amdgpu_device *adev, bool enable) static int gmc_v6_0_gart_enable(struct amdgpu_device *adev) { uint64_t table_addr; - int r, i; u32 field; + int i; if (adev->gart.bo == NULL) { dev_err(adev->dev, "No VRAM object for PCIE GART.\n"); return -EINVAL; } - r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); - if (r) - return r; + amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); table_addr = amdgpu_bo_gpu_offset(adev->gart.bo); @@ -558,7 +556,6 @@ static int gmc_v6_0_gart_enable(struct amdgpu_device *adev) dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n", (unsigned)(adev->gmc.gart_size >> 20), (unsigned long long)table_addr); - adev->gart.ready = true; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 8800a18b0cf6..344d819b4c1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -613,17 +613,14 @@ static void gmc_v7_0_set_prt(struct amdgpu_device *adev, bool enable) static int gmc_v7_0_gart_enable(struct amdgpu_device *adev) { uint64_t table_addr; - int r, i; u32 tmp, field; + int i; if (adev->gart.bo == NULL) { dev_err(adev->dev, "No VRAM object for PCIE GART.\n"); return -EINVAL; } - r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); - if (r) - return r; - + amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); table_addr = amdgpu_bo_gpu_offset(adev->gart.bo); /* Setup TLB control */ @@ -712,7 +709,6 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev) DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", (unsigned)(adev->gmc.gart_size >> 20), (unsigned long long)table_addr); - adev->gart.ready = true; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 1c10fa5d0db7..ca9841d5669f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -837,17 +837,14 @@ static void gmc_v8_0_set_prt(struct amdgpu_device *adev, bool enable) static int gmc_v8_0_gart_enable(struct amdgpu_device *adev) { uint64_t table_addr; - int r, i; u32 tmp, field; + int i; if (adev->gart.bo == NULL) { dev_err(adev->dev, "No VRAM object for PCIE GART.\n"); return -EINVAL; } - r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); - if (r) - return r; - + amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); table_addr = amdgpu_bo_gpu_offset(adev->gart.bo); /* Setup TLB control */ @@ -953,7 +950,6 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev) DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", (unsigned)(adev->gmc.gart_size >> 20), (unsigned long long)table_addr); - adev->gart.ready = true; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6866e0311b49..de32dbca9ab8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1783,14 +1783,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) return -EINVAL; } - if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) - goto skip_pin_bo; - - r = amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); - if (r) - return r; - -skip_pin_bo: + amdgpu_gtt_mgr_recover(&adev->mman.gtt_mgr); r = adev->gfxhub.funcs->gart_enable(adev); if (r) return r; @@ -1807,7 +1800,6 @@ skip_pin_bo: DRM_INFO("PTB located at 0x%016llX\n", (unsigned long long)amdgpu_bo_gpu_offset(adev->gart.bo)); - adev->gart.ready = true; return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index ed5385137f48..d986f9ee0e1f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -86,10 +86,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t npages, cpu_addr = &job->ibs[0].ptr[num_dw]; - r = amdgpu_gart_map(adev, 0, npages, addr, pte_flags, cpu_addr); - if (r) - goto error_free; - + amdgpu_gart_map(adev, 0, npages, addr, pte_flags, cpu_addr); r = amdgpu_job_submit(job, &adev->mman.entity, AMDGPU_FENCE_OWNER_UNDEFINED, &fence); if (r) From 590e86fe3462da81f1cbc4fc8d4cbf8b16b4f968 Mon Sep 17 00:00:00 2001 From: Jonathan Kim Date: Tue, 18 Jan 2022 10:48:49 -0500 Subject: [PATCH 091/339] drm/amdgpu: fix broken debug sdma vram access function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debug VRAM access through SDMA has several broken parts resulting in silent MMIO fallback. BO kernel creation takes the location of the cpu addr pointer, not the pointer itself for address kmap. drm_dev_enter return true on success so change access check. The source BO is reserved but not pinned so find the address using the cursor offset relative to its memory domain start. Signed-off-by: Jonathan Kim Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index f0cd52b157f8..74d8b721bd7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1406,6 +1406,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, { struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); + struct amdgpu_res_cursor src_mm; struct amdgpu_job *job; struct dma_fence *fence; uint64_t src_addr, dst_addr; @@ -1418,9 +1419,8 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, if (!adev->mman.sdma_access_ptr) return -EACCES; - r = drm_dev_enter(adev_to_drm(adev), &idx); - if (r) - return r; + if (!drm_dev_enter(adev_to_drm(adev), &idx)) + return -ENODEV; if (write) memcpy(adev->mman.sdma_access_ptr, buf, len); @@ -1430,7 +1430,8 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, if (r) goto out; - src_addr = amdgpu_bo_gpu_offset(abo); + amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm); + src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + src_mm.start; dst_addr = amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo); if (write) swap(src_addr, dst_addr); @@ -1828,7 +1829,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) if (amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, &adev->mman.sdma_access_bo, NULL, - adev->mman.sdma_access_ptr)) + &adev->mman.sdma_access_ptr)) DRM_WARN("Debug VRAM access will use slowpath MM access\n"); return 0; @@ -1852,6 +1853,8 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) if (adev->mman.stolen_reserved_size) amdgpu_bo_free_kernel(&adev->mman.stolen_reserved_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL, + &adev->mman.sdma_access_ptr); amdgpu_ttm_fw_reserve_vram_fini(adev); if (drm_dev_enter(adev_to_drm(adev), &idx)) { @@ -1871,8 +1874,6 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) ttm_range_man_fini(&adev->mman.bdev, AMDGPU_PL_OA); ttm_device_fini(&adev->mman.bdev); adev->mman.initialized = false; - amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL, - &adev->mman.sdma_access_ptr); DRM_INFO("amdgpu: ttm finalized\n"); } From f61c40c0757a79bcf744314df606c2bc8ae6a729 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 18 Jan 2022 10:57:54 -0500 Subject: [PATCH 092/339] drm/amdkfd: enable heavy-weight TLB flush on Arcturus SDMA FW fixes the hang issue for adding heavy-weight TLB flush on Arcturus, so we can enable it. Signed-off-by: Eric Huang Acked-by: Alex Deucher Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 ------ drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 ++++++++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index f9bab963a948..5df387c4d7fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1813,12 +1813,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( true); ret = unreserve_bo_and_vms(&ctx, false, false); - /* Only apply no TLB flush on Aldebaran to - * workaround regressions on other Asics. - */ - if (table_freed && (adev->asic_type != CHIP_ALDEBARAN)) - *table_freed = true; - goto out; out_unreserve: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 4bfc0c8ab764..337953af7c2f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1416,6 +1416,12 @@ err_unlock: return ret; } +static bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) { + return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2) || + (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1) && + dev->adev->sdma.instance[0].fw_version >= 18); +} + static int kfd_ioctl_map_memory_to_gpu(struct file *filep, struct kfd_process *p, void *data) { @@ -1503,7 +1509,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, } /* Flush TLBs after waiting for the page table updates to complete */ - if (table_freed) { + if (table_freed || !kfd_flush_tlb_after_unmap(dev)) { for (i = 0; i < args->n_devices; i++) { peer = kfd_device_by_id(devices_arr[i]); if (WARN_ON_ONCE(!peer)) @@ -1603,7 +1609,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, } mutex_unlock(&p->mutex); - if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2)) { + if (kfd_flush_tlb_after_unmap(dev)) { err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, (struct kgd_mem *) mem, true); if (err) { From f548f4291e89e6144d3c5b8a9ada66c7dbaa1639 Mon Sep 17 00:00:00 2001 From: Zhan Liu Date: Wed, 19 Jan 2022 16:55:16 -0500 Subject: [PATCH 093/339] drm/amd/display: Correct MPC split policy for DCN301 [Why] DCN301 has seamless boot enabled. With MPC split enabled at the same time, system will hang. [How] Revert MPC split policy back to "MPC_SPLIT_AVOID". Since we have ODM combine enabled on DCN301, pipe split is not necessary here. Signed-off-by: Zhan Liu Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index c1c6e602b06c..b4001233867c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -686,7 +686,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_clock_gate = true, .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .pipe_split_policy = MPC_SPLIT_AVOID, .force_single_disp_pipe_split = false, .disable_dcc = DCC_ENABLE, .vsr_support = true, From 6d1d72fb4fcf85ff0a96de1c16c46162b3baf9a6 Mon Sep 17 00:00:00 2001 From: Zhan Liu Date: Wed, 19 Jan 2022 17:07:53 -0500 Subject: [PATCH 094/339] drm/amd/display: change FIFO reset condition to embedded display only [Why] FIFO reset is only necessary for fast boot sequence, where otg is disabled and dig fe is enabled when changing dispclk. Fast boot is only enabled on embedded displays. [How] Change FIFO reset condition to "embedded display only". Signed-off-by: Zhan Liu Reviewed-by: Charlene Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f1593186e964..f3ff141b706a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1608,7 +1608,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst); - if (dc_is_dp_signal(pipe_ctx->stream->signal) && + if (dc_is_embedded_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc->funcs->reset_fifo) pipe_ctx->stream_res.stream_enc->funcs->reset_fifo( pipe_ctx->stream_res.stream_enc); From 37ff945f804c2d40d030713fc8692e793a81eff8 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Thu, 20 Jan 2022 00:17:44 +0800 Subject: [PATCH 095/339] drm/amdgpu: fix convert bad page retiremt Pmfw read ecc info registers and store values in eccinfo_table in the following order umc0 ch_inst 0, 1, 2 ... 7 umc1 ch_inst 0, 1, 2 ... 7 ... umc3 ch_inst 0, 1, 2 ... 7 Driver should convert eccinfo_table_idx to channel_index according to channel_idx_tbl. Signed-off-by: Stanley.Yang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 526de1ca9b8d..f5a1ba7db75a 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -58,29 +58,33 @@ static inline uint32_t get_umc_v6_7_channel_index(struct amdgpu_device *adev, } static void umc_v6_7_ecc_info_query_correctable_error_count(struct amdgpu_device *adev, - uint32_t channel_index, + uint32_t umc_inst, uint32_t ch_inst, unsigned long *error_count) { uint64_t mc_umc_status; + uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; /* check for SRAM correctable error MCUMC_STATUS is a 64 bit register */ - mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status; if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) *error_count += 1; } static void umc_v6_7_ecc_info_querry_uncorrectable_error_count(struct amdgpu_device *adev, - uint32_t channel_index, + uint32_t umc_inst, uint32_t ch_inst, unsigned long *error_count) { uint64_t mc_umc_status; + uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; /* check the MCUMC_STATUS */ - mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status; if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 || REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || @@ -97,19 +101,15 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, uint32_t umc_inst = 0; uint32_t ch_inst = 0; - uint32_t channel_index = 0; /*TODO: driver needs to toggle DF Cstate to ensure * safe access of UMC registers. Will add the protection */ LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - channel_index = get_umc_v6_7_channel_index(adev, - umc_inst, - ch_inst); umc_v6_7_ecc_info_query_correctable_error_count(adev, - channel_index, + umc_inst, ch_inst, &(err_data->ce_count)); umc_v6_7_ecc_info_querry_uncorrectable_error_count(adev, - channel_index, + umc_inst, ch_inst, &(err_data->ue_count)); } } @@ -122,12 +122,14 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, uint64_t mc_umc_status, err_addr, retired_page; struct eeprom_table_record *err_rec; uint32_t channel_index; + uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; - mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status; if (mc_umc_status == 0) return; @@ -142,7 +144,7 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) { - err_addr = ras->umc_ecc.ecc[channel_index].mca_umc_addr; + err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr; err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); /* translate umc channel address to soc pa, 3 parts are included */ From a357dca964e0c77c479075dd65ef86199078d82f Mon Sep 17 00:00:00 2001 From: Xiaojian Du Date: Thu, 20 Jan 2022 15:48:55 +0800 Subject: [PATCH 096/339] drm/amdgpu: fix the page fault caused by uninitialized variables This patch will fix the page fault caused by uninitialized variables. Error Log: ...... [ 130.246323] [drm] GART: num cpu pages 131072, num gpu pages 131072 [ 131.963112] [drm] PCIE GART of 512M enabled (table at 0x0000008000000000). [ 131.963130] BUG: unable to handle page fault for address: 000000000002db80 [ 131.963181] #PF: supervisor write access in kernel mode [ 131.963210] #PF: error_code(0x0002) - not-present page [ 131.963233] PGD 0 P4D 0 [ 131.963253] Oops: 0002 [#1] SMP NOPTI [ 131.963273] CPU: 3 PID: 1411 Comm: modprobe Not tainted 5.13.0+ #1 [ 131.963338] RIP: 0010:osq_lock+0x4d/0x120 [ 131.963381] Code: 10 00 00 00 00 48 c7 02 00 00 00 00 89 42 14 87 07 85 c0 0f 84 d0 00 00 00 83 e8 01 48 98 48 03 0c c5 00 d9 ea 9c 48 89 4a 08 <48> 89 11 44 8b 42 10 45 85 c0 0f 85 af 00 00 00 55 48 89 fe 65 4c [ 131.963460] RSP: 0018:ffffa40481717768 EFLAGS: 00010202 [ 131.963483] RAX: fffffffffffffffe RBX: ffffa40481717920 RCX: 000000000002db80 [ 131.963520] RDX: ffff9256fecedb80 RSI: ffff9256cbed2e80 RDI: ffffa40481717ac4 [ 131.963547] RBP: ffffa40481717808 R08: ffffa40481717920 R09: 00000000ffffffff [ 131.963582] R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000000 [ 131.963609] R13: ffffa40481717ac4 R14: ffffa40481717ab8 R15: ffff9256c9480000 [ 131.963646] FS: 00007f23d9b9c540(0000) GS:ffff9256fecc0000(0000) knlGS:0000000000000000 [ 131.963687] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 131.963721] CR2: 000000000002db80 CR3: 0000000008444000 CR4: 00000000000506e0 [ 131.963758] Call Trace: [ 131.963772] ? __ww_mutex_lock.isra.0+0x3a2/0x760 [ 131.963810] ? prb_read_valid+0x1c/0x20 [ 131.963830] ? console_unlock+0x2fe/0x4f0 [ 131.963849] __ww_mutex_lock_interruptible_slowpath+0x16/0x20 [ 131.963882] ww_mutex_lock_interruptible+0x83/0x90 [ 131.963908] amdgpu_bo_create_reserved+0xf0/0x1e0 [amdgpu] [ 131.964237] amdgpu_bo_create_kernel+0x17/0x80 [amdgpu] [ 131.964509] amdgpu_gmc_vram_checking+0x41/0xf0 [amdgpu] [ 131.964807] gmc_v10_0_hw_init+0x105/0x120 [amdgpu] [ 131.965108] amdgpu_device_init.cold+0x1aa4/0x1e3e [amdgpu] ...... Signed-off-by: Xiaojian Du Reviewed-by: Yang Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index cbe30ccf6162..e15f6b8a62ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -825,9 +825,9 @@ void amdgpu_gmc_get_reserved_allocation(struct amdgpu_device *adev) int amdgpu_gmc_vram_checking(struct amdgpu_device *adev) { - struct amdgpu_bo *vram_bo; - uint64_t vram_gpu; - void *vram_ptr; + struct amdgpu_bo *vram_bo = NULL; + uint64_t vram_gpu = 0; + void *vram_ptr = NULL; int ret, size = 0x100000; uint8_t cptr[10]; From 901abf367d3eecd54f21829ced48c20f53c74c57 Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Thu, 20 Jan 2022 10:39:41 -0500 Subject: [PATCH 097/339] drm/amdgpu: Disable FRU EEPROM access for SRIOV VF acces the EEPROM is blocked by security policy, we might need other way to get SKUs info for VF v2: squash in compilation fix from Luben Signed-off-by: shaoyunl Acked-by: Alex Deucher Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 2a786e788627..60e7e637eaa3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -40,6 +40,12 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) */ struct atom_context *atom_ctx = adev->mode_info.atom_context; + /* The i2c access is blocked on VF + * TODO: Need other way to get the info + */ + if (amdgpu_sriov_vf(adev)) + return false; + /* VBIOS is of the format ###-DXXXYY-##. For SKU identification, * we can use just the "DXXX" portion. If there were more models, we * could convert the 3 characters to a hex integer and use a switch From 828904660a2e0a31d5c8a2ce75711f7123896bd5 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 18 Jan 2022 19:10:42 -0600 Subject: [PATCH 098/339] drm/amd: Fix MSB of SMU version printing Yellow carp has been outputting versions like `1093.24.0`, but this is supposed to be 69.24.0. That is the MSB is being interpreted incorrectly. The MSB is not part of the major version, but has generally been treated that way thus far. It's actually the program, and used to distinguish between two programs from a similar family but different codebase. Reviewed-by: Lijo Lazar Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 +++++----- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 10 +++++----- drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c | 10 +++++----- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 14 +++++++------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 85f06396d184..e5e69fcc3af3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1425,8 +1425,7 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused) struct drm_amdgpu_info_firmware fw_info; struct drm_amdgpu_query_fw query_fw; struct atom_context *ctx = adev->mode_info.atom_context; - uint8_t smu_minor, smu_debug; - uint16_t smu_major; + uint8_t smu_program, smu_major, smu_minor, smu_debug; int ret, i; static const char *ta_fw_name[TA_FW_TYPE_MAX_INDEX] = { @@ -1572,11 +1571,12 @@ static int amdgpu_debugfs_firmware_info_show(struct seq_file *m, void *unused) ret = amdgpu_firmware_info(&fw_info, &query_fw, adev); if (ret) return ret; - smu_major = (fw_info.ver >> 16) & 0xffff; + smu_program = (fw_info.ver >> 24) & 0xff; + smu_major = (fw_info.ver >> 16) & 0xff; smu_minor = (fw_info.ver >> 8) & 0xff; smu_debug = (fw_info.ver >> 0) & 0xff; - seq_printf(m, "SMC feature version: %u, firmware version: 0x%08x (%d.%d.%d)\n", - fw_info.feature, fw_info.ver, smu_major, smu_minor, smu_debug); + seq_printf(m, "SMC feature version: %u, program: %d, firmware version: 0x%08x (%d.%d.%d)\n", + fw_info.feature, smu_program, fw_info.ver, smu_major, smu_minor, smu_debug); /* SDMA */ query_fw.fw_type = AMDGPU_INFO_FW_SDMA; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 7029e5deb6b3..e94a400db669 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -225,15 +225,15 @@ int smu_v11_0_check_fw_version(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint32_t if_version = 0xff, smu_version = 0xff; - uint16_t smu_major; - uint8_t smu_minor, smu_debug; + uint8_t smu_program, smu_major, smu_minor, smu_debug; int ret = 0; ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); if (ret) return ret; - smu_major = (smu_version >> 16) & 0xffff; + smu_program = (smu_version >> 24) & 0xff; + smu_major = (smu_version >> 16) & 0xff; smu_minor = (smu_version >> 8) & 0xff; smu_debug = (smu_version >> 0) & 0xff; if (smu->is_apu) @@ -287,9 +287,9 @@ int smu_v11_0_check_fw_version(struct smu_context *smu) */ if (if_version != smu->smc_driver_if_version) { dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " - "smu fw version = 0x%08x (%d.%d.%d)\n", + "smu fw program = %d, version = 0x%08x (%d.%d.%d)\n", smu->smc_driver_if_version, if_version, - smu_version, smu_major, smu_minor, smu_debug); + smu_program, smu_version, smu_major, smu_minor, smu_debug); dev_warn(smu->adev->dev, "SMU driver if version not matched\n"); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c index 9c91e79c955f..56a02bc60cee 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c @@ -74,15 +74,15 @@ int smu_v12_0_check_fw_version(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint32_t if_version = 0xff, smu_version = 0xff; - uint16_t smu_major; - uint8_t smu_minor, smu_debug; + uint8_t smu_program, smu_major, smu_minor, smu_debug; int ret = 0; ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); if (ret) return ret; - smu_major = (smu_version >> 16) & 0xffff; + smu_program = (smu_version >> 24) & 0xff; + smu_major = (smu_version >> 16) & 0xff; smu_minor = (smu_version >> 8) & 0xff; smu_debug = (smu_version >> 0) & 0xff; if (smu->is_apu) @@ -98,9 +98,9 @@ int smu_v12_0_check_fw_version(struct smu_context *smu) */ if (if_version != smu->smc_driver_if_version) { dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " - "smu fw version = 0x%08x (%d.%d.%d)\n", + "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n", smu->smc_driver_if_version, if_version, - smu_version, smu_major, smu_minor, smu_debug); + smu_program, smu_version, smu_major, smu_minor, smu_debug); dev_warn(smu->adev->dev, "SMU driver if version not matched\n"); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index f66d8b9135ca..d9e3ebfeee73 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -198,15 +198,15 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint32_t if_version = 0xff, smu_version = 0xff; - uint16_t smu_major; - uint8_t smu_minor, smu_debug; + uint8_t smu_program, smu_major, smu_minor, smu_debug; int ret = 0; ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); if (ret) return ret; - smu_major = (smu_version >> 16) & 0xffff; + smu_program = (smu_version >> 24) & 0xff; + smu_major = (smu_version >> 16) & 0xff; smu_minor = (smu_version >> 8) & 0xff; smu_debug = (smu_version >> 0) & 0xff; if (smu->is_apu) @@ -229,8 +229,8 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) /* only for dGPU w/ SMU13*/ if (adev->pm.fw) - dev_dbg(adev->dev, "smu fw reported version = 0x%08x (%d.%d.%d)\n", - smu_version, smu_major, smu_minor, smu_debug); + dev_dbg(smu->adev->dev, "smu fw reported program %d, version = 0x%08x (%d.%d.%d)\n", + smu_program, smu_version, smu_major, smu_minor, smu_debug); /* * 1. if_version mismatch is not critical as our fw is designed @@ -242,9 +242,9 @@ int smu_v13_0_check_fw_version(struct smu_context *smu) */ if (if_version != smu->smc_driver_if_version) { dev_info(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " - "smu fw version = 0x%08x (%d.%d.%d)\n", + "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n", smu->smc_driver_if_version, if_version, - smu_version, smu_major, smu_minor, smu_debug); + smu_program, smu_version, smu_major, smu_minor, smu_debug); dev_warn(adev->dev, "SMU driver if version not matched\n"); } From 6a6c2ab687c8eabaec4a55a4f13eb5ee68181403 Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Thu, 20 Jan 2022 14:01:29 +0800 Subject: [PATCH 099/339] drm/amdgpu: enable amdgpu_dc module parameter It doesn't work under IP discovery mode. Make it work! Signed-off-by: Lang Yu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index e6a26b554254..8dd15a7b8dcc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -846,8 +846,14 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev) { if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) { amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block); + return 0; + } + + if (!amdgpu_device_has_dc_support(adev)) + return 0; + #if defined(CONFIG_DRM_AMD_DC) - } else if (adev->ip_versions[DCE_HWIP][0]) { + if (adev->ip_versions[DCE_HWIP][0]) { switch (adev->ip_versions[DCE_HWIP][0]) { case IP_VERSION(1, 0, 0): case IP_VERSION(1, 0, 1): @@ -882,8 +888,8 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev) adev->ip_versions[DCI_HWIP][0]); return -EINVAL; } -#endif } +#endif return 0; } From 239d6de307b0dd1d48ec9b935b57531f07f6db11 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 20 Jan 2022 15:03:37 +0800 Subject: [PATCH 100/339] drm/amdgpu: suppress the warning about enum value 'AMD_IP_BLOCK_TYPE_NUM' Suppress the warning below on building htmldocs: drivers/gpu/drm/amd/include/amd_shared.h:103: warning: Enum value 'AMD_IP_BLOCK_TYPE_NUM' not described in enum 'amd_ip_block_type' Fixes: 6ee27ee27ba8 ("drm/amd/pm: avoid duplicate powergate/ungate setting") Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/amd_shared.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index fb6ad56ad6f1..fe4e585781bb 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -83,6 +83,7 @@ enum amd_apu_flags { * @AMD_IP_BLOCK_TYPE_VCN: Video Core/Codec Next * @AMD_IP_BLOCK_TYPE_MES: Micro-Engine Scheduler * @AMD_IP_BLOCK_TYPE_JPEG: JPEG Engine +* @AMD_IP_BLOCK_TYPE_NUM: Total number of IP block types */ enum amd_ip_block_type { AMD_IP_BLOCK_TYPE_COMMON, From e0638c7abc4d3d3c46e8f2fc07e02c3877c3c402 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 11:05:28 +0800 Subject: [PATCH 101/339] drm/amd/pm: drop unneeded lock protection smu->mutex As all those APIs are already protected either by adev->pm.mutex or smu->message_lock. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 316 ++---------------- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 4 +- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 4 +- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 4 +- 6 files changed, 34 insertions(+), 299 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 828cb932f6a9..eaaa5b033d46 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -55,8 +55,7 @@ static int smu_force_smuclk_levels(struct smu_context *smu, uint32_t mask); static int smu_handle_task(struct smu_context *smu, enum amd_dpm_forced_level level, - enum amd_pp_task task_id, - bool lock_needed); + enum amd_pp_task task_id); static int smu_reset(struct smu_context *smu); static int smu_set_fan_speed_pwm(void *handle, u32 speed); static int smu_set_fan_control_mode(void *handle, u32 value); @@ -68,36 +67,22 @@ static int smu_sys_get_pp_feature_mask(void *handle, char *buf) { struct smu_context *smu = handle; - int size = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - - size = smu_get_pp_feature_mask(smu, buf); - - mutex_unlock(&smu->mutex); - - return size; + return smu_get_pp_feature_mask(smu, buf); } static int smu_sys_set_pp_feature_mask(void *handle, uint64_t new_mask) { struct smu_context *smu = handle; - int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - - ret = smu_set_pp_feature_mask(smu, new_mask); - - mutex_unlock(&smu->mutex); - - return ret; + return smu_set_pp_feature_mask(smu, new_mask); } int smu_get_status_gfxoff(struct smu_context *smu, uint32_t *value) @@ -117,16 +102,12 @@ int smu_set_soft_freq_range(struct smu_context *smu, { int ret = 0; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_soft_freq_limited_range) ret = smu->ppt_funcs->set_soft_freq_limited_range(smu, clk_type, min, max); - mutex_unlock(&smu->mutex); - return ret; } @@ -140,16 +121,12 @@ int smu_get_dpm_freq_range(struct smu_context *smu, if (!min && !max) return -EINVAL; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_dpm_ultimate_freq) ret = smu->ppt_funcs->get_dpm_ultimate_freq(smu, clk_type, min, max); - mutex_unlock(&smu->mutex); - return ret; } @@ -482,7 +459,6 @@ static int smu_sys_get_pp_table(void *handle, { struct smu_context *smu = handle; struct smu_table_context *smu_table = &smu->smu_table; - uint32_t powerplay_table_size; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; @@ -490,18 +466,12 @@ static int smu_sys_get_pp_table(void *handle, if (!smu_table->power_play_table && !smu_table->hardcode_pptable) return -EINVAL; - mutex_lock(&smu->mutex); - if (smu_table->hardcode_pptable) *table = smu_table->hardcode_pptable; else *table = smu_table->power_play_table; - powerplay_table_size = smu_table->power_play_table_size; - - mutex_unlock(&smu->mutex); - - return powerplay_table_size; + return smu_table->power_play_table_size; } static int smu_sys_set_pp_table(void *handle, @@ -521,12 +491,10 @@ static int smu_sys_set_pp_table(void *handle, return -EIO; } - mutex_lock(&smu->mutex); - if (!smu_table->hardcode_pptable) - smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); if (!smu_table->hardcode_pptable) { - ret = -ENOMEM; - goto failed; + smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); + if (!smu_table->hardcode_pptable) + return -ENOMEM; } memcpy(smu_table->hardcode_pptable, buf, size); @@ -545,8 +513,6 @@ static int smu_sys_set_pp_table(void *handle, smu->uploading_custom_pp_table = false; -failed: - mutex_unlock(&smu->mutex); return ret; } @@ -633,7 +599,6 @@ static int smu_early_init(void *handle) smu->adev = adev; smu->pm_enabled = !!amdgpu_dpm; smu->is_apu = false; - mutex_init(&smu->mutex); mutex_init(&smu->smu_baco.mutex); smu->smu_baco.state = SMU_BACO_STATE_EXIT; smu->smu_baco.platform_support = false; @@ -736,8 +701,7 @@ static int smu_late_init(void *handle) smu_handle_task(smu, smu->smu_dpm.dpm_level, - AMD_PP_TASK_COMPLETE_INIT, - false); + AMD_PP_TASK_COMPLETE_INIT); smu_restore_dpm_user_profile(smu); @@ -1013,12 +977,8 @@ static void smu_interrupt_work_fn(struct work_struct *work) struct smu_context *smu = container_of(work, struct smu_context, interrupt_work); - mutex_lock(&smu->mutex); - if (smu->ppt_funcs && smu->ppt_funcs->interrupt_work) smu->ppt_funcs->interrupt_work(smu); - - mutex_unlock(&smu->mutex); } static int smu_sw_init(void *handle) @@ -1632,8 +1592,6 @@ static int smu_display_configuration_change(void *handle, if (!display_config) return -EINVAL; - mutex_lock(&smu->mutex); - smu_set_min_dcef_deep_sleep(smu, display_config->min_dcef_deep_sleep_set_clk / 100); @@ -1642,8 +1600,6 @@ static int smu_display_configuration_change(void *handle, num_of_active_display++; } - mutex_unlock(&smu->mutex); - return 0; } @@ -1766,22 +1722,18 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu, static int smu_handle_task(struct smu_context *smu, enum amd_dpm_forced_level level, - enum amd_pp_task task_id, - bool lock_needed) + enum amd_pp_task task_id) { int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - if (lock_needed) - mutex_lock(&smu->mutex); - switch (task_id) { case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE: ret = smu_pre_display_config_changed(smu); if (ret) - goto out; + return ret; ret = smu_adjust_power_state_dynamic(smu, level, false); break; case AMD_PP_TASK_COMPLETE_INIT: @@ -1792,10 +1744,6 @@ static int smu_handle_task(struct smu_context *smu, break; } -out: - if (lock_needed) - mutex_unlock(&smu->mutex); - return ret; } @@ -1806,7 +1754,7 @@ static int smu_handle_dpm_task(void *handle, struct smu_context *smu = handle; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - return smu_handle_task(smu, smu_dpm->dpm_level, task_id, true); + return smu_handle_task(smu, smu_dpm->dpm_level, task_id); } @@ -1825,8 +1773,6 @@ static int smu_switch_power_profile(void *handle, if (!(type < PP_SMC_POWER_PROFILE_CUSTOM)) return -EINVAL; - mutex_lock(&smu->mutex); - if (!en) { smu->workload_mask &= ~(1 << smu->workload_prority[type]); index = fls(smu->workload_mask); @@ -1843,8 +1789,6 @@ static int smu_switch_power_profile(void *handle, smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) smu_bump_power_profile_mode(smu, &workload, 0); - mutex_unlock(&smu->mutex); - return 0; } @@ -1852,7 +1796,6 @@ static enum amd_dpm_forced_level smu_get_performance_level(void *handle) { struct smu_context *smu = handle; struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - enum amd_dpm_forced_level level; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; @@ -1860,11 +1803,7 @@ static enum amd_dpm_forced_level smu_get_performance_level(void *handle) if (!smu->is_apu && !smu_dpm_ctx->dpm_context) return -EINVAL; - mutex_lock(&(smu->mutex)); - level = smu_dpm_ctx->dpm_level; - mutex_unlock(&(smu->mutex)); - - return level; + return smu_dpm_ctx->dpm_level; } static int smu_force_performance_level(void *handle, @@ -1880,19 +1819,12 @@ static int smu_force_performance_level(void *handle, if (!smu->is_apu && !smu_dpm_ctx->dpm_context) return -EINVAL; - mutex_lock(&smu->mutex); - ret = smu_enable_umd_pstate(smu, &level); - if (ret) { - mutex_unlock(&smu->mutex); + if (ret) return ret; - } ret = smu_handle_task(smu, level, - AMD_PP_TASK_READJUST_POWER_STATE, - false); - - mutex_unlock(&smu->mutex); + AMD_PP_TASK_READJUST_POWER_STATE); /* reset user dpm clock state */ if (!ret && smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { @@ -1906,16 +1838,11 @@ static int smu_force_performance_level(void *handle, static int smu_set_display_count(void *handle, uint32_t count) { struct smu_context *smu = handle; - int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - ret = smu_init_display_count(smu, count); - mutex_unlock(&smu->mutex); - - return ret; + return smu_init_display_count(smu, count); } static int smu_force_smuclk_levels(struct smu_context *smu, @@ -1933,8 +1860,6 @@ static int smu_force_smuclk_levels(struct smu_context *smu, return -EINVAL; } - mutex_lock(&smu->mutex); - if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels) { ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask); if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { @@ -1943,8 +1868,6 @@ static int smu_force_smuclk_levels(struct smu_context *smu, } } - mutex_unlock(&smu->mutex); - return ret; } @@ -2003,14 +1926,10 @@ static int smu_set_mp1_state(void *handle, if (!smu->pm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs && smu->ppt_funcs->set_mp1_state) ret = smu->ppt_funcs->set_mp1_state(smu, mp1_state); - mutex_unlock(&smu->mutex); - return ret; } @@ -2026,14 +1945,10 @@ static int smu_set_df_cstate(void *handle, if (!smu->ppt_funcs || !smu->ppt_funcs->set_df_cstate) return 0; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->set_df_cstate(smu, state); if (ret) dev_err(smu->adev->dev, "[SetDfCstate] failed!\n"); - mutex_unlock(&smu->mutex); - return ret; } @@ -2047,38 +1962,25 @@ int smu_allow_xgmi_power_down(struct smu_context *smu, bool en) if (!smu->ppt_funcs || !smu->ppt_funcs->allow_xgmi_power_down) return 0; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->allow_xgmi_power_down(smu, en); if (ret) dev_err(smu->adev->dev, "[AllowXgmiPowerDown] failed!\n"); - mutex_unlock(&smu->mutex); - return ret; } int smu_write_watermarks_table(struct smu_context *smu) { - int ret = 0; - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - - ret = smu_set_watermarks_table(smu, NULL); - - mutex_unlock(&smu->mutex); - - return ret; + return smu_set_watermarks_table(smu, NULL); } static int smu_set_watermarks_for_clock_ranges(void *handle, struct pp_smu_wm_range_sets *clock_ranges) { struct smu_context *smu = handle; - int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; @@ -2086,13 +1988,7 @@ static int smu_set_watermarks_for_clock_ranges(void *handle, if (smu->disable_watermark) return 0; - mutex_lock(&smu->mutex); - - ret = smu_set_watermarks_table(smu, clock_ranges); - - mutex_unlock(&smu->mutex); - - return ret; + return smu_set_watermarks_table(smu, clock_ranges); } int smu_set_ac_dc(struct smu_context *smu) @@ -2106,14 +2002,12 @@ int smu_set_ac_dc(struct smu_context *smu) if (smu->dc_controlled_by_gpio) return 0; - mutex_lock(&smu->mutex); ret = smu_set_power_source(smu, smu->adev->pm.ac_power ? SMU_POWER_SOURCE_AC : SMU_POWER_SOURCE_DC); if (ret) dev_err(smu->adev->dev, "Failed to switch to %s mode!\n", smu->adev->pm.ac_power ? "AC" : "DC"); - mutex_unlock(&smu->mutex); return ret; } @@ -2200,13 +2094,9 @@ static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled) { int ret = 0; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_gfx_cgpg) ret = smu->ppt_funcs->set_gfx_cgpg(smu, enabled); - mutex_unlock(&smu->mutex); - return ret; } @@ -2224,8 +2114,6 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed) if (speed == U32_MAX) return -EINVAL; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_RPM; @@ -2236,8 +2124,6 @@ static int smu_set_fan_speed_rpm(void *handle, uint32_t speed) smu->user_dpm_profile.fan_speed_pwm = 0; } - mutex_unlock(&smu->mutex); - return ret; } @@ -2293,8 +2179,6 @@ int smu_get_power_limit(void *handle, break; } - mutex_lock(&smu->mutex); - if (limit_type != SMU_DEFAULT_PPT_LIMIT) { if (smu->ppt_funcs->get_ppt_limit) ret = smu->ppt_funcs->get_ppt_limit(smu, limit, limit_type, limit_level); @@ -2328,8 +2212,6 @@ int smu_get_power_limit(void *handle, } } - mutex_unlock(&smu->mutex); - return ret; } @@ -2342,21 +2224,16 @@ static int smu_set_power_limit(void *handle, uint32_t limit) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - limit &= (1<<24)-1; if (limit_type != SMU_DEFAULT_PPT_LIMIT) - if (smu->ppt_funcs->set_power_limit) { - ret = smu->ppt_funcs->set_power_limit(smu, limit_type, limit); - goto out; - } + if (smu->ppt_funcs->set_power_limit) + return smu->ppt_funcs->set_power_limit(smu, limit_type, limit); if (limit > smu->max_power_limit) { dev_err(smu->adev->dev, "New power limit (%d) is over the max allowed %d\n", limit, smu->max_power_limit); - ret = -EINVAL; - goto out; + return -EINVAL; } if (!limit) @@ -2368,9 +2245,6 @@ static int smu_set_power_limit(void *handle, uint32_t limit) smu->user_dpm_profile.power_limit = limit; } -out: - mutex_unlock(&smu->mutex); - return ret; } @@ -2381,13 +2255,9 @@ static int smu_print_smuclk_levels(struct smu_context *smu, enum smu_clk_type cl if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->print_clk_levels) ret = smu->ppt_funcs->print_clk_levels(smu, clk_type, buf); - mutex_unlock(&smu->mutex); - return ret; } @@ -2444,14 +2314,10 @@ static int smu_od_edit_dpm_table(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->od_edit_dpm_table) { ret = smu->ppt_funcs->od_edit_dpm_table(smu, type, input, size); } - mutex_unlock(&smu->mutex); - return ret; } @@ -2475,8 +2341,6 @@ static int smu_read_sensor(void *handle, size_val = *size_arg; size = &size_val; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->read_sensor) if (!smu->ppt_funcs->read_sensor(smu, sensor, data, size)) goto unlock; @@ -2517,8 +2381,6 @@ static int smu_read_sensor(void *handle, } unlock: - mutex_unlock(&smu->mutex); - // assign uint32_t to int *size_arg = size_val; @@ -2528,7 +2390,6 @@ unlock: static int smu_get_power_profile_mode(void *handle, char *buf) { struct smu_context *smu = handle; - int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled || !smu->ppt_funcs->get_power_profile_mode) @@ -2536,13 +2397,7 @@ static int smu_get_power_profile_mode(void *handle, char *buf) if (!buf) return -EINVAL; - mutex_lock(&smu->mutex); - - ret = smu->ppt_funcs->get_power_profile_mode(smu, buf); - - mutex_unlock(&smu->mutex); - - return ret; + return smu->ppt_funcs->get_power_profile_mode(smu, buf); } static int smu_set_power_profile_mode(void *handle, @@ -2550,19 +2405,12 @@ static int smu_set_power_profile_mode(void *handle, uint32_t param_size) { struct smu_context *smu = handle; - int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled || !smu->ppt_funcs->set_power_profile_mode) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - - smu_bump_power_profile_mode(smu, param, param_size); - - mutex_unlock(&smu->mutex); - - return ret; + return smu_bump_power_profile_mode(smu, param, param_size); } @@ -2579,12 +2427,8 @@ static int smu_get_fan_control_mode(void *handle, u32 *fan_mode) if (!fan_mode) return -EINVAL; - mutex_lock(&smu->mutex); - *fan_mode = smu->ppt_funcs->get_fan_control_mode(smu); - mutex_unlock(&smu->mutex); - return 0; } @@ -2602,8 +2446,6 @@ static int smu_set_fan_control_mode(void *handle, u32 value) if (value == U32_MAX) return -EINVAL; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->set_fan_control_mode(smu, value); if (ret) goto out; @@ -2620,8 +2462,6 @@ static int smu_set_fan_control_mode(void *handle, u32 value) } out: - mutex_unlock(&smu->mutex); - return ret; } @@ -2639,12 +2479,8 @@ static int smu_get_fan_speed_pwm(void *handle, u32 *speed) if (!speed) return -EINVAL; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->get_fan_speed_pwm(smu, speed); - mutex_unlock(&smu->mutex); - return ret; } @@ -2662,8 +2498,6 @@ static int smu_set_fan_speed_pwm(void *handle, u32 speed) if (speed == U32_MAX) return -EINVAL; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->set_fan_speed_pwm(smu, speed); if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { smu->user_dpm_profile.flags |= SMU_CUSTOM_FAN_SPEED_PWM; @@ -2674,8 +2508,6 @@ static int smu_set_fan_speed_pwm(void *handle, u32 speed) smu->user_dpm_profile.fan_speed_rpm = 0; } - mutex_unlock(&smu->mutex); - return ret; } @@ -2693,30 +2525,19 @@ static int smu_get_fan_speed_rpm(void *handle, uint32_t *speed) if (!speed) return -EINVAL; - mutex_lock(&smu->mutex); - ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); - mutex_unlock(&smu->mutex); - return ret; } static int smu_set_deep_sleep_dcefclk(void *handle, uint32_t clk) { struct smu_context *smu = handle; - int ret = 0; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - - ret = smu_set_min_dcef_deep_sleep(smu, clk); - - mutex_unlock(&smu->mutex); - - return ret; + return smu_set_min_dcef_deep_sleep(smu, clk); } static int smu_get_clock_by_type_with_latency(void *handle, @@ -2730,8 +2551,6 @@ static int smu_get_clock_by_type_with_latency(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_clock_by_type_with_latency) { switch (type) { case amd_pp_sys_clock: @@ -2748,15 +2567,12 @@ static int smu_get_clock_by_type_with_latency(void *handle, break; default: dev_err(smu->adev->dev, "Invalid clock type!\n"); - mutex_unlock(&smu->mutex); return -EINVAL; } ret = smu->ppt_funcs->get_clock_by_type_with_latency(smu, clk_type, clocks); } - mutex_unlock(&smu->mutex); - return ret; } @@ -2769,13 +2585,9 @@ static int smu_display_clock_voltage_request(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->display_clock_voltage_request) ret = smu->ppt_funcs->display_clock_voltage_request(smu, clock_req); - mutex_unlock(&smu->mutex); - return ret; } @@ -2789,13 +2601,9 @@ static int smu_display_disable_memory_clock_switch(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->display_disable_memory_clock_switch) ret = smu->ppt_funcs->display_disable_memory_clock_switch(smu, disable_memory_clock_switch); - mutex_unlock(&smu->mutex); - return ret; } @@ -2808,13 +2616,9 @@ static int smu_set_xgmi_pstate(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_xgmi_pstate) ret = smu->ppt_funcs->set_xgmi_pstate(smu, pstate); - mutex_unlock(&smu->mutex); - if(ret) dev_err(smu->adev->dev, "Failed to set XGMI pstate!\n"); @@ -2824,21 +2628,16 @@ static int smu_set_xgmi_pstate(void *handle, static int smu_get_baco_capability(void *handle, bool *cap) { struct smu_context *smu = handle; - int ret = 0; *cap = false; if (!smu->pm_enabled) return 0; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs && smu->ppt_funcs->baco_is_support) *cap = smu->ppt_funcs->baco_is_support(smu); - mutex_unlock(&smu->mutex); - - return ret; + return 0; } static int smu_baco_set_state(void *handle, int state) @@ -2850,20 +2649,11 @@ static int smu_baco_set_state(void *handle, int state) return -EOPNOTSUPP; if (state == 0) { - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->baco_exit) ret = smu->ppt_funcs->baco_exit(smu); - - mutex_unlock(&smu->mutex); } else if (state == 1) { - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->baco_enter) ret = smu->ppt_funcs->baco_enter(smu); - - mutex_unlock(&smu->mutex); - } else { return -EINVAL; } @@ -2882,13 +2672,9 @@ bool smu_mode1_reset_is_support(struct smu_context *smu) if (!smu->pm_enabled) return false; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs && smu->ppt_funcs->mode1_reset_is_support) ret = smu->ppt_funcs->mode1_reset_is_support(smu); - mutex_unlock(&smu->mutex); - return ret; } @@ -2899,13 +2685,9 @@ bool smu_mode2_reset_is_support(struct smu_context *smu) if (!smu->pm_enabled) return false; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs && smu->ppt_funcs->mode2_reset_is_support) ret = smu->ppt_funcs->mode2_reset_is_support(smu); - mutex_unlock(&smu->mutex); - return ret; } @@ -2916,13 +2698,9 @@ int smu_mode1_reset(struct smu_context *smu) if (!smu->pm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->mode1_reset) ret = smu->ppt_funcs->mode1_reset(smu); - mutex_unlock(&smu->mutex); - return ret; } @@ -2934,13 +2712,9 @@ static int smu_mode2_reset(void *handle) if (!smu->pm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->mode2_reset) ret = smu->ppt_funcs->mode2_reset(smu); - mutex_unlock(&smu->mutex); - if (ret) dev_err(smu->adev->dev, "Mode2 reset failed!\n"); @@ -2956,13 +2730,9 @@ static int smu_get_max_sustainable_clocks_by_dc(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_max_sustainable_clocks_by_dc) ret = smu->ppt_funcs->get_max_sustainable_clocks_by_dc(smu, max_clocks); - mutex_unlock(&smu->mutex); - return ret; } @@ -2976,13 +2746,9 @@ static int smu_get_uclk_dpm_states(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_uclk_dpm_states) ret = smu->ppt_funcs->get_uclk_dpm_states(smu, clock_values_in_khz, num_states); - mutex_unlock(&smu->mutex); - return ret; } @@ -2994,13 +2760,9 @@ static enum amd_pm_state_type smu_get_current_power_state(void *handle) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_current_power_state) pm_state = smu->ppt_funcs->get_current_power_state(smu); - mutex_unlock(&smu->mutex); - return pm_state; } @@ -3013,20 +2775,15 @@ static int smu_get_dpm_clock_table(void *handle, if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_dpm_clock_table) ret = smu->ppt_funcs->get_dpm_clock_table(smu, clock_table); - mutex_unlock(&smu->mutex); - return ret; } static ssize_t smu_sys_get_gpu_metrics(void *handle, void **table) { struct smu_context *smu = handle; - ssize_t size; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; @@ -3034,13 +2791,7 @@ static ssize_t smu_sys_get_gpu_metrics(void *handle, void **table) if (!smu->ppt_funcs->get_gpu_metrics) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - - size = smu->ppt_funcs->get_gpu_metrics(smu, table); - - mutex_unlock(&smu->mutex); - - return size; + return smu->ppt_funcs->get_gpu_metrics(smu, table); } static int smu_enable_mgpu_fan_boost(void *handle) @@ -3051,13 +2802,9 @@ static int smu_enable_mgpu_fan_boost(void *handle) if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; - mutex_lock(&smu->mutex); - if (smu->ppt_funcs->enable_mgpu_fan_boost) ret = smu->ppt_funcs->enable_mgpu_fan_boost(smu); - mutex_unlock(&smu->mutex); - return ret; } @@ -3067,10 +2814,8 @@ static int smu_gfx_state_change_set(void *handle, struct smu_context *smu = handle; int ret = 0; - mutex_lock(&smu->mutex); if (smu->ppt_funcs->gfx_state_change_set) ret = smu->ppt_funcs->gfx_state_change_set(smu, state); - mutex_unlock(&smu->mutex); return ret; } @@ -3079,10 +2824,8 @@ int smu_handle_passthrough_sbr(struct smu_context *smu, bool enable) { int ret = 0; - mutex_lock(&smu->mutex); if (smu->ppt_funcs->smu_handle_passthrough_sbr) ret = smu->ppt_funcs->smu_handle_passthrough_sbr(smu, enable); - mutex_unlock(&smu->mutex); return ret; } @@ -3091,11 +2834,9 @@ int smu_get_ecc_info(struct smu_context *smu, void *umc_ecc) { int ret = -EOPNOTSUPP; - mutex_lock(&smu->mutex); if (smu->ppt_funcs && smu->ppt_funcs->get_ecc_info) ret = smu->ppt_funcs->get_ecc_info(smu, umc_ecc); - mutex_unlock(&smu->mutex); return ret; @@ -3112,12 +2853,10 @@ static int smu_get_prv_buffer_details(void *handle, void **addr, size_t *size) *addr = NULL; *size = 0; - mutex_lock(&smu->mutex); if (memory_pool->bo) { *addr = memory_pool->cpu_addr; *size = memory_pool->size; } - mutex_unlock(&smu->mutex); return 0; } @@ -3181,11 +2920,8 @@ int smu_wait_for_event(struct smu_context *smu, enum smu_event_type event, { int ret = -EINVAL; - if (smu->ppt_funcs->wait_for_event) { - mutex_lock(&smu->mutex); + if (smu->ppt_funcs->wait_for_event) ret = smu->ppt_funcs->wait_for_event(smu, event, event_arg); - mutex_unlock(&smu->mutex); - } return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 3fdab6a44901..00760f3c6da5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -488,7 +488,6 @@ struct smu_context const struct cmn2asic_mapping *table_map; const struct cmn2asic_mapping *pwr_src_map; const struct cmn2asic_mapping *workload_map; - struct mutex mutex; struct mutex sensor_lock; struct mutex metrics_lock; struct mutex message_lock; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index d3963bfe5c89..1b265b8c7996 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2118,9 +2118,9 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&smu->mutex); + mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&smu->mutex); + mutex_unlock(&adev->pm.mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 37e11716e919..5cdf88f3bb6c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2826,9 +2826,9 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&smu->mutex); + mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&smu->mutex); + mutex_unlock(&adev->pm.mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index c29353e05fd2..5c0ad4dd6543 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3497,9 +3497,9 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&smu->mutex); + mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&smu->mutex); + mutex_unlock(&adev->pm.mutex); if (r) goto fail; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index ac8ba5e0e697..3085a07e70d2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1521,9 +1521,9 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, } } } - mutex_lock(&smu->mutex); + mutex_lock(&adev->pm.mutex); r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); - mutex_unlock(&smu->mutex); + mutex_unlock(&adev->pm.mutex); if (r) goto fail; From 974d5ef0dd9d251dd4571e30d5e79e7e4940d424 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 13:15:57 +0800 Subject: [PATCH 102/339] drm/amd/pm: drop unneeded vcn/jpeg_gate_lock As those related APIs are already protected by adev->pm.mutex. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 63 ++++--------------- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 2 - 2 files changed, 11 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index eaaa5b033d46..8ac87733d211 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -158,8 +158,8 @@ static u32 smu_get_sclk(void *handle, bool low) return clk_freq * 100; } -static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu, - bool enable) +static int smu_dpm_set_vcn_enable(struct smu_context *smu, + bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -178,24 +178,8 @@ static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu, return ret; } -static int smu_dpm_set_vcn_enable(struct smu_context *smu, - bool enable) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int ret = 0; - - mutex_lock(&power_gate->vcn_gate_lock); - - ret = smu_dpm_set_vcn_enable_locked(smu, enable); - - mutex_unlock(&power_gate->vcn_gate_lock); - - return ret; -} - -static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu, - bool enable) +static int smu_dpm_set_jpeg_enable(struct smu_context *smu, + bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -214,22 +198,6 @@ static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu, return ret; } -static int smu_dpm_set_jpeg_enable(struct smu_context *smu, - bool enable) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int ret = 0; - - mutex_lock(&power_gate->jpeg_gate_lock); - - ret = smu_dpm_set_jpeg_enable_locked(smu, enable); - - mutex_unlock(&power_gate->jpeg_gate_lock); - - return ret; -} - /** * smu_dpm_set_power_gate - power gate/ungate the specific IP block * @@ -620,32 +588,25 @@ static int smu_set_default_dpm_table(struct smu_context *smu) if (!smu->ppt_funcs->set_default_dpm_table) return 0; - mutex_lock(&power_gate->vcn_gate_lock); - mutex_lock(&power_gate->jpeg_gate_lock); - vcn_gate = atomic_read(&power_gate->vcn_gated); jpeg_gate = atomic_read(&power_gate->jpeg_gated); - ret = smu_dpm_set_vcn_enable_locked(smu, true); + ret = smu_dpm_set_vcn_enable(smu, true); if (ret) - goto err0_out; + return ret; - ret = smu_dpm_set_jpeg_enable_locked(smu, true); + ret = smu_dpm_set_jpeg_enable(smu, true); if (ret) - goto err1_out; + goto err_out; ret = smu->ppt_funcs->set_default_dpm_table(smu); if (ret) dev_err(smu->adev->dev, "Failed to setup default dpm clock tables!\n"); - smu_dpm_set_jpeg_enable_locked(smu, !jpeg_gate); -err1_out: - smu_dpm_set_vcn_enable_locked(smu, !vcn_gate); -err0_out: - mutex_unlock(&power_gate->jpeg_gate_lock); - mutex_unlock(&power_gate->vcn_gate_lock); - + smu_dpm_set_jpeg_enable(smu, !jpeg_gate); +err_out: + smu_dpm_set_vcn_enable(smu, !vcn_gate); return ret; } @@ -1007,8 +968,6 @@ static int smu_sw_init(void *handle) atomic_set(&smu->smu_power.power_gate.vcn_gated, 1); atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1); - mutex_init(&smu->smu_power.power_gate.vcn_gate_lock); - mutex_init(&smu->smu_power.power_gate.jpeg_gate_lock); smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 00760f3c6da5..c3efe4fea5e0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -376,8 +376,6 @@ struct smu_power_gate { bool vce_gated; atomic_t vcn_gated; atomic_t jpeg_gated; - struct mutex vcn_gate_lock; - struct mutex jpeg_gate_lock; }; struct smu_power_context { From da11407f066c28c49bb7a4ff6a6b742b7a18d7ca Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 13:37:26 +0800 Subject: [PATCH 103/339] drm/amd/pm: drop unneeded smu->metrics_lock As all those related APIs are already well protected by adev->pm.mutex and smu->message_lock. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 - drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 14 +-- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 10 +- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 112 +++++------------- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 27 ++--- .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 28 ++--- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 14 +-- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 23 ++-- .../drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 10 +- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 21 +--- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 4 - 12 files changed, 70 insertions(+), 195 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8ac87733d211..f10a0665a286 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -956,7 +956,6 @@ static int smu_sw_init(void *handle) bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX); mutex_init(&smu->sensor_lock); - mutex_init(&smu->metrics_lock); mutex_init(&smu->message_lock); INIT_WORK(&smu->throttling_logging_work, smu_throttling_logging_work_fn); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index c3efe4fea5e0..63ed807c96f5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -487,7 +487,6 @@ struct smu_context const struct cmn2asic_mapping *pwr_src_map; const struct cmn2asic_mapping *workload_map; struct mutex sensor_lock; - struct mutex metrics_lock; struct mutex message_lock; uint64_t pool_size; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 1b265b8c7996..5a8b2d549c2b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -602,15 +602,11 @@ static int arcturus_get_smu_metrics_data(struct smu_context *smu, SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -693,8 +689,6 @@ static int arcturus_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index 2238ee19c222..7ae6b1bd648a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -150,13 +150,9 @@ cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, NULL, false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -200,8 +196,6 @@ cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 5cdf88f3bb6c..68ead70673c5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -546,15 +546,11 @@ static int navi10_get_legacy_smu_metrics_data(struct smu_context *smu, (SmuMetrics_legacy_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -624,8 +620,6 @@ static int navi10_get_legacy_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -638,15 +632,11 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -719,8 +709,6 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -733,15 +721,11 @@ static int navi12_get_legacy_smu_metrics_data(struct smu_context *smu, (SmuMetrics_NV12_legacy_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -811,8 +795,6 @@ static int navi12_get_legacy_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -825,15 +807,11 @@ static int navi12_get_smu_metrics_data(struct smu_context *smu, (SmuMetrics_NV12_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -906,8 +884,6 @@ static int navi12_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -2708,20 +2684,14 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu, SmuMetrics_legacy_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - true); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + true); + if (ret) return ret; - } memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_legacy_t)); - mutex_unlock(&smu->metrics_lock); - smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); gpu_metrics->temperature_edge = metrics.TemperatureEdge; @@ -2901,20 +2871,14 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - true); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + true); + if (ret) return ret; - } memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); - mutex_unlock(&smu->metrics_lock); - smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); gpu_metrics->temperature_edge = metrics.TemperatureEdge; @@ -2979,20 +2943,14 @@ static ssize_t navi12_get_legacy_gpu_metrics(struct smu_context *smu, SmuMetrics_NV12_legacy_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - true); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + true); + if (ret) return ret; - } memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_legacy_t)); - mutex_unlock(&smu->metrics_lock); - smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); gpu_metrics->temperature_edge = metrics.TemperatureEdge; @@ -3060,20 +3018,14 @@ static ssize_t navi12_get_gpu_metrics(struct smu_context *smu, SmuMetrics_NV12_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - true); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + true); + if (ret) return ret; - } memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); - mutex_unlock(&smu->metrics_lock); - smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); gpu_metrics->temperature_edge = metrics.TemperatureEdge; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 5c0ad4dd6543..73579996a1ab 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -539,15 +539,11 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, uint16_t average_gfx_activity; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -647,8 +643,6 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -3580,14 +3574,11 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, uint16_t average_gfx_activity; int ret = 0; - mutex_lock(&smu->metrics_lock); - ret = smu_cmn_get_metrics_table_locked(smu, - &metrics_external, - true); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + &metrics_external, + true); + if (ret) return ret; - } smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3); @@ -3677,8 +3668,6 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, smu_v11_0_get_current_pcie_link_speed(smu); } - mutex_unlock(&smu->metrics_lock); - gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); *table = (void *)gpu_metrics; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 5cb07ed227fb..c736adca6fbb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -273,15 +273,11 @@ static int vangogh_get_legacy_smu_metrics_data(struct smu_context *smu, SmuMetrics_legacy_t *metrics = (SmuMetrics_legacy_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -335,8 +331,6 @@ static int vangogh_get_legacy_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -348,15 +342,11 @@ static int vangogh_get_smu_metrics_data(struct smu_context *smu, SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -410,8 +400,6 @@ static int vangogh_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 25c4b135f830..d75508085578 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -1128,15 +1128,11 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu, SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_AVERAGE_GFXCLK: @@ -1201,8 +1197,6 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 3085a07e70d2..05b7d8e38196 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -571,15 +571,11 @@ static int aldebaran_get_smu_metrics_data(struct smu_context *smu, SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) return ret; - } switch (member) { case METRICS_CURR_GFXCLK: @@ -653,8 +649,6 @@ static int aldebaran_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } @@ -1594,17 +1588,14 @@ static void aldebaran_get_unique_id(struct smu_context *smu) uint32_t upper32 = 0, lower32 = 0; int ret; - mutex_lock(&smu->metrics_lock); - ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); + ret = smu_cmn_get_metrics_table(smu, NULL, false); if (ret) - goto out_unlock; + goto out; upper32 = metrics->PublicSerialNumUpper32; lower32 = metrics->PublicSerialNumLower32; -out_unlock: - mutex_unlock(&smu->metrics_lock); - +out: adev->unique_id = ((uint64_t)upper32 << 32) | lower32; if (adev->serial[0] == '\0') sprintf(adev->serial, "%016llx", adev->unique_id); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index caf1775d48ef..451d30dcc639 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -310,13 +310,9 @@ static int yellow_carp_get_smu_metrics_data(struct smu_context *smu, SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); - if (ret) { - mutex_unlock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table(smu, NULL, false); + if (ret) return ret; - } switch (member) { case METRICS_AVERAGE_GFXCLK: @@ -387,8 +383,6 @@ static int yellow_carp_get_smu_metrics_data(struct smu_context *smu, break; } - mutex_unlock(&smu->metrics_lock); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index ee1a312fd497..849e4403cc0e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -964,9 +964,9 @@ int smu_cmn_write_pptable(struct smu_context *smu) true); } -int smu_cmn_get_metrics_table_locked(struct smu_context *smu, - void *metrics_table, - bool bypass_cache) +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; uint32_t table_size = @@ -994,21 +994,6 @@ int smu_cmn_get_metrics_table_locked(struct smu_context *smu, return 0; } -int smu_cmn_get_metrics_table(struct smu_context *smu, - void *metrics_table, - bool bypass_cache) -{ - int ret = 0; - - mutex_lock(&smu->metrics_lock); - ret = smu_cmn_get_metrics_table_locked(smu, - metrics_table, - bypass_cache); - mutex_unlock(&smu->metrics_lock); - - return ret; -} - void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev) { struct metrics_table_header *header = (struct metrics_table_header *)table; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 67a25da79256..f0b4fb2a0960 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -101,10 +101,6 @@ int smu_cmn_write_watermarks_table(struct smu_context *smu); int smu_cmn_write_pptable(struct smu_context *smu); -int smu_cmn_get_metrics_table_locked(struct smu_context *smu, - void *metrics_table, - bool bypass_cache); - int smu_cmn_get_metrics_table(struct smu_context *smu, void *metrics_table, bool bypass_cache); From 56383e8f4d296a33cc5b2a11864025d8205e9438 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 13:51:34 +0800 Subject: [PATCH 104/339] drm/amd/pm: drop unneeded smu->sensor_lock As all those related APIs are already well protected by adev->pm.mutex and smu->message_lock. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 - drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 4 ---- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 2 -- drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 2 -- 10 files changed, 20 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index f10a0665a286..57f3d26b03fe 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -955,7 +955,6 @@ static int smu_sw_init(void *handle) bitmap_zero(smu->smu_feature.enabled, SMU_FEATURE_MAX); bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX); - mutex_init(&smu->sensor_lock); mutex_init(&smu->message_lock); INIT_WORK(&smu->throttling_logging_work, smu_throttling_logging_work_fn); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 63ed807c96f5..2cef7ff46010 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -486,7 +486,6 @@ struct smu_context const struct cmn2asic_mapping *table_map; const struct cmn2asic_mapping *pwr_src_map; const struct cmn2asic_mapping *workload_map; - struct mutex sensor_lock; struct mutex message_lock; uint64_t pool_size; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 5a8b2d549c2b..2c78d04d5611 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1113,7 +1113,6 @@ static int arcturus_read_sensor(struct smu_context *smu, if (!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_MAX_FAN_RPM: *(uint32_t *)data = pptable->FanMaximumRpm; @@ -1174,7 +1173,6 @@ static int arcturus_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index 7ae6b1bd648a..2acd7470431e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -209,8 +209,6 @@ static int cyan_skillfish_read_sensor(struct smu_context *smu, if (!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); - switch (sensor) { case AMDGPU_PP_SENSOR_GFX_SCLK: ret = cyan_skillfish_get_smu_metrics_data(smu, @@ -261,8 +259,6 @@ static int cyan_skillfish_read_sensor(struct smu_context *smu, break; } - mutex_unlock(&smu->sensor_lock); - return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 68ead70673c5..84834c24a7e9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1964,7 +1964,6 @@ static int navi10_read_sensor(struct smu_context *smu, if(!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_MAX_FAN_RPM: *(uint32_t *)data = pptable->FanMaximumRpm; @@ -2024,7 +2023,6 @@ static int navi10_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 73579996a1ab..651fe748e423 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1619,7 +1619,6 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu, if(!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_MAX_FAN_RPM: GET_PPTABLE_MEMBER(FanMaximumRpm, &temp); @@ -1680,7 +1679,6 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index c736adca6fbb..721027917f81 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -1494,7 +1494,6 @@ static int vangogh_read_sensor(struct smu_context *smu, if (!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_GPU_LOAD: ret = vangogh_common_get_smu_metrics_data(smu, @@ -1556,7 +1555,6 @@ static int vangogh_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index d75508085578..e99e7b2bf25b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -1209,7 +1209,6 @@ static int renoir_read_sensor(struct smu_context *smu, if (!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_GPU_LOAD: ret = renoir_get_smu_metrics_data(smu, @@ -1277,7 +1276,6 @@ static int renoir_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 05b7d8e38196..8c02adbf446a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1141,7 +1141,6 @@ static int aldebaran_read_sensor(struct smu_context *smu, if (!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_MEM_LOAD: case AMDGPU_PP_SENSOR_GPU_LOAD: @@ -1180,7 +1179,6 @@ static int aldebaran_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index 451d30dcc639..bd24a2632214 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -395,7 +395,6 @@ static int yellow_carp_read_sensor(struct smu_context *smu, if (!data || !size) return -EINVAL; - mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_GPU_LOAD: ret = yellow_carp_get_smu_metrics_data(smu, @@ -463,7 +462,6 @@ static int yellow_carp_read_sensor(struct smu_context *smu, ret = -EOPNOTSUPP; break; } - mutex_unlock(&smu->sensor_lock); return ret; } From 1c4dba5e14c0085d412429d50cbcf8e9e2a18924 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 14:02:25 +0800 Subject: [PATCH 105/339] drm/amd/pm: drop unneeded smu_baco->mutex As those APIs related are already well protected by adev->pm.mutex. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 - drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 19 +++++-------------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 57f3d26b03fe..fe155a7874b0 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -567,7 +567,6 @@ static int smu_early_init(void *handle) smu->adev = adev; smu->pm_enabled = !!amdgpu_dpm; smu->is_apu = false; - mutex_init(&smu->smu_baco.mutex); smu->smu_baco.state = SMU_BACO_STATE_EXIT; smu->smu_baco.platform_support = false; smu->user_dpm_profile.fan_mode = -1; diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 2cef7ff46010..79b2a817491c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -428,7 +428,6 @@ enum smu_baco_state struct smu_baco_context { - struct mutex mutex; uint32_t state; bool platform_support; }; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index e94a400db669..b58a4c2823c2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1617,13 +1617,8 @@ bool smu_v11_0_baco_is_support(struct smu_context *smu) enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) { struct smu_baco_context *smu_baco = &smu->smu_baco; - enum smu_baco_state baco_state; - mutex_lock(&smu_baco->mutex); - baco_state = smu_baco->state; - mutex_unlock(&smu_baco->mutex); - - return baco_state; + return smu_baco->state; } #define D3HOT_BACO_SEQUENCE 0 @@ -1640,8 +1635,6 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) if (smu_v11_0_baco_get_state(smu) == state) return 0; - mutex_lock(&smu_baco->mutex); - if (state == SMU_BACO_STATE_ENTER) { switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(11, 0, 7): @@ -1682,18 +1675,16 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) } else { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL); if (ret) - goto out; + return ret; /* clear vbios scratch 6 and 7 for coming asic reinit */ WREG32(adev->bios_scratch_reg_offset + 6, 0); WREG32(adev->bios_scratch_reg_offset + 7, 0); } - if (ret) - goto out; - smu_baco->state = state; -out: - mutex_unlock(&smu_baco->mutex); + if (!ret) + smu_baco->state = state; + return ret; } From 1f2cf08aa010594036ccfb19d207e5b80b5bb7a0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 14:36:32 +0800 Subject: [PATCH 106/339] drm/amd/pm: drop unneeded feature->mutex As all those related APIs are already well protected by adev->pm.mutex. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 - drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 20 ++++++++----------- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 19 ++---------------- 4 files changed, 10 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index fe155a7874b0..5ace30434e60 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -949,7 +949,6 @@ static int smu_sw_init(void *handle) smu->pool_size = adev->pm.smu_prv_buffer_size; smu->smu_feature.feature_num = SMU_FEATURE_MAX; - mutex_init(&smu->smu_feature.mutex); bitmap_zero(smu->smu_feature.supported, SMU_FEATURE_MAX); bitmap_zero(smu->smu_feature.enabled, SMU_FEATURE_MAX); bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 79b2a817491c..18f24db7d202 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -391,7 +391,6 @@ struct smu_feature DECLARE_BITMAP(supported, SMU_FEATURE_MAX); DECLARE_BITMAP(allowed, SMU_FEATURE_MAX); DECLARE_BITMAP(enabled, SMU_FEATURE_MAX); - struct mutex mutex; }; struct smu_clocks { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index d9e3ebfeee73..1754a3720179 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -722,25 +722,21 @@ int smu_v13_0_set_allowed_mask(struct smu_context *smu) int ret = 0; uint32_t feature_mask[2]; - mutex_lock(&feature->mutex); - if (bitmap_empty(feature->allowed, SMU_FEATURE_MAX) || feature->feature_num < 64) - goto failed; + if (bitmap_empty(feature->allowed, SMU_FEATURE_MAX) || + feature->feature_num < 64) + return -EINVAL; bitmap_copy((unsigned long *)feature_mask, feature->allowed, 64); ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskHigh, feature_mask[1], NULL); if (ret) - goto failed; + return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskLow, - feature_mask[0], NULL); - if (ret) - goto failed; - -failed: - mutex_unlock(&feature->mutex); - return ret; + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetAllowedFeaturesMaskLow, + feature_mask[0], + NULL); } int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 849e4403cc0e..2c1eff9fe4f2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -481,7 +481,6 @@ int smu_cmn_feature_is_supported(struct smu_context *smu, { struct smu_feature *feature = &smu->smu_feature; int feature_id; - int ret = 0; feature_id = smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_FEATURE, @@ -491,11 +490,7 @@ int smu_cmn_feature_is_supported(struct smu_context *smu, WARN_ON(feature_id > feature->feature_num); - mutex_lock(&feature->mutex); - ret = test_bit(feature_id, feature->supported); - mutex_unlock(&feature->mutex); - - return ret; + return test_bit(feature_id, feature->supported); } int smu_cmn_feature_is_enabled(struct smu_context *smu, @@ -504,7 +499,6 @@ int smu_cmn_feature_is_enabled(struct smu_context *smu, struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; int feature_id; - int ret = 0; if (smu->is_apu && adev->family < AMDGPU_FAMILY_VGH) return 1; @@ -517,11 +511,7 @@ int smu_cmn_feature_is_enabled(struct smu_context *smu, WARN_ON(feature_id > feature->feature_num); - mutex_lock(&feature->mutex); - ret = test_bit(feature_id, feature->enabled); - mutex_unlock(&feature->mutex); - - return ret; + return test_bit(feature_id, feature->enabled); } bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, @@ -666,14 +656,12 @@ int smu_cmn_feature_update_enable_state(struct smu_context *smu, return ret; } - mutex_lock(&feature->mutex); if (enabled) bitmap_or(feature->enabled, feature->enabled, (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); else bitmap_andnot(feature->enabled, feature->enabled, (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); - mutex_unlock(&feature->mutex); return ret; } @@ -843,11 +831,8 @@ int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, } if (no_hw_disablement) { - mutex_lock(&feature->mutex); bitmap_andnot(feature->enabled, feature->enabled, (unsigned long *)(&features_to_disable), SMU_FEATURE_MAX); - mutex_unlock(&feature->mutex); - return 0; } else { return smu_cmn_feature_update_enable_state(smu, From a746c77e5ee86829c03dfaf718e18b589f849be3 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 29 Nov 2021 14:57:00 +0800 Subject: [PATCH 107/339] drm/amd/pm: drop unneeded hwmgr->smu_lock As all those related APIs are already well protected by adev->pm.mutex. Signed-off-by: Evan Quan Reviewed-by: Guchun Chen Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 278 +++--------------- drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 1 - 2 files changed, 38 insertions(+), 241 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index 76c26ae368f9..a2da46bf3985 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -50,7 +50,6 @@ static int amd_powerplay_create(struct amdgpu_device *adev) hwmgr->adev = adev; hwmgr->not_vf = !amdgpu_sriov_vf(adev); hwmgr->device = amdgpu_cgs_create_device(adev); - mutex_init(&hwmgr->smu_lock); mutex_init(&hwmgr->msg_lock); hwmgr->chip_family = adev->family; hwmgr->chip_id = adev->asic_type; @@ -178,12 +177,9 @@ static int pp_late_init(void *handle) struct amdgpu_device *adev = handle; struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - if (hwmgr && hwmgr->pm_en) { - mutex_lock(&hwmgr->smu_lock); + if (hwmgr && hwmgr->pm_en) hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL); - mutex_unlock(&hwmgr->smu_lock); - } if (adev->pm.smu_prv_buffer_size != 0) pp_reserve_vram_for_smu(adev); @@ -345,11 +341,9 @@ static int pp_dpm_force_performance_level(void *handle, if (level == hwmgr->dpm_level) return 0; - mutex_lock(&hwmgr->smu_lock); pp_dpm_en_umd_pstate(hwmgr, &level); hwmgr->request_dpm_level = level; hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -358,21 +352,16 @@ static enum amd_dpm_forced_level pp_dpm_get_performance_level( void *handle) { struct pp_hwmgr *hwmgr = handle; - enum amd_dpm_forced_level level; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - level = hwmgr->dpm_level; - mutex_unlock(&hwmgr->smu_lock); - return level; + return hwmgr->dpm_level; } static uint32_t pp_dpm_get_sclk(void *handle, bool low) { struct pp_hwmgr *hwmgr = handle; - uint32_t clk = 0; if (!hwmgr || !hwmgr->pm_en) return 0; @@ -381,16 +370,12 @@ static uint32_t pp_dpm_get_sclk(void *handle, bool low) pr_info_ratelimited("%s was not implemented.\n", __func__); return 0; } - mutex_lock(&hwmgr->smu_lock); - clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low); - mutex_unlock(&hwmgr->smu_lock); - return clk; + return hwmgr->hwmgr_func->get_sclk(hwmgr, low); } static uint32_t pp_dpm_get_mclk(void *handle, bool low) { struct pp_hwmgr *hwmgr = handle; - uint32_t clk = 0; if (!hwmgr || !hwmgr->pm_en) return 0; @@ -399,10 +384,7 @@ static uint32_t pp_dpm_get_mclk(void *handle, bool low) pr_info_ratelimited("%s was not implemented.\n", __func__); return 0; } - mutex_lock(&hwmgr->smu_lock); - clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low); - mutex_unlock(&hwmgr->smu_lock); - return clk; + return hwmgr->hwmgr_func->get_mclk(hwmgr, low); } static void pp_dpm_powergate_vce(void *handle, bool gate) @@ -416,9 +398,7 @@ static void pp_dpm_powergate_vce(void *handle, bool gate) pr_info_ratelimited("%s was not implemented.\n", __func__); return; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); - mutex_unlock(&hwmgr->smu_lock); } static void pp_dpm_powergate_uvd(void *handle, bool gate) @@ -432,25 +412,18 @@ static void pp_dpm_powergate_uvd(void *handle, bool gate) pr_info_ratelimited("%s was not implemented.\n", __func__); return; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); - mutex_unlock(&hwmgr->smu_lock); } static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id, enum amd_pm_state_type *user_state) { - int ret = 0; struct pp_hwmgr *hwmgr = handle; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr_handle_task(hwmgr, task_id, user_state); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return hwmgr_handle_task(hwmgr, task_id, user_state); } static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) @@ -462,8 +435,6 @@ static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - state = hwmgr->current_ps; switch (state->classification.ui_label) { @@ -483,7 +454,6 @@ static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) pm_type = POWER_STATE_TYPE_DEFAULT; break; } - mutex_unlock(&hwmgr->smu_lock); return pm_type; } @@ -501,9 +471,7 @@ static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) if (mode == U32_MAX) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -521,16 +489,13 @@ static int pp_dpm_get_fan_control_mode(void *handle, uint32_t *fan_mode) if (!fan_mode) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); *fan_mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); - mutex_unlock(&hwmgr->smu_lock); return 0; } static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EOPNOTSUPP; @@ -541,16 +506,12 @@ static int pp_dpm_set_fan_speed_pwm(void *handle, uint32_t speed) if (speed == U32_MAX) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->set_fan_speed_pwm(hwmgr, speed); } static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EOPNOTSUPP; @@ -561,16 +522,12 @@ static int pp_dpm_get_fan_speed_pwm(void *handle, uint32_t *speed) if (!speed) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->get_fan_speed_pwm(hwmgr, speed); } static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EOPNOTSUPP; @@ -581,16 +538,12 @@ static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) if (!rpm) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm); } static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EOPNOTSUPP; @@ -601,10 +554,7 @@ static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm) if (rpm == U32_MAX) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm); } static int pp_dpm_get_pp_num_states(void *handle, @@ -618,8 +568,6 @@ static int pp_dpm_get_pp_num_states(void *handle, if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - data->nums = hwmgr->num_ps; for (i = 0; i < hwmgr->num_ps; i++) { @@ -642,23 +590,18 @@ static int pp_dpm_get_pp_num_states(void *handle, data->states[i] = POWER_STATE_TYPE_DEFAULT; } } - mutex_unlock(&hwmgr->smu_lock); return 0; } static int pp_dpm_get_pp_table(void *handle, char **table) { struct pp_hwmgr *hwmgr = handle; - int size = 0; if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); *table = (char *)hwmgr->soft_pp_table; - size = hwmgr->soft_pp_table_size; - mutex_unlock(&hwmgr->smu_lock); - return size; + return hwmgr->soft_pp_table_size; } static int amd_powerplay_reset(void *handle) @@ -685,13 +628,12 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) if (!hwmgr || !hwmgr->pm_en) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); if (!hwmgr->hardcode_pp_table) { hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table, hwmgr->soft_pp_table_size, GFP_KERNEL); if (!hwmgr->hardcode_pp_table) - goto err; + return ret; } memcpy(hwmgr->hardcode_pp_table, buf, size); @@ -700,17 +642,11 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) ret = amd_powerplay_reset(handle); if (ret) - goto err; + return ret; - if (hwmgr->hwmgr_func->avfs_control) { + if (hwmgr->hwmgr_func->avfs_control) ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false); - if (ret) - goto err; - } - mutex_unlock(&hwmgr->smu_lock); - return 0; -err: - mutex_unlock(&hwmgr->smu_lock); + return ret; } @@ -718,7 +654,6 @@ static int pp_dpm_force_clock_level(void *handle, enum pp_clock_type type, uint32_t mask) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -733,17 +668,13 @@ static int pp_dpm_force_clock_level(void *handle, return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); } static int pp_dpm_print_clock_levels(void *handle, enum pp_clock_type type, char *buf) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -752,16 +683,12 @@ static int pp_dpm_print_clock_levels(void *handle, pr_info_ratelimited("%s was not implemented.\n", __func__); return 0; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); } static int pp_dpm_get_sclk_od(void *handle) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -770,16 +697,12 @@ static int pp_dpm_get_sclk_od(void *handle) pr_info_ratelimited("%s was not implemented.\n", __func__); return 0; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->get_sclk_od(hwmgr); } static int pp_dpm_set_sclk_od(void *handle, uint32_t value) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -789,16 +712,12 @@ static int pp_dpm_set_sclk_od(void *handle, uint32_t value) return 0; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); } static int pp_dpm_get_mclk_od(void *handle) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -807,16 +726,12 @@ static int pp_dpm_get_mclk_od(void *handle) pr_info_ratelimited("%s was not implemented.\n", __func__); return 0; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->get_mclk_od(hwmgr); } static int pp_dpm_set_mclk_od(void *handle, uint32_t value) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -825,17 +740,13 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) pr_info_ratelimited("%s was not implemented.\n", __func__); return 0; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); } static int pp_dpm_read_sensor(void *handle, int idx, void *value, int *size) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en || !value) return -EINVAL; @@ -854,10 +765,7 @@ static int pp_dpm_read_sensor(void *handle, int idx, *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM; return 0; default: - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size); } } @@ -877,36 +785,28 @@ pp_dpm_get_vce_clock_state(void *handle, unsigned idx) static int pp_get_power_profile_mode(void *handle, char *buf) { struct pp_hwmgr *hwmgr = handle; - int ret; if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->get_power_profile_mode) return -EOPNOTSUPP; if (!buf) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf); } static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) { struct pp_hwmgr *hwmgr = handle; - int ret = -EOPNOTSUPP; if (!hwmgr || !hwmgr->pm_en || !hwmgr->hwmgr_func->set_power_profile_mode) - return ret; + return -EOPNOTSUPP; if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { pr_debug("power profile setting is for manual dpm mode only.\n"); return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); } static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size) @@ -971,8 +871,6 @@ static int pp_dpm_switch_power_profile(void *handle, if (!(type < PP_SMC_POWER_PROFILE_CUSTOM)) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - if (!en) { hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]); index = fls(hwmgr->workload_mask); @@ -987,15 +885,12 @@ static int pp_dpm_switch_power_profile(void *handle, if (type == PP_SMC_POWER_PROFILE_COMPUTE && hwmgr->hwmgr_func->disable_power_features_for_compute_performance) { - if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en)) { - mutex_unlock(&hwmgr->smu_lock); + if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en)) return -EINVAL; - } } if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1025,10 +920,8 @@ static int pp_set_power_limit(void *handle, uint32_t limit) if (limit > max_power_limit) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_power_limit(hwmgr, limit); hwmgr->power_limit = limit; - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1045,8 +938,6 @@ static int pp_get_power_limit(void *handle, uint32_t *limit, if (power_type != PP_PWR_TYPE_SUSTAINED) return -EOPNOTSUPP; - mutex_lock(&hwmgr->smu_lock); - switch (pp_limit_level) { case PP_PWR_LIMIT_CURRENT: *limit = hwmgr->power_limit; @@ -1066,8 +957,6 @@ static int pp_get_power_limit(void *handle, uint32_t *limit, break; } - mutex_unlock(&hwmgr->smu_lock); - return ret; } @@ -1079,9 +968,7 @@ static int pp_display_configuration_change(void *handle, if (!hwmgr || !hwmgr->pm_en) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); phm_store_dal_configuration_data(hwmgr, display_config); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1089,15 +976,11 @@ static int pp_get_display_power_level(void *handle, struct amd_pp_simple_clock_info *output) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en ||!output) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = phm_get_dal_power_level(hwmgr, output); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return phm_get_dal_power_level(hwmgr, output); } static int pp_get_current_clocks(void *handle, @@ -1111,8 +994,6 @@ static int pp_get_current_clocks(void *handle, if (!hwmgr || !hwmgr->pm_en) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - phm_get_dal_power_level(hwmgr, &simple_clocks); if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, @@ -1125,7 +1006,6 @@ static int pp_get_current_clocks(void *handle, if (ret) { pr_debug("Error in phm_get_clock_info \n"); - mutex_unlock(&hwmgr->smu_lock); return -EINVAL; } @@ -1148,14 +1028,12 @@ static int pp_get_current_clocks(void *handle, clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; } - mutex_unlock(&hwmgr->smu_lock); return 0; } static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -1163,10 +1041,7 @@ static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struc if (clocks == NULL) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = phm_get_clock_by_type(hwmgr, type, clocks); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return phm_get_clock_by_type(hwmgr, type, clocks); } static int pp_get_clock_by_type_with_latency(void *handle, @@ -1174,15 +1049,11 @@ static int pp_get_clock_by_type_with_latency(void *handle, struct pp_clock_levels_with_latency *clocks) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en ||!clocks) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks); - mutex_unlock(&hwmgr->smu_lock); - return ret; + return phm_get_clock_by_type_with_latency(hwmgr, type, clocks); } static int pp_get_clock_by_type_with_voltage(void *handle, @@ -1190,50 +1061,34 @@ static int pp_get_clock_by_type_with_voltage(void *handle, struct pp_clock_levels_with_voltage *clocks) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en ||!clocks) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - - ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks); - - mutex_unlock(&hwmgr->smu_lock); - return ret; + return phm_get_clock_by_type_with_voltage(hwmgr, type, clocks); } static int pp_set_watermarks_for_clocks_ranges(void *handle, void *clock_ranges) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en || !clock_ranges) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = phm_set_watermarks_for_clocks_ranges(hwmgr, - clock_ranges); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return phm_set_watermarks_for_clocks_ranges(hwmgr, + clock_ranges); } static int pp_display_clock_voltage_request(void *handle, struct pp_display_clock_request *clock) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en ||!clock) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = phm_display_clock_voltage_request(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return phm_display_clock_voltage_request(hwmgr, clock); } static int pp_get_display_mode_validation_clocks(void *handle, @@ -1247,12 +1102,9 @@ static int pp_get_display_mode_validation_clocks(void *handle, clocks->level = PP_DAL_POWERLEVEL_7; - mutex_lock(&hwmgr->smu_lock); - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState)) ret = phm_get_max_high_clocks(hwmgr, clocks); - mutex_unlock(&hwmgr->smu_lock); return ret; } @@ -1364,9 +1216,7 @@ static int pp_notify_smu_enable_pwe(void *handle) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->smus_notify_pwe(hwmgr); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1382,9 +1232,7 @@ static int pp_enable_mgpu_fan_boost(void *handle) hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) return 0; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1401,9 +1249,7 @@ static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1420,9 +1266,7 @@ static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1439,9 +1283,7 @@ static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1449,16 +1291,11 @@ static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock) static int pp_set_active_display_count(void *handle, uint32_t count) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; - mutex_lock(&hwmgr->smu_lock); - ret = phm_set_active_display_count(hwmgr, count); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return phm_set_active_display_count(hwmgr, count); } static int pp_get_asic_baco_capability(void *handle, bool *cap) @@ -1473,9 +1310,7 @@ static int pp_get_asic_baco_capability(void *handle, bool *cap) !hwmgr->hwmgr_func->get_asic_baco_capability) return 0; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1490,9 +1325,7 @@ static int pp_get_asic_baco_state(void *handle, int *state) if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state) return 0; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1508,9 +1341,7 @@ static int pp_set_asic_baco_state(void *handle, int state) !hwmgr->hwmgr_func->set_asic_baco_state) return 0; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1518,7 +1349,6 @@ static int pp_set_asic_baco_state(void *handle, int state) static int pp_get_ppfeature_status(void *handle, char *buf) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en || !buf) return -EINVAL; @@ -1528,17 +1358,12 @@ static int pp_get_ppfeature_status(void *handle, char *buf) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf); } static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -1548,17 +1373,12 @@ static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks); } static int pp_asic_reset_mode_2(void *handle) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -1568,17 +1388,12 @@ static int pp_asic_reset_mode_2(void *handle) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2); } static int pp_smu_i2c_bus_access(void *handle, bool acquire) { struct pp_hwmgr *hwmgr = handle; - int ret = 0; if (!hwmgr || !hwmgr->pm_en) return -EINVAL; @@ -1588,11 +1403,7 @@ static int pp_smu_i2c_bus_access(void *handle, bool acquire) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire); - mutex_unlock(&hwmgr->smu_lock); - - return ret; + return hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire); } static int pp_set_df_cstate(void *handle, enum pp_df_cstate state) @@ -1605,9 +1416,7 @@ static int pp_set_df_cstate(void *handle, enum pp_df_cstate state) if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate) return 0; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_df_cstate(hwmgr, state); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1622,9 +1431,7 @@ static int pp_set_xgmi_pstate(void *handle, uint32_t pstate) if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate) return 0; - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1632,7 +1439,6 @@ static int pp_set_xgmi_pstate(void *handle, uint32_t pstate) static ssize_t pp_get_gpu_metrics(void *handle, void **table) { struct pp_hwmgr *hwmgr = handle; - ssize_t size; if (!hwmgr) return -EINVAL; @@ -1640,11 +1446,7 @@ static ssize_t pp_get_gpu_metrics(void *handle, void **table) if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics) return -EOPNOTSUPP; - mutex_lock(&hwmgr->smu_lock); - size = hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table); - mutex_unlock(&hwmgr->smu_lock); - - return size; + return hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table); } static int pp_gfx_state_change_set(void *handle, uint32_t state) @@ -1659,9 +1461,7 @@ static int pp_gfx_state_change_set(void *handle, uint32_t state) return -EINVAL; } - mutex_lock(&hwmgr->smu_lock); hwmgr->hwmgr_func->gfx_state_change(hwmgr, state); - mutex_unlock(&hwmgr->smu_lock); return 0; } @@ -1675,12 +1475,10 @@ static int pp_get_prv_buffer_details(void *handle, void **addr, size_t *size) *addr = NULL; *size = 0; - mutex_lock(&hwmgr->smu_lock); if (adev->pm.smu_prv_buffer) { amdgpu_bo_kmap(adev->pm.smu_prv_buffer, addr); *size = adev->pm.smu_prv_buffer_size; } - mutex_unlock(&hwmgr->smu_lock); return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h index 03226baea65e..4f7f2f455301 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h @@ -748,7 +748,6 @@ struct pp_hwmgr { bool not_vf; bool pm_en; bool pp_one_vf; - struct mutex smu_lock; struct mutex msg_lock; uint32_t pp_table_version; From 83a3766b147053e542f3c91c121cb9594239e644 Mon Sep 17 00:00:00 2001 From: Rajib Mahapatra Date: Mon, 10 Jan 2022 13:15:19 +0530 Subject: [PATCH 108/339] drm/amd/display: Not to call dpcd_set_source_specific_data during resume. [Why] During resume path, dpcd_set_source_specific_data is taking extra time when core_link_write_dpcd fails on DP_SOURCE_OUI+0x03 and DP_SOURCE_MINIMUM_HBLANK_SUPPORTED. Here,aux->transfer fails with multiple retries and consume significant amount time during S0i3 resume. [How] Not to call dpcd_set_source_specific_data during resume path when there is no oled panel connected and achieve faster resume during S0i3. Reviewed-by: Hersen Wu Signed-off-by: Rajib Mahapatra Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 0c64dea4fdd8..e5d63b0d2594 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -862,7 +862,8 @@ static bool dc_link_detect_helper(struct dc_link *link, (!link->dc->config.allow_edp_hotplug_detection)) && link->local_sink) { // need to re-write OUI and brightness in resume case - if (link->connector_signal == SIGNAL_TYPE_EDP) { + if (link->connector_signal == SIGNAL_TYPE_EDP && + (link->dpcd_sink_ext_caps.bits.oled == 1)) { dpcd_set_source_specific_data(link); msleep(post_oui_delay); dc_link_set_default_brightness_aux(link); From f9130b81aea2de3fb6d356e9495a384b2d35b1d1 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 21 Jan 2022 16:43:33 +0800 Subject: [PATCH 109/339] drm/amdgpu: drop WARN_ON in amdgpu_gart_bind/unbind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NULL pointer check has guarded it already. calltrace: amdgpu_ttm_gart_bind+0x49/0xa0 [amdgpu] amdgpu_ttm_alloc_gart+0x13f/0x180 [amdgpu] amdgpu_bo_create_reserved+0x139/0x2c0 [amdgpu] ? amdgpu_ttm_debugfs_init+0x120/0x120 [amdgpu] amdgpu_bo_create_kernel+0x17/0x80 [amdgpu] amdgpu_ttm_init+0x542/0x5e0 [amdgpu] Fixes: 1b08dfb889b2c5 ("drm/amdgpu: remove gart.ready flag") Signed-off-by: Guchun Chen Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 53cc844346f0..91d8207336c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -161,7 +161,7 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, uint64_t flags = 0; int idx; - if (WARN_ON(!adev->gart.ptr)) + if (!adev->gart.ptr) return; if (!drm_dev_enter(adev_to_drm(adev), &idx)) @@ -241,7 +241,7 @@ void amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, int pages, dma_addr_t *dma_addr, uint64_t flags) { - if (WARN_ON(!adev->gart.ptr)) + if (!adev->gart.ptr) return; amdgpu_gart_map(adev, offset, pages, dma_addr, flags, adev->gart.ptr); From a685572c91b08e2e5143e52f4c5bbdd3d22271b3 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 21 Jan 2022 10:40:40 +0800 Subject: [PATCH 110/339] drm/amd/pm: use dev_*** to print output in multiple GPUs In multiple GPU configuration, when failed to send a SMU message, it's hard to figure out which GPU has such problem. So it's not comfortable to user. [40190.142181] amdgpu: [powerplay] last message was failed ret is 65535 [40190.242420] amdgpu: [powerplay] failed to send message 201 ret is 65535 [40190.392763] amdgpu: [powerplay] last message was failed ret is 65535 [40190.492997] amdgpu: [powerplay] failed to send message 200 ret is 65535 [40190.743575] amdgpu: [powerplay] last message was failed ret is 65535 [40190.843812] amdgpu: [powerplay] failed to send message 282 ret is 65535 Signed-off-by: Guchun Chen Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 4 +++- .../gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c | 4 ++-- drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c | 11 +++++++---- drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c | 2 +- .../gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c index 93a1c7248e26..5ca3c422f7d4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c @@ -208,6 +208,7 @@ static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { + struct amdgpu_device *adev = hwmgr->adev; int ret; cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); @@ -218,7 +219,8 @@ static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); if (ret != 1) - pr_info("\n failed to send message %x ret is %d\n", msg, ret); + dev_info(adev->dev, + "failed to send message %x ret is %d\n", msg,ret); return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c index 47b34c6ca924..88a5641465dc 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c @@ -87,7 +87,7 @@ static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) smu10_send_msg_to_smc_without_waiting(hwmgr, msg); if (smu10_wait_for_response(hwmgr) == 0) - printk("Failed to send Message %x.\n", msg); + dev_err(adev->dev, "Failed to send Message %x.\n", msg); return 0; } @@ -108,7 +108,7 @@ static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, if (smu10_wait_for_response(hwmgr) == 0) - printk("Failed to send Message %x.\n", msg); + dev_err(adev->dev, "Failed to send Message %x.\n", msg); return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c index aae25243eb10..5a010cd38303 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c @@ -165,6 +165,7 @@ bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr) int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { + struct amdgpu_device *adev = hwmgr->adev; int ret; PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); @@ -172,9 +173,10 @@ int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); if (ret == 0xFE) - pr_debug("last message was not supported\n"); + dev_dbg(adev->dev, "last message was not supported\n"); else if (ret != 1) - pr_info("\n last message was failed ret is %d\n", ret); + dev_info(adev->dev, + "\nlast message was failed ret is %d\n", ret); cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); @@ -184,9 +186,10 @@ int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); if (ret == 0xFE) - pr_debug("message %x was not supported\n", msg); + dev_dbg(adev->dev, "message %x was not supported\n", msg); else if (ret != 1) - pr_info("\n failed to send message %x ret is %d \n", msg, ret); + dev_dbg(adev->dev, + "failed to send message %x ret is %d \n", msg, ret); return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c index 23e5de3c4ec1..8c9bf4940dc1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c @@ -126,7 +126,7 @@ int smu9_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) ret = smu9_wait_for_response(hwmgr); if (ret != 1) - pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret); + dev_err(adev->dev, "Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret); return 0; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c index 741fbc87467f..9ad26c285ecd 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c @@ -115,7 +115,7 @@ static int vega20_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) ret = vega20_wait_for_response(hwmgr); if (ret != PPSMC_Result_OK) - pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret); + dev_err(adev->dev, "Failed to send message 0x%x, response 0x%x\n", msg, ret); return (ret == PPSMC_Result_OK) ? 0 : -EIO; } @@ -143,7 +143,7 @@ static int vega20_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, ret = vega20_wait_for_response(hwmgr); if (ret != PPSMC_Result_OK) - pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret); + dev_err(adev->dev, "Failed to send message 0x%x, response 0x%x\n", msg, ret); return (ret == PPSMC_Result_OK) ? 0 : -EIO; } From 25c6aefceee60850bf78e16ae9d7fcc4a9d20884 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Jan 2022 12:17:07 -0500 Subject: [PATCH 111/339] drm/amdgpu: filter out radeon secondary ids as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older radeon boards (r2xx-r5xx) had secondary PCI functions which we solely there for supporting multi-head on OSs with special requirements. Add them to the unsupported list as well so we don't attempt to bind to them. The driver would fail to bind to them anyway, but this does so in a cleaner way that should not confuse the user. Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 81 +++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index cc6585193236..1a691a801928 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1497,6 +1497,87 @@ static const u16 amdgpu_unsupported_pciidlist[] = { 0x99A0, 0x99A2, 0x99A4, + /* radeon secondary ids */ + 0x3171, + 0x3e70, + 0x4164, + 0x4165, + 0x4166, + 0x4168, + 0x4170, + 0x4171, + 0x4172, + 0x4173, + 0x496e, + 0x4a69, + 0x4a6a, + 0x4a6b, + 0x4a70, + 0x4a74, + 0x4b69, + 0x4b6b, + 0x4b6c, + 0x4c6e, + 0x4e64, + 0x4e65, + 0x4e66, + 0x4e67, + 0x4e68, + 0x4e69, + 0x4e6a, + 0x4e71, + 0x4f73, + 0x5569, + 0x556b, + 0x556d, + 0x556f, + 0x5571, + 0x5854, + 0x5874, + 0x5940, + 0x5941, + 0x5b72, + 0x5b73, + 0x5b74, + 0x5b75, + 0x5d44, + 0x5d45, + 0x5d6d, + 0x5d6f, + 0x5d72, + 0x5d77, + 0x5e6b, + 0x5e6d, + 0x7120, + 0x7124, + 0x7129, + 0x712e, + 0x712f, + 0x7162, + 0x7163, + 0x7166, + 0x7167, + 0x7172, + 0x7173, + 0x71a0, + 0x71a1, + 0x71a3, + 0x71a7, + 0x71bb, + 0x71e0, + 0x71e1, + 0x71e2, + 0x71e6, + 0x71e7, + 0x71f2, + 0x7269, + 0x726b, + 0x726e, + 0x72a0, + 0x72a8, + 0x72b1, + 0x72b3, + 0x793f, }; static const struct pci_device_id pciidlist[] = { From 5e0c8ddf029e0a8533bfb04e4542b46356cbcade Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Jan 2022 12:52:13 -0500 Subject: [PATCH 112/339] drm/amdgpu/display: adjust msleep limit in dp_wait_for_training_aux_rd_interval Some architectures (e.g., ARM) have relatively low udelay limits. On most architectures, anything longer than 2000us is not recommended. Change the check to align with other similar checks in DC. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index cb2f96690b4a..5831eef78fb1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -202,7 +202,7 @@ void dp_wait_for_training_aux_rd_interval( uint32_t wait_in_micro_secs) { #if defined(CONFIG_DRM_AMD_DC_DCN) - if (wait_in_micro_secs > 16000) + if (wait_in_micro_secs > 1000) msleep(wait_in_micro_secs/1000); else udelay(wait_in_micro_secs); From 0fc2549d55a238da5e4c1b1ae20ebc3856922334 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 20 Jan 2022 12:57:33 -0500 Subject: [PATCH 113/339] drm/amdgpu/display: use msleep rather than udelay for long delays Some architectures (e.g., ARM) throw an compilation error if the udelay is too long. In general udelays of longer than 2000us are not recommended on any architecture. Switch to msleep in these cases. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 5831eef78fb1..6f6929435885 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -6935,7 +6935,7 @@ bool dpcd_write_128b_132b_sst_payload_allocation_table( } } retries++; - udelay(5000); + msleep(5); } if (!result && retries == max_retries) { @@ -6987,7 +6987,7 @@ bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link) break; } - udelay(5000); + msleep(5); } if (result == ACT_FAILED) { From dfced44f122c500004a48ecc8db516bb6a295a1b Mon Sep 17 00:00:00 2001 From: Xin Xiong Date: Fri, 21 Jan 2022 15:46:23 -0500 Subject: [PATCH 114/339] drm/amd/amdgpu/amdgpu_cs: fix refcount leak of a dma_fence obj MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This issue takes place in an error path in amdgpu_cs_fence_to_handle_ioctl(). When `info->in.what` falls into default case, the function simply returns -EINVAL, forgetting to decrement the reference count of a dma_fence obj, which is bumped earlier by amdgpu_cs_get_fence(). This may result in reference count leaks. Fix it by decreasing the refcount of specific object before returning the error code. Reviewed-by: Christian König Signed-off-by: Xin Xiong Signed-off-by: Xin Tan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 06d07502a1f6..a34be65c9eaa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1509,6 +1509,7 @@ int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data, return 0; default: + dma_fence_put(fence); return -EINVAL; } } From 1418b9c38270f4c7843627cb0e9047b19eb3365a Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Fri, 21 Jan 2022 19:48:00 +0800 Subject: [PATCH 115/339] drm/amd/pm: remove useless if Clean the following coccicheck warning: ./drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c:7035:2-4: WARNING: possible condition with no effect (if == else). Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index 23ff0d812e4b..7427c50409d4 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -7032,10 +7032,7 @@ static int si_power_control_set_level(struct amdgpu_device *adev) ret = si_resume_smc(adev); if (ret) return ret; - ret = si_set_sw_state(adev); - if (ret) - return ret; - return 0; + return si_set_sw_state(adev); } static void si_set_vce_clock(struct amdgpu_device *adev, From 5d5c6dba2b43e28845d7d7ed32a36802329a5f52 Mon Sep 17 00:00:00 2001 From: Yongzhi Liu Date: Fri, 21 Jan 2022 11:26:13 +0000 Subject: [PATCH 116/339] drm/amd/display: Fix memory leak [why] Resource release is needed on the error handling path to prevent memory leak. [how] Fix this by adding kfree on the error handling path. Reviewed-by: Harry Wentland Signed-off-by: Yongzhi Liu Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 80 ++++++++++++++----- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 26719efa5396..12d437d9a0e4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -227,8 +227,10 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -389,8 +391,10 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf, break; r = put_user((*(rd_buf + result)), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -1359,8 +1363,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -1376,8 +1382,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -1546,8 +1554,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -1563,8 +1573,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -1731,8 +1743,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -1748,8 +1762,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -1912,8 +1928,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -1929,8 +1947,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -2088,8 +2108,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -2105,8 +2127,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -2145,8 +2169,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -2162,8 +2188,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -2217,8 +2245,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -2234,8 +2264,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -2289,8 +2321,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, break; } - if (!pipe_ctx) + if (!pipe_ctx) { + kfree(rd_buf); return -ENXIO; + } dsc = pipe_ctx->stream_res.dsc; if (dsc) @@ -2306,8 +2340,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; @@ -3459,8 +3495,10 @@ static ssize_t dcc_en_bits_read( dc->hwss.get_dcc_en_bits(dc, dcc_en_bits); rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL); - if (!rd_buf) + if (!rd_buf) { + kfree(dcc_en_bits); return -ENOMEM; + } for (i = 0; i < num_pipes; i++) offset += snprintf(rd_buf + offset, rd_buf_size - offset, @@ -3473,8 +3511,10 @@ static ssize_t dcc_en_bits_read( if (*pos >= rd_buf_size) break; r = put_user(*(rd_buf + result), buf); - if (r) + if (r) { + kfree(rd_buf); return r; /* r = -EFAULT */ + } buf += 1; size -= 1; *pos += 1; From 5bb1465fbdc291593a7c385cede0416ff6873280 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Fri, 21 Jan 2022 06:10:21 +0000 Subject: [PATCH 117/339] drm/amd/display: clean up some inconsistent indenting Eliminate the follow smatch warning: drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c:3415 bw_calcs() warn: inconsistent indenting Reported-by: Abaci Robot Signed-off-by: Yang Li Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/calcs/dce_calcs.c | 48 +++++++++---------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c index ff5bb152ef49..8f136db39f3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c @@ -3411,35 +3411,33 @@ bool bw_calcs(struct dc_context *ctx, calcs_output->stutter_exit_wm_ns[5].c_mark = bw_fixed_to_int(bw_mul(data-> stutter_exit_watermark[9], bw_int_to_fixed(1000))); - - calcs_output->stutter_entry_wm_ns[0].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[4], bw_int_to_fixed(1000))); - calcs_output->stutter_entry_wm_ns[1].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[5], bw_int_to_fixed(1000))); - calcs_output->stutter_entry_wm_ns[2].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[6], bw_int_to_fixed(1000))); - if (ctx->dc->caps.max_slave_planes) { - calcs_output->stutter_entry_wm_ns[3].c_mark = + calcs_output->stutter_entry_wm_ns[0].c_mark = bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[0], bw_int_to_fixed(1000))); - calcs_output->stutter_entry_wm_ns[4].c_mark = + stutter_entry_watermark[4], bw_int_to_fixed(1000))); + calcs_output->stutter_entry_wm_ns[1].c_mark = bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[1], bw_int_to_fixed(1000))); - } else { - calcs_output->stutter_entry_wm_ns[3].c_mark = + stutter_entry_watermark[5], bw_int_to_fixed(1000))); + calcs_output->stutter_entry_wm_ns[2].c_mark = bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[7], bw_int_to_fixed(1000))); - calcs_output->stutter_entry_wm_ns[4].c_mark = + stutter_entry_watermark[6], bw_int_to_fixed(1000))); + if (ctx->dc->caps.max_slave_planes) { + calcs_output->stutter_entry_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data->stutter_entry_watermark[0], + bw_int_to_fixed(1000))); + calcs_output->stutter_entry_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data->stutter_entry_watermark[1], + bw_int_to_fixed(1000))); + } else { + calcs_output->stutter_entry_wm_ns[3].c_mark = + bw_fixed_to_int(bw_mul(data->stutter_entry_watermark[7], + bw_int_to_fixed(1000))); + calcs_output->stutter_entry_wm_ns[4].c_mark = + bw_fixed_to_int(bw_mul(data->stutter_entry_watermark[8], + bw_int_to_fixed(1000))); + } + calcs_output->stutter_entry_wm_ns[5].c_mark = bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[8], bw_int_to_fixed(1000))); - } - calcs_output->stutter_entry_wm_ns[5].c_mark = - bw_fixed_to_int(bw_mul(data-> - stutter_entry_watermark[9], bw_int_to_fixed(1000))); - + stutter_entry_watermark[9], bw_int_to_fixed(1000))); calcs_output->urgent_wm_ns[0].c_mark = bw_fixed_to_int(bw_mul(data-> urgent_watermark[4], bw_int_to_fixed(1000))); From 29dbcac82f96d06608f3658aacd3e14efb7ac0cd Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 18 Jan 2022 16:04:02 +0800 Subject: [PATCH 118/339] drm/amdgpu: add helper to query rlcg reg access flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Query rlc indirect register access approach specified by sriov host driver per ip blocks Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 35 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 8 ++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 07bc0f504713..a40e4fcdfa46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -820,3 +820,38 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev, } } } + +bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags, + u32 hwip, bool write, u32 *rlcg_flag) +{ + bool ret = false; + + switch (hwip) { + case GC_HWIP: + if (amdgpu_sriov_reg_indirect_gc(adev)) { + *rlcg_flag = + write ? AMDGPU_RLCG_GC_WRITE : AMDGPU_RLCG_GC_READ; + ret = true; + /* only in new version, AMDGPU_REGS_NO_KIQ and + * AMDGPU_REGS_RLC are enabled simultaneously */ + } else if ((acc_flags & AMDGPU_REGS_RLC) && + !(acc_flags & AMDGPU_REGS_NO_KIQ)) { + *rlcg_flag = AMDGPU_RLCG_GC_WRITE_LEGACY; + ret = true; + } + break; + case MMHUB_HWIP: + if (amdgpu_sriov_reg_indirect_mmhub(adev) && + (acc_flags & AMDGPU_REGS_RLC) && write) { + *rlcg_flag = AMDGPU_RLCG_MMHUB_WRITE; + ret = true; + } + break; + default: + dev_err(adev->dev, + "indirect registers access through rlcg is not supported\n"); + ret = false; + break; + } + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 9adfb8d63280..404a06e57f30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -32,6 +32,12 @@ #define AMDGPU_PASSTHROUGH_MODE (1 << 3) /* thw whole GPU is pass through for VM */ #define AMDGPU_SRIOV_CAPS_RUNTIME (1 << 4) /* is out of full access mode */ +/* flags for indirect register access path supported by rlcg for sriov */ +#define AMDGPU_RLCG_GC_WRITE_LEGACY (0x8 << 28) +#define AMDGPU_RLCG_GC_WRITE (0x0 << 28) +#define AMDGPU_RLCG_GC_READ (0x1 << 28) +#define AMDGPU_RLCG_MMHUB_WRITE (0x2 << 28) + /* all asic after AI use this offset */ #define mmRCC_IOV_FUNC_IDENTIFIER 0xDE5 /* tonga/fiji use this offset */ @@ -321,4 +327,6 @@ enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *ad void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev, struct amdgpu_video_codec_info *encode, uint32_t encode_array_size, struct amdgpu_video_codec_info *decode, uint32_t decode_array_size); +bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags, + u32 hwip, bool write, u32 *rlcg_flag); #endif From 97d1a3b967a3cbeb0dd29a8b5bcd4ac1fd9ccd9b Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Sun, 16 Jan 2022 16:45:54 +0800 Subject: [PATCH 119/339] drm/amdgpu: switch to get_rlcg_reg_access_flag for gfx9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to common helper to query rlcg access flag specified by sriov host driver for gfx9 Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 33 ++++----------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index e12f9f5c3beb..17704cd99aaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -63,9 +63,6 @@ #define mmGCEA_PROBE_MAP 0x070c #define mmGCEA_PROBE_MAP_BASE_IDX 0 -#define GFX9_RLCG_GC_WRITE_OLD (0x8 << 28) -#define GFX9_RLCG_GC_WRITE (0x0 << 28) -#define GFX9_RLCG_GC_READ (0x1 << 28) #define GFX9_RLCG_VFGATE_DISABLED 0x4000000 #define GFX9_RLCG_WRONG_OPERATION_TYPE 0x2000000 #define GFX9_RLCG_NOT_IN_RANGE 0x1000000 @@ -815,35 +812,12 @@ static u32 gfx_v9_0_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint3 return ret; } -static bool gfx_v9_0_get_rlcg_flag(struct amdgpu_device *adev, u32 acc_flags, u32 hwip, - int write, u32 *rlcg_flag) -{ - - switch (hwip) { - case GC_HWIP: - if (amdgpu_sriov_reg_indirect_gc(adev)) { - *rlcg_flag = write ? GFX9_RLCG_GC_WRITE : GFX9_RLCG_GC_READ; - - return true; - /* only in new version, AMDGPU_REGS_NO_KIQ and AMDGPU_REGS_RLC enabled simultaneously */ - } else if ((acc_flags & AMDGPU_REGS_RLC) && !(acc_flags & AMDGPU_REGS_NO_KIQ) && write) { - *rlcg_flag = GFX9_RLCG_GC_WRITE_OLD; - return true; - } - - break; - default: - return false; - } - - return false; -} - static u32 gfx_v9_0_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip) { u32 rlcg_flag; - if (!amdgpu_sriov_runtime(adev) && gfx_v9_0_get_rlcg_flag(adev, acc_flags, hwip, 0, &rlcg_flag)) + if (!amdgpu_sriov_runtime(adev) && + amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag)) return gfx_v9_0_rlcg_rw(adev, offset, 0, rlcg_flag); if (acc_flags & AMDGPU_REGS_NO_KIQ) @@ -857,7 +831,8 @@ static void gfx_v9_0_sriov_wreg(struct amdgpu_device *adev, u32 offset, { u32 rlcg_flag; - if (!amdgpu_sriov_runtime(adev) && gfx_v9_0_get_rlcg_flag(adev, acc_flags, hwip, 1, &rlcg_flag)) { + if (!amdgpu_sriov_runtime(adev) && + amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) { gfx_v9_0_rlcg_rw(adev, offset, value, rlcg_flag); return; } From 7bbe43f8a4e7775daf6ca62807e0023b0642a20b Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Sun, 16 Jan 2022 17:04:09 +0800 Subject: [PATCH 120/339] drm/amdgpu: switch to get_rlcg_reg_access_flag for gfx10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to common helper to query rlcg access flag specified by sriov host driver for gfx10 Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 41 ++------------------------ 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index dbe7442fb25c..588c922573e9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -180,11 +180,6 @@ #define mmRLC_SPARE_INT_0_Sienna_Cichlid 0x4ca5 #define mmRLC_SPARE_INT_0_Sienna_Cichlid_BASE_IDX 1 -#define GFX_RLCG_GC_WRITE_OLD (0x8 << 28) -#define GFX_RLCG_GC_WRITE (0x0 << 28) -#define GFX_RLCG_GC_READ (0x1 << 28) -#define GFX_RLCG_MMHUB_WRITE (0x2 << 28) - #define RLCG_ERROR_REPORT_ENABLED(adev) \ (amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev)) @@ -1463,38 +1458,6 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00c00000) }; -static bool gfx_v10_get_rlcg_flag(struct amdgpu_device *adev, u32 acc_flags, u32 hwip, - int write, u32 *rlcg_flag) -{ - switch (hwip) { - case GC_HWIP: - if (amdgpu_sriov_reg_indirect_gc(adev)) { - *rlcg_flag = write ? GFX_RLCG_GC_WRITE : GFX_RLCG_GC_READ; - - return true; - /* only in new version, AMDGPU_REGS_NO_KIQ and AMDGPU_REGS_RLC enabled simultaneously */ - } else if ((acc_flags & AMDGPU_REGS_RLC) && !(acc_flags & AMDGPU_REGS_NO_KIQ)) { - *rlcg_flag = GFX_RLCG_GC_WRITE_OLD; - - return true; - } - - break; - case MMHUB_HWIP: - if (amdgpu_sriov_reg_indirect_mmhub(adev) && - (acc_flags & AMDGPU_REGS_RLC) && write) { - *rlcg_flag = GFX_RLCG_MMHUB_WRITE; - return true; - } - - break; - default: - DRM_DEBUG("Not program register by RLCG\n"); - } - - return false; -} - static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32_t flag) { static void *scratch_reg0; @@ -1575,7 +1538,7 @@ static void gfx_v10_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value u32 rlcg_flag; if (!amdgpu_sriov_runtime(adev) && - gfx_v10_get_rlcg_flag(adev, acc_flags, hwip, 1, &rlcg_flag)) { + amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) { gfx_v10_rlcg_rw(adev, offset, value, rlcg_flag); return; } @@ -1591,7 +1554,7 @@ static u32 gfx_v10_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_fl u32 rlcg_flag; if (!amdgpu_sriov_runtime(adev) && - gfx_v10_get_rlcg_flag(adev, acc_flags, hwip, 0, &rlcg_flag)) + amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag)) return gfx_v10_rlcg_rw(adev, offset, 0, rlcg_flag); if (acc_flags & AMDGPU_REGS_NO_KIQ) From b12252b0538183d8b88bd4a8d8d05a808c46472c Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 18 Jan 2022 16:11:02 +0800 Subject: [PATCH 121/339] drm/amdgpu: add structures for rlcg indirect reg access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add structures that are used to cache registers offsets for rlcg indirect reg access ctrl and flag availability of such interface Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h index 00afd0dcae86..286b2347d063 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h @@ -132,6 +132,16 @@ struct amdgpu_rlc_funcs { bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg); }; +struct amdgpu_rlcg_reg_access_ctrl { + uint32_t scratch_reg0; + uint32_t scratch_reg1; + uint32_t scratch_reg2; + uint32_t scratch_reg3; + uint32_t grbm_cntl; + uint32_t grbm_idx; + uint32_t spare_int; +}; + struct amdgpu_rlc { /* for power gating */ struct amdgpu_bo *save_restore_obj; @@ -191,6 +201,10 @@ struct amdgpu_rlc { struct amdgpu_bo *rlc_toc_bo; uint64_t rlc_toc_gpu_addr; void *rlc_toc_buf; + + bool rlcg_reg_access_supported; + /* registers for rlcg indirect reg access */ + struct amdgpu_rlcg_reg_access_ctrl reg_access_ctrl; }; void amdgpu_gfx_rlc_enter_safe_mode(struct amdgpu_device *adev); From 4819732f5986ed8b3d88bf4272d2d5bf1ccff9da Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 18 Jan 2022 21:28:04 +0800 Subject: [PATCH 122/339] drm/amdgpu: init rlcg_reg_access_ctrl for gfx9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize all the register offsets that will be used in rlcg indirect reg access path for gfx9 in sw_init phase Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 30 +++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 17704cd99aaf..c7bccf1a28b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1983,6 +1983,21 @@ static int gfx_v9_0_cp_jump_table_num(struct amdgpu_device *adev) return 4; } +static void gfx_v9_0_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev) +{ + struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl; + + reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl; + reg_access_ctrl->scratch_reg0 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG0); + reg_access_ctrl->scratch_reg1 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG1); + reg_access_ctrl->scratch_reg2 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG2); + reg_access_ctrl->scratch_reg3 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG3); + reg_access_ctrl->grbm_cntl = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL); + reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX); + reg_access_ctrl->spare_int = SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT); + adev->gfx.rlc.rlcg_reg_access_supported = true; +} + static int gfx_v9_0_rlc_init(struct amdgpu_device *adev) { const struct cs_section_def *cs_data; @@ -2023,6 +2038,9 @@ static int gfx_v9_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.funcs->update_spm_vmid) adev->gfx.rlc.funcs->update_spm_vmid(adev, 0xf); + /* init rlcg reg access ctrl */ + gfx_v9_0_init_rlcg_reg_access_ctrl(adev); + return 0; } @@ -2432,10 +2450,14 @@ static int gfx_v9_0_sw_init(void *handle) return r; } - r = adev->gfx.rlc.funcs->init(adev); - if (r) { - DRM_ERROR("Failed to init rlc BOs!\n"); - return r; + if (adev->gfx.rlc.funcs) { + if (adev->gfx.rlc.funcs->init) { + r = adev->gfx.rlc.funcs->init(adev); + if (r) { + dev_err(adev->dev, "Failed to init rlc BOs!\n"); + return r; + } + } } r = gfx_v9_0_mec_init(adev); From f8f96b17f0fa302b246e35773074f39e43add023 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 18 Jan 2022 21:33:05 +0800 Subject: [PATCH 123/339] drm/amdgpu: init rlcg_reg_access_ctrl for gfx10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize all the register offsets that will be used in rlcg indirect reg access path for gfx10 in sw_init phase Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 38 +++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 588c922573e9..3fb484214d3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4411,6 +4411,30 @@ static void gfx_v10_0_rlc_fini(struct amdgpu_device *adev) (void **)&adev->gfx.rlc.cp_table_ptr); } +static void gfx_v10_0_init_rlcg_reg_access_ctrl(struct amdgpu_device *adev) +{ + struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl; + + reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl; + reg_access_ctrl->scratch_reg0 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG0); + reg_access_ctrl->scratch_reg1 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG1); + reg_access_ctrl->scratch_reg2 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG2); + reg_access_ctrl->scratch_reg3 = SOC15_REG_OFFSET(GC, 0, mmSCRATCH_REG3); + reg_access_ctrl->grbm_cntl = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_CNTL); + reg_access_ctrl->grbm_idx = SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX); + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 0): + reg_access_ctrl->spare_int = + SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT_0_Sienna_Cichlid); + break; + default: + reg_access_ctrl->spare_int = + SOC15_REG_OFFSET(GC, 0, mmRLC_SPARE_INT); + break; + } + adev->gfx.rlc.rlcg_reg_access_supported = true; +} + static int gfx_v10_0_rlc_init(struct amdgpu_device *adev) { const struct cs_section_def *cs_data; @@ -4431,6 +4455,8 @@ static int gfx_v10_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.funcs->update_spm_vmid) adev->gfx.rlc.funcs->update_spm_vmid(adev, 0xf); + gfx_v10_0_init_rlcg_reg_access_ctrl(adev); + return 0; } @@ -4828,10 +4854,14 @@ static int gfx_v10_0_sw_init(void *handle) if (r) return r; - r = gfx_v10_0_rlc_init(adev); - if (r) { - DRM_ERROR("Failed to init rlc BOs!\n"); - return r; + if (adev->gfx.rlc.funcs) { + if (adev->gfx.rlc.funcs->init) { + r = adev->gfx.rlc.funcs->init(adev); + if (r) { + dev_err(adev->dev, "Failed to init rlc BOs!\n"); + return r; + } + } } r = gfx_v10_0_mec_init(adev); From 5d447e296701484f3df5b31a7a078cbf1e3a9cc9 Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 18 Jan 2022 21:44:06 +0800 Subject: [PATCH 124/339] drm/amdgpu: add helper for rlcg indirect reg access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The helper will be used to access registers from sriov guest in full access time Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 111 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 14 ++- 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index a40e4fcdfa46..8c27d31f3e53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -855,3 +855,114 @@ bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_fl } return ret; } + +static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v, u32 flag) +{ + struct amdgpu_rlcg_reg_access_ctrl *reg_access_ctrl; + uint32_t timeout = 50000; + uint32_t i, tmp; + uint32_t ret = 0; + static void *scratch_reg0; + static void *scratch_reg1; + static void *scratch_reg2; + static void *scratch_reg3; + static void *spare_int; + + if (!adev->gfx.rlc.rlcg_reg_access_supported) { + dev_err(adev->dev, + "indirect registers access through rlcg is not available\n"); + return 0; + } + + scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0; + scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1; + scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2; + scratch_reg3 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg3; + if (reg_access_ctrl->spare_int) + spare_int = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->spare_int; + + if (offset == reg_access_ctrl->grbm_cntl) { + /* if the target reg offset is grbm_cntl, write to scratch_reg2 */ + writel(v, scratch_reg2); + writel(v, ((void __iomem *)adev->rmmio) + (offset * 4)); + } else if (offset == reg_access_ctrl->grbm_idx) { + /* if the target reg offset is grbm_idx, write to scratch_reg3 */ + writel(v, scratch_reg3); + writel(v, ((void __iomem *)adev->rmmio) + (offset * 4)); + } else { + /* + * SCRATCH_REG0 = read/write value + * SCRATCH_REG1[30:28] = command + * SCRATCH_REG1[19:0] = address in dword + * SCRATCH_REG1[26:24] = Error reporting + */ + writel(v, scratch_reg0); + writel((offset | flag), scratch_reg1); + if (reg_access_ctrl->spare_int) + writel(1, spare_int); + + for (i = 0; i < timeout; i++) { + tmp = readl(scratch_reg1); + if (!(tmp & flag)) + break; + udelay(10); + } + + if (i >= timeout) { + if (amdgpu_sriov_rlcg_error_report_enabled(adev)) { + if (tmp & AMDGPU_RLCG_VFGATE_DISABLED) { + dev_err(adev->dev, + "vfgate is disabled, rlcg failed to program reg: 0x%05x\n", offset); + } else if (tmp & AMDGPU_RLCG_WRONG_OPERATION_TYPE) { + dev_err(adev->dev, + "wrong operation type, rlcg failed to program reg: 0x%05x\n", offset); + } else if (tmp & AMDGPU_RLCG_REG_NOT_IN_RANGE) { + dev_err(adev->dev, + "regiser is not in range, rlcg failed to program reg: 0x%05x\n", offset); + } else { + dev_err(adev->dev, + "unknown error type, rlcg failed to program reg: 0x%05x\n", offset); + } + } else { + dev_err(adev->dev, + "timeout: rlcg faled to program reg: 0x%05x\n", offset); + } + } + } + + ret = readl(scratch_reg0); + return ret; +} + +void amdgpu_sriov_wreg(struct amdgpu_device *adev, + u32 offset, u32 value, + u32 acc_flags, u32 hwip) +{ + u32 rlcg_flag; + + if (!amdgpu_sriov_runtime(adev) && + amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) { + amdgpu_virt_rlcg_reg_rw(adev, offset, value, rlcg_flag); + return; + } + + if (acc_flags & AMDGPU_REGS_NO_KIQ) + WREG32_NO_KIQ(offset, value); + else + WREG32(offset, value); +} + +u32 amdgpu_sriov_rreg(struct amdgpu_device *adev, + u32 offset, u32 acc_flags, u32 hwip) +{ + u32 rlcg_flag; + + if (!amdgpu_sriov_runtime(adev) && + amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag)) + return amdgpu_virt_rlcg_reg_rw(adev, offset, 0, rlcg_flag); + + if (acc_flags & AMDGPU_REGS_NO_KIQ) + return RREG32_NO_KIQ(offset); + else + return RREG32(offset); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 404a06e57f30..dbfa3ba445c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -38,6 +38,11 @@ #define AMDGPU_RLCG_GC_READ (0x1 << 28) #define AMDGPU_RLCG_MMHUB_WRITE (0x2 << 28) +/* error code for indirect register access path supported by rlcg for sriov */ +#define AMDGPU_RLCG_VFGATE_DISABLED 0x4000000 +#define AMDGPU_RLCG_WRONG_OPERATION_TYPE 0x2000000 +#define AMDGPU_RLCG_REG_NOT_IN_RANGE 0x1000000 + /* all asic after AI use this offset */ #define mmRCC_IOV_FUNC_IDENTIFIER 0xDE5 /* tonga/fiji use this offset */ @@ -281,6 +286,9 @@ struct amdgpu_video_codec_info; (amdgpu_sriov_vf((adev)) && \ ((adev)->virt.reg_access & (AMDGIM_FEATURE_GC_REG_RLC_EN))) +#define amdgpu_sriov_rlcg_error_report_enabled(adev) \ + (amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev)) + #define amdgpu_passthrough(adev) \ ((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE) @@ -299,7 +307,6 @@ static inline bool is_virtual_machine(void) ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) #define amdgpu_sriov_is_normal(adev) \ ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) - bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev, @@ -329,4 +336,9 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev, struct amdgpu_video_codec_info *decode, uint32_t decode_array_size); bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags, u32 hwip, bool write, u32 *rlcg_flag); +void amdgpu_sriov_wreg(struct amdgpu_device *adev, + u32 offset, u32 value, + u32 acc_flags, u32 hwip); +u32 amdgpu_sriov_rreg(struct amdgpu_device *adev, + u32 offset, u32 acc_flags, u32 hwip); #endif From 1b2dc99e2dc6f35f55f0487e12fc9166fbd023ed Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Tue, 18 Jan 2022 21:47:39 +0800 Subject: [PATCH 125/339] drm/amdgpu: switch to amdgpu_sriov_rreg/wreg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of ip specific implementation for rlcg indirect register access Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/amd/amdgpu/soc15_common.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index fcde99c69c47..5159c6dedc04 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -566,7 +566,7 @@ void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev, adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->is_rlcg_access_range) { if (adev->gfx.rlc.funcs->is_rlcg_access_range(adev, reg)) - return adev->gfx.rlc.funcs->sriov_wreg(adev, reg, v, 0, 0); + return amdgpu_sriov_wreg(adev, reg, v, 0, 0); } else if ((reg * 4) >= adev->rmmio_size) { adev->pcie_wreg(adev, reg * 4, v); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/soc15_common.h b/drivers/gpu/drm/amd/amdgpu/soc15_common.h index 473767e03676..acce8c2e0328 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15_common.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15_common.h @@ -28,13 +28,13 @@ #define SOC15_REG_OFFSET(ip, inst, reg) (adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg) #define __WREG32_SOC15_RLC__(reg, value, flag, hwip) \ - ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_wreg) ? \ - adev->gfx.rlc.funcs->sriov_wreg(adev, reg, value, flag, hwip) : \ + ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.rlcg_reg_access_supported) ? \ + amdgpu_sriov_wreg(adev, reg, value, flag, hwip) : \ WREG32(reg, value)) #define __RREG32_SOC15_RLC__(reg, flag, hwip) \ - ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.funcs->sriov_rreg) ? \ - adev->gfx.rlc.funcs->sriov_rreg(adev, reg, flag, hwip) : \ + ((amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs && adev->gfx.rlc.rlcg_reg_access_supported) ? \ + amdgpu_sriov_rreg(adev, reg, flag, hwip) : \ RREG32(reg)) #define WREG32_FIELD15(ip, idx, reg, field, val) \ From 381519dff88845bbe522e7446ec1e32e351c670d Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 17 Jan 2022 14:33:23 +0800 Subject: [PATCH 126/339] drm/amdgpu: retire rlc callbacks sriov_rreg/wreg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not needed anymore. Signed-off-by: Hawking Zhang Reviewed-by: Zhou, Peng Ju Acked-by: Christian König Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 2 - drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 114 ----------------------- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 106 --------------------- 5 files changed, 3 insertions(+), 226 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h index 286b2347d063..3f671a62b009 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.h @@ -127,8 +127,6 @@ struct amdgpu_rlc_funcs { void (*reset)(struct amdgpu_device *adev); void (*start)(struct amdgpu_device *adev); void (*update_spm_vmid)(struct amdgpu_device *adev, unsigned vmid); - void (*sriov_wreg)(struct amdgpu_device *adev, u32 offset, u32 v, u32 acc_flags, u32 hwip); - u32 (*sriov_rreg)(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip); bool (*is_rlcg_access_range)(struct amdgpu_device *adev, uint32_t reg); }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 8c27d31f3e53..80c25176c993 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -821,8 +821,9 @@ void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev, } } -bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags, - u32 hwip, bool write, u32 *rlcg_flag) +static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, + u32 acc_flags, u32 hwip, + bool write, u32 *rlcg_flag) { bool ret = false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index dbfa3ba445c3..c5edd84c1c12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -334,8 +334,6 @@ enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *ad void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev, struct amdgpu_video_codec_info *encode, uint32_t encode_array_size, struct amdgpu_video_codec_info *decode, uint32_t decode_array_size); -bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, u32 acc_flags, - u32 hwip, bool write, u32 *rlcg_flag); void amdgpu_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 3fb484214d3a..f54e106e2b86 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -56,10 +56,6 @@ #define GFX10_NUM_GFX_RINGS_Sienna_Cichlid 1 #define GFX10_MEC_HPD_SIZE 2048 -#define RLCG_VFGATE_DISABLED 0x4000000 -#define RLCG_WRONG_OPERATION_TYPE 0x2000000 -#define RLCG_NOT_IN_RANGE 0x1000000 - #define F32_CE_PROGRAM_RAM_SIZE 65536 #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L @@ -180,9 +176,6 @@ #define mmRLC_SPARE_INT_0_Sienna_Cichlid 0x4ca5 #define mmRLC_SPARE_INT_0_Sienna_Cichlid_BASE_IDX 1 -#define RLCG_ERROR_REPORT_ENABLED(adev) \ - (amdgpu_sriov_reg_indirect_mmhub(adev) || amdgpu_sriov_reg_indirect_gc(adev)) - MODULE_FIRMWARE("amdgpu/navi10_ce.bin"); MODULE_FIRMWARE("amdgpu/navi10_pfp.bin"); MODULE_FIRMWARE("amdgpu/navi10_me.bin"); @@ -1458,111 +1451,6 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00c00000) }; -static u32 gfx_v10_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32_t flag) -{ - static void *scratch_reg0; - static void *scratch_reg1; - static void *scratch_reg2; - static void *scratch_reg3; - static void *spare_int; - static uint32_t grbm_cntl; - static uint32_t grbm_idx; - uint32_t i = 0; - uint32_t retries = 50000; - u32 ret = 0; - u32 tmp; - - scratch_reg0 = adev->rmmio + - (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0) * 4; - scratch_reg1 = adev->rmmio + - (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1) * 4; - scratch_reg2 = adev->rmmio + - (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG2) * 4; - scratch_reg3 = adev->rmmio + - (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG3) * 4; - - if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0)) { - spare_int = adev->rmmio + - (adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_0_Sienna_Cichlid_BASE_IDX] - + mmRLC_SPARE_INT_0_Sienna_Cichlid) * 4; - } else { - spare_int = adev->rmmio + - (adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT) * 4; - } - - grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL; - grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX; - - if (offset == grbm_cntl || offset == grbm_idx) { - if (offset == grbm_cntl) - writel(v, scratch_reg2); - else if (offset == grbm_idx) - writel(v, scratch_reg3); - - writel(v, ((void __iomem *)adev->rmmio) + (offset * 4)); - } else { - writel(v, scratch_reg0); - writel(offset | flag, scratch_reg1); - writel(1, spare_int); - - for (i = 0; i < retries; i++) { - tmp = readl(scratch_reg1); - if (!(tmp & flag)) - break; - - udelay(10); - } - - if (i >= retries) { - if (RLCG_ERROR_REPORT_ENABLED(adev)) { - if (tmp & RLCG_VFGATE_DISABLED) - pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset); - else if (tmp & RLCG_WRONG_OPERATION_TYPE) - pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset); - else if (tmp & RLCG_NOT_IN_RANGE) - pr_err("The register is not in range, program reg:0x%05x failed!\n", offset); - else - pr_err("Unknown error type, program reg:0x%05x failed!\n", offset); - } else - pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset); - } - } - - ret = readl(scratch_reg0); - - return ret; -} - -static void gfx_v10_sriov_wreg(struct amdgpu_device *adev, u32 offset, u32 value, u32 acc_flags, u32 hwip) -{ - u32 rlcg_flag; - - if (!amdgpu_sriov_runtime(adev) && - amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) { - gfx_v10_rlcg_rw(adev, offset, value, rlcg_flag); - return; - } - - if (acc_flags & AMDGPU_REGS_NO_KIQ) - WREG32_NO_KIQ(offset, value); - else - WREG32(offset, value); -} - -static u32 gfx_v10_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip) -{ - u32 rlcg_flag; - - if (!amdgpu_sriov_runtime(adev) && - amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag)) - return gfx_v10_rlcg_rw(adev, offset, 0, rlcg_flag); - - if (acc_flags & AMDGPU_REGS_NO_KIQ) - return RREG32_NO_KIQ(offset); - else - return RREG32(offset); -} - static const struct soc15_reg_golden golden_settings_gc_10_1_nv14[] = { /* Pending on emulation bring up */ @@ -8370,8 +8258,6 @@ static const struct amdgpu_rlc_funcs gfx_v10_0_rlc_funcs_sriov = { .reset = gfx_v10_0_rlc_reset, .start = gfx_v10_0_rlc_start, .update_spm_vmid = gfx_v10_0_update_spm_vmid, - .sriov_wreg = gfx_v10_sriov_wreg, - .sriov_rreg = gfx_v10_sriov_rreg, .is_rlcg_access_range = gfx_v10_0_is_rlcg_access_range, }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index c7bccf1a28b4..ca7b886c6ce6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -63,10 +63,6 @@ #define mmGCEA_PROBE_MAP 0x070c #define mmGCEA_PROBE_MAP_BASE_IDX 0 -#define GFX9_RLCG_VFGATE_DISABLED 0x4000000 -#define GFX9_RLCG_WRONG_OPERATION_TYPE 0x2000000 -#define GFX9_RLCG_NOT_IN_RANGE 0x1000000 - MODULE_FIRMWARE("amdgpu/vega10_ce.bin"); MODULE_FIRMWARE("amdgpu/vega10_pfp.bin"); MODULE_FIRMWARE("amdgpu/vega10_me.bin"); @@ -743,106 +739,6 @@ static const u32 GFX_RLC_SRM_INDEX_CNTL_DATA_OFFSETS[] = mmRLC_SRM_INDEX_CNTL_DATA_7 - mmRLC_SRM_INDEX_CNTL_DATA_0, }; -static u32 gfx_v9_0_rlcg_rw(struct amdgpu_device *adev, u32 offset, u32 v, uint32_t flag) -{ - static void *scratch_reg0; - static void *scratch_reg1; - static void *scratch_reg2; - static void *scratch_reg3; - static void *spare_int; - static uint32_t grbm_cntl; - static uint32_t grbm_idx; - uint32_t i = 0; - uint32_t retries = 50000; - u32 ret = 0; - u32 tmp; - - scratch_reg0 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG0_BASE_IDX] + mmSCRATCH_REG0)*4; - scratch_reg1 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG1_BASE_IDX] + mmSCRATCH_REG1)*4; - scratch_reg2 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG2_BASE_IDX] + mmSCRATCH_REG2)*4; - scratch_reg3 = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmSCRATCH_REG3_BASE_IDX] + mmSCRATCH_REG3)*4; - spare_int = adev->rmmio + (adev->reg_offset[GC_HWIP][0][mmRLC_SPARE_INT_BASE_IDX] + mmRLC_SPARE_INT)*4; - - grbm_cntl = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_CNTL_BASE_IDX] + mmGRBM_GFX_CNTL; - grbm_idx = adev->reg_offset[GC_HWIP][0][mmGRBM_GFX_INDEX_BASE_IDX] + mmGRBM_GFX_INDEX; - - if (offset == grbm_cntl || offset == grbm_idx) { - if (offset == grbm_cntl) - writel(v, scratch_reg2); - else if (offset == grbm_idx) - writel(v, scratch_reg3); - - writel(v, ((void __iomem *)adev->rmmio) + (offset * 4)); - } else { - /* - * SCRATCH_REG0 = read/write value - * SCRATCH_REG1[30:28] = command - * SCRATCH_REG1[19:0] = address in dword - * SCRATCH_REG1[26:24] = Error reporting - */ - writel(v, scratch_reg0); - writel(offset | flag, scratch_reg1); - writel(1, spare_int); - - for (i = 0; i < retries; i++) { - tmp = readl(scratch_reg1); - if (!(tmp & flag)) - break; - - udelay(10); - } - - if (i >= retries) { - if (amdgpu_sriov_reg_indirect_gc(adev)) { - if (tmp & GFX9_RLCG_VFGATE_DISABLED) - pr_err("The vfgate is disabled, program reg:0x%05x failed!\n", offset); - else if (tmp & GFX9_RLCG_WRONG_OPERATION_TYPE) - pr_err("Wrong operation type, program reg:0x%05x failed!\n", offset); - else if (tmp & GFX9_RLCG_NOT_IN_RANGE) - pr_err("The register is not in range, program reg:0x%05x failed!\n", offset); - else - pr_err("Unknown error type, program reg:0x%05x failed!\n", offset); - } else - pr_err("timeout: rlcg program reg:0x%05x failed!\n", offset); - } - } - - ret = readl(scratch_reg0); - - return ret; -} - -static u32 gfx_v9_0_sriov_rreg(struct amdgpu_device *adev, u32 offset, u32 acc_flags, u32 hwip) -{ - u32 rlcg_flag; - - if (!amdgpu_sriov_runtime(adev) && - amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, false, &rlcg_flag)) - return gfx_v9_0_rlcg_rw(adev, offset, 0, rlcg_flag); - - if (acc_flags & AMDGPU_REGS_NO_KIQ) - return RREG32_NO_KIQ(offset); - else - return RREG32(offset); -} - -static void gfx_v9_0_sriov_wreg(struct amdgpu_device *adev, u32 offset, - u32 value, u32 acc_flags, u32 hwip) -{ - u32 rlcg_flag; - - if (!amdgpu_sriov_runtime(adev) && - amdgpu_virt_get_rlcg_reg_access_flag(adev, acc_flags, hwip, true, &rlcg_flag)) { - gfx_v9_0_rlcg_rw(adev, offset, value, rlcg_flag); - return; - } - - if (acc_flags & AMDGPU_REGS_NO_KIQ) - WREG32_NO_KIQ(offset, value); - else - WREG32(offset, value); -} - #define VEGA10_GB_ADDR_CONFIG_GOLDEN 0x2a114042 #define VEGA12_GB_ADDR_CONFIG_GOLDEN 0x24104041 #define RAVEN_GB_ADDR_CONFIG_GOLDEN 0x24000042 @@ -5268,8 +5164,6 @@ static const struct amdgpu_rlc_funcs gfx_v9_0_rlc_funcs = { .reset = gfx_v9_0_rlc_reset, .start = gfx_v9_0_rlc_start, .update_spm_vmid = gfx_v9_0_update_spm_vmid, - .sriov_wreg = gfx_v9_0_sriov_wreg, - .sriov_rreg = gfx_v9_0_sriov_rreg, .is_rlcg_access_range = gfx_v9_0_is_rlcg_access_range, }; From 04022982fc5ddac6cc783d66846f2464fe4985fb Mon Sep 17 00:00:00 2001 From: Hawking Zhang Date: Mon, 10 Jan 2022 17:31:27 +0800 Subject: [PATCH 127/339] drm/amdgpu: switch to common helper to read bios from rom create a common helper function for soc15 and onwards to read bios image from rom Signed-off-by: Hawking Zhang Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 38 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/nv.c | 34 +-------------------- drivers/gpu/drm/amd/amdgpu/soc15.c | 37 ++--------------------- 4 files changed, 43 insertions(+), 69 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 8658312764bc..845c92dc73f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -372,7 +372,8 @@ int amdgpu_device_ip_block_add(struct amdgpu_device *adev, */ bool amdgpu_get_bios(struct amdgpu_device *adev); bool amdgpu_read_bios(struct amdgpu_device *adev); - +bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes); /* * Clocks */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 27b19503773b..0eddca795e96 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -464,3 +464,41 @@ success: adev->is_atom_fw = (adev->asic_type >= CHIP_VEGA10) ? true : false; return true; } + +/* helper function for soc15 and onwards to read bios from rom */ +bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes) +{ + u32 *dw_ptr; + u32 i, length_dw; + u32 rom_index_offset; + u32 rom_data_offset; + + if (bios == NULL) + return false; + if (length_bytes == 0) + return false; + /* APU vbios image is part of sbios image */ + if (adev->flags & AMD_IS_APU) + return false; + if (!adev->smuio.funcs || + !adev->smuio.funcs->get_rom_index_offset || + !adev->smuio.funcs->get_rom_data_offset) + return false; + + dw_ptr = (u32 *)bios; + length_dw = ALIGN(length_bytes, 4) / 4; + + rom_index_offset = + adev->smuio.funcs->get_rom_index_offset(adev); + rom_data_offset = + adev->smuio.funcs->get_rom_data_offset(adev); + + /* set rom index to 0 */ + WREG32(rom_index_offset, 0); + /* read out the rom data */ + for (i = 0; i < length_dw; i++) + dw_ptr[i] = RREG32(rom_data_offset); + + return true; +} diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 8f0c92cbdc4a..f76834085b34 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -330,38 +330,6 @@ static bool nv_read_disabled_bios(struct amdgpu_device *adev) return false; } -static bool nv_read_bios_from_rom(struct amdgpu_device *adev, - u8 *bios, u32 length_bytes) -{ - u32 *dw_ptr; - u32 i, length_dw; - u32 rom_index_offset, rom_data_offset; - - if (bios == NULL) - return false; - if (length_bytes == 0) - return false; - /* APU vbios image is part of sbios image */ - if (adev->flags & AMD_IS_APU) - return false; - - dw_ptr = (u32 *)bios; - length_dw = ALIGN(length_bytes, 4) / 4; - - rom_index_offset = - adev->smuio.funcs->get_rom_index_offset(adev); - rom_data_offset = - adev->smuio.funcs->get_rom_data_offset(adev); - - /* set rom index to 0 */ - WREG32(rom_index_offset, 0); - /* read out the rom data */ - for (i = 0; i < length_dw; i++) - dw_ptr[i] = RREG32(rom_data_offset); - - return true; -} - static struct soc15_allowed_register_entry nv_allowed_read_registers[] = { { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS2)}, @@ -678,7 +646,7 @@ static int nv_update_umd_stable_pstate(struct amdgpu_device *adev, static const struct amdgpu_asic_funcs nv_asic_funcs = { .read_disabled_bios = &nv_read_disabled_bios, - .read_bios_from_rom = &nv_read_bios_from_rom, + .read_bios_from_rom = &amdgpu_soc15_read_bios_from_rom, .read_register = &nv_read_register, .reset = &nv_asic_reset, .reset_method = &nv_asic_reset_method, diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 6c8fcc4e29f4..a0235f75dbcb 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -375,39 +375,6 @@ static bool soc15_read_disabled_bios(struct amdgpu_device *adev) return false; } -static bool soc15_read_bios_from_rom(struct amdgpu_device *adev, - u8 *bios, u32 length_bytes) -{ - u32 *dw_ptr; - u32 i, length_dw; - uint32_t rom_index_offset; - uint32_t rom_data_offset; - - if (bios == NULL) - return false; - if (length_bytes == 0) - return false; - /* APU vbios image is part of sbios image */ - if (adev->flags & AMD_IS_APU) - return false; - - dw_ptr = (u32 *)bios; - length_dw = ALIGN(length_bytes, 4) / 4; - - rom_index_offset = - adev->smuio.funcs->get_rom_index_offset(adev); - rom_data_offset = - adev->smuio.funcs->get_rom_data_offset(adev); - - /* set rom index to 0 */ - WREG32(rom_index_offset, 0); - /* read out the rom data */ - for (i = 0; i < length_dw; i++) - dw_ptr[i] = RREG32(rom_data_offset); - - return true; -} - static struct soc15_allowed_register_entry soc15_allowed_read_registers[] = { { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS2)}, @@ -925,7 +892,7 @@ static void soc15_pre_asic_init(struct amdgpu_device *adev) static const struct amdgpu_asic_funcs soc15_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, - .read_bios_from_rom = &soc15_read_bios_from_rom, + .read_bios_from_rom = &amdgpu_soc15_read_bios_from_rom, .read_register = &soc15_read_register, .reset = &soc15_asic_reset, .reset_method = &soc15_asic_reset_method, @@ -947,7 +914,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs = static const struct amdgpu_asic_funcs vega20_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, - .read_bios_from_rom = &soc15_read_bios_from_rom, + .read_bios_from_rom = &amdgpu_soc15_read_bios_from_rom, .read_register = &soc15_read_register, .reset = &soc15_asic_reset, .reset_method = &soc15_asic_reset_method, From d6dac2bc12bd968acfcec7a0c92c59d2e19dacc9 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Fri, 21 Jan 2022 16:50:48 +0800 Subject: [PATCH 128/339] drm/amdgpu: fix channel index mapping for SIENNA_CICHLID Pmfw read ecc info registers in the following order, umc0: ch_inst 0, 1, 2 ... 7 umc1: ch_inst 0, 1, 2 ... 7 The position of the register value stored in eccinfo table is calculated according to the below formula, channel_index = umc_inst * channel_in_umc + ch_inst Driver directly use the index of eccinfo table array as channel index, it's not correct, driver needs convert eccinfo table array index to channel index according to channel_idx_tbl. Reviewed-by: Tao Zhou Signed-off-by: Stanley.Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index cd57f39df7d1..d70417196662 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -55,29 +55,36 @@ static inline uint32_t get_umc_v8_7_channel_index(struct amdgpu_device *adev, } static void umc_v8_7_ecc_info_query_correctable_error_count(struct amdgpu_device *adev, - uint32_t channel_index, + uint32_t umc_inst, uint32_t ch_inst, unsigned long *error_count) { uint64_t mc_umc_status; + uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + + eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; + /* check for SRAM correctable error * MCUMC_STATUS is a 64 bit register */ - mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status; if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) *error_count += 1; } static void umc_v8_7_ecc_info_querry_uncorrectable_error_count(struct amdgpu_device *adev, - uint32_t channel_index, + uint32_t umc_inst, uint32_t ch_inst, unsigned long *error_count) { uint64_t mc_umc_status; + uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; + /* check the MCUMC_STATUS */ - mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status; if ((REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 || REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || @@ -94,20 +101,16 @@ static void umc_v8_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev, uint32_t umc_inst = 0; uint32_t ch_inst = 0; - uint32_t channel_index = 0; /* TODO: driver needs to toggle DF Cstate to ensure * safe access of UMC registers. Will add the protection */ LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - channel_index = get_umc_v8_7_channel_index(adev, - umc_inst, - ch_inst); umc_v8_7_ecc_info_query_correctable_error_count(adev, - channel_index, + umc_inst, ch_inst, &(err_data->ce_count)); umc_v8_7_ecc_info_querry_uncorrectable_error_count(adev, - channel_index, + umc_inst, ch_inst, &(err_data->ue_count)); } } @@ -120,12 +123,14 @@ static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, uint64_t mc_umc_status, err_addr, retired_page; struct eeprom_table_record *err_rec; uint32_t channel_index; + uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + eccinfo_table_idx = umc_inst * adev->umc.channel_inst_num + ch_inst; channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; - mc_umc_status = ras->umc_ecc.ecc[channel_index].mca_umc_status; + mc_umc_status = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_status; if (mc_umc_status == 0) return; @@ -140,7 +145,7 @@ static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1)) { - err_addr = ras->umc_ecc.ecc[channel_index].mca_umc_addr; + err_addr = ras->umc_ecc.ecc[eccinfo_table_idx].mca_umc_addr; err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); /* translate umc channel address to soc pa, 3 parts are included */ From 1f33bd18d703ecdf7b664168d640439e867d1605 Mon Sep 17 00:00:00 2001 From: yipechai Date: Tue, 18 Jan 2022 17:59:45 +0800 Subject: [PATCH 129/339] drm/amdgpu: Move xgmi ras initialization from .late_init to .early_init Move xgmi ras initialization from .late_init to .early_init, which let xgmi ras can be initialized only once. Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 15 ++++++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 5 +++++ drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 5 +++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index e15f6b8a62ea..ec1203d49799 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -436,6 +436,16 @@ void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr, } while (fault->timestamp < tmp); } +int amdgpu_gmc_ras_early_init(struct amdgpu_device *adev) +{ + if (!adev->gmc.xgmi.connected_to_cpu) { + adev->gmc.xgmi.ras = &xgmi_ras; + amdgpu_ras_register_ras_block(adev, &adev->gmc.xgmi.ras->ras_block); + } + + return 0; +} + int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) { int r; @@ -452,11 +462,6 @@ int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev) return r; } - if (!adev->gmc.xgmi.connected_to_cpu) { - adev->gmc.xgmi.ras = &xgmi_ras; - amdgpu_ras_register_ras_block(adev, &adev->gmc.xgmi.ras->ras_block); - } - if (adev->gmc.xgmi.ras && adev->gmc.xgmi.ras->ras_block.ras_late_init) { r = adev->gmc.xgmi.ras->ras_block.ras_late_init(adev, NULL); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index a5e8e0e08970..93505bb0a36c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -318,6 +318,7 @@ bool amdgpu_gmc_filter_faults(struct amdgpu_device *adev, uint16_t pasid, uint64_t timestamp); void amdgpu_gmc_filter_faults_remove(struct amdgpu_device *adev, uint64_t addr, uint16_t pasid); +int amdgpu_gmc_ras_early_init(struct amdgpu_device *adev); int amdgpu_gmc_ras_late_init(struct amdgpu_device *adev); void amdgpu_gmc_ras_fini(struct amdgpu_device *adev); int amdgpu_gmc_allocate_vm_inv_eng(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 5e88655cdfa5..73ab0eebe4e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -719,6 +719,7 @@ static void gmc_v10_0_set_gfxhub_funcs(struct amdgpu_device *adev) static int gmc_v10_0_early_init(void *handle) { + int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; gmc_v10_0_set_mmhub_funcs(adev); @@ -734,6 +735,10 @@ static int gmc_v10_0_early_init(void *handle) adev->gmc.private_aperture_end = adev->gmc.private_aperture_start + (4ULL << 30) - 1; + r = amdgpu_gmc_ras_early_init(adev); + if (r) + return r; + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index de32dbca9ab8..600ff658ab1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1318,6 +1318,7 @@ static void gmc_v9_0_set_mca_funcs(struct amdgpu_device *adev) static int gmc_v9_0_early_init(void *handle) { + int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* ARCT and VEGA20 don't have XGMI defined in their IP discovery tables */ @@ -1347,6 +1348,10 @@ static int gmc_v9_0_early_init(void *handle) adev->gmc.private_aperture_end = adev->gmc.private_aperture_start + (4ULL << 30) - 1; + r = amdgpu_gmc_ras_early_init(adev); + if (r) + return r; + return 0; } From e9287ef8d46cee538c9a71bb8978b2f7e975c452 Mon Sep 17 00:00:00 2001 From: yipechai Date: Wed, 19 Jan 2022 16:49:42 +0800 Subject: [PATCH 130/339] Revert "drm/amdgpu: No longer insert ras blocks into ras_list if it already exists in ras_list" This reverts commit df4f0041c6ef497e598a67e367db835489162754. Xgmi ras initialization had been moved from .late_init to early_init, the defect of repeated calling amdgpu_ras_register_ras_block had been fixed, so revert this patch. Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 4992bc554c0c..d4e07d0acb66 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2763,19 +2763,12 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object *ras_block_obj) { - struct amdgpu_ras_block_object *obj, *tmp; if (!adev || !ras_block_obj) return -EINVAL; if (!amdgpu_ras_asic_supported(adev)) return 0; - /* If the ras object is in ras_list, don't add it again */ - list_for_each_entry_safe(obj, tmp, &adev->ras_list, node) { - if (obj == ras_block_obj) - return 0; - } - INIT_LIST_HEAD(&ras_block_obj->node); list_add_tail(&ras_block_obj->node, &adev->ras_list); From d435c1ed56b9f9347189924395588cfdf7489af5 Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Mon, 24 Jan 2022 14:25:34 +0800 Subject: [PATCH 131/339] drm/amd/pm: add get_dpm_ultimate_freq function for cyan skillfish Some clients(e.g., kfd) query sclk/mclk through this function. As cyan skillfish doesn't support dpm, for sclk, set min/max to CYAN_SKILLFISH_SCLK_MIN/CYAN_SKILLFISH_SCLK_MAX(to maintain the existing logic).For others, set both min and max to current value. Before this patch: # /opt/rocm/opencl/bin/clinfo Max clock frequency: 0Mhz After this patch: # /opt/rocm/opencl/bin/clinfo Max clock frequency: 2000Mhz v2: - Maintain the existing min/max sclk logic.(Lijo) v3: - Avoid fetching metrics table twice.(Lijo) Signed-off-by: Lang Yu Reviewed-by: Lijo Lazar Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index 2acd7470431e..d743984b68a2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -542,6 +542,36 @@ static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, return ret; } +static int cyan_skillfish_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + int ret = 0; + uint32_t low, high; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + low = CYAN_SKILLFISH_SCLK_MIN; + high = CYAN_SKILLFISH_SCLK_MAX; + break; + default: + ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &low); + if (ret) + return ret; + high = low; + break; + } + + if (min) + *min = low; + if (max) + *max = high; + + return 0; +} + static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .check_fw_status = smu_v11_0_check_fw_status, @@ -555,6 +585,7 @@ static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .is_dpm_running = cyan_skillfish_is_dpm_running, .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, + .get_dpm_ultimate_freq = cyan_skillfish_get_dpm_ultimate_freq, .register_irq_handler = smu_v11_0_register_irq_handler, .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, From 5b680dbfbf6899afaf8bbe59b859509149d59129 Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Mon, 24 Jan 2022 14:34:48 +0800 Subject: [PATCH 132/339] drm/amd/pm: use existing fini_smc_tables function for cyan skillfish Remove redundant code and use general smu_v11_0_fini_smc_tables function. Signed-off-by: Lang Yu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index d743984b68a2..2f57333e6071 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -125,22 +125,6 @@ static int cyan_skillfish_init_smc_tables(struct smu_context *smu) return smu_v11_0_init_smc_tables(smu); } -static int cyan_skillfish_finit_smc_tables(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - - kfree(smu_table->metrics_table); - smu_table->metrics_table = NULL; - - kfree(smu_table->gpu_metrics_table); - smu_table->gpu_metrics_table = NULL; - smu_table->gpu_metrics_table_size = 0; - - smu_table->metrics_time = 0; - - return 0; -} - static int cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, @@ -579,7 +563,7 @@ static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .init_power = smu_v11_0_init_power, .fini_power = smu_v11_0_fini_power, .init_smc_tables = cyan_skillfish_init_smc_tables, - .fini_smc_tables = cyan_skillfish_finit_smc_tables, + .fini_smc_tables = smu_v11_0_fini_smc_tables, .read_sensor = cyan_skillfish_read_sensor, .print_clk_levels = cyan_skillfish_print_clk_levels, .is_dpm_running = cyan_skillfish_is_dpm_running, From c282d9512cdd167384fe0d233d13deea538658f2 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jan 2022 16:24:36 +0800 Subject: [PATCH 133/339] drm/amd/display: factor out dp detection link training and mst top detection [why] dc_link_detect_helper has multiple purpose: 1. Detect link and local sink. 2. Verify link capability by performing detection link training. 3. Start mst topology discovery and if succeeded fails the current interface. This is difficult to maintain as item 2 has become more destructive to current dc state. The change is to decouple these sequences to its own functions. Eventually only item 2 is a destructive method and we will redesign this sequence with a more unified policy across different encoder types. Tested-by: Daniel Wheeler Reviewed-by: Chris Park Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 362 +++++++++++------- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 164 ++------ .../drm/amd/display/dc/core/dc_link_hwss.c | 16 - drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 7 +- 5 files changed, 259 insertions(+), 291 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index e5d63b0d2594..af2d7f3abfca 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -720,35 +720,8 @@ static bool detect_dp(struct dc_link *link, sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT; if (!detect_dp_sink_caps(link)) return false; - if (is_mst_supported(link)) { - sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT_MST; - link->type = dc_connection_mst_branch; - dal_ddc_service_set_transaction_type(link->ddc, - sink_caps->transaction_type); - -#if defined(CONFIG_DRM_AMD_DC_DCN) - /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock - * reports DSC support. - */ - if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && - link->type == dc_connection_mst_branch && - link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && - link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && - !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) - link->wa_flags.dpia_mst_dsc_always_on = true; -#endif - -#if defined(CONFIG_DRM_AMD_DC_HDCP) - /* In case of fallback to SST when topology discovery below fails - * HDCP caps will be querried again later by the upper layer (caller - * of this function). */ - query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link); -#endif - } - - if (link->type != dc_connection_mst_branch && - is_dp_branch_device(link)) + if (is_dp_branch_device(link)) /* DP SST branch */ link->type = dc_connection_sst_branch; } else { @@ -824,15 +797,215 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link) return false; } -/* - * dc_link_detect() - Detect if a sink is attached to a given link +static void apply_dpia_mst_dsc_always_on_wa(struct dc_link *link) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock + * reports DSC support. + */ + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && + link->type == dc_connection_mst_branch && + link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && + link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && + !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) + link->wa_flags.dpia_mst_dsc_always_on = true; +#endif +} + +static void revert_dpia_mst_dsc_always_on_wa(struct dc_link *link) +{ + /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */ + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) + link->wa_flags.dpia_mst_dsc_always_on = false; +} + +static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason reason) +{ + DC_LOGGER_INIT(link->ctx->logger); + + LINK_INFO("link=%d, mst branch is now Connected\n", + link->link_index); + + apply_dpia_mst_dsc_always_on_wa(link); + link->type = dc_connection_mst_branch; + dm_helpers_dp_update_branch_info(link->ctx, link); + if (dm_helpers_dp_mst_start_top_mgr(link->ctx, + link, reason == DETECT_REASON_BOOT)) { + link_disconnect_sink(link); + } else { + link->type = dc_connection_sst_branch; + } + + return link->type == dc_connection_mst_branch; +} + +static void reset_cur_dp_mst_topology(struct dc_link *link) +{ + DC_LOGGER_INIT(link->ctx->logger); + + LINK_INFO("link=%d, mst branch is now Disconnected\n", + link->link_index); + + revert_dpia_mst_dsc_always_on_wa(link); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); + + link->mst_stream_alloc_table.stream_count = 0; + memset(link->mst_stream_alloc_table.stream_allocations, + 0, + sizeof(link->mst_stream_alloc_table.stream_allocations)); +} + +static bool should_prepare_phy_clocks_for_link_verification(const struct dc *dc, + enum dc_detect_reason reason) +{ + int i; + bool can_apply_seamless_boot = false; + + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->streams[i]->apply_seamless_boot_optimization) { + can_apply_seamless_boot = true; + break; + } + } + + return !can_apply_seamless_boot && reason != DETECT_REASON_BOOT; +} + +static void prepare_phy_clocks_for_destructive_link_verification(const struct dc *dc) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN) + dc_z10_restore(dc); +#endif + clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); +} + +static void restore_phy_clocks_for_destructive_link_verification(const struct dc *dc) +{ + clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); +} + +static void set_all_streams_dpms_off_for_link(struct dc_link *link) +{ + int i; + struct pipe_ctx *pipe_ctx; + struct dc_stream_update stream_update; + bool dpms_off = true; + + memset(&stream_update, 0, sizeof(stream_update)); + stream_update.dpms_off = &dpms_off; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + stream_update.stream = pipe_ctx->stream; + dc_commit_updates_for_stream(link->ctx->dc, NULL, 0, + pipe_ctx->stream, &stream_update, + link->ctx->dc->current_state); + } + } +} + +static void verify_link_capability_destructive(struct dc_link *link, + struct dc_sink *sink, + enum dc_detect_reason reason) +{ + struct link_resource link_res = { 0 }; + bool should_prepare_phy_clocks = + should_prepare_phy_clocks_for_link_verification(link->dc, reason); + + if (should_prepare_phy_clocks) + prepare_phy_clocks_for_destructive_link_verification(link->dc); + + + if (dc_is_dp_signal(link->local_sink->sink_signal)) { + struct dc_link_settings known_limit_link_setting = + dp_get_max_link_cap(link); + + set_all_streams_dpms_off_for_link(link); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&known_limit_link_setting) == + DP_128b_132b_ENCODING) + link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( + &link->dc->current_state->res_ctx, + link->dc->res_pool, + link); +#endif + dp_verify_link_cap_with_retries( + link, &link_res, &known_limit_link_setting, + LINK_TRAINING_MAX_VERIFY_RETRY); + } else { + ASSERT(0); + } + + if (should_prepare_phy_clocks) + restore_phy_clocks_for_destructive_link_verification(link->dc); +} + +static void verify_link_capability_non_destructive(struct dc_link *link) +{ + if (dc_is_dp_signal(link->local_sink->sink_signal)) { + if (dc_is_embedded_signal(link->local_sink->sink_signal) || + link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) + /* TODO - should we check link encoder's max link caps here? + * How do we know which link encoder to check from? + */ + link->verified_link_cap = link->reported_link_cap; + else + link->verified_link_cap = dp_get_max_link_cap(link); + } +} + +static bool should_verify_link_capability_destructively(struct dc_link *link, + enum dc_detect_reason reason) +{ + bool destrictive = false; + struct dc_link_settings max_link_cap; + bool is_link_enc_unavailable = link->link_enc && + link->dc->res_pool->funcs->link_encs_assign && + !link_enc_cfg_is_link_enc_avail( + link->ctx->dc, + link->link_enc->preferred_engine, + link); + + if (dc_is_dp_signal(link->local_sink->sink_signal)) { + max_link_cap = dp_get_max_link_cap(link); + destrictive = true; + + if (link->dc->debug.skip_detection_link_training || + dc_is_embedded_signal(link->local_sink->sink_signal) || + link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { + destrictive = false; + } else if (dp_get_link_encoding_format(&max_link_cap) == + DP_8b_10b_ENCODING) { + if (link->dpcd_caps.is_mst_capable || + is_link_enc_unavailable) { + destrictive = false; + } + } + } + + return destrictive; +} + +static void verify_link_capability(struct dc_link *link, struct dc_sink *sink, + enum dc_detect_reason reason) +{ + if (should_verify_link_capability_destructively(link, reason)) + verify_link_capability_destructive(link, sink, reason); + else + verify_link_capability_non_destructive(link); +} + + +/** + * detect_link_and_local_sink() - Detect if a sink is attached to a given link * * link->local_sink is created or destroyed as needed. * - * This does not create remote sinks but will trigger DM - * to start MST detection if a branch is detected. + * This does not create remote sinks. */ -static bool dc_link_detect_helper(struct dc_link *link, +static bool detect_link_and_local_sink(struct dc_link *link, enum dc_detect_reason reason) { struct dc_sink_init_data sink_init_data = { 0 }; @@ -848,9 +1021,7 @@ static bool dc_link_detect_helper(struct dc_link *link, struct dpcd_caps prev_dpcd_caps; enum dc_connection_type new_connection_type = dc_connection_none; enum dc_connection_type pre_connection_type = dc_connection_none; - bool perform_dp_seamless_boot = false; const uint32_t post_oui_delay = 30; // 30ms - struct link_resource link_res = { 0 }; DC_LOGGER_INIT(link->ctx->logger); @@ -944,61 +1115,6 @@ static bool dc_link_detect_helper(struct dc_link *link, return false; } -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) - link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( - &link->dc->current_state->res_ctx, - link->dc->res_pool, - link); -#endif - - if (link->type == dc_connection_mst_branch) { - LINK_INFO("link=%d, mst branch is now Connected\n", - link->link_index); - /* Need to setup mst link_cap struct here - * otherwise dc_link_detect() will leave mst link_cap - * empty which leads to allocate_mst_payload() has "0" - * pbn_per_slot value leading to exception on dc_fixpt_div() - */ - dp_verify_mst_link_cap(link, &link_res); - - /* - * This call will initiate MST topology discovery. Which - * will detect MST ports and add new DRM connector DRM - * framework. Then read EDID via remote i2c over aux. In - * the end, will notify DRM detect result and save EDID - * into DRM framework. - * - * .detect is called by .fill_modes. - * .fill_modes is called by user mode ioctl - * DRM_IOCTL_MODE_GETCONNECTOR. - * - * .get_modes is called by .fill_modes. - * - * call .get_modes, AMDGPU DM implementation will create - * new dc_sink and add to dc_link. For long HPD plug - * in/out, MST has its own handle. - * - * Therefore, just after dc_create, link->sink is not - * created for MST until user mode app calls - * DRM_IOCTL_MODE_GETCONNECTOR. - * - * Need check ->sink usages in case ->sink = NULL - * TODO: s3 resume check - */ - - dm_helpers_dp_update_branch_info(link->ctx, link); - if (dm_helpers_dp_mst_start_top_mgr(link->ctx, - link, reason == DETECT_REASON_BOOT)) { - if (prev_sink) - dc_sink_release(prev_sink); - return false; - } else { - link->type = dc_connection_sst_branch; - sink_caps.signal = SIGNAL_TYPE_DISPLAY_PORT; - } - } - /* Active SST downstream branch device unplug*/ if (link->type == dc_connection_sst_branch && link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) { @@ -1019,7 +1135,6 @@ static bool dc_link_detect_helper(struct dc_link *link, if (pre_connection_type == dc_connection_mst_branch && link->type != dc_connection_mst_branch) dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); - break; } @@ -1108,13 +1223,6 @@ static bool dc_link_detect_helper(struct dc_link *link, #if defined(CONFIG_DRM_AMD_DC_HDCP) query_hdcp_capability(sink->sink_signal, link); #endif - - // verify link cap for SST non-seamless boot - if (!perform_dp_seamless_boot) - dp_verify_link_cap_with_retries(link, - &link_res, - &link->reported_link_cap, - LINK_TRAINING_MAX_VERIFY_RETRY); } else { // If edid is the same, then discard new sink and revert back to original sink if (same_edid) { @@ -1174,27 +1282,6 @@ static bool dc_link_detect_helper(struct dc_link *link, } } else { /* From Connected-to-Disconnected. */ - if (link->type == dc_connection_mst_branch) { - LINK_INFO("link=%d, mst branch is now Disconnected\n", - link->link_index); - - /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */ - if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) - link->wa_flags.dpia_mst_dsc_always_on = false; - - dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); - - link->mst_stream_alloc_table.stream_count = 0; - memset(link->mst_stream_alloc_table.stream_allocations, - 0, - sizeof(link->mst_stream_alloc_table.stream_allocations)); - } - -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) - reset_dp_hpo_stream_encoders_for_link(link); -#endif - link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; /* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk @@ -1219,33 +1306,26 @@ static bool dc_link_detect_helper(struct dc_link *link, bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { - const struct dc *dc = link->dc; - bool ret; - bool can_apply_seamless_boot = false; - int i; + bool is_local_sink_detect_success; + bool is_remote_sink_detect_required = false; + enum dc_connection_type pre_link_type = link->type; - for (i = 0; i < dc->current_state->stream_count; i++) { - if (dc->current_state->streams[i]->apply_seamless_boot_optimization) { - can_apply_seamless_boot = true; - break; - } - } + is_local_sink_detect_success = detect_link_and_local_sink(link, reason); -#if defined(CONFIG_DRM_AMD_DC_DCN) - dc_z10_restore(dc); -#endif + if (is_local_sink_detect_success && link->local_sink) + verify_link_capability(link, link->local_sink, reason); - /* get out of low power state */ - if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) - clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + if (is_local_sink_detect_success && link->local_sink && + dc_is_dp_signal(link->local_sink->sink_signal) && + link->dpcd_caps.is_mst_capable) + is_remote_sink_detect_required = discover_dp_mst_topology(link, reason); - ret = dc_link_detect_helper(link, reason); + if (is_local_sink_detect_success && + pre_link_type == dc_connection_mst_branch && + link->type != dc_connection_mst_branch) + reset_cur_dp_mst_topology(link); - /* Go back to power optimized state */ - if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) - clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); - - return ret; + return is_local_sink_detect_success && !is_remote_sink_detect_required; } bool dc_link_get_hpd_state(struct dc_link *dc_link) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 6f6929435885..8dc03c41fabf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -104,9 +104,6 @@ static bool decide_fallback_link_setting( struct dc_link_settings initial_link_settings, struct dc_link_settings *current_link_setting, enum link_training_result training_result); -static struct dc_link_settings get_common_supported_link_settings( - struct dc_link_settings link_setting_a, - struct dc_link_settings link_setting_b); static void maximize_lane_settings(const struct link_training_settings *lt_settings, struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); static void override_lane_settings(const struct link_training_settings *lt_settings, @@ -3186,13 +3183,11 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_ return false; } -static struct dc_link_settings get_max_link_cap(struct dc_link *link, - const struct link_resource *link_res) + +struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) { struct dc_link_settings max_link_cap = {0}; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_link_rate lttpr_max_link_rate; -#endif struct link_encoder *link_enc = NULL; /* Links supporting dynamically assigned link encoder will be assigned next @@ -3210,13 +3205,6 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link, /* get max link encoder capability */ if (link_enc) link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap); -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (max_link_cap.link_rate >= LINK_RATE_UHBR10) { - if (!link_res->hpo_dp_link_enc || - link->dc->debug.disable_uhbr) - max_link_cap.link_rate = LINK_RATE_HIGH3; - } -#endif /* Lower link settings based on sink's link cap */ if (link->reported_link_cap.lane_count < max_link_cap.lane_count) @@ -3236,22 +3224,21 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link, if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) { if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; - -#if defined(CONFIG_DRM_AMD_DC_DCN) lttpr_max_link_rate = get_lttpr_max_link_rate(link); if (lttpr_max_link_rate < max_link_cap.link_rate) max_link_cap.link_rate = lttpr_max_link_rate; -#else - if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate) - max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; -#endif DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n", __func__, max_link_cap.lane_count, max_link_cap.link_rate); } + + if (dp_get_link_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING && + link->dc->debug.disable_uhbr) + max_link_cap.link_rate = LINK_RATE_HIGH3; + return max_link_cap; } @@ -3376,10 +3363,9 @@ bool dp_verify_link_cap( struct dc_link_settings *known_limit_link_setting, int *fail_count) { - struct dc_link_settings max_link_cap = {0}; struct dc_link_settings cur_link_setting = {0}; struct dc_link_settings *cur = &cur_link_setting; - struct dc_link_settings initial_link_settings = {0}; + struct dc_link_settings initial_link_settings = *known_limit_link_setting; bool success; bool skip_link_training; bool skip_video_pattern; @@ -3387,28 +3373,6 @@ bool dp_verify_link_cap( enum link_training_result status; union hpd_irq_data irq_data; - /* link training starts with the maximum common settings - * supported by both sink and ASIC. - */ - max_link_cap = get_max_link_cap(link, link_res); - initial_link_settings = get_common_supported_link_settings( - *known_limit_link_setting, - max_link_cap); - - /* Accept reported capabilities if link supports flexible encoder mapping or encoder already in use. */ - if (link->dc->debug.skip_detection_link_training || - link->is_dig_mapping_flexible) { - /* TODO - should we check link encoder's max link caps here? - * How do we know which link encoder to check from? - */ - link->verified_link_cap = *known_limit_link_setting; - return true; - } else if (link->link_enc && link->dc->res_pool->funcs->link_encs_assign && - !link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine, link)) { - link->verified_link_cap = initial_link_settings; - return true; - } - memset(&irq_data, 0, sizeof(irq_data)); success = false; skip_link_training = false; @@ -3420,10 +3384,6 @@ bool dp_verify_link_cap( core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); } -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) - reset_dp_hpo_stream_encoders_for_link(link); -#endif /* TODO implement override and monitor patch later */ /* try to train the link from high to low to @@ -3540,79 +3500,32 @@ bool dp_verify_link_cap_with_retries( return success; } -bool dp_verify_mst_link_cap( - struct dc_link *link, const struct link_resource *link_res) +/* in DP compliance test, DPR-120 may have + * a random value in its MAX_LINK_BW dpcd field. + * We map it to the maximum supported link rate that + * is smaller than MAX_LINK_BW in this case. + */ +static enum dc_link_rate get_link_rate_from_max_link_bw( + uint8_t max_link_bw) { - struct dc_link_settings max_link_cap = {0}; + enum dc_link_rate link_rate; - if (dp_get_link_encoding_format(&link->reported_link_cap) == - DP_8b_10b_ENCODING) { - max_link_cap = get_max_link_cap(link, link_res); - link->verified_link_cap = get_common_supported_link_settings( - link->reported_link_cap, - max_link_cap); - } -#if defined(CONFIG_DRM_AMD_DC_DCN) - else if (dp_get_link_encoding_format(&link->reported_link_cap) == - DP_128b_132b_ENCODING) { - dp_verify_link_cap_with_retries(link, - link_res, - &link->reported_link_cap, - LINK_TRAINING_MAX_VERIFY_RETRY); - } -#endif - return true; -} - -static struct dc_link_settings get_common_supported_link_settings( - struct dc_link_settings link_setting_a, - struct dc_link_settings link_setting_b) -{ - struct dc_link_settings link_settings = {0}; - - link_settings.lane_count = - (link_setting_a.lane_count <= - link_setting_b.lane_count) ? - link_setting_a.lane_count : - link_setting_b.lane_count; - link_settings.link_rate = - (link_setting_a.link_rate <= - link_setting_b.link_rate) ? - link_setting_a.link_rate : - link_setting_b.link_rate; - link_settings.link_spread = LINK_SPREAD_DISABLED; - - /* in DP compliance test, DPR-120 may have - * a random value in its MAX_LINK_BW dpcd field. - * We map it to the maximum supported link rate that - * is smaller than MAX_LINK_BW in this case. - */ -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (link_settings.link_rate > LINK_RATE_UHBR20) { - link_settings.link_rate = LINK_RATE_UHBR20; - } else if (link_settings.link_rate < LINK_RATE_UHBR20 && - link_settings.link_rate > LINK_RATE_UHBR13_5) { - link_settings.link_rate = LINK_RATE_UHBR13_5; - } else if (link_settings.link_rate < LINK_RATE_UHBR10 && - link_settings.link_rate > LINK_RATE_HIGH3) { -#else - if (link_settings.link_rate > LINK_RATE_HIGH3) { -#endif - link_settings.link_rate = LINK_RATE_HIGH3; - } else if (link_settings.link_rate < LINK_RATE_HIGH3 - && link_settings.link_rate > LINK_RATE_HIGH2) { - link_settings.link_rate = LINK_RATE_HIGH2; - } else if (link_settings.link_rate < LINK_RATE_HIGH2 - && link_settings.link_rate > LINK_RATE_HIGH) { - link_settings.link_rate = LINK_RATE_HIGH; - } else if (link_settings.link_rate < LINK_RATE_HIGH - && link_settings.link_rate > LINK_RATE_LOW) { - link_settings.link_rate = LINK_RATE_LOW; - } else if (link_settings.link_rate < LINK_RATE_LOW) { - link_settings.link_rate = LINK_RATE_UNKNOWN; + if (max_link_bw >= LINK_RATE_HIGH3) { + link_rate = LINK_RATE_HIGH3; + } else if (max_link_bw < LINK_RATE_HIGH3 + && max_link_bw >= LINK_RATE_HIGH2) { + link_rate = LINK_RATE_HIGH2; + } else if (max_link_bw < LINK_RATE_HIGH2 + && max_link_bw >= LINK_RATE_HIGH) { + link_rate = LINK_RATE_HIGH; + } else if (max_link_bw < LINK_RATE_HIGH + && max_link_bw >= LINK_RATE_LOW) { + link_rate = LINK_RATE_LOW; + } else { + link_rate = LINK_RATE_UNKNOWN; } - return link_settings; + return link_rate; } static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count) @@ -5516,6 +5429,9 @@ static bool retrieve_link_cap(struct dc_link *link) read_dp_device_vendor_id(link); + /* TODO - decouple raw mst capability from policy decision */ + link->dpcd_caps.is_mst_capable = is_mst_supported(link); + get_active_converter_info(ds_port.byte, link); dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data)); @@ -5534,8 +5450,8 @@ static bool retrieve_link_cap(struct dc_link *link) link->reported_link_cap.lane_count = link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; - link->reported_link_cap.link_rate = dpcd_data[ - DP_MAX_LINK_RATE - DP_DPCD_REV]; + link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw( + dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]); link->reported_link_cap.link_spread = link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; @@ -5759,14 +5675,6 @@ bool dp_overwrite_extended_receiver_cap(struct dc_link *link) bool detect_dp_sink_caps(struct dc_link *link) { return retrieve_link_cap(link); - - /* dc init_hw has power encoder using default - * signal for connector. For native DP, no - * need to power up encoder again. If not native - * DP, hw_init may need check signal or power up - * encoder here. - */ - /* TODO save sink caps in link->sink */ } static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz) @@ -5844,8 +5752,6 @@ void detect_edp_sink_caps(struct dc_link *link) } } } - link->verified_link_cap = link->reported_link_cap; - core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP, &backlight_adj_cap, sizeof(backlight_adj_cap)); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 45d03d3a95c3..e2409c14df34 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -897,21 +897,5 @@ void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) } } -void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link) -{ - const struct dc *dc = link->dc; - struct dc_state *state = dc->current_state; - uint8_t i; - - for (i = 0; i < MAX_PIPES; i++) { - if (state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc && - state->res_ctx.pipe_ctx[i].stream && - state->res_ctx.pipe_ctx[i].stream->link == link && - !state->res_ctx.pipe_ctx[i].stream->dpms_off) { - setup_dp_hpo_stream(&state->res_ctx.pipe_ctx[i], false); - } - } -} - #undef DC_LOGGER #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 235e33f73913..5ba6abdbd3aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1212,6 +1212,7 @@ struct dpcd_caps { bool is_branch_dev; /* Dongle's downstream count. */ union sink_count sink_count; + bool is_mst_capable; /* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER, indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/ struct dc_dongle_caps dongle_caps; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index cd52813a8432..b18c8198f66d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -54,6 +54,8 @@ enum { PEAK_FACTOR_X1000 = 1006, }; +struct dc_link_settings dp_get_max_link_cap(struct dc_link *link); + bool dp_verify_link_cap( struct dc_link *link, const struct link_resource *link_res, @@ -66,10 +68,6 @@ bool dp_verify_link_cap_with_retries( struct dc_link_settings *known_limit_link_setting, int attempts); -bool dp_verify_mst_link_cap( - struct dc_link *link, - const struct link_resource *link_res); - bool dp_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing); @@ -222,7 +220,6 @@ void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal); void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx); -void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link); bool dp_retrieve_lttpr_cap(struct dc_link *link); void edp_panel_backlight_power_on(struct dc_link *link); From 31d64b8219e057705d7a9debffcf6abbccb7781e Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Wed, 19 Jan 2022 16:24:37 +0800 Subject: [PATCH 134/339] drm/amd/display: Add work around to enforce TBT3 compatibility. [Why] According to the USB4 specification, FEC and DSC should be disabled when a USB4 DPIA operates in TBT3 compatibility mode. [How] Upon detecting that a USB4 DPIA is connected to a device that is known to operate in TBT3 mode, disable FEC and DSC support if they have been reported by the TBT3 device. Tested-by: Daniel Wheeler Reviewed-by: Meenakshikumar Somasundaram Acked-by: Rodrigo Siqueira Signed-off-by: Jimmy Kizito Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 22 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 13 ++++++----- drivers/gpu/drm/amd/display/dc/dc_link.h | 2 ++ .../amd/display/include/ddc_service_types.h | 2 ++ 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index af2d7f3abfca..81402c1d68ff 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -806,6 +806,7 @@ static void apply_dpia_mst_dsc_always_on_wa(struct dc_link *link) if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->type == dc_connection_mst_branch && link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && + link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_20 && link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT && !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around) link->wa_flags.dpia_mst_dsc_always_on = true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 8dc03c41fabf..5122c1de4492 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5550,6 +5550,28 @@ static bool retrieve_link_cap(struct dc_link *link) link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); #endif + + /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode + * only if required. + */ + if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + !link->dc->debug.dpia_debug.bits.disable_force_tbt3_work_around && +#endif + link->dpcd_caps.is_branch_dev && + link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && + link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_10 && + (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE || + link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT)) { + /* A TBT3 device is expected to report no support for FEC or DSC to a USB4 DPIA. + * Clear FEC and DSC capabilities as a work around if that is not the case. + */ + link->wa_flags.dpia_forced_tbt3_mode = true; + memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps)); + memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); + DC_LOG_DSC("Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode", link->link_index); + } else + link->wa_flags.dpia_forced_tbt3_mode = false; } if (!dpcd_read_sink_ext_caps(link)) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5ba6abdbd3aa..14abba495f4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -519,12 +519,13 @@ union root_clock_optimization_options { union dpia_debug_options { struct { - uint32_t disable_dpia:1; - uint32_t force_non_lttpr:1; - uint32_t extend_aux_rd_interval:1; - uint32_t disable_mst_dsc_work_around:1; - uint32_t hpd_delay_in_ms:12; - uint32_t reserved:16; + uint32_t disable_dpia:1; /* bit 0 */ + uint32_t force_non_lttpr:1; /* bit 1 */ + uint32_t extend_aux_rd_interval:1; /* bit 2 */ + uint32_t disable_mst_dsc_work_around:1; /* bit 3 */ + uint32_t hpd_delay_in_ms:12; /* bits 4-15 */ + uint32_t disable_force_tbt3_work_around:1; /* bit 16 */ + uint32_t reserved:15; } bits; uint32_t raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index c0e37ad0e26c..704323654468 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -197,6 +197,8 @@ struct dc_link { bool dp_mot_reset_segment; /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */ bool dpia_mst_dsc_always_on; + /* Forced DPIA into TBT3 compatibility mode. */ + bool dpia_forced_tbt3_mode; } wa_flags; struct link_mst_stream_allocation_table mst_stream_alloc_table; diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index a2b80514d83e..57f92bd2814f 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -34,6 +34,8 @@ #define DP_BRANCH_DEVICE_ID_90CC24 0x90CC24 #define DP_BRANCH_DEVICE_ID_00E04C 0x00E04C #define DP_BRANCH_DEVICE_ID_006037 0x006037 +#define DP_BRANCH_HW_REV_10 0x10 +#define DP_BRANCH_HW_REV_20 0x20 #define DP_DEVICE_ID_38EC11 0x38EC11 enum ddc_result { From d9eb8fea6862e63421f7b9c93e32bef348488c41 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jan 2022 16:24:38 +0800 Subject: [PATCH 135/339] drm/amd/display: Drop DCN for DP2.x logic [Why & How] DCN guard is not necessary for DP2.x relevant logic. Drop them. v2: squash in fix for misplaced #endif (Alex) Tested-by: Daniel Wheeler Reviewed-by: Rodrigo Siqueira Reviewed-by: Jerry Zuo Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +- .../drm/amd/display/dc/bios/bios_parser2.c | 2 - .../drm/amd/display/dc/bios/command_table2.c | 4 - drivers/gpu/drm/amd/display/dc/core/dc.c | 4 - drivers/gpu/drm/amd/display/dc/core/dc_link.c | 294 +++--------------- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 249 +-------------- .../drm/amd/display/dc/core/dc_link_hwss.c | 78 +---- .../gpu/drm/amd/display/dc/core/dc_resource.c | 14 - drivers/gpu/drm/amd/display/dc/dc.h | 13 +- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 43 +-- drivers/gpu/drm/amd/display/dc/dc_link.h | 6 - drivers/gpu/drm/amd/display/dc/dc_stream.h | 6 - drivers/gpu/drm/amd/display/dc/dc_types.h | 6 - .../display/dc/dce110/dce110_hw_sequencer.c | 54 +--- .../gpu/drm/amd/display/dc/inc/core_types.h | 12 - drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 4 +- .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 2 - .../drm/amd/display/dc/inc/hw/link_encoder.h | 2 - .../amd/display/dc/inc/hw/stream_encoder.h | 2 - .../amd/display/dc/inc/hw/timing_generator.h | 2 - .../amd/display/dc/inc/hw_sequencer_private.h | 2 - drivers/gpu/drm/amd/display/dc/inc/resource.h | 6 - .../amd/display/include/bios_parser_types.h | 2 - .../gpu/drm/amd/display/include/dpcd_defs.h | 4 - .../amd/display/include/grph_object_defs.h | 2 - .../drm/amd/display/include/grph_object_id.h | 2 - .../amd/display/include/link_service_types.h | 12 - 27 files changed, 84 insertions(+), 749 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 29f07c26d080..b32a68a3586a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -797,16 +797,12 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream) sizeof(new_downspread)); } -#if defined(CONFIG_DRM_AMD_DC_DCN) void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) { - // FPGA programming for this clock in diags framework that - // needs to go through dm layer, therefore leave dummy interace here + // TODO } - void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) { /* TODO: add peridic detection implementation */ } -#endif diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 1e385d55e7fb..23a3b640f0ee 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1692,7 +1692,6 @@ static enum bp_result bios_parser_get_encoder_cap_info( ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0; info->HDMI_6GB_EN = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0; -#if defined(CONFIG_DRM_AMD_DC_DCN) info->IS_DP2_CAPABLE = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0; info->DP_UHBR10_EN = (record->encodercaps & @@ -1701,7 +1700,6 @@ static enum bp_result bios_parser_get_encoder_cap_info( ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0; info->DP_UHBR20_EN = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0; -#endif info->DP_IS_USB_C = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index 9afa5eb2e6d3..f52f7ff7ead4 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -338,12 +338,10 @@ static enum bp_result transmitter_control_v1_7( const struct command_table_helper *cmd = bp->cmd_helper; struct dmub_dig_transmitter_control_data_v1_7 dig_v1_7 = {0}; -#if defined(CONFIG_DRM_AMD_DC_DCN) uint8_t hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_0; if (dc_is_dp_signal(cntl->signal)) hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_DP_0; -#endif dig_v1_7.phyid = cmd->phy_id_to_atom(cntl->transmitter); dig_v1_7.action = (uint8_t)cntl->action; @@ -358,9 +356,7 @@ static enum bp_result transmitter_control_v1_7( dig_v1_7.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); dig_v1_7.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); dig_v1_7.connobj_id = (uint8_t)cntl->connector_obj_id.id; -#if defined(CONFIG_DRM_AMD_DC_DCN) dig_v1_7.HPO_instance = hpo_instance; -#endif dig_v1_7.symclk_units.symclk_10khz = cntl->pixel_clock/10; if (cntl->action == TRANSMITTER_CONTROL_ENABLE || diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 91c4874473d6..0b8811ef3717 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2370,10 +2370,8 @@ static enum surface_update_type check_update_surfaces_for_stream( if (stream_update->dsc_config) su_flags->bits.dsc_changed = 1; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (stream_update->mst_bw_update) su_flags->bits.mst_bw = 1; -#endif if (su_flags->raw != 0) overall_type = UPDATE_TYPE_FULL; @@ -2752,14 +2750,12 @@ static void commit_planes_do_stream_update(struct dc *dc, if (stream_update->dsc_config) dp_update_dsc_config(pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (stream_update->mst_bw_update) { if (stream_update->mst_bw_update->is_increase) dc_link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); else dc_link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); } -#endif if (stream_update->pending_test_pattern) { dc_link_dp_set_test_pattern(stream->link, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 81402c1d68ff..84afe0d1a791 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -924,14 +924,12 @@ static void verify_link_capability_destructive(struct dc_link *link, dp_get_max_link_cap(link); set_all_streams_dpms_off_for_link(link); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&known_limit_link_setting) == DP_128b_132b_ENCODING) link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( &link->dc->current_state->res_ctx, link->dc->res_pool, link); -#endif dp_verify_link_cap_with_retries( link, &link_res, &known_limit_link_setting, LINK_TRAINING_MAX_VERIFY_RETRY); @@ -1656,9 +1654,7 @@ static bool dc_link_construct_legacy(struct dc_link *link, } DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); -#if defined(CONFIG_DRM_AMD_DC_DCN) DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE); -#endif /* Update link encoder tracking variables. These are used for the dynamic * assignment of link encoders to streams. @@ -1941,7 +1937,6 @@ static enum dc_status enable_link_dp(struct dc_state *state, if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) do_fallback = true; -#if defined(CONFIG_DRM_AMD_DC_DCN) /* * Temporary w/a to get DP2.0 link rates to work with SST. * TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved. @@ -1951,7 +1946,6 @@ static enum dc_status enable_link_dp(struct dc_state *state, link->dc->debug.set_mst_en_for_sst) { dp_enable_mst_on_sink(link, true); } -#endif if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) { /*in case it is not on*/ @@ -1959,7 +1953,6 @@ static enum dc_status enable_link_dp(struct dc_state *state, link->dc->hwss.edp_wait_for_hpd_ready(link, true); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) { /* TODO - DP2.0 HW: calculate 32 symbol clock for HPO encoder */ } else { @@ -1969,13 +1962,6 @@ static enum dc_status enable_link_dp(struct dc_state *state, state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false); } -#else - pipe_ctx->stream_res.pix_clk_params.requested_sym_clk = - link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - if (state->clk_mgr && !apply_seamless_boot_optimization) - state->clk_mgr->funcs->update_clocks(state->clk_mgr, - state, false); -#endif // during mode switch we do DP_SET_POWER off then on, and OUI is lost dpcd_set_source_specific_data(link); @@ -2004,12 +1990,8 @@ static enum dc_status enable_link_dp(struct dc_state *state, else fec_enable = true; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) dp_set_fec_enable(link, fec_enable); -#else - dp_set_fec_enable(link, fec_enable); -#endif // during mode set we do DP_SET_POWER off then on, aux writes are lost if (link->dpcd_sink_ext_caps.bits.oled == 1 || @@ -2565,9 +2547,7 @@ static void disable_link(struct dc_link *link, const struct link_resource *link_ if (dc_is_dp_signal(signal)) { /* SST DP, eDP */ -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_link_settings link_settings = link->cur_link_settings; -#endif if (dc_is_dp_sst_signal(signal)) dp_disable_link_phy(link, link_res, signal); else @@ -2575,15 +2555,10 @@ static void disable_link(struct dc_link *link, const struct link_resource *link_ if (dc_is_dp_sst_signal(signal) || link->mst_stream_alloc_table.stream_count == 0) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) { dp_set_fec_enable(link, false); dp_set_fec_ready(link, link_res, false); } -#else - dp_set_fec_enable(link, false); - dp_set_fec_ready(link, link_res, false); -#endif } } else { if (signal != SIGNAL_TYPE_VIRTUAL) @@ -2766,72 +2741,63 @@ static bool dp_active_dongle_validate_timing( break; } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dpcd_caps->dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER && dongle_caps->extendedCapValid == true) { -#else - if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER || - dongle_caps->extendedCapValid == false) - return true; -#endif + /* Check Pixel Encoding */ + switch (timing->pixel_encoding) { + case PIXEL_ENCODING_RGB: + case PIXEL_ENCODING_YCBCR444: + break; + case PIXEL_ENCODING_YCBCR422: + if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through) + return false; + break; + case PIXEL_ENCODING_YCBCR420: + if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through) + return false; + break; + default: + /* Invalid Pixel Encoding*/ + return false; + } - /* Check Pixel Encoding */ - switch (timing->pixel_encoding) { - case PIXEL_ENCODING_RGB: - case PIXEL_ENCODING_YCBCR444: - break; - case PIXEL_ENCODING_YCBCR422: - if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through) + switch (timing->display_color_depth) { + case COLOR_DEPTH_666: + case COLOR_DEPTH_888: + /*888 and 666 should always be supported*/ + break; + case COLOR_DEPTH_101010: + if (dongle_caps->dp_hdmi_max_bpc < 10) + return false; + break; + case COLOR_DEPTH_121212: + if (dongle_caps->dp_hdmi_max_bpc < 12) + return false; + break; + case COLOR_DEPTH_141414: + case COLOR_DEPTH_161616: + default: + /* These color depths are currently not supported */ return false; - break; - case PIXEL_ENCODING_YCBCR420: - if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through) - return false; - break; - default: - /* Invalid Pixel Encoding*/ - return false; - } - - switch (timing->display_color_depth) { - case COLOR_DEPTH_666: - case COLOR_DEPTH_888: - /*888 and 666 should always be supported*/ - break; - case COLOR_DEPTH_101010: - if (dongle_caps->dp_hdmi_max_bpc < 10) - return false; - break; - case COLOR_DEPTH_121212: - if (dongle_caps->dp_hdmi_max_bpc < 12) - return false; - break; - case COLOR_DEPTH_141414: - case COLOR_DEPTH_161616: - default: - /* These color depths are currently not supported */ - return false; - } + } #if defined(CONFIG_DRM_AMD_DC_DCN) - if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter - struct dc_crtc_timing outputTiming = *timing; + if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter + struct dc_crtc_timing outputTiming = *timing; - if (timing->flags.DSC && !timing->dsc_cfg.is_frl) - /* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */ - outputTiming.flags.DSC = 0; - if (dc_bandwidth_in_kbps_from_timing(&outputTiming) > dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps) - return false; - } else { // DP to HDMI TMDS converter + if (timing->flags.DSC && !timing->dsc_cfg.is_frl) + /* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */ + outputTiming.flags.DSC = 0; + if (dc_bandwidth_in_kbps_from_timing(&outputTiming) > dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps) + return false; + } else { // DP to HDMI TMDS converter + if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10)) + return false; + } +#else if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10)) return false; - } -#else - if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10)) - return false; #endif - -#if defined(CONFIG_DRM_AMD_DC_DCN) } if (dpcd_caps->channel_coding_cap.bits.DP_128b_132b_SUPPORTED == 0 && @@ -2912,7 +2878,6 @@ static bool dp_active_dongle_validate_timing( return false; } } -#endif return true; } @@ -3385,9 +3350,7 @@ static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx) static void update_mst_stream_alloc_table( struct dc_link *link, struct stream_encoder *stream_enc, -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc? -#endif const struct dp_mst_stream_allocation_table *proposed_table) { struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 }; @@ -3423,9 +3386,7 @@ static void update_mst_stream_alloc_table( work_table[i].slot_count = proposed_table->stream_allocations[i].slot_count; work_table[i].stream_enc = stream_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) work_table[i].hpo_dp_stream_enc = hpo_dp_stream_enc; -#endif } } @@ -3436,7 +3397,7 @@ static void update_mst_stream_alloc_table( link->mst_stream_alloc_table.stream_allocations[i] = work_table[i]; } -#if defined(CONFIG_DRM_AMD_DC_DCN) + static void dc_log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp) { const uint32_t VCP_Y_PRECISION = 1000; @@ -3538,7 +3499,6 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, */ return DC_OK; } -#endif /* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table * because stream_encoder is not exposed to dm @@ -3549,10 +3509,8 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_link *link = stream->link; struct link_encoder *link_encoder = NULL; struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc; struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; -#endif struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; @@ -3578,17 +3536,12 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) stream->ctx, stream, &proposed_table, - true)) { + true)) update_mst_stream_alloc_table( -#if defined(CONFIG_DRM_AMD_DC_DCN) link, pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.hpo_dp_stream_enc, &proposed_table); -#else - link, pipe_ctx->stream_res.stream_enc, &proposed_table); -#endif - } else DC_LOG_WARNING("Failed to update" "MST allocation table for" @@ -3601,7 +3554,6 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) link->mst_stream_alloc_table.stream_count); for (i = 0; i < MAX_CONTROLLER_NUM; i++) { -#if defined(CONFIG_DRM_AMD_DC_DCN) DC_LOG_MST("stream_enc[%d]: %p " "stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d " @@ -3614,17 +3566,6 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) link->mst_stream_alloc_table.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table.stream_allocations[i].slot_count); -#else - DC_LOG_MST("stream_enc[%d]: %p " - "stream[%d].vcp_id: %d " - "stream[%d].slot_count: %d\n", - i, - (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc, - i, - link->mst_stream_alloc_table.stream_allocations[i].vcp_id, - i, - link->mst_stream_alloc_table.stream_allocations[i].slot_count); -#endif } ASSERT(proposed_table.stream_count > 0); @@ -3644,7 +3585,6 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) } /* program DP source TX for payload */ -#if defined(CONFIG_DRM_AMD_DC_DCN) switch (dp_get_link_encoding_format(&link->cur_link_settings)) { case DP_8b_10b_ENCODING: link_encoder->funcs->update_mst_stream_allocation_table( @@ -3660,11 +3600,6 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) DC_LOG_ERROR("Failure: unknown encoding format\n"); return DC_ERROR_UNEXPECTED; } -#else - link_encoder->funcs->update_mst_stream_allocation_table( - link_encoder, - &link->mst_stream_alloc_table); -#endif /* send down message */ ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger( @@ -3687,7 +3622,6 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) pbn = get_pbn_from_timing(pipe_ctx); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); -#if defined(CONFIG_DRM_AMD_DC_DCN) switch (dp_get_link_encoding_format(&link->cur_link_settings)) { case DP_8b_10b_ENCODING: stream_encoder->funcs->set_throttled_vcp_size( @@ -3704,17 +3638,11 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) DC_LOG_ERROR("Failure: unknown encoding format\n"); return DC_ERROR_UNEXPECTED; } -#else - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, - avg_time_slots_per_mtp); -#endif return DC_OK; } -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps) { struct dc_stream_state *stream = pipe_ctx->stream; @@ -3871,7 +3799,6 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t return DC_OK; } -#endif static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) { @@ -3879,10 +3806,8 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_link *link = stream->link; struct link_encoder *link_encoder = NULL; struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc; struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; -#endif struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; @@ -3904,7 +3829,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) */ /* slot X.Y */ -#if defined(CONFIG_DRM_AMD_DC_DCN) switch (dp_get_link_encoding_format(&link->cur_link_settings)) { case DP_8b_10b_ENCODING: stream_encoder->funcs->set_throttled_vcp_size( @@ -3921,11 +3845,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) DC_LOG_ERROR("Failure: unknown encoding format\n"); return DC_ERROR_UNEXPECTED; } -#else - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, - avg_time_slots_per_mtp); -#endif /* TODO: which component is responsible for remove payload table? */ if (mst_mode) { @@ -3935,16 +3854,11 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) &proposed_table, false)) { -#if defined(CONFIG_DRM_AMD_DC_DCN) update_mst_stream_alloc_table( link, pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.hpo_dp_stream_enc, &proposed_table); -#else - update_mst_stream_alloc_table( - link, pipe_ctx->stream_res.stream_enc, &proposed_table); -#endif } else { DC_LOG_WARNING("Failed to update" @@ -3960,7 +3874,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) link->mst_stream_alloc_table.stream_count); for (i = 0; i < MAX_CONTROLLER_NUM; i++) { -#if defined(CONFIG_DRM_AMD_DC_DCN) DC_LOG_MST("stream_enc[%d]: %p " "stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d " @@ -3973,17 +3886,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) link->mst_stream_alloc_table.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table.stream_allocations[i].slot_count); -#else - DC_LOG_MST("stream_enc[%d]: %p " - "stream[%d].vcp_id: %d " - "stream[%d].slot_count: %d\n", - i, - (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc, - i, - link->mst_stream_alloc_table.stream_allocations[i].vcp_id, - i, - link->mst_stream_alloc_table.stream_allocations[i].slot_count); -#endif } if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { @@ -4000,7 +3902,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) status, mst_alloc_slots, prev_mst_slots_in_use); } -#if defined(CONFIG_DRM_AMD_DC_DCN) switch (dp_get_link_encoding_format(&link->cur_link_settings)) { case DP_8b_10b_ENCODING: link_encoder->funcs->update_mst_stream_allocation_table( @@ -4016,11 +3917,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) DC_LOG_ERROR("Failure: unknown encoding format\n"); return DC_ERROR_UNEXPECTED; } -#else - link_encoder->funcs->update_mst_stream_allocation_table( - link_encoder, - &link->mst_stream_alloc_table); -#endif if (mst_mode) { dm_helpers_dp_mst_poll_for_allocation_change_trigger( @@ -4068,21 +3964,18 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) /* stream encoder index */ config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; -#endif /* dig back end */ config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst; /* link encoder index */ config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst; -#endif + /* dio output index */ config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; @@ -4097,9 +3990,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP) ? 1 : 0; config.mst_enabled = (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) ? 1 : 0; -#if defined(CONFIG_DRM_AMD_DC_DCN) config.dp2_enabled = is_dp_128b_132b_signal(pipe_ctx) ? 1 : 0; -#endif config.usb4_enabled = (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ? 1 : 0; config.dpms_off = dpms_off; @@ -4111,7 +4002,6 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) } #endif -#if defined(CONFIG_DRM_AMD_DC_DCN) static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pipe_ctx *pipe_ctx) { struct dc *dc = pipe_ctx->stream->ctx->dc; @@ -4191,7 +4081,6 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings); } -#endif void core_link_enable_stream( struct dc_state *state, @@ -4202,13 +4091,12 @@ void core_link_enable_stream( struct dc_link *link = stream->sink->link; enum dc_status status; struct link_encoder *link_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; if (is_dp_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; -#endif + DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); if (!IS_DIAG_DC(dc->ctx->dce_environment) && @@ -4221,12 +4109,8 @@ void core_link_enable_stream( link_enc = stream->link->link_enc; ASSERT(link_enc); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (!dc_is_virtual_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx)) { -#else - if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) { -#endif if (link_enc) link_enc->funcs->setup( link_enc, @@ -4237,7 +4121,6 @@ void core_link_enable_stream( stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->set_stream_attribute( pipe_ctx->stream_res.hpo_dp_stream_enc, @@ -4255,14 +4138,6 @@ void core_link_enable_stream( stream->use_vsc_sdp_for_colorimetry, stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); } -#else - pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( - pipe_ctx->stream_res.stream_enc, - &stream->timing, - stream->output_color_space, - stream->use_vsc_sdp_for_colorimetry, - stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); -#endif if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); @@ -4276,10 +4151,8 @@ void core_link_enable_stream( pipe_ctx->stream->link->link_state_valid = true; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (pipe_ctx->stream_res.tg->funcs->set_out_mux) pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest); -#endif if (dc_is_dvi_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute( @@ -4299,11 +4172,9 @@ void core_link_enable_stream( pipe_ctx->stream->apply_edp_fast_boot_optimization = false; -#if defined(CONFIG_DRM_AMD_DC_DCN) // Enable VPG before building infoframe if (vpg && vpg->funcs->vpg_poweron) vpg->funcs->vpg_poweron(vpg); -#endif resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); @@ -4389,12 +4260,8 @@ void core_link_enable_stream( * as a workaround for the incorrect value being applied * from transmitter control. */ -#if defined(CONFIG_DRM_AMD_DC_DCN) if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) || is_dp_128b_132b_signal(pipe_ctx))) -#else - if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) -#endif if (link_enc) link_enc->funcs->setup( link_enc, @@ -4413,11 +4280,9 @@ void core_link_enable_stream( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) dc_link_allocate_mst_payload(pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN) else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && is_dp_128b_132b_signal(pipe_ctx)) dc_link_update_sst_payload(pipe_ctx, true); -#endif dc->hwss.unblank_stream(pipe_ctx, &pipe_ctx->stream->link->cur_link_settings); @@ -4434,11 +4299,9 @@ void core_link_enable_stream( dc->hwss.enable_audio_stream(pipe_ctx); } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { fpga_dp_hpo_enable_link_and_stream(state, pipe_ctx); } -#endif if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) dp_set_dsc_enable(pipe_ctx, true); @@ -4455,12 +4318,10 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; if (is_dp_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; -#endif if (!IS_DIAG_DC(dc->ctx->dce_environment) && dc_is_virtual_signal(pipe_ctx->stream->signal)) @@ -4480,11 +4341,9 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN) else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && is_dp_128b_132b_signal(pipe_ctx)) dc_link_update_sst_payload(pipe_ctx, false); -#endif if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { struct ext_hdmi_settings settings = {0}; @@ -4511,7 +4370,6 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) } } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && !is_dp_128b_132b_signal(pipe_ctx)) { @@ -4528,27 +4386,18 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) dc->hwss.disable_stream(pipe_ctx); disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal); } -#else - disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal); - - dc->hwss.disable_stream(pipe_ctx); -#endif if (pipe_ctx->stream->timing.flags.DSC) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_set_dsc_enable(pipe_ctx, false); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { if (pipe_ctx->stream_res.tg->funcs->set_out_mux) pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); } -#endif -#if defined(CONFIG_DRM_AMD_DC_DCN) if (vpg && vpg->funcs->vpg_powerdown) vpg->funcs->vpg_powerdown(vpg); -#endif } void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) @@ -4687,11 +4536,9 @@ void dc_link_set_preferred_training_settings(struct dc *dc, if (link_setting != NULL) { link->preferred_link_setting = *link_setting; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(link_setting) == DP_128b_132b_ENCODING) /* TODO: add dc update for acquiring link res */ skip_immediate_retrain = true; -#endif } else { link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; @@ -4733,7 +4580,6 @@ uint32_t dc_link_bandwidth_kbps( const struct dc_link *link, const struct dc_link_settings *link_setting) { -#if defined(CONFIG_DRM_AMD_DC_DCN) uint32_t total_data_bw_efficiency_x10000 = 0; uint32_t link_rate_per_lane_kbps = 0; @@ -4764,40 +4610,6 @@ uint32_t dc_link_bandwidth_kbps( /* overall effective link bandwidth = link rate per lane * lane count * total data bandwidth efficiency */ return link_rate_per_lane_kbps * link_setting->lane_count / 10000 * total_data_bw_efficiency_x10000; -#else - uint32_t link_bw_kbps = - link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; /* bytes per sec */ - - link_bw_kbps *= 8; /* 8 bits per byte*/ - link_bw_kbps *= link_setting->lane_count; - - if (dc_link_should_enable_fec(link)) { - /* Account for FEC overhead. - * We have to do it based on caps, - * and not based on FEC being set ready, - * because FEC is set ready too late in - * the process to correctly be picked up - * by mode enumeration. - * - * There's enough zeros at the end of 'kbps' - * that make the below operation 100% precise - * for our purposes. - * 'long long' makes it work even for HDMI 2.1 - * max bandwidth (and much, much bigger bandwidths - * than that, actually). - * - * NOTE: Reducing link BW by 3% may not be precise - * because it may be a stream BT that increases by 3%, and so - * 1/1.03 = 0.970873 factor should have been used instead, - * but the difference is minimal and is in a safe direction, - * which all works well around potential ambiguity of DP 1.4a spec. - */ - long long fec_link_bw_kbps = link_bw_kbps * 970LL; - link_bw_kbps = (uint32_t)(div64_s64(fec_link_bw_kbps, 1000LL)); - } - return link_bw_kbps; - -#endif } const struct dc_link_settings *dc_link_get_link_cap( @@ -4953,7 +4765,6 @@ const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link) */ void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) { -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_link *link; uint8_t i; uint32_t hpo_dp_recycle_map = 0; @@ -4973,7 +4784,6 @@ void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) } *map |= (hpo_dp_recycle_map << LINK_RES_HPO_DP_REC_MAP__SHIFT); } -#endif } /** @@ -4996,7 +4806,6 @@ void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) */ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map) { -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_link *link; uint8_t i; unsigned int available_hpo_dp_count; @@ -5034,5 +4843,4 @@ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map) } } } -#endif } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 5122c1de4492..68f9e099beae 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -62,7 +62,6 @@ enum { POST_LT_ADJ_REQ_TIMEOUT = 200 }; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dp_lt_fallback_entry { enum dc_lane_count lane_count; enum dc_link_rate link_rate; @@ -97,7 +96,6 @@ static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = { {LANE_COUNT_ONE, LINK_RATE_HIGH}, {LANE_COUNT_ONE, LINK_RATE_LOW}, }; -#endif static bool decide_fallback_link_setting( struct dc_link *link, @@ -114,7 +112,7 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link, { union training_aux_rd_interval training_rd_interval; uint32_t wait_in_micro_secs = 100; -#if defined(CONFIG_DRM_AMD_DC_DCN) + memset(&training_rd_interval, 0, sizeof(training_rd_interval)); if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING && link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { @@ -126,15 +124,7 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link, if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; } -#else - core_link_read_dpcd( - link, - DP_TRAINING_AUX_RD_INTERVAL, - (uint8_t *)&training_rd_interval, - sizeof(training_rd_interval)); - if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) - wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; -#endif + return wait_in_micro_secs; } @@ -142,7 +132,6 @@ static uint32_t get_eq_training_aux_rd_interval( struct dc_link *link, const struct dc_link_settings *link_settings) { -#if defined(CONFIG_DRM_AMD_DC_DCN) union training_aux_rd_interval training_rd_interval; memset(&training_rd_interval, 0, sizeof(training_rd_interval)); @@ -171,41 +160,16 @@ static uint32_t get_eq_training_aux_rd_interval( case 6: return 64000; default: return 400; } -#else - union training_aux_rd_interval training_rd_interval; - uint32_t wait_in_micro_secs = 400; - - memset(&training_rd_interval, 0, sizeof(training_rd_interval)); - /* overwrite the delay if rev > 1.1*/ - if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { - /* DP 1.2 or later - retrieve delay through - * "DPCD_ADDR_TRAINING_AUX_RD_INTERVAL" register */ - core_link_read_dpcd( - link, - DP_TRAINING_AUX_RD_INTERVAL, - (uint8_t *)&training_rd_interval, - sizeof(training_rd_interval)); - - if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) - wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; - } - - return wait_in_micro_secs; -#endif } void dp_wait_for_training_aux_rd_interval( struct dc_link *link, uint32_t wait_in_micro_secs) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (wait_in_micro_secs > 1000) msleep(wait_in_micro_secs/1000); else udelay(wait_in_micro_secs); -#else - udelay(wait_in_micro_secs); -#endif DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n", __func__, @@ -233,7 +197,6 @@ enum dpcd_training_patterns case DP_TRAINING_PATTERN_SEQUENCE_4: dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case DP_128b_132b_TPS1: dpcd_tr_pattern = DPCD_128b_132b_TPS1; break; @@ -243,7 +206,6 @@ enum dpcd_training_patterns case DP_128b_132b_TPS2_CDS: dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS; break; -#endif case DP_TRAINING_PATTERN_VIDEOIDLE: dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE; break; @@ -286,10 +248,8 @@ static enum dc_dp_training_pattern decide_cr_training_pattern( case DP_8b_10b_ENCODING: default: return DP_TRAINING_PATTERN_SEQUENCE_1; -#if defined(CONFIG_DRM_AMD_DC_DCN) case DP_128b_132b_ENCODING: return DP_128b_132b_TPS1; -#endif } } @@ -297,7 +257,6 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li const struct dc_link_settings *link_settings) { struct link_encoder *link_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct encoder_feature_support *enc_caps; struct dpcd_caps *rx_caps = &link->dpcd_caps; enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2; @@ -332,41 +291,8 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li break; } return pattern; -#else - enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2; - struct encoder_feature_support *features; - struct dpcd_caps *dpcd_caps = &link->dpcd_caps; - - /* Access link encoder capability based on whether it is statically - * or dynamically assigned to a link. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - else - link_enc = link->link_enc; - ASSERT(link_enc); - features = &link_enc->features; - - if (features->flags.bits.IS_TPS3_CAPABLE) - highest_tp = DP_TRAINING_PATTERN_SEQUENCE_3; - - if (features->flags.bits.IS_TPS4_CAPABLE) - highest_tp = DP_TRAINING_PATTERN_SEQUENCE_4; - - if (dpcd_caps->max_down_spread.bits.TPS4_SUPPORTED && - highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_4) - return DP_TRAINING_PATTERN_SEQUENCE_4; - - if (dpcd_caps->max_ln_count.bits.TPS3_SUPPORTED && - highest_tp >= DP_TRAINING_PATTERN_SEQUENCE_3) - return DP_TRAINING_PATTERN_SEQUENCE_3; - - return DP_TRAINING_PATTERN_SEQUENCE_2; -#endif } -#if defined(CONFIG_DRM_AMD_DC_DCN) static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings) { uint8_t link_rate = 0; @@ -394,7 +320,6 @@ static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings) return link_rate; } -#endif static void vendor_specific_lttpr_wa_one_start(struct dc_link *link) { @@ -537,10 +462,8 @@ static void vendor_specific_lttpr_wa_four( const uint8_t offset = dp_convert_to_count( link->dpcd_caps.lttpr_caps.phy_repeater_cnt); uint32_t vendor_lttpr_write_address = 0xF004F; -#if defined(CONFIG_DRM_AMD_DC_DP2_0) uint8_t sink_status = 0; uint8_t i; -#endif if (offset != 0xFF) vendor_lttpr_write_address += @@ -566,7 +489,6 @@ static void vendor_specific_lttpr_wa_four( sizeof(vendor_lttpr_write_data_two)); } -#if defined(CONFIG_DRM_AMD_DC_DP2_0) /* poll for intra-hop disable */ for (i = 0; i < 10; i++) { if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) && @@ -574,7 +496,6 @@ static void vendor_specific_lttpr_wa_four( break; udelay(1000); } -#endif } static void vendor_specific_lttpr_wa_five( @@ -662,11 +583,7 @@ enum dc_status dpcd_set_link_settings( status = core_link_write_dpcd(link, DP_LINK_RATE_SET, <_settings->link_settings.link_rate_set, 1); } else { -#if defined(CONFIG_DRM_AMD_DC_DCN) rate = get_dpcd_link_rate(<_settings->link_settings); -#else - rate = (uint8_t) (lt_settings->link_settings.link_rate); -#endif if (link->dc->debug.apply_vendor_specific_lttpr_wa && (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && link->lttpr_mode == LTTPR_MODE_TRANSPARENT) @@ -717,10 +634,8 @@ uint8_t dc_dp_initialize_scrambling_data_symbols( disable_scrabled_data_symbols = 1; break; case DP_TRAINING_PATTERN_SEQUENCE_4: -#if defined(CONFIG_DRM_AMD_DC_DCN) case DP_128b_132b_TPS1: case DP_128b_132b_TPS2: -#endif disable_scrabled_data_symbols = 0; break; default: @@ -791,7 +706,6 @@ static void dpcd_set_lt_pattern_and_lane_settings( size_in_bytes); if (is_repeater(link, offset)) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" @@ -802,7 +716,6 @@ static void dpcd_set_lt_pattern_and_lane_settings( lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE); else if (dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) -#endif DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, @@ -813,7 +726,6 @@ static void dpcd_set_lt_pattern_and_lane_settings( lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); } else { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n", @@ -822,14 +734,13 @@ static void dpcd_set_lt_pattern_and_lane_settings( lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE); else if (dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) -#endif - DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", - __func__, - dpcd_base_lt_offset, - lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET, - lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET, - lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, - lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); + DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", + __func__, + dpcd_base_lt_offset, + lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET, + lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET, + lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED, + lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); } if (edp_workaround) { /* for eDP write in 2 parts because the 5-byte burst is @@ -847,7 +758,6 @@ static void dpcd_set_lt_pattern_and_lane_settings( (uint8_t *)(lt_settings->dpcd_lane_settings), size_in_bytes); -#if defined(CONFIG_DRM_AMD_DC_DCN) } else if (dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) { core_link_write_dpcd( @@ -855,10 +765,9 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_base_lt_offset, dpcd_lt_buffer, sizeof(dpcd_lt_buffer)); -#endif - } else + } else /* write it all in (1 + number-of-lanes)-byte burst*/ - core_link_write_dpcd( + core_link_write_dpcd( link, dpcd_base_lt_offset, dpcd_lt_buffer, @@ -925,13 +834,11 @@ void dp_hw_to_dpcd_lane_settings( (hw_lane_settings[lane].PRE_EMPHASIS == PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); } -#if defined(CONFIG_DRM_AMD_DC_DCN) else if (dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) { dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE = hw_lane_settings[lane].FFE_PRESET.settings.level; } -#endif } } @@ -953,13 +860,11 @@ void dp_decide_lane_settings( (enum dc_pre_emphasis)(ln_adjust[lane].bits. PRE_EMPHASIS_LANE); } -#if defined(CONFIG_DRM_AMD_DC_DCN) else if (dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) { hw_lane_settings[lane].FFE_PRESET.raw = ln_adjust[lane].tx_ffe.PRESET_VALUE; } -#endif } dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings); @@ -1010,9 +915,7 @@ static void maximize_lane_settings(const struct link_training_settings *lt_setti max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING; max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS; -#if defined(CONFIG_DRM_AMD_DC_DCN) max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET; -#endif /* Determine what the maximum of the requested settings are*/ for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) { @@ -1021,12 +924,10 @@ static void maximize_lane_settings(const struct link_training_settings *lt_setti if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS) max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (lane_settings[lane].FFE_PRESET.settings.level > max_requested.FFE_PRESET.settings.level) max_requested.FFE_PRESET.settings.level = lane_settings[lane].FFE_PRESET.settings.level; -#endif } /* make sure the requested settings are @@ -1036,10 +937,8 @@ static void maximize_lane_settings(const struct link_training_settings *lt_setti if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL) max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL) max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL; -#endif /* make sure the pre-emphasis matches the voltage swing*/ if (max_requested.PRE_EMPHASIS > @@ -1052,9 +951,7 @@ static void maximize_lane_settings(const struct link_training_settings *lt_setti for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING; lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS; -#if defined(CONFIG_DRM_AMD_DC_DCN) lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET; -#endif } } @@ -1065,9 +962,7 @@ static void override_lane_settings(const struct link_training_settings *lt_setti if (lt_settings->voltage_swing == NULL && lt_settings->pre_emphasis == NULL && -#if defined(CONFIG_DRM_AMD_DC_DCN) lt_settings->ffe_preset == NULL && -#endif lt_settings->post_cursor2 == NULL) return; @@ -1079,10 +974,8 @@ static void override_lane_settings(const struct link_training_settings *lt_setti lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis; if (lt_settings->post_cursor2) lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (lt_settings->ffe_preset) lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset; -#endif } } @@ -1186,7 +1079,6 @@ enum dc_status dpcd_set_lane_settings( link_training_setting->link_settings.lane_count); if (is_repeater(link, offset)) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_training_setting->link_settings) == DP_128b_132b_ENCODING) DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" @@ -1197,7 +1089,6 @@ enum dc_status dpcd_set_lane_settings( link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE); else if (dp_get_link_encoding_format(&link_training_setting->link_settings) == DP_8b_10b_ENCODING) -#endif DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n" " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, @@ -1209,7 +1100,6 @@ enum dc_status dpcd_set_lane_settings( link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED); } else { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_training_setting->link_settings) == DP_128b_132b_ENCODING) DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n", @@ -1218,7 +1108,6 @@ enum dc_status dpcd_set_lane_settings( link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE); else if (dp_get_link_encoding_format(&link_training_setting->link_settings) == DP_8b_10b_ENCODING) -#endif DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, lane0_set_address, @@ -1354,14 +1243,12 @@ uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval case 0x04: aux_rd_interval_us = 16000; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case 0x05: aux_rd_interval_us = 32000; break; case 0x06: aux_rd_interval_us = 64000; break; -#endif default: break; } @@ -1402,13 +1289,8 @@ static enum link_training_result perform_channel_equalization_sequence( /* Note: also check that TPS4 is a supported feature*/ tr_pattern = lt_settings->pattern_for_eq; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_repeater(link, offset) && dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; -#else - if (is_repeater(link, offset)) - tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; -#endif dp_set_hw_training_pattern(link, link_res, tr_pattern, offset); @@ -1579,15 +1461,10 @@ static enum link_training_result perform_clock_recovery_sequence( return LINK_TRAINING_SUCCESS; /* 6. max VS reached*/ -#if defined(CONFIG_DRM_AMD_DC_DCN) if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) && dp_is_max_vs_reached(lt_settings)) break; -#else - if (dp_is_max_vs_reached(lt_settings)) - break; -#endif /* 7. same lane settings*/ /* Note: settings are the same for all lanes, @@ -1596,12 +1473,10 @@ static enum link_training_result perform_clock_recovery_sequence( lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET == dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE) retries_cr++; -#if defined(CONFIG_DRM_AMD_DC_DCN) else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) && lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE == dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE) retries_cr++; -#endif else retries_cr = 0; @@ -1639,11 +1514,7 @@ static inline enum link_training_result dp_transition_to_video_idle( * TPS4 must be used instead of POST_LT_ADJ_REQ. */ if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || -#if defined(CONFIG_DRM_AMD_DC_DCN) lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) { -#else - lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) { -#endif /* delay 5ms after Main Link output idle pattern and then check * DPCD 0202h. */ @@ -1742,7 +1613,6 @@ static inline void decide_8b_10b_training_settings( dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); } -#if defined(CONFIG_DRM_AMD_DC_DCN) static inline void decide_128b_132b_training_settings(struct dc_link *link, const struct dc_link_settings *link_settings, struct link_training_settings *lt_settings) @@ -1769,7 +1639,6 @@ static inline void decide_128b_132b_training_settings(struct dc_link *link, dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); } -#endif void dp_decide_training_settings( struct dc_link *link, @@ -1778,10 +1647,8 @@ void dp_decide_training_settings( { if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) decide_8b_10b_training_settings(link, link_settings, lt_settings); -#if defined(CONFIG_DRM_AMD_DC_DCN) else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) decide_128b_132b_training_settings(link, link_settings, lt_settings); -#endif } static void override_training_settings( @@ -1804,10 +1671,8 @@ static void override_training_settings( lt_settings->pre_emphasis = overrides->pre_emphasis; if (overrides->post_cursor2 != NULL) lt_settings->post_cursor2 = overrides->post_cursor2; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (overrides->ffe_preset != NULL) lt_settings->ffe_preset = overrides->ffe_preset; -#endif /* Override HW lane settings with BIOS forced values if present */ if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { @@ -2011,7 +1876,6 @@ static void print_status_message( case LINK_RATE_HIGH3: link_rate = "HBR3"; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case LINK_RATE_UHBR10: link_rate = "UHBR10"; break; @@ -2021,7 +1885,6 @@ static void print_status_message( case LINK_RATE_UHBR20: link_rate = "UHBR20"; break; -#endif default: break; } @@ -2051,7 +1914,6 @@ static void print_status_message( case LINK_TRAINING_LINK_LOSS: lt_result = "Link loss"; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case DP_128b_132b_LT_FAILED: lt_result = "LT_FAILED received"; break; @@ -2064,7 +1926,6 @@ static void print_status_message( case DP_128b_132b_CDS_DONE_TIMEOUT: lt_result = "CDS timeout"; break; -#endif default: break; } @@ -2084,9 +1945,9 @@ static void print_status_message( } /* Connectivity log: link training */ -#if defined(CONFIG_DRM_AMD_DC_DCN) + /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */ -#endif + CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s", link_rate, lt_settings->link_settings.lane_count, @@ -2174,15 +2035,12 @@ enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_train static void dpcd_exit_training_mode(struct dc_link *link) { -#if defined(CONFIG_DRM_AMD_DC_DCN) uint8_t sink_status = 0; uint8_t i; -#endif /* clear training pattern set */ dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE); -#if defined(CONFIG_DRM_AMD_DC_DCN) /* poll for intra-hop disable */ for (i = 0; i < 10; i++) { if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) && @@ -2190,7 +2048,6 @@ static void dpcd_exit_training_mode(struct dc_link *link) break; udelay(1000); } -#endif } enum dc_status dpcd_configure_channel_coding(struct dc_link *link, @@ -2214,7 +2071,6 @@ enum dc_status dpcd_configure_channel_coding(struct dc_link *link, return status; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link, uint32_t *interval_in_us) { @@ -2345,7 +2201,6 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence( return status; } -#endif static enum link_training_result dp_perform_8b_10b_link_training( struct dc_link *link, @@ -2406,7 +2261,6 @@ static enum link_training_result dp_perform_8b_10b_link_training( return status; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static enum link_training_result dp_perform_128b_132b_link_training( struct dc_link *link, const struct link_resource *link_res, @@ -2434,7 +2288,6 @@ static enum link_training_result dp_perform_128b_132b_link_training( return result; } -#endif static enum link_training_result dc_link_dp_perform_fixed_vs_pe_training_sequence( struct dc_link *link, @@ -2511,11 +2364,7 @@ static enum link_training_result dc_link_dp_perform_fixed_vs_pe_training_sequenc core_link_write_dpcd(link, DP_LANE_COUNT_SET, &lane_count_set.raw, 1); -#if defined(CONFIG_DRM_AMD_DC_DCN) rate = get_dpcd_link_rate(<_settings->link_settings); -#else - rate = (uint8_t) (lt_settings->link_settings.link_rate); -#endif /* Vendor specific: Toggle link rate */ toggle_rate = (rate == 0x6) ? 0xA : 0x6; @@ -2816,10 +2665,8 @@ enum link_training_result dc_link_dp_perform_link_training( status = dc_link_dp_perform_fixed_vs_pe_training_sequence(link, link_res, <_settings); else if (encoding == DP_8b_10b_ENCODING) status = dp_perform_8b_10b_link_training(link, link_res, <_settings); -#if defined(CONFIG_DRM_AMD_DC_DCN) else if (encoding == DP_128b_132b_ENCODING) status = dp_perform_128b_132b_link_training(link, link_res, <_settings); -#endif else ASSERT(0); @@ -3071,14 +2918,10 @@ enum link_training_result dc_link_dp_sync_lt_attempt( dp_cs_id, link_settings); /* Set FEC enable */ -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { -#endif fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable; dp_set_fec_ready(link, NULL, fec_enable); -#if defined(CONFIG_DRM_AMD_DC_DCN) } -#endif if (lt_overrides->alternate_scrambler_reset) { if (*lt_overrides->alternate_scrambler_reset) @@ -3121,13 +2964,9 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) * Still shouldn't turn off dp_receiver (DPCD:600h) */ if (link_down == true) { -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_link_settings link_settings = link->cur_link_settings; -#endif dp_disable_link_phy(link, NULL, link->connector_signal); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) -#endif dp_set_fec_ready(link, NULL, false); } @@ -3135,7 +2974,6 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) return true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) { enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; @@ -3149,7 +2987,6 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) return lttpr_max_link_rate; } -#endif bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) { @@ -3555,14 +3392,12 @@ static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) { switch (link_rate) { -#if defined(CONFIG_DRM_AMD_DC_DCN) case LINK_RATE_UHBR20: return LINK_RATE_UHBR13_5; case LINK_RATE_UHBR13_5: return LINK_RATE_UHBR10; case LINK_RATE_UHBR10: return LINK_RATE_HIGH3; -#endif case LINK_RATE_HIGH3: return LINK_RATE_HIGH2; case LINK_RATE_HIGH2: @@ -3597,20 +3432,17 @@ static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) return LINK_RATE_HIGH2; case LINK_RATE_HIGH2: return LINK_RATE_HIGH3; -#if defined(CONFIG_DRM_AMD_DC_DCN) case LINK_RATE_HIGH3: return LINK_RATE_UHBR10; case LINK_RATE_UHBR10: return LINK_RATE_UHBR13_5; case LINK_RATE_UHBR13_5: return LINK_RATE_UHBR20; -#endif default: return LINK_RATE_UNKNOWN; } } -#if defined(CONFIG_DRM_AMD_DC_DCN) static bool decide_fallback_link_setting_max_bw_policy( const struct dc_link_settings *max, struct dc_link_settings *cur) @@ -3644,7 +3476,6 @@ static bool decide_fallback_link_setting_max_bw_policy( return found; } -#endif /* * function: set link rate and lane count fallback based @@ -3662,12 +3493,10 @@ static bool decide_fallback_link_setting( { if (!current_link_setting) return false; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING || link->dc->debug.force_dp2_lt_fallback_method) return decide_fallback_link_setting_max_bw_policy(&initial_link_settings, current_link_setting); -#endif switch (training_result) { case LINK_TRAINING_CR_FAIL_LANE0: @@ -4205,15 +4034,9 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) union phy_test_pattern dpcd_test_pattern; union lane_adjust dpcd_lane_adjustment[2]; unsigned char dpcd_post_cursor_2_adjustment = 0; -#if defined(CONFIG_DRM_AMD_DC_DCN) unsigned char test_pattern_buffer[ (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 - DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0}; -#else - unsigned char test_pattern_buffer[ - (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; -#endif unsigned int test_pattern_size = 0; enum dp_test_pattern test_pattern; union lane_adjust dpcd_lane_adjust; @@ -4284,7 +4107,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) case PHY_TEST_PATTERN_CP2520_3: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case PHY_TEST_PATTERN_128b_132b_TPS1: test_pattern = DP_TEST_PATTERN_128b_132b_TPS1; break; @@ -4312,7 +4134,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) case PHY_TEST_PATTERN_SQUARE_PULSE: test_pattern = DP_TEST_PATTERN_SQUARE_PULSE; break; -#endif default: test_pattern = DP_TEST_PATTERN_VIDEO_MODE; break; @@ -4328,7 +4149,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern_size); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) { test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) core_link_read_dpcd( @@ -4347,7 +4167,6 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern_buffer, test_pattern_size); } -#endif /* prepare link training settings */ link_training_settings.link_settings = link->cur_link_settings; @@ -4368,14 +4187,11 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) link_training_settings.hw_lane_settings[lane].POST_CURSOR2 = (enum dc_post_cursor2) ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); - } -#if defined(CONFIG_DRM_AMD_DC_DCN) - else if (dp_get_link_encoding_format(&link->cur_link_settings) == + } else if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) { link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw = dpcd_lane_adjust.tx_ffe.PRESET_VALUE; } -#endif } dp_hw_to_dpcd_lane_settings(&link_training_settings, @@ -5072,7 +4888,6 @@ static void get_active_converter_info( dp_hw_fw_revision.ieee_fw_rev, sizeof(dp_hw_fw_revision.ieee_fw_rev)); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) { union dp_dfp_cap_ext dfp_cap_ext; @@ -5108,7 +4923,6 @@ static void get_active_converter_info( DC_LOG_DP2("\tdfp_cap_ext.max_video_h_active_width = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width); DC_LOG_DP2("\tdfp_cap_ext.max_video_v_active_height = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height); } -#endif } static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data, @@ -5168,12 +4982,8 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) bool dp_retrieve_lttpr_cap(struct dc_link *link) { -#if defined(CONFIG_DRM_AMD_DC_DCN) uint8_t lttpr_dpcd_data[8]; bool allow_lttpr_non_transparent_mode = 0; -#else - uint8_t lttpr_dpcd_data[6]; -#endif bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable; bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; enum dc_status status = DC_ERROR_UNEXPECTED; @@ -5181,7 +4991,6 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); -#if defined(CONFIG_DRM_AMD_DC_DCN) if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 && link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) { allow_lttpr_non_transparent_mode = 1; @@ -5189,7 +4998,6 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { allow_lttpr_non_transparent_mode = 1; } -#endif /* * Logic to determine LTTPR mode @@ -5198,21 +5006,12 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) if (vbios_lttpr_enable && vbios_lttpr_interop) link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; else if (!vbios_lttpr_enable && vbios_lttpr_interop) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (allow_lttpr_non_transparent_mode) -#else - if (link->dc->config.allow_lttpr_non_transparent_mode) -#endif link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; else link->lttpr_mode = LTTPR_MODE_TRANSPARENT; } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support) -#else - if (!link->dc->config.allow_lttpr_non_transparent_mode - || !link->dc->caps.extended_aux_timeout_support) -#endif link->lttpr_mode = LTTPR_MODE_NON_LTTPR; else link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; @@ -5262,7 +5061,6 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; -#if defined(CONFIG_DRM_AMD_DC_DCN) link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; @@ -5270,7 +5068,6 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = lttpr_dpcd_data[DP_PHY_REPEATER_128b_132b_RATES - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; -#endif /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && @@ -5528,7 +5325,6 @@ static bool retrieve_link_cap(struct dc_link *link) DP_DSC_SUPPORT, link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw)); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) { status = core_link_read_dpcd( link, @@ -5543,19 +5339,12 @@ static bool retrieve_link_cap(struct dc_link *link) DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x", link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH); } -#else - status = core_link_read_dpcd( - link, - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, - link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, - sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); -#endif /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode * only if required. */ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) +#if defined(CONFIG_DRM_AMD_DC_DCN) !link->dc->debug.dpia_debug.bits.disable_force_tbt3_work_around && #endif link->dpcd_caps.is_branch_dev && @@ -5577,7 +5366,6 @@ static bool retrieve_link_cap(struct dc_link *link) if (!dpcd_read_sink_ext_caps(link)) link->dpcd_sink_ext_caps.raw = 0; -#if defined(CONFIG_DRM_AMD_DC_DCN) link->dpcd_caps.channel_coding_cap.raw = dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_CAP - DP_DPCD_REV]; if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { @@ -5624,7 +5412,6 @@ static bool retrieve_link_cap(struct dc_link *link) if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE) DC_LOG_DP2("\tFEC aggregated error counters are supported"); } -#endif /* Connectivity log: detection */ CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); @@ -6096,7 +5883,6 @@ bool dc_link_dp_set_test_pattern( case DP_TEST_PATTERN_CP2520_3: pattern = PHY_TEST_PATTERN_CP2520_3; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case DP_TEST_PATTERN_128b_132b_TPS1: pattern = PHY_TEST_PATTERN_128b_132b_TPS1; break; @@ -6124,7 +5910,6 @@ bool dc_link_dp_set_test_pattern( case DP_TEST_PATTERN_SQUARE_PULSE: pattern = PHY_TEST_PATTERN_SQUARE_PULSE; break; -#endif default: return false; } @@ -6727,15 +6512,12 @@ enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings if ((link_settings->link_rate >= LINK_RATE_LOW) && (link_settings->link_rate <= LINK_RATE_HIGH3)) return DP_8b_10b_ENCODING; -#if defined(CONFIG_DRM_AMD_DC_DCN) else if ((link_settings->link_rate >= LINK_RATE_UHBR10) && (link_settings->link_rate <= LINK_RATE_UHBR20)) return DP_128b_132b_ENCODING; -#endif return DP_UNKNOWN_ENCODING; } -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link) { struct dc_link_settings link_settings = {0}; @@ -6952,7 +6734,6 @@ bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx) pipe_ctx->link_res.hpo_dp_link_enc && dc_is_dp_signal(pipe_ctx->stream->signal)); } -#endif void edp_panel_backlight_power_on(struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index e2409c14df34..c84822cd7e53 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -120,49 +120,32 @@ void dp_enable_link_phy( link->cur_link_settings = *link_settings; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { /* TODO - DP2.0 HW: notify link rate change here */ } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { if (dc->clk_mgr->funcs->notify_link_rate_change) dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); } -#else - if (dc->clk_mgr->funcs->notify_link_rate_change) - dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); -#endif + if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { enable_dp_hpo_output(link, link_res, link_settings); } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { if (dc_is_dp_sst_signal(signal)) { link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); + link_enc, + link_settings, + clock_source); } else { link_enc->funcs->enable_dp_mst_output( - link_enc, - link_settings, - clock_source); + link_enc, + link_settings, + clock_source); } } -#else - if (dc_is_dp_sst_signal(signal)) { - link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); - } else { - link_enc->funcs->enable_dp_mst_output( - link_enc, - link_settings, - clock_source); - } -#endif + if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); @@ -242,9 +225,7 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_ { struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_link_encoder *hpo_link_enc = link_res->hpo_dp_link_enc; -#endif struct link_encoder *link_enc; /* Link should always be assigned encoder when en-/disabling. */ @@ -260,28 +241,22 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_ if (signal == SIGNAL_TYPE_EDP) { if (link->dc->hwss.edp_backlight_control) link->dc->hwss.edp_backlight_control(link, false); -#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) disable_dp_hpo_output(link, link_res, signal); else link_enc->funcs->disable_output(link_enc, signal); -#else - link_enc->funcs->disable_output(link_enc, signal); -#endif link->dc->hwss.edp_power_control(link, false); } else { if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING && hpo_link_enc) disable_dp_hpo_output(link, link_res, signal); else link_enc->funcs->disable_output(link_enc, signal); -#else - link_enc->funcs->disable_output(link_enc, signal); -#endif + if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); } @@ -330,14 +305,12 @@ bool dp_set_hw_training_pattern( case DP_TRAINING_PATTERN_SEQUENCE_4: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; break; -#if defined(CONFIG_DRM_AMD_DC_DCN) case DP_128b_132b_TPS1: test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE; break; case DP_128b_132b_TPS2: test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE; break; -#endif default: break; } @@ -347,10 +320,8 @@ bool dp_set_hw_training_pattern( return true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) #define DC_LOGGER \ link->ctx->logger -#endif void dp_set_hw_lane_settings( struct dc_link *link, const struct link_resource *link_res, @@ -363,7 +334,6 @@ void dp_set_hw_lane_settings( return; /* call Encoder to set lane settings */ -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dp_get_link_encoding_format(&link_settings->link_settings) == DP_128b_132b_ENCODING) { link_res->hpo_dp_link_enc->funcs->set_ffe( @@ -374,9 +344,6 @@ void dp_set_hw_lane_settings( == DP_8b_10b_ENCODING) { encoder->funcs->dp_set_lane_settings(encoder, link_settings); } -#else - encoder->funcs->dp_set_lane_settings(encoder, link_settings); -#endif memmove(link->cur_lane_setting, link_settings->lane_settings, sizeof(link->cur_lane_setting)); @@ -391,9 +358,7 @@ void dp_set_hw_test_pattern( { struct encoder_set_dp_phy_pattern_param pattern_param = {0}; struct link_encoder *encoder; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dp_link_encoding link_encoding_format = dp_get_link_encoding_format(&link->cur_link_settings); -#endif /* Access link encoder based on whether it is statically * or dynamically assigned to a link. @@ -409,7 +374,6 @@ void dp_set_hw_test_pattern( pattern_param.custom_pattern_size = custom_pattern_size; pattern_param.dp_panel_mode = dp_get_panel_mode(link); -#if defined(CONFIG_DRM_AMD_DC_DCN) switch (link_encoding_format) { case DP_128b_132b_ENCODING: link_res->hpo_dp_link_enc->funcs->set_link_test_pattern( @@ -423,14 +387,10 @@ void dp_set_hw_test_pattern( DC_LOG_ERROR("%s: Unknown link encoding format.", __func__); break; } -#else - encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); -#endif + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); } -#if defined(CONFIG_DRM_AMD_DC_DCN) #undef DC_LOGGER -#endif void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, @@ -579,12 +539,8 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; /* Enable DSC in encoder */ -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && !is_dp_128b_132b_signal(pipe_ctx)) { -#else - if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { -#endif DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); dsc_optc_config_log(dsc, &dsc_optc_cfg); pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, @@ -610,17 +566,13 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) /* disable DSC in stream encoder */ if (dc_is_dp_signal(stream->signal)) { - -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, false, NULL, true); - else -#endif - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( pipe_ctx->stream_res.stream_enc, OPTC_DSC_DISABLED, 0, 0); @@ -696,7 +648,6 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_u dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); if (dc_is_dp_signal(stream->signal)) { DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, @@ -704,7 +655,6 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_u &dsc_packed_pps[0], immediate_update); else -#endif pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc, true, @@ -714,7 +664,6 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_u } else { /* disable DSC PPS in stream encoder */ if (dc_is_dp_signal(stream->signal)) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, @@ -722,7 +671,6 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_u NULL, true); else -#endif pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc, false, NULL, true); } @@ -746,7 +694,6 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) return true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) #undef DC_LOGGER #define DC_LOGGER \ link->ctx->logger @@ -898,4 +845,3 @@ void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) } #undef DC_LOGGER -#endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b34bf59cf54b..3aa6d347d73c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -356,7 +356,6 @@ bool resource_construct( } } -#if defined(CONFIG_DRM_AMD_DC_DCN) pool->hpo_dp_stream_enc_count = 0; if (create_funcs->create_hpo_dp_stream_encoder) { for (i = 0; i < caps->num_hpo_dp_stream_encoder; i++) { @@ -377,7 +376,6 @@ bool resource_construct( pool->hpo_dp_link_enc_count++; } } -#endif #if defined(CONFIG_DRM_AMD_DC_DCN) for (i = 0; i < caps->num_mpc_3dlut; i++) { @@ -1713,7 +1711,6 @@ static void update_stream_engine_usage( } } -#if defined(CONFIG_DRM_AMD_DC_DCN) static void update_hpo_dp_stream_engine_usage( struct resource_context *res_ctx, const struct resource_pool *pool, @@ -1815,7 +1812,6 @@ static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx, pipe_ctx->link_res.hpo_dp_link_enc = NULL; } } -#endif /* TODO: release audio object */ void update_audio_usage( @@ -1861,7 +1857,6 @@ static int acquire_first_free_pipe( return -1; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link( struct resource_context *res_ctx, const struct resource_pool *pool, @@ -1879,7 +1874,6 @@ static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for return NULL; } -#endif static struct audio *find_first_free_audio( struct resource_context *res_ctx, @@ -1971,7 +1965,6 @@ enum dc_status dc_remove_stream_from_ctx( if (dc->res_pool->funcs->link_enc_unassign) dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(del_pipe)) { update_hpo_dp_stream_engine_usage( &new_ctx->res_ctx, dc->res_pool, @@ -1979,7 +1972,6 @@ enum dc_status dc_remove_stream_from_ctx( false); remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream); } -#endif if (del_pipe->stream_res.audio) update_audio_usage( @@ -2232,7 +2224,6 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream_res.stream_enc, true); -#if defined(CONFIG_DRM_AMD_DC_DCN) /* Allocate DP HPO Stream Encoder based on signal, hw capabilities * and link settings */ @@ -2257,7 +2248,6 @@ enum dc_status resource_map_pool_resources( return DC_NO_LINK_ENC_RESOURCE; } } -#endif /* TODO: Add check if ASIC support and EDID audio */ if (!stream->converter_disable_audio && @@ -2927,12 +2917,10 @@ bool pipe_need_reprogram( if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) return true; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc) return true; if (pipe_ctx_old->link_res.hpo_dp_link_enc != pipe_ctx->link_res.hpo_dp_link_enc) return true; -#endif /* DIG link encoder resource assignment for stream changed. */ if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { @@ -3199,7 +3187,6 @@ void get_audio_check(struct audio_info *aud_modes, } } -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( const struct resource_context *res_ctx, const struct resource_pool *pool, @@ -3218,7 +3205,6 @@ struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( return hpo_dp_link_enc; } -#endif void reset_syncd_pipes_from_disabled_pipes(struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 14abba495f4a..ff5093e52f2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -195,10 +195,8 @@ struct dc_caps { unsigned int cursor_cache_size; struct dc_plane_cap planes[MAX_PLANES]; struct dc_color_caps color; -#if defined(CONFIG_DRM_AMD_DC_DCN) bool dp_hpo; bool hdmi_frl_pcon_support; -#endif bool edp_dsc_support; bool vbios_lttpr_aware; bool vbios_lttpr_enable; @@ -306,7 +304,6 @@ struct dc_cap_funcs { struct link_training_settings; -#if defined(CONFIG_DRM_AMD_DC_DCN) union allow_lttpr_non_transparent_mode { struct { bool DP1_4A : 1; @@ -314,7 +311,7 @@ union allow_lttpr_non_transparent_mode { } bits; unsigned char raw; }; -#endif + /* Structure to hold configuration flags set by dm at dc creation. */ struct dc_config { bool gpu_vm_support; @@ -327,11 +324,7 @@ struct dc_config { bool edp_no_power_sequencing; bool force_enum_edp; bool forced_clocks; -#if defined(CONFIG_DRM_AMD_DC_DCN) union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode; -#else - bool allow_lttpr_non_transparent_mode; -#endif bool multi_mon_pp_mclk_switch; bool disable_dmcu; bool enable_4to1MPC; @@ -689,13 +682,11 @@ struct dc_debug_options { bool disable_dsc_edp; unsigned int force_dsc_edp_policy; bool enable_dram_clock_change_one_display_vactive; -#if defined(CONFIG_DRM_AMD_DC_DCN) /* TODO - remove once tested */ bool legacy_dp2_lt; bool set_mst_en_for_sst; bool disable_uhbr; bool force_dp2_lt_fallback_method; -#endif union mem_low_power_enable_options enable_mem_low_power; union root_clock_optimization_options root_clock_optimization; bool hpo_optimization; @@ -1239,12 +1230,10 @@ struct dpcd_caps { struct psr_caps psr_caps; struct dpcd_usb4_dp_tunneling_info usb4_dp_tun_info; -#if defined(CONFIG_DRM_AMD_DC_DCN) union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates; union dp_main_line_channel_coding_cap channel_coding_cap; union dp_sink_video_fallback_formats fallback_formats; union dp_fec_capability1 fec_cap1; -#endif }; union dpcd_sink_ext_caps { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 353dac420f34..7b1103e9f7a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -53,7 +53,6 @@ enum dc_link_rate { LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2)- 3.24 Gbps/Lane LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane LINK_RATE_HIGH2 = 0x14, // Rate_7 (HBR2)- 5.40 Gbps/Lane -#if defined(CONFIG_DRM_AMD_DC_DCN) LINK_RATE_HIGH3 = 0x1E, // Rate_8 (HBR3)- 8.10 Gbps/Lane /* Starting from DP2.0 link rate enum directly represents actual * link rate value in unit of 10 mbps @@ -61,9 +60,6 @@ enum dc_link_rate { LINK_RATE_UHBR10 = 1000, // UHBR10 - 10.0 Gbps/Lane LINK_RATE_UHBR13_5 = 1350, // UHBR13.5 - 13.5 Gbps/Lane LINK_RATE_UHBR20 = 2000, // UHBR10 - 20.0 Gbps/Lane -#else - LINK_RATE_HIGH3 = 0x1E // Rate_8 (HBR3)- 8.10 Gbps/Lane -#endif }; enum dc_link_spread { @@ -100,7 +96,6 @@ enum dc_post_cursor2 { POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3, }; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_dp_ffe_preset_level { DP_FFE_PRESET_LEVEL0 = 0, DP_FFE_PRESET_LEVEL1, @@ -120,7 +115,6 @@ enum dc_dp_ffe_preset_level { DP_FFE_PRESET_LEVEL15, DP_FFE_PRESET_MAX_LEVEL = DP_FFE_PRESET_LEVEL15, }; -#endif enum dc_dp_training_pattern { DP_TRAINING_PATTERN_SEQUENCE_1 = 0, @@ -128,19 +122,15 @@ enum dc_dp_training_pattern { DP_TRAINING_PATTERN_SEQUENCE_3, DP_TRAINING_PATTERN_SEQUENCE_4, DP_TRAINING_PATTERN_VIDEOIDLE, -#if defined(CONFIG_DRM_AMD_DC_DCN) DP_128b_132b_TPS1, DP_128b_132b_TPS2, DP_128b_132b_TPS2_CDS, -#endif }; enum dp_link_encoding { DP_UNKNOWN_ENCODING = 0, DP_8b_10b_ENCODING = 1, -#if defined(CONFIG_DRM_AMD_DC_DCN) DP_128b_132b_ENCODING = 2, -#endif }; struct dc_link_settings { @@ -152,7 +142,6 @@ struct dc_link_settings { bool dpcd_source_device_specific_field_support; }; -#if defined(CONFIG_DRM_AMD_DC_DCN) union dc_dp_ffe_preset { struct { uint8_t level : 4; @@ -163,24 +152,19 @@ union dc_dp_ffe_preset { } settings; uint8_t raw; }; -#endif struct dc_lane_settings { enum dc_voltage_swing VOLTAGE_SWING; enum dc_pre_emphasis PRE_EMPHASIS; enum dc_post_cursor2 POST_CURSOR2; -#if defined(CONFIG_DRM_AMD_DC_DCN) union dc_dp_ffe_preset FFE_PRESET; -#endif }; struct dc_link_training_overrides { enum dc_voltage_swing *voltage_swing; enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; -#if defined(CONFIG_DRM_AMD_DC_DCN) union dc_dp_ffe_preset *ffe_preset; -#endif uint16_t *cr_pattern_time; uint16_t *eq_pattern_time; @@ -194,7 +178,6 @@ struct dc_link_training_overrides { bool *fec_enable; }; -#if defined(CONFIG_DRM_AMD_DC_DCN) union payload_table_update_status { struct { uint8_t VC_PAYLOAD_TABLE_UPDATED:1; @@ -202,7 +185,6 @@ union payload_table_update_status { } bits; uint8_t raw; }; -#endif union dpcd_rev { struct { @@ -291,14 +273,10 @@ union lane_align_status_updated { struct { uint8_t INTERLANE_ALIGN_DONE:1; uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; -#if defined(CONFIG_DRM_AMD_DC_DCN) uint8_t EQ_INTERLANE_ALIGN_DONE_128b_132b:1; uint8_t CDS_INTERLANE_ALIGN_DONE_128b_132b:1; uint8_t LT_FAILED_128b_132b:1; uint8_t RESERVED:1; -#else - uint8_t RESERVED:4; -#endif uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; uint8_t LINK_STATUS_UPDATED:1; } bits; @@ -311,12 +289,10 @@ union lane_adjust { uint8_t PRE_EMPHASIS_LANE:2; uint8_t RESERVED:4; } bits; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct { uint8_t PRESET_VALUE :4; uint8_t RESERVED :4; } tx_ffe; -#endif uint8_t raw; }; @@ -346,12 +322,10 @@ union dpcd_training_lane { uint8_t MAX_PRE_EMPHASIS_REACHED:1; uint8_t RESERVED:2; } bits; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct { uint8_t PRESET_VALUE :4; uint8_t RESERVED :4; } tx_ffe; -#endif uint8_t raw; }; @@ -665,18 +639,9 @@ union test_response { union phy_test_pattern { struct { -#if defined(CONFIG_DRM_AMD_DC_DCN) /* This field is 7 bits for DP2.0 */ uint8_t PATTERN :7; uint8_t RESERVED :1; -#else - /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 - * and 3 bits for DP1.2. - */ - uint8_t PATTERN :3; - /* BY speci, bit7:2 is 0 for DP1.1. */ - uint8_t RESERVED :5; -#endif } bits; uint8_t raw; }; @@ -754,14 +719,10 @@ union dpcd_fec_capability { uint8_t UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t CORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t BIT_ERROR_COUNT_CAPABLE:1; -#if defined(CONFIG_DRM_AMD_DC_DCN) uint8_t PARITY_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t ARITY_BIT_ERROR_COUNT_CAPABLE:1; uint8_t FEC_RUNNING_INDICATOR_SUPPORTED:1; uint8_t FEC_ERROR_REPORTING_POLICY_SUPPORTED:1; -#else - uint8_t RESERVED:4; -#endif } bits; uint8_t raw; }; @@ -925,7 +886,6 @@ struct dpcd_usb4_dp_tunneling_info { uint8_t usb4_topology_id[DPCD_USB4_TOPOLOGY_ID_LEN]; }; -#if defined(CONFIG_DRM_AMD_DC_DCN) #ifndef DP_MAIN_LINK_CHANNEL_CODING_CAP #define DP_MAIN_LINK_CHANNEL_CODING_CAP 0x006 #endif @@ -994,8 +954,8 @@ struct dpcd_usb4_dp_tunneling_info { #endif #ifndef DP_INTRA_HOP_AUX_REPLY_INDICATION #define DP_INTRA_HOP_AUX_REPLY_INDICATION (1 << 3) -#endif /* TODO - Use DRM header to replace above once available */ +#endif // DP_INTRA_HOP_AUX_REPLY_INDICATION union dp_main_line_channel_coding_cap { struct { @@ -1091,6 +1051,5 @@ union dp_128b_132b_training_aux_rd_interval { } bits; uint8_t raw; }; -#endif #endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 704323654468..9014c0a0a63b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -47,10 +47,8 @@ struct dc_link_status { struct link_mst_stream_allocation { /* DIG front */ const struct stream_encoder *stream_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) /* HPO DP Stream Encoder */ const struct hpo_dp_stream_encoder *hpo_dp_stream_enc; -#endif /* associate DRM payload table with DC stream encoder */ uint8_t vcp_id; /* number of slots required for the DP stream in transport packet */ @@ -318,10 +316,8 @@ enum dc_detect_reason { bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); bool dc_link_get_hpd_state(struct dc_link *dc_link); enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn); enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn); -#endif /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). * Return: @@ -455,10 +451,8 @@ uint32_t dc_bandwidth_in_kbps_from_timing( bool dc_link_is_fec_supported(const struct dc_link *link); bool dc_link_should_enable_fec(const struct dc_link *link); -#if defined(CONFIG_DRM_AMD_DC_DCN) uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw); enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link); -#endif const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link); /* take a snapshot of current link resource allocation state */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index e37c4a10bfd5..f631b61abedd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -115,12 +115,10 @@ struct periodic_interrupt_config { int lines_offset; }; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_mst_stream_bw_update { bool is_increase; // is bandwidth reduced or increased uint32_t mst_stream_bw; // new mst bandwidth in kbps }; -#endif union stream_update_flags { struct { @@ -132,9 +130,7 @@ union stream_update_flags { uint32_t gamut_remap:1; uint32_t wb_update:1; uint32_t dsc_changed : 1; -#if defined(CONFIG_DRM_AMD_DC_DCN) uint32_t mst_bw : 1; -#endif } bits; uint32_t raw; @@ -288,9 +284,7 @@ struct dc_stream_update { struct dc_writeback_update *wb_update; struct dc_dsc_config *dsc_config; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_mst_stream_bw_update *mst_bw_update; -#endif struct dc_transfer_func *func_shaper; struct dc_3dlut *lut3d_func; diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 0285a4b38d05..48859d5fc172 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -395,14 +395,11 @@ struct dc_lttpr_caps { uint8_t max_link_rate; uint8_t phy_repeater_cnt; uint8_t max_ext_timeout; -#if defined(CONFIG_DRM_AMD_DC_DCN) union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding; union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; -#endif uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; }; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_dongle_dfp_cap_ext { bool supported; uint16_t max_pixel_rate_in_mps; @@ -414,7 +411,6 @@ struct dc_dongle_dfp_cap_ext { struct dp_color_depth_caps ycbcr422_color_depth_caps; struct dp_color_depth_caps ycbcr420_color_depth_caps; }; -#endif struct dc_dongle_caps { /* dongle type (DP converter, CV smart dongle) */ @@ -429,10 +425,8 @@ struct dc_dongle_caps { bool is_dp_hdmi_ycbcr420_converter; uint32_t dp_hdmi_max_bpc; uint32_t dp_hdmi_max_pixel_clk_in_khz; -#if defined(CONFIG_DRM_AMD_DC_DCN) uint32_t dp_hdmi_frl_max_link_bw_in_kbps; struct dc_dongle_dfp_cap_ext dfp_cap_ext; -#endif }; /* Scaling format */ enum scaling_transformation { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f3ff141b706a..b83c5544247d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -49,9 +49,7 @@ #include "link_enc_cfg.h" #include "link_hwss.h" #include "dc_link_dp.h" -#if defined(CONFIG_DRM_AMD_DC_DCN) #include "dccg.h" -#endif #include "clock_source.h" #include "clk_mgr.h" #include "abm.h" @@ -1112,17 +1110,12 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) clk_mgr->funcs->enable_pme_wa(clk_mgr); /* un-mute audio */ /* TODO: audio should be per stream rather than per link */ -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.hpo_dp_stream_enc, false); else pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, false); -#else - pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.stream_enc, false); -#endif if (pipe_ctx->stream_res.audio) pipe_ctx->stream_res.audio->enabled = true; } @@ -1145,32 +1138,22 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) return; -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.hpo_dp_stream_enc, true); else pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, true); -#else - pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( - pipe_ctx->stream_res.stream_enc, true); -#endif if (pipe_ctx->stream_res.audio) { pipe_ctx->stream_res.audio->enabled = false; if (dc_is_dp_signal(pipe_ctx->stream->signal)) -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable( pipe_ctx->stream_res.hpo_dp_stream_enc); else pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( pipe_ctx->stream_res.stream_enc); -#else - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( - pipe_ctx->stream_res.stream_enc); -#endif else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); @@ -1204,14 +1187,10 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.hpo_dp_stream_enc); } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) -#else - if (dc_is_dp_signal(pipe_ctx->stream->signal)) -#endif pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.stream_enc); @@ -1224,7 +1203,6 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); ASSERT(link_enc); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable( pipe_ctx->stream_res.hpo_dp_stream_enc); @@ -1237,13 +1215,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->id, false); } -#else - if (link_enc) - link_enc->funcs->connect_dig_be_to_fe( - link->link_enc, - pipe_ctx->stream_res.stream_enc->id, - false); -#endif + if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); @@ -1285,15 +1257,11 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) link->dc->hwss.set_abm_immediate_disable(pipe_ctx); } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_blank( pipe_ctx->stream_res.hpo_dp_stream_enc); } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { -#else - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { -#endif pipe_ctx->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc); if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) { @@ -1535,7 +1503,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( build_audio_output(context, pipe_ctx, &audio_output); if (dc_is_dp_signal(pipe_ctx->stream->signal)) -#if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_res.hpo_dp_stream_enc, @@ -1546,12 +1513,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.audio->inst, &pipe_ctx->stream->audio_info); -#else - pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( - pipe_ctx->stream_res.stream_enc, - pipe_ctx->stream_res.audio->inst, - &pipe_ctx->stream->audio_info); -#endif else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_res.stream_enc, @@ -1570,14 +1531,12 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (!pipe_ctx->stream->apply_seamless_boot_optimization && dc->config.use_pipe_ctx_sync_logic) check_syncd_pipes_for_disabled_master_pipe(dc, context, pipe_ctx->pipe_idx); -#if defined(CONFIG_DRM_AMD_DC_DCN) /* DCN3.1 FPGA Workaround * Need to enable HPO DP Stream Encoder before setting OTG master enable. * To do so, move calling function enable_stream_timing to only be done AFTER calling * function core_link_enable_stream */ if (!(hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx))) -#endif /* */ /* Do not touch stream timing on seamless boot optimization. */ if (!pipe_ctx->stream->apply_seamless_boot_optimization) @@ -1643,7 +1602,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (!stream->dpms_off) core_link_enable_stream(context, pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN) /* DCN3.1 FPGA Workaround * Need to enable HPO DP Stream Encoder before setting OTG master enable. * To do so, move calling function enable_stream_timing to only be done AFTER calling @@ -1653,7 +1611,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (!pipe_ctx->stream->apply_seamless_boot_optimization) hws->funcs.enable_stream_timing(pipe_ctx, context, dc); } -#endif pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; @@ -2233,8 +2190,6 @@ static void dce110_setup_audio_dto( build_audio_output(context, pipe_ctx, &audio_output); -#if defined(CONFIG_DRM_AMD_DC_DCN) - /* For DCN3.1, audio to HPO FRL encoder is using audio DTBCLK DTO */ if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) { /* disable audio DTBCLK DTO */ dc->res_pool->dccg->funcs->set_audio_dtbclk_dto( @@ -2251,13 +2206,6 @@ static void dce110_setup_audio_dto( pipe_ctx->stream->signal, &audio_output.crtc_info, &audio_output.pll_info); -#else - pipe_ctx->stream_res.audio->funcs->wall_dto_setup( - pipe_ctx->stream_res.audio, - pipe_ctx->stream->signal, - &audio_output.crtc_info, - &audio_output.pll_info); -#endif break; } } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 943240e2809e..e90123b0ee0e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -249,12 +249,10 @@ struct resource_pool { /* Number of USB4 DPIA (DisplayPort Input Adapter) link objects created.*/ unsigned int usb4_dpia_count; -#if defined(CONFIG_DRM_AMD_DC_DCN) unsigned int hpo_dp_stream_enc_count; struct hpo_dp_stream_encoder *hpo_dp_stream_enc[MAX_HPO_DP2_ENCODERS]; unsigned int hpo_dp_link_enc_count; struct hpo_dp_link_encoder *hpo_dp_link_enc[MAX_HPO_DP2_LINK_ENCODERS]; -#endif #if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_3dlut *mpc_lut[MAX_PIPES]; struct dc_transfer_func *mpc_shaper[MAX_PIPES]; @@ -307,9 +305,7 @@ struct stream_resource { struct display_stream_compressor *dsc; struct timing_generator *tg; struct stream_encoder *stream_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_stream_encoder *hpo_dp_stream_enc; -#endif struct audio *audio; struct pixel_clk_params pix_clk_params; @@ -334,18 +330,12 @@ struct plane_resource { struct dcn_fe_bandwidth bw; }; -#if defined(CONFIG_DRM_AMD_DC_DCN) #define LINK_RES_HPO_DP_REC_MAP__MASK 0xFFFF #define LINK_RES_HPO_DP_REC_MAP__SHIFT 0 -#endif /* all mappable hardware resources used to enable a link */ struct link_resource { -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_link_encoder *hpo_dp_link_enc; -#else - void *dummy; -#endif }; union pipe_update_flags { @@ -425,11 +415,9 @@ struct resource_context { uint8_t dp_clock_source_ref_count; bool is_dsc_acquired[MAX_PIPES]; struct link_enc_cfg_context link_enc_cfg_ctx; -#if defined(CONFIG_DRM_AMD_DC_DCN) bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS]; unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS]; int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS]; -#endif #if defined(CONFIG_DRM_AMD_DC_DCN) bool is_mpc_3dlut_acquired[MAX_PIPES]; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index c940fdfda144..b2fa4de47734 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -79,7 +79,7 @@ struct dccg_funcs { void (*otg_drop_pixel)(struct dccg *dccg, uint32_t otg_inst); void (*dccg_init)(struct dccg *dccg); -#if defined(CONFIG_DRM_AMD_DC_DCN) + void (*set_dpstreamclk)( struct dccg *dccg, enum hdmistreamclk_source src, @@ -102,7 +102,7 @@ struct dccg_funcs { void (*disable_symclk32_le)( struct dccg *dccg, int hpo_le_inst); -#endif + void (*set_physymclk)( struct dccg *dccg, int phy_inst, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 10ecbc667ffa..d89bd55f110f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -38,10 +38,8 @@ #define MAX_PIPES 6 #define MAX_DIG_LINK_ENCODERS 7 #define MAX_DWB_PIPES 1 -#if defined(CONFIG_DRM_AMD_DC_DCN) #define MAX_HPO_DP2_ENCODERS 4 #define MAX_HPO_DP2_LINK_ENCODERS 2 -#endif struct gamma_curve { uint32_t offset; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 2ce15cd10d80..101444c6f145 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -220,7 +220,6 @@ enum link_enc_cfg_mode { LINK_ENC_CFG_TRANSIENT /* During commit state - use state to be committed. */ }; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dp2_link_mode { DP2_LINK_TRAINING_TPS1, DP2_LINK_TRAINING_TPS2, @@ -306,6 +305,5 @@ struct hpo_dp_link_encoder_funcs { const struct dc_link_settings *link_settings, uint8_t ffe_preset); }; -#endif #endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 073f8b667eff..d9a3a204cc23 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -249,7 +249,6 @@ struct stream_encoder_funcs { struct stream_encoder *enc); }; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_stream_encoder_state { uint32_t stream_enc_enabled; uint32_t vid_stream_enabled; @@ -329,6 +328,5 @@ struct hpo_dp_stream_encoder_funcs { struct hpo_dp_stream_encoder *enc, struct hpo_dp_stream_encoder_state *state); }; -#endif #endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index c29320b3855d..59a704781e34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -100,9 +100,7 @@ enum crc_selection { enum otg_out_mux_dest { OUT_MUX_DIO = 0, -#if defined(CONFIG_DRM_AMD_DC_DCN) OUT_MUX_HPO_DP = 2, -#endif }; enum h_timing_div_mode { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index c2008258c50a..280c8764b636 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -41,9 +41,7 @@ struct dce_hwseq_wa { bool DEGVIDCN10_254; bool DEGVIDCN21; bool disallow_self_refresh_during_multi_plane_transition; -#if defined(CONFIG_DRM_AMD_DC_DCN) bool dp_hpo_and_otg_sequence; -#endif }; struct hwseq_wa_state { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 028180f58f71..ccb13dcb867b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -54,10 +54,8 @@ struct resource_caps { int num_dsc; unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output). unsigned int num_usb4_dpia; // Total number of USB4 DPIA (DisplayPort Input Adapters). -#if defined(CONFIG_DRM_AMD_DC_DCN) int num_hpo_dp_stream_encoder; int num_hpo_dp_link_encoder; -#endif int num_mpc_3dlut; }; @@ -77,14 +75,12 @@ struct resource_create_funcs { struct stream_encoder *(*create_stream_encoder)( enum engine_id eng_id, struct dc_context *ctx); -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)( enum engine_id eng_id, struct dc_context *ctx); struct hpo_dp_link_encoder *(*create_hpo_dp_link_encoder)( uint8_t inst, struct dc_context *ctx); -#endif struct dce_hwseq *(*create_hwseq)( struct dc_context *ctx); @@ -205,12 +201,10 @@ int get_num_mpc_splits(struct pipe_ctx *pipe); int get_num_odm_splits(struct pipe_ctx *pipe); -#if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( const struct resource_context *res_ctx, const struct resource_pool *pool, const struct dc_link *link); -#endif void reset_syncd_pipes_from_disabled_pipes(struct dc *dc, struct dc_state *context); diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index b8ffb216ebc4..cf4027cc3f4c 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -152,10 +152,8 @@ struct bp_transmitter_control { enum signal_type signal; enum dc_color_depth color_depth; /* not used for DCE6.0 */ enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */ -#if defined(CONFIG_DRM_AMD_DC_DCN) enum tx_ffe_id txffe_sel; /* used for DCN3 */ enum engine_id hpo_engine_id; /* used for DCN3 */ -#endif struct graphics_object_id connector_obj_id; /* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should * be pixel clock * deep_color_ratio (in KHz) diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index ffd0df1701e6..4edaa3318714 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -144,14 +144,10 @@ enum dpcd_training_patterns { DPCD_TRAINING_PATTERN_1, DPCD_TRAINING_PATTERN_2, DPCD_TRAINING_PATTERN_3, -#if defined(CONFIG_DRM_AMD_DC_DCN) DPCD_TRAINING_PATTERN_4 = 7, DPCD_128b_132b_TPS1 = 1, DPCD_128b_132b_TPS2 = 2, DPCD_128b_132b_TPS2_CDS = 3, -#else - DPCD_TRAINING_PATTERN_4 = 7 -#endif }; /* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus diff --git a/drivers/gpu/drm/amd/display/include/grph_object_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_defs.h index 84b299ff500a..05ba188a7c3b 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_defs.h @@ -140,7 +140,6 @@ enum sync_source { SYNC_SOURCE_DUAL_GPU_PIN }; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum tx_ffe_id { TX_FFE0 = 0, TX_FFE1, @@ -150,7 +149,6 @@ enum tx_ffe_id { TX_FFE_PreShoot_Only, TX_FFE_No_FFE, }; -#endif /* connector sizes in millimeters - from BiosParserTypes.hpp */ #define CONNECTOR_SIZE_DVI 40 diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h index 01775417cf4b..fed1edc038d8 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_id.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -184,14 +184,12 @@ enum engine_id { ENGINE_ID_DACA, ENGINE_ID_DACB, ENGINE_ID_VCE, /* wireless display pseudo-encoder */ -#if defined(CONFIG_DRM_AMD_DC_DCN) ENGINE_ID_HPO_0, ENGINE_ID_HPO_1, ENGINE_ID_HPO_DP_0, ENGINE_ID_HPO_DP_1, ENGINE_ID_HPO_DP_2, ENGINE_ID_HPO_DP_3, -#endif ENGINE_ID_VIRTUAL, ENGINE_ID_COUNT, diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 424bccd36434..447a56286dd0 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -74,12 +74,10 @@ enum link_training_result { LINK_TRAINING_LINK_LOSS, /* Abort link training (because sink unplugged) */ LINK_TRAINING_ABORT, -#if defined(CONFIG_DRM_AMD_DC_DCN) DP_128b_132b_LT_FAILED, DP_128b_132b_MAX_LOOP_COUNT_REACHED, DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT, DP_128b_132b_CDS_DONE_TIMEOUT, -#endif }; enum lttpr_mode { @@ -99,23 +97,19 @@ struct link_training_settings { enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; bool should_set_fec_ready; -#if defined(CONFIG_DRM_AMD_DC_DCN) /* TODO - factor lane_settings out because it changes during LT */ union dc_dp_ffe_preset *ffe_preset; -#endif uint16_t cr_pattern_time; uint16_t eq_pattern_time; uint16_t cds_pattern_time; enum dc_dp_training_pattern pattern_for_cr; enum dc_dp_training_pattern pattern_for_eq; -#if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_dp_training_pattern pattern_for_cds; uint32_t eq_wait_time_limit; uint8_t eq_loop_count_limit; uint32_t cds_wait_time_limit; -#endif bool enhanced_framing; enum lttpr_mode lttpr_mode; @@ -161,7 +155,6 @@ enum dp_test_pattern { DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_CP2520_3, -#if defined(CONFIG_DRM_AMD_DC_DCN) DP_TEST_PATTERN_128b_132b_TPS1, DP_TEST_PATTERN_128b_132b_TPS2, DP_TEST_PATTERN_PRBS9, @@ -171,20 +164,15 @@ enum dp_test_pattern { DP_TEST_PATTERN_PRBS31, DP_TEST_PATTERN_264BIT_CUSTOM, DP_TEST_PATTERN_SQUARE_PULSE, -#endif /* Link Training Patterns */ DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN4, -#if defined(CONFIG_DRM_AMD_DC_DCN) DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE, DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE, DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE, -#else - DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, -#endif /* link test patterns*/ DP_TEST_PATTERN_COLOR_SQUARES, From 5279e091616b74ff0e4a24e220e0552b10d88d46 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jan 2022 16:24:39 +0800 Subject: [PATCH 136/339] drm/amd/display: abstract encoder related hwseq across different types [why] Current we have hundreds of if/else or switch statement to check encoder type in dc_link level. The reason is because depending on the type of encoder dc_link needs to perform similar programming task but with different encoder interfaces. The story is to abstract these interfaces so dc_link can just perform the programming task without knowing the detail of which encoder it's dealing with. Tested-by: Daniel Wheeler Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 83 ++++++++---------- .../drm/amd/display/dc/core/dc_link_hwss.c | 85 +++++++++++++++++++ .../amd/display/dc/inc/hw/stream_encoder.h | 4 + .../gpu/drm/amd/display/dc/inc/link_hwss.h | 19 +++++ 4 files changed, 143 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 84afe0d1a791..fafe05608818 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3433,6 +3433,8 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; struct link_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; + const struct dc_link_settings empty_link_settings = {0}; + const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* slot X.Y for SST payload deallocate */ @@ -3441,10 +3443,11 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, dc_log_vcp_x_y(link, avg_time_slots_per_mtp); - hpo_dp_link_encoder->funcs->set_throttled_vcp_size( - hpo_dp_link_encoder, - hpo_dp_stream_encoder->inst, - avg_time_slots_per_mtp); + link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->set_hblank_min_symbol_width) + link_hwss->set_hblank_min_symbol_width(pipe_ctx, + &empty_link_settings, + avg_time_slots_per_mtp); } /* calculate VC payload and update branch with new payload allocation table*/ @@ -3488,10 +3491,11 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, dc_log_vcp_x_y(link, avg_time_slots_per_mtp); - hpo_dp_link_encoder->funcs->set_throttled_vcp_size( - hpo_dp_link_encoder, - hpo_dp_stream_encoder->inst, - avg_time_slots_per_mtp); + link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->set_hblank_min_symbol_width) + link_hwss->set_hblank_min_symbol_width(pipe_ctx, + &link->cur_link_settings, + avg_time_slots_per_mtp); } /* Always return DC_OK. @@ -3508,15 +3512,14 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; struct link_encoder *link_encoder = NULL; - struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc; - struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; int i; enum act_return_status ret; + const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ @@ -3622,22 +3625,13 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) pbn = get_pbn_from_timing(pipe_ctx); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); - switch (dp_get_link_encoding_format(&link->cur_link_settings)) { - case DP_8b_10b_ENCODING: - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, - avg_time_slots_per_mtp); - break; - case DP_128b_132b_ENCODING: - hpo_dp_link_encoder->funcs->set_throttled_vcp_size( - hpo_dp_link_encoder, - hpo_dp_stream_encoder->inst, + dc_log_vcp_x_y(link, avg_time_slots_per_mtp); + + link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->set_hblank_min_symbol_width) + link_hwss->set_hblank_min_symbol_width(pipe_ctx, + &link->cur_link_settings, avg_time_slots_per_mtp); - break; - case DP_UNKNOWN_ENCODING: - DC_LOG_ERROR("Failure: unknown encoding format\n"); - return DC_ERROR_UNEXPECTED; - } return DC_OK; @@ -3651,10 +3645,10 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; struct link_encoder *link_encoder = link->link_enc; - struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; + const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* decrease throttled vcp size */ @@ -3662,8 +3656,10 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw pbn = get_pbn_from_bw_in_kbps(bw_in_kbps); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, + link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->set_hblank_min_symbol_width) + link_hwss->set_hblank_min_symbol_width(pipe_ctx, + &link->cur_link_settings, avg_time_slots_per_mtp); /* send ALLOCATE_PAYLOAD sideband message with updated pbn */ @@ -3731,10 +3727,10 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t struct fixed31_32 pbn; struct fixed31_32 pbn_per_slot; struct link_encoder *link_encoder = link->link_enc; - struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; + const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* notify immediate branch device table update */ @@ -3793,8 +3789,10 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t pbn_per_slot = get_pbn_per_slot(stream); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, + link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->set_hblank_min_symbol_width) + link_hwss->set_hblank_min_symbol_width(pipe_ctx, + &link->cur_link_settings, avg_time_slots_per_mtp); return DC_OK; @@ -3805,13 +3803,13 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; struct link_encoder *link_encoder = NULL; - struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc; - struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; struct dp_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; bool mst_mode = (link->type == dc_connection_mst_branch); + const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct dc_link_settings empty_link_settings = {0}; DC_LOGGER_INIT(link->ctx->logger); /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ @@ -3829,22 +3827,11 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) */ /* slot X.Y */ - switch (dp_get_link_encoding_format(&link->cur_link_settings)) { - case DP_8b_10b_ENCODING: - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, - avg_time_slots_per_mtp); - break; - case DP_128b_132b_ENCODING: - hpo_dp_link_encoder->funcs->set_throttled_vcp_size( - hpo_dp_link_encoder, - hpo_dp_stream_encoder->inst, + link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->set_hblank_min_symbol_width) + link_hwss->set_hblank_min_symbol_width(pipe_ctx, + &empty_link_settings, avg_time_slots_per_mtp); - break; - case DP_UNKNOWN_ENCODING: - DC_LOG_ERROR("Failure: unknown encoding format\n"); - return DC_ERROR_UNEXPECTED; - } /* TODO: which component is responsible for remove payload table? */ if (mst_mode) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index c84822cd7e53..93392c67c909 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -844,4 +844,89 @@ void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) } } +/******************************* dio_link_hwss ********************************/ +static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size) +{ + struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; + + stream_encoder->funcs->set_throttled_vcp_size( + stream_encoder, + throttled_vcp_size); +} + +/***************************** hpo_dp_link_hwss *******************************/ +static void set_dp_hpo_throttled_vcp_size(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size) +{ + struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; + struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc; + + hpo_dp_link_encoder->funcs->set_throttled_vcp_size(hpo_dp_link_encoder, + hpo_dp_stream_encoder->inst, + throttled_vcp_size); +} + +static void set_dp_hpo_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, + const struct dc_link_settings *link_settings, + struct fixed31_32 throttled_vcp_size) +{ + struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; + struct fixed31_32 h_blank_in_ms, time_slot_in_ms, mtp_cnt_per_h_blank; + uint32_t link_bw_in_kbps = dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings); + uint16_t hblank_min_symbol_width = 0; + + if (link_bw_in_kbps > 0) { + h_blank_in_ms = dc_fixpt_div(dc_fixpt_from_int(timing->h_total-timing->h_addressable), + dc_fixpt_from_fraction(timing->pix_clk_100hz, 10)); + time_slot_in_ms = dc_fixpt_from_fraction(32 * 4, link_bw_in_kbps); + mtp_cnt_per_h_blank = dc_fixpt_div(h_blank_in_ms, dc_fixpt_mul_int(time_slot_in_ms, 64)); + hblank_min_symbol_width = dc_fixpt_floor( + dc_fixpt_mul(mtp_cnt_per_h_blank, throttled_vcp_size)); + } + + hpo_dp_stream_encoder->funcs->set_hblank_min_symbol_width(hpo_dp_stream_encoder, + hblank_min_symbol_width); +} + +static const struct dc_link_hwss hpo_dp_link_hwss = { + .set_throttled_vcp_size = set_dp_hpo_throttled_vcp_size, + + /* function pointers below this point require check for NULL + * ********************************************************************* + */ + .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, +}; + +static const struct dc_link_hwss dio_link_hwss = { + .set_throttled_vcp_size = set_dio_throttled_vcp_size, +}; + +const struct dc_link_hwss *dc_link_hwss_get(const struct dc_link *link, + const struct link_resource *link_res) +{ + if (link_res->hpo_dp_link_enc) + /* TODO: some assumes that if decided link settings is 128b/132b + * channel coding format hpo_dp_link_enc should be used. + * Others believe that if hpo_dp_link_enc is available in link + * resource then hpo_dp_link_enc must be used. This bound between + * hpo_dp_link_enc != NULL and decided link settings is loosely coupled + * with a premise that both hpo_dp_link_enc pointer and decided link + * settings are determined based on single policy function like + * "decide_link_settings" from upper layer. This "convention" + * cannot be maintained and enforced at current level. + * Therefore a refactor is due so we can enforce a strong bound + * between those two parameters at this level. + * + * To put it simple, we want to make enforcement at low level so that + * we will not return link hwss if caller plans to do 8b/10b + * with an hpo encoder. Or we can return a very dummy one that doesn't + * do work for all functions + */ + return &hpo_dp_link_hwss; + else + return &dio_link_hwss; +} + #undef DC_LOGGER diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index d9a3a204cc23..36ec56524afd 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -327,6 +327,10 @@ struct hpo_dp_stream_encoder_funcs { void (*read_state)( struct hpo_dp_stream_encoder *enc, struct hpo_dp_stream_encoder_state *state); + + void (*set_hblank_min_symbol_width)( + struct hpo_dp_stream_encoder *enc, + uint16_t width); }; #endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 69d63763a10e..bd3b2b807431 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -72,4 +72,23 @@ void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, bool skip_video_pattern); +struct dc_link; +struct link_resource; +struct fixed31_32; +struct pipe_ctx; + +struct dc_link_hwss { + void (*set_throttled_vcp_size)(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size); + + /* function pointers below this point require check for NULL + * ********************************************************************* + */ + void (*set_hblank_min_symbol_width)(struct pipe_ctx *pipe_ctx, + const struct dc_link_settings *link_settings, + struct fixed31_32 throttled_vcp_size); +}; + +const struct dc_link_hwss *dc_link_hwss_get(const struct dc_link *link, const struct link_resource *link_res); + #endif /* __DC_LINK_HWSS_H__ */ From ccba4e5bc856471ed009d92747376ee506fcc6ad Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jan 2022 16:24:40 +0800 Subject: [PATCH 137/339] drm/amd/display: add more link_hwss types and method to decide which one [why] as we add more link_hwss we are making a generic way to determine which type of link_hwss we should use. Later on we may think of introduce a link policy layer. it could be a thin layer that decide the type of link_hwss we use. So instead of passing in link and link_res we can just pass in link_policy and swtich based on link_policy->get_link_hwss_type. Tested-by: Daniel Wheeler Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 53 ++++++++++++++++--- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 3 ++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 93392c67c909..c65955eafaa2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -844,7 +844,16 @@ void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) } } -/******************************* dio_link_hwss ********************************/ +static void set_dummy_throttled_vcp_size(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size); + +/************************* below goes to dio_link_hwss ************************/ +static bool can_use_dio_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link->link_enc != NULL; +} + static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size) { @@ -855,7 +864,17 @@ static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, throttled_vcp_size); } -/***************************** hpo_dp_link_hwss *******************************/ +static const struct dc_link_hwss dio_link_hwss = { + .set_throttled_vcp_size = set_dio_throttled_vcp_size, +}; + +/*********************** below goes to hpo_dp_link_hwss ***********************/ +static bool can_use_dp_hpo_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link_res->hpo_dp_link_enc != NULL; +} + static void set_dp_hpo_throttled_vcp_size(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size) { @@ -898,15 +917,33 @@ static const struct dc_link_hwss hpo_dp_link_hwss = { */ .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, }; +/*********************** below goes to dpia_link_hwss *************************/ +static bool can_use_dpia_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign; +} -static const struct dc_link_hwss dio_link_hwss = { - .set_throttled_vcp_size = set_dio_throttled_vcp_size, +static const struct dc_link_hwss dpia_link_hwss = { + .set_throttled_vcp_size = set_dummy_throttled_vcp_size, +}; + +/*********************** below goes to link_hwss ******************************/ +static void set_dummy_throttled_vcp_size(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size) +{ + return; +} + +static const struct dc_link_hwss dummy_link_hwss = { + .set_throttled_vcp_size = set_dummy_throttled_vcp_size, }; const struct dc_link_hwss *dc_link_hwss_get(const struct dc_link *link, const struct link_resource *link_res) { - if (link_res->hpo_dp_link_enc) + if (can_use_dp_hpo_link_hwss(link, link_res)) /* TODO: some assumes that if decided link settings is 128b/132b * channel coding format hpo_dp_link_enc should be used. * Others believe that if hpo_dp_link_enc is available in link @@ -925,8 +962,12 @@ const struct dc_link_hwss *dc_link_hwss_get(const struct dc_link *link, * do work for all functions */ return &hpo_dp_link_hwss; - else + else if (can_use_dpia_link_hwss(link, link_res)) + return &dpia_link_hwss; + else if (can_use_dio_link_hwss(link, link_res)) return &dio_link_hwss; + else + return &dummy_link_hwss; } #undef DC_LOGGER diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index bd3b2b807431..8eff386da95e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -78,6 +78,9 @@ struct fixed31_32; struct pipe_ctx; struct dc_link_hwss { + /* you must define a dummy implementation and assign the function to + * dummy_link_hwss if you don't want to check for NULL pointer + */ void (*set_throttled_vcp_size)(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size); From 3ea07c89fbb777669c668452e94275a98dc8afbe Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jan 2022 16:24:41 +0800 Subject: [PATCH 138/339] drm/amd/display: rename dc_link_hwss struct to link_hwss [why] This is internal to dc so we don't have to add a prefix to indicate it is dc link_hwss instead someone else link_hwss. Tested-by: Daniel Wheeler Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 10 +++++----- drivers/gpu/drm/amd/display/dc/inc/link_hwss.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fafe05608818..64584a472f4a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3434,7 +3434,7 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, struct link_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; const struct dc_link_settings empty_link_settings = {0}; - const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* slot X.Y for SST payload deallocate */ @@ -3519,7 +3519,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) struct fixed31_32 pbn_per_slot; int i; enum act_return_status ret; - const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ @@ -3648,7 +3648,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw struct dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; - const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* decrease throttled vcp size */ @@ -3730,7 +3730,7 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t struct dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; - const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* notify immediate branch device table update */ @@ -3808,7 +3808,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; bool mst_mode = (link->type == dc_connection_mst_branch); - const struct dc_link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); const struct dc_link_settings empty_link_settings = {0}; DC_LOGGER_INIT(link->ctx->logger); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index c65955eafaa2..01254b4e7ac6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -864,7 +864,7 @@ static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, throttled_vcp_size); } -static const struct dc_link_hwss dio_link_hwss = { +static const struct link_hwss dio_link_hwss = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, }; @@ -909,7 +909,7 @@ static void set_dp_hpo_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, hblank_min_symbol_width); } -static const struct dc_link_hwss hpo_dp_link_hwss = { +static const struct link_hwss hpo_dp_link_hwss = { .set_throttled_vcp_size = set_dp_hpo_throttled_vcp_size, /* function pointers below this point require check for NULL @@ -925,7 +925,7 @@ static bool can_use_dpia_link_hwss(const struct dc_link *link, link->dc->res_pool->funcs->link_encs_assign; } -static const struct dc_link_hwss dpia_link_hwss = { +static const struct link_hwss dpia_link_hwss = { .set_throttled_vcp_size = set_dummy_throttled_vcp_size, }; @@ -936,11 +936,11 @@ static void set_dummy_throttled_vcp_size(struct pipe_ctx *pipe_ctx, return; } -static const struct dc_link_hwss dummy_link_hwss = { +static const struct link_hwss dummy_link_hwss = { .set_throttled_vcp_size = set_dummy_throttled_vcp_size, }; -const struct dc_link_hwss *dc_link_hwss_get(const struct dc_link *link, +const struct link_hwss *dc_link_hwss_get(const struct dc_link *link, const struct link_resource *link_res) { if (can_use_dp_hpo_link_hwss(link, link_res)) diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 8eff386da95e..5b361924ed8f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -77,7 +77,7 @@ struct link_resource; struct fixed31_32; struct pipe_ctx; -struct dc_link_hwss { +struct link_hwss { /* you must define a dummy implementation and assign the function to * dummy_link_hwss if you don't want to check for NULL pointer */ @@ -92,6 +92,6 @@ struct dc_link_hwss { struct fixed31_32 throttled_vcp_size); }; -const struct dc_link_hwss *dc_link_hwss_get(const struct dc_link *link, const struct link_resource *link_res); +const struct link_hwss *dc_link_hwss_get(const struct dc_link *link, const struct link_resource *link_res); #endif /* __DC_LINK_HWSS_H__ */ From 1f6c40d5c0095959a260c014a6251a0ac124c721 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Wed, 19 Jan 2022 16:24:42 +0800 Subject: [PATCH 139/339] drm/amd/display: fix a coding error causing set throttled vcp size skipped for dpia [why] There is a recent refactor that contains a typo to cause set throttled vcp size skipped for dpia link. The change is to fix this typo so it won't cause black screen Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Wayne Lin Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 01254b4e7ac6..c5146263f93c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -926,7 +926,7 @@ static bool can_use_dpia_link_hwss(const struct dc_link *link, } static const struct link_hwss dpia_link_hwss = { - .set_throttled_vcp_size = set_dummy_throttled_vcp_size, + .set_throttled_vcp_size = set_dio_throttled_vcp_size, }; /*********************** below goes to link_hwss ******************************/ From 09ece5ac397f8e3539ea9ffb776e1cc6702acb9a Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 19 Jan 2022 16:24:43 +0800 Subject: [PATCH 140/339] drm/amd/display: Don't update drm connector when read local EDID [Why] Currently, when we're tentatively detecting link configuration under mst case, we will wrongly notify a none existing stream sink to drm layer. It's due to we'll call amdgpu_dm_update_connector_after_detect() within dm_helpers_read_local_edid() to update connector when we're still under tentative detection procedure. [How] dm_helpers_read_local_edid() was designed to do "read" only. Don't update drm connector status when we're still under detection process. Tested-by: Daniel Wheeler Reviewed-by: Rodrigo Siqueira Signed-off-by: Wayne Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index b32a68a3586a..bfeace371ac1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -648,14 +648,6 @@ enum dc_edid_status dm_helpers_read_local_edid( /* We don't need the original edid anymore */ kfree(edid); - /* connector->display_info is parsed from EDID and saved - * into drm_connector->display_info - * - * drm_connector->display_info will be used by amdgpu_dm funcs, - * like fill_stream_properties_from_drm_display_mode - */ - amdgpu_dm_update_connector_after_detect(aconnector); - edid_status = dm_helpers_parse_edid_caps( link, &sink->dc_edid, From d715c9a2cbd4b5dbf72bec82b033698db3c6eca5 Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Sun, 23 Jan 2022 13:19:58 -0500 Subject: [PATCH 141/339] drm/amd/display: add protection in link encoder matching logic [Why] Link encoders are created based on its engine ID. The position of a link encoder in an array could be null since it didn't be allocated. Current matching logic didn't consider this situation and could get null encoder. [How] To add null encoder check to make the matching logic can go to next to get a valid one. Tested-by: Daniel Wheeler Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Martin Tsai Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 11 +--- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 66 ++----------------- .../drm/amd/display/dc/core/dc_link_enc_cfg.c | 23 ++++++- .../drm/amd/display/dc/core/dc_link_hwss.c | 22 ++----- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 1 - .../gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 3 + 7 files changed, 36 insertions(+), 92 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8a46b8430f1e..c0ab23274f96 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8366,7 +8366,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, break; case DRM_MODE_CONNECTOR_DisplayPort: aconnector->base.polled = DRM_CONNECTOR_POLL_HPD; - link->link_enc = dp_get_link_enc(link); + link->link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link->link_enc); if (link->link_enc) aconnector->base.ycbcr_420_allowed = diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 64584a472f4a..147a03a1500b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4621,16 +4621,7 @@ bool dc_link_is_fec_supported(const struct dc_link *link) */ struct link_encoder *link_enc = NULL; - /* Links supporting dynamically assigned link encoder will be assigned next - * available encoder if one not already assigned. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc); - } else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); return (dc_is_dp_signal(link->connector_signal) && link_enc && diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 68f9e099beae..a514f19d8f8b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -261,14 +261,7 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li struct dpcd_caps *rx_caps = &link->dpcd_caps; enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2; - /* Access link encoder capability based on whether it is statically - * or dynamically assigned to a link. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); enc_caps = &link_enc->features; @@ -2997,16 +2990,7 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_ return false; } - /* Links supporting dynamically assigned link encoder will be assigned next - * available encoder if one not already assigned. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc); - } else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (link_enc && link_enc->funcs->get_max_link_cap) { @@ -3027,16 +3011,7 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) enum dc_link_rate lttpr_max_link_rate; struct link_encoder *link_enc = NULL; - /* Links supporting dynamically assigned link encoder will be assigned next - * available encoder if one not already assigned. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc); - } else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); /* get max link encoder capability */ @@ -6175,14 +6150,7 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource enum dc_status status = DC_OK; uint8_t fec_config = 0; - /* Access link encoder based on whether it is statically - * or dynamically assigned to a link. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (!dc_link_should_enable_fec(link)) @@ -6222,14 +6190,7 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) { struct link_encoder *link_enc = NULL; - /* Access link encoder based on whether it is statically - * or dynamically assigned to a link. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (!dc_link_should_enable_fec(link)) @@ -6255,23 +6216,6 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) } } -struct link_encoder *dp_get_link_enc(struct dc_link *link) -{ - struct link_encoder *link_enc; - - link_enc = link->link_enc; - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, - link); - if (!link->link_enc) - link_enc = link_enc_cfg_get_next_avail_link_enc( - link->ctx->dc); - } - - return link_enc; -} - void dpcd_set_source_specific_data(struct dc_link *link) { if (!link->dc->vendor_signature.is_valid) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index a55944da8d53..a380611b1e42 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -486,7 +486,8 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc(struct dc *dc) } for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) { - if (encs_assigned[i] == ENGINE_ID_UNKNOWN) { + if (encs_assigned[i] == ENGINE_ID_UNKNOWN && + dc->res_pool->link_encoders[i] != NULL) { link_enc = dc->res_pool->link_encoders[i]; break; } @@ -506,6 +507,26 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( return link_enc; } +struct link_encoder *link_enc_cfg_get_link_enc( + const struct dc_link *link) +{ + struct link_encoder *link_enc = NULL; + + /* Links supporting dynamically assigned link encoder will be assigned next + * available encoder if one not already assigned. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) { + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); + if (link_enc == NULL) + link_enc = link_enc_cfg_get_next_avail_link_enc( + link->ctx->dc); + } else + link_enc = link->link_enc; + + return link_enc; +} + bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link) { bool is_avail = true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index c5146263f93c..5e9054fdb339 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -86,11 +86,7 @@ void dp_enable_link_phy( link->dc->res_pool->dp_clock_source; unsigned int i; - /* Link should always be assigned encoder when en-/disabling. */ - if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, link); - else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (link->connector_signal == SIGNAL_TYPE_EDP) { @@ -228,11 +224,7 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_ struct hpo_dp_link_encoder *hpo_link_enc = link_res->hpo_dp_link_enc; struct link_encoder *link_enc; - /* Link should always be assigned encoder when en-/disabling. */ - if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, link); - else - link_enc = link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (!link->wa_flags.dp_keep_receiver_powered) @@ -360,14 +352,8 @@ void dp_set_hw_test_pattern( struct link_encoder *encoder; enum dp_link_encoding link_encoding_format = dp_get_link_encoding_format(&link->cur_link_settings); - /* Access link encoder based on whether it is statically - * or dynamically assigned to a link. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - encoder = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - else - encoder = link->link_enc; + encoder = link_enc_cfg_get_link_enc(link); + ASSERT(encoder); pattern_param.dp_phy_pattern = test_pattern; pattern_param.custom_pattern = custom_pattern; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b18c8198f66d..b7c5c42d67ed 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -171,7 +171,6 @@ uint8_t dc_dp_initialize_scrambling_data_symbols( enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready); void dp_set_fec_enable(struct dc_link *link, bool enable); -struct link_encoder *dp_get_link_enc(struct dc_link *link); bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update); void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h index a4e43b4826e0..c2f08514a1d9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -96,6 +96,9 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( struct dc *dc, const struct dc_stream_state *stream); +/* Return DIG link encoder. NULL if unused. */ +struct link_encoder *link_enc_cfg_get_link_enc(const struct dc_link *link); + /* Return true if encoder available to use. */ bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link); From 9506b8d9626f4fbc230dad30cea1b3b095f1e4d4 Mon Sep 17 00:00:00 2001 From: Josip Pavic Date: Sun, 23 Jan 2022 13:19:59 -0500 Subject: [PATCH 142/339] drm/amd/display: do not compare integers of different widths [Why & How] Increase width of some variables to avoid comparing integers of different widths Tested-by: Daniel Wheeler Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Josip Pavic Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 147a03a1500b..f8f363773920 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4744,7 +4744,7 @@ const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link) void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) { struct dc_link *link; - uint8_t i; + uint32_t i; uint32_t hpo_dp_recycle_map = 0; *map = 0; @@ -4785,7 +4785,7 @@ void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) void dc_restore_link_res_map(const struct dc *dc, uint32_t *map) { struct dc_link *link; - uint8_t i; + uint32_t i; unsigned int available_hpo_dp_count; uint32_t hpo_dp_recycle_map = (*map & LINK_RES_HPO_DP_REC_MAP__MASK) >> LINK_RES_HPO_DP_REC_MAP__SHIFT; From 2eee829ed48747181b17f3f8d458b23981f2bb7b Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Sun, 23 Jan 2022 13:20:00 -0500 Subject: [PATCH 143/339] drm/amd/display: Driver support for MCLK query tool Implement handling for escape call to query the MCLK switch support for the current display config. Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Alvin Lee Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dml/display_mode_vba.c | 24 +++++++++++++++++++ .../drm/amd/display/dc/dml/display_mode_vba.h | 1 + 2 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 0fad15020c74..c0740dbdcc2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -47,6 +47,7 @@ static void recalculate_params( unsigned int num_pipes); static unsigned int CursorBppEnumToBits(enum cursor_bpp ebpp); +static void cache_debug_params(struct display_mode_lib *mode_lib); unsigned int dml_get_voltage_level( struct display_mode_lib *mode_lib, @@ -73,6 +74,7 @@ unsigned int dml_get_voltage_level( PixelClockAdjustmentForProgressiveToInterlaceUnit(mode_lib); } mode_lib->funcs.validate(mode_lib); + cache_debug_params(mode_lib); return mode_lib->vba.VoltageLevel; } @@ -745,6 +747,28 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.HostVMEnable = mode_lib->vba.HostVMEnable && !!ip->hostvm_enable; } +/** + * ******************************************************************************************** + * cache_debug_params: Cache any params that needed to be maintained from the initial validation + * for debug purposes. + * + * The DML getters can modify some of the VBA params that we are interested in (for example when + * calculating with dummy p-state latency), so cache any params here that we want for debugging + * + * @param [in] mode_lib: mode_lib input/output of validate call + * + * @return: void + * + * ******************************************************************************************** + */ +static void cache_debug_params(struct display_mode_lib *mode_lib) +{ + int k = 0; + + for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; k++) + mode_lib->vba.CachedActiveDRAMClockChangeLatencyMargin[k] = mode_lib->vba.ActiveDRAMClockChangeLatencyMargin[k]; +} + // in wm mode we pull the parameters needed from the display_e2e_pipe_params_st structs // rather than working them out as in recalculate_ms static void recalculate_params( diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 8fe74a3b39a8..0603b32971a6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -195,6 +195,7 @@ struct vba_vars_st { unsigned int LBLatencyHidingSourceLinesY; unsigned int LBLatencyHidingSourceLinesC; double ActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; + double CachedActiveDRAMClockChangeLatencyMargin[DC__NUM_DPP__MAX]; // Cache in dml_get_voltage_level for debug purposes only double MinActiveDRAMClockChangeMargin; double InitFillLevel; double FinalFillMargin; From e2d8ea4320c6fcf9f042e432232240f858ae9ed8 Mon Sep 17 00:00:00 2001 From: Varone Date: Sun, 23 Jan 2022 13:20:01 -0500 Subject: [PATCH 144/339] drm/amd/display: Change error to warning when hpd remains low for eDP [WHY?] SKUs that contain an unused eDP connector will throw an error when no display is connected. [HOW?] Change error to a warning. Tested-by: Daniel Wheeler Reviewed-by: Martin Leung Acked-by: Rodrigo Siqueira Signed-off-by: Dillon Varone Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b83c5544247d..72dd41e7a7d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -793,7 +793,7 @@ void dce110_edp_wait_for_hpd_ready( dal_gpio_destroy_irq(&hpd); if (false == edp_hpd_high) { - DC_LOG_ERROR( + DC_LOG_WARNING( "%s: wait timed out!\n", __func__); } } From 1210b17dd4ece454d68a9283f391e3b036aeb010 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Sun, 23 Jan 2022 13:20:02 -0500 Subject: [PATCH 145/339] drm/amd/display: Only set PSR version when valid [Why] DMCUB will hang if we send a PSR unsupported set version command. This can occur if we fall-through into the default case in the switch statement for PSR version. [How] Add an unsupported check after the switch statement. Tested-by: Daniel Wheeler Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 87ed48d5530d..8bd265b40847 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -138,6 +138,10 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * cmd.psr_set_version.psr_set_version_data.version = PSR_VERSION_UNSUPPORTED; break; } + + if (cmd.psr_set_version.psr_set_version_data.version == PSR_VERSION_UNSUPPORTED) + return false; + cmd.psr_set_version.psr_set_version_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; cmd.psr_set_version.psr_set_version_data.panel_inst = panel_inst; cmd.psr_set_version.header.payload_bytes = sizeof(struct dmub_cmd_psr_set_version_data); From 87e298d6e3a2169831a2f4a29e35575ee5747036 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Sun, 23 Jan 2022 13:20:03 -0500 Subject: [PATCH 146/339] drm/amd/display: Change return type of dm_helpers_dp_mst_stop_top_mgr Prepare for future dm can have different implementation depends on the return value. Tested-by: Daniel Wheeler Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Signed-off-by: Ian Chen Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 24 ++++--------------- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 14 ++++++----- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 2 +- 3 files changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index bfeace371ac1..575840c4db58 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -445,40 +445,24 @@ bool dm_helpers_dp_mst_start_top_mgr( return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0); } -void dm_helpers_dp_mst_stop_top_mgr( +bool dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, struct dc_link *link) { struct amdgpu_dm_connector *aconnector = link->priv; - uint8_t i; if (!aconnector) { DRM_ERROR("Failed to find connector for link!"); - return; + return false; } DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n", aconnector, aconnector->base.base.id); - if (aconnector->mst_mgr.mst_state == true) { + if (aconnector->mst_mgr.mst_state == true) drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false); - for (i = 0; i < MAX_SINKS_PER_LINK; i++) { - if (link->remote_sinks[i] == NULL) - continue; - - if (link->remote_sinks[i]->sink_signal == - SIGNAL_TYPE_DISPLAY_PORT_MST) { - dc_link_remove_remote_sink(link, link->remote_sinks[i]); - - if (aconnector->dc_sink) { - dc_sink_release(aconnector->dc_sink); - aconnector->dc_sink = NULL; - aconnector->dc_link->cur_link_settings.lane_count = 0; - } - } - } - } + return false; } bool dm_helpers_dp_read_dpcd( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f8f363773920..08fbf0ab047a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -840,20 +840,22 @@ static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason return link->type == dc_connection_mst_branch; } -static void reset_cur_dp_mst_topology(struct dc_link *link) +static bool reset_cur_dp_mst_topology(struct dc_link *link) { + bool result = false; DC_LOGGER_INIT(link->ctx->logger); LINK_INFO("link=%d, mst branch is now Disconnected\n", link->link_index); revert_dpia_mst_dsc_always_on_wa(link); - dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); + result = dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); link->mst_stream_alloc_table.stream_count = 0; memset(link->mst_stream_alloc_table.stream_allocations, 0, sizeof(link->mst_stream_alloc_table.stream_allocations)); + return result; } static bool should_prepare_phy_clocks_for_link_verification(const struct dc *dc, @@ -1306,7 +1308,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { bool is_local_sink_detect_success; - bool is_remote_sink_detect_required = false; + bool is_delegated_to_mst_top_mgr = false; enum dc_connection_type pre_link_type = link->type; is_local_sink_detect_success = detect_link_and_local_sink(link, reason); @@ -1317,14 +1319,14 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) if (is_local_sink_detect_success && link->local_sink && dc_is_dp_signal(link->local_sink->sink_signal) && link->dpcd_caps.is_mst_capable) - is_remote_sink_detect_required = discover_dp_mst_topology(link, reason); + is_delegated_to_mst_top_mgr = discover_dp_mst_topology(link, reason); if (is_local_sink_detect_success && pre_link_type == dc_connection_mst_branch && link->type != dc_connection_mst_branch) - reset_cur_dp_mst_topology(link); + is_delegated_to_mst_top_mgr = reset_cur_dp_mst_topology(link); - return is_local_sink_detect_success && !is_remote_sink_detect_required; + return is_local_sink_detect_success && !is_delegated_to_mst_top_mgr; } bool dc_link_get_hpd_state(struct dc_link *dc_link) diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index a5497ba89f15..b71b5fb894e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -113,7 +113,7 @@ bool dm_helpers_dp_mst_start_top_mgr( const struct dc_link *link, bool boot); -void dm_helpers_dp_mst_stop_top_mgr( +bool dm_helpers_dp_mst_stop_top_mgr( struct dc_context *ctx, struct dc_link *link); /** From b80ddeb29d9df449f875f0b6f5de08d7537c02b8 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Sun, 23 Jan 2022 13:20:04 -0500 Subject: [PATCH 147/339] drm/amd/display: Use PSR version selected during set_psr_caps [Why] If the DPCD caps specifies a PSR version newer than PSR_VERSION_1 then we fallback to using PSR_VERSION_1 in amdgpu_dm_set_psr_caps. This gets overriden with the raw DPCD value in amdgpu_dm_link_setup_psr, which can result in DMCUB hanging if we pass in an unsupported PSR version number. [How] Fix the hang by using link->psr_settings.psr_version directly during amdgpu_dm_link_setup_psr. Tested-by: Daniel Wheeler Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index c510638b4f99..a009fc654ac9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -149,10 +149,8 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream) link = stream->link; - psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version; - - if (psr_config.psr_version > 0) { - psr_config.psr_exit_link_training_required = 0x1; + if (link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) { + psr_config.psr_version = link->psr_settings.psr_version; psr_config.psr_frame_capture_indication_req = 0; psr_config.psr_rfb_setup_time = 0x37; psr_config.psr_sdp_transmit_line_num_deadline = 0x20; From 4a3ad932b2c538c62e4a60dd4b7411f802e018ec Mon Sep 17 00:00:00 2001 From: "Shen, George" Date: Sun, 23 Jan 2022 13:20:05 -0500 Subject: [PATCH 148/339] drm/amd/display: Add Cable ID support for native DP [Why/How] We need to handle cable capabilities for cables that support cable ID. The cable attributes are intersected with the verified link caps to determine appropriate max link rate. After determining cable attributes we update the DP receiver. Tested-by: Daniel Wheeler Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Signed-off-by: George Shen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 ++ .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 59 +++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 + drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 16 +++++ drivers/gpu/drm/amd/display/dc/dc_link.h | 7 +++ .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 3 + 6 files changed, 92 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 08fbf0ab047a..47cced994bfb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1291,6 +1291,8 @@ static bool detect_link_and_local_sink(struct dc_link *link, * Clear dongle_max_pix_clk on disconnect to fix this */ link->dongle_max_pix_clk = 0; + + dc_link_dp_clear_rx_status(link); } LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n", @@ -1970,6 +1972,9 @@ static enum dc_status enable_link_dp(struct dc_state *state, if (link->dpcd_sink_ext_caps.raw != 0) msleep(post_oui_delay); + // similarly, mode switch can cause loss of cable ID + dpcd_update_cable_id(link); + skip_video_pattern = true; if (link_settings.link_rate == LINK_RATE_LOW) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index a514f19d8f8b..062bdbadc781 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2981,6 +2981,20 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) return lttpr_max_link_rate; } +static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link) +{ + enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3; + + if (link->dpcd_caps.cable_attributes.bits.UHBR10_20_CAPABILITY & DP_UHBR20) + cable_max_link_rate = LINK_RATE_UHBR20; + else if (link->dpcd_caps.cable_attributes.bits.UHBR13_5_CAPABILITY) + cable_max_link_rate = LINK_RATE_UHBR13_5; + else if (link->dpcd_caps.cable_attributes.bits.UHBR10_20_CAPABILITY & DP_UHBR10) + cable_max_link_rate = LINK_RATE_UHBR10; + + return cable_max_link_rate; +} + bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) { struct link_encoder *link_enc = NULL; @@ -3009,8 +3023,10 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) { struct dc_link_settings max_link_cap = {0}; enum dc_link_rate lttpr_max_link_rate; + enum dc_link_rate cable_max_link_rate; struct link_encoder *link_enc = NULL; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); @@ -3029,6 +3045,14 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) max_link_cap.link_spread) max_link_cap.link_spread = link->reported_link_cap.link_spread; + + /* Lower link settings based on cable attributes */ + cable_max_link_rate = get_cable_max_link_rate(link); + + if (!link->dc->debug.ignore_cable_id && + cable_max_link_rate < max_link_cap.link_rate) + max_link_cap.link_rate = cable_max_link_rate; + /* * account for lttpr repeaters cap * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). @@ -5059,6 +5083,13 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) return is_lttpr_present; } + +static bool is_usbc_connector(struct dc_link *link) +{ + return link->link_enc && + link->link_enc->features.flags.bits.DP_IS_USB_C; +} + static bool retrieve_link_cap(struct dc_link *link) { /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16, @@ -5115,6 +5146,9 @@ static bool retrieve_link_cap(struct dc_link *link) */ msleep(post_oui_delay); + /* Read cable ID and update receiver */ + dpcd_update_cable_id(link); + for (i = 0; i < read_dpcd_retry_cnt; i++) { status = core_link_read_dpcd( link, @@ -6292,6 +6326,26 @@ void dpcd_set_source_specific_data(struct dc_link *link) } } +void dpcd_update_cable_id(struct dc_link *link) +{ + if (!link->link_enc->features.flags.bits.IS_UHBR10_CAPABLE || + link->dprx_status.cable_id_updated) + return; + + /* Retrieve cable attributes */ + if (!is_usbc_connector(link)) + core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX, + &link->dpcd_caps.cable_attributes.raw, + sizeof(uint8_t)); + + /* Update receiver with cable attributes */ + core_link_write_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX, + &link->dpcd_caps.cable_attributes.raw, + sizeof(link->dpcd_caps.cable_attributes.raw)); + + link->dprx_status.cable_id_updated = 1; +} + bool dc_link_set_backlight_level_nits(struct dc_link *link, bool isHDR, uint32_t backlight_millinits, @@ -6689,3 +6743,8 @@ void edp_panel_backlight_power_on(struct dc_link *link) if (link->dc->hwss.edp_backlight_control) link->dc->hwss.edp_backlight_control(link, true); } + +void dc_link_dp_clear_rx_status(struct dc_link *link) +{ + memset(&link->dprx_status, 0, sizeof(link->dprx_status)); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ff5093e52f2d..0dc183d6af5d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -687,6 +687,7 @@ struct dc_debug_options { bool set_mst_en_for_sst; bool disable_uhbr; bool force_dp2_lt_fallback_method; + bool ignore_cable_id; union mem_low_power_enable_options enable_mem_low_power; union root_clock_optimization_options root_clock_optimization; bool hpo_optimization; @@ -1234,6 +1235,7 @@ struct dpcd_caps { union dp_main_line_channel_coding_cap channel_coding_cap; union dp_sink_video_fallback_formats fallback_formats; union dp_fec_capability1 fec_cap1; + union dp_cable_attributes cable_attributes; }; union dpcd_sink_ext_caps { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 7b1103e9f7a2..772084406795 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -901,6 +901,9 @@ struct dpcd_usb4_dp_tunneling_info { #ifndef DP_LINK_SQUARE_PATTERN #define DP_LINK_SQUARE_PATTERN 0x10F #endif +#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX +#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX 0x110 +#endif #ifndef DP_DSC_CONFIGURATION #define DP_DSC_CONFIGURATION 0x161 #endif @@ -913,6 +916,9 @@ struct dpcd_usb4_dp_tunneling_info { #ifndef DP_128b_132b_TRAINING_AUX_RD_INTERVAL #define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216 #endif +#ifndef DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX +#define DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX 0x2217 +#endif #ifndef DP_TEST_264BIT_CUSTOM_PATTERN_7_0 #define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230 #endif @@ -1012,6 +1018,16 @@ union dp_fec_capability1 { uint8_t raw; }; +union dp_cable_attributes { + struct { + uint8_t UHBR10_20_CAPABILITY :2; + uint8_t UHBR13_5_CAPABILITY :1; + uint8_t CABLE_TYPE :3; + uint8_t RESERVED :2; + } bits; + uint8_t raw; +}; + struct dp_color_depth_caps { uint8_t support_6bpc :1; uint8_t support_8bpc :1; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 9014c0a0a63b..b1c79b3f26aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -43,6 +43,10 @@ struct dc_link_status { struct dpcd_caps *dpcd_caps; }; +struct dp_receiver_status { + bool cable_id_updated; +}; + /* DP MST stream allocation (payload bandwidth number) */ struct link_mst_stream_allocation { /* DIG front */ @@ -201,6 +205,7 @@ struct dc_link { struct link_mst_stream_allocation_table mst_stream_alloc_table; struct dc_link_status link_status; + struct dp_receiver_status dprx_status; struct link_trace link_trace; struct gpio *hpd_gpio; @@ -459,4 +464,6 @@ const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link) void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map); /* restore link resource allocation state from a snapshot */ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map); + +void dc_link_dp_clear_rx_status(struct dc_link *link); #endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b7c5c42d67ed..3ed2dbbf5642 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -112,6 +112,9 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); bool dp_overwrite_extended_receiver_cap(struct dc_link *link); void dpcd_set_source_specific_data(struct dc_link *link); + +void dpcd_update_cable_id(struct dc_link *link); + /* Write DPCD link configuration data. */ enum dc_status dpcd_set_link_settings( struct dc_link *link, From 2ca97adccdc90247c907541089e85101b2d87574 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Sun, 23 Jan 2022 13:20:06 -0500 Subject: [PATCH 149/339] drm/amd/display: Add Synaptics Fifo Reset Workaround Sequence to reset synaptics SDP fifo before enabling first stream Tested-by: Daniel Wheeler Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 133 ++++++++++++++++++ .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 10 ++ 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 575840c4db58..8554c93c9fa9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -536,6 +536,139 @@ bool dm_helpers_submit_i2c( return result; } + +static bool execute_synatpics_rc_command(struct drm_dp_aux *aux, + bool is_write_cmd, + unsigned char cmd, + unsigned int length, + unsigned int offset, + unsigned char *data) +{ + bool success = false; + unsigned char rc_data[16] = {0}; + unsigned char rc_offset[4] = {0}; + unsigned char rc_length[2] = {0}; + unsigned char rc_cmd = 0; + unsigned char rc_result = 0xFF; + unsigned char i = 0; + uint8_t ret = 0; + + if (is_write_cmd) { + // write rc data + memmove(rc_data, data, length); + ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_DATA, rc_data, sizeof(rc_data)); + } + + // write rc offset + rc_offset[0] = (unsigned char) offset & 0xFF; + rc_offset[1] = (unsigned char) (offset >> 8) & 0xFF; + rc_offset[2] = (unsigned char) (offset >> 16) & 0xFF; + rc_offset[3] = (unsigned char) (offset >> 24) & 0xFF; + ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_OFFSET, rc_offset, sizeof(rc_offset)); + + // write rc length + rc_length[0] = (unsigned char) length & 0xFF; + rc_length[1] = (unsigned char) (length >> 8) & 0xFF; + ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_LENGTH, rc_length, sizeof(rc_length)); + + // write rc cmd + rc_cmd = cmd | 0x80; + ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd)); + + if (ret < 0) { + DRM_ERROR(" execute_synatpics_rc_command - write cmd ..., err = %d\n", ret); + return false; + } + + // poll until active is 0 + for (i = 0; i < 10; i++) { + drm_dp_dpcd_read(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd)); + if (rc_cmd == cmd) + // active is 0 + break; + msleep(10); + } + + // read rc result + drm_dp_dpcd_read(aux, SYNAPTICS_RC_RESULT, &rc_result, sizeof(rc_result)); + success = (rc_result == 0); + + if (success && !is_write_cmd) { + // read rc data + drm_dp_dpcd_read(aux, SYNAPTICS_RC_DATA, data, length); + } + + DC_LOG_DC(" execute_synatpics_rc_command - success = %d\n", success); + + return success; +} + +static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux) +{ + unsigned char data[16] = {0}; + + DC_LOG_DC("Start apply_synaptics_fifo_reset_wa\n"); + + // Step 2 + data[0] = 'P'; + data[1] = 'R'; + data[2] = 'I'; + data[3] = 'U'; + data[4] = 'S'; + + if (!execute_synatpics_rc_command(aux, true, 0x01, 5, 0, data)) + return; + + // Step 3 and 4 + if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220998, data)) + return; + + data[0] &= (~(1 << 1)); // set bit 1 to 0 + if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220998, data)) + return; + + if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) + return; + + data[0] &= (~(1 << 1)); // set bit 1 to 0 + if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220D98, data)) + return; + + if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x221198, data)) + return; + + data[0] &= (~(1 << 1)); // set bit 1 to 0 + if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x221198, data)) + return; + + // Step 3 and 5 + if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220998, data)) + return; + + data[0] |= (1 << 1); // set bit 1 to 1 + if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220998, data)) + return; + + if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) + return; + + data[0] |= (1 << 1); // set bit 1 to 1 + return; + + if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x221198, data)) + return; + + data[0] |= (1 << 1); // set bit 1 to 1 + if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x221198, data)) + return; + + // Step 6 + if (!execute_synatpics_rc_command(aux, true, 0x02, 0, 0, NULL)) + return; + + DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n"); +} + bool dm_helpers_dp_write_dsc_enable( struct dc_context *ctx, const struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index cc34a35d0bcb..23cc6a6fe70e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -159,7 +159,7 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { }; #if defined(CONFIG_DRM_AMD_DC_DCN) -static bool needs_dsc_aux_workaround(struct dc_link *link) +bool needs_dsc_aux_workaround(struct dc_link *link) { if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && (link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) && diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 900d3f7a8498..5da28ca03372 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -26,6 +26,14 @@ #ifndef __DAL_AMDGPU_DM_MST_TYPES_H__ #define __DAL_AMDGPU_DM_MST_TYPES_H__ +#define DP_BRANCH_DEVICE_ID_90CC24 0x90CC24 + +#define SYNAPTICS_RC_COMMAND 0x4B2 +#define SYNAPTICS_RC_RESULT 0x4B3 +#define SYNAPTICS_RC_LENGTH 0x4B8 +#define SYNAPTICS_RC_OFFSET 0x4BC +#define SYNAPTICS_RC_DATA 0x4C0 + struct amdgpu_display_manager; struct amdgpu_dm_connector; @@ -50,6 +58,8 @@ struct dsc_mst_fairness_vars { bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, struct dc_state *dc_state, struct dsc_mst_fairness_vars *vars); + +bool needs_dsc_aux_workaround(struct dc_link *link); #endif #endif From 09db246ceef70bc6bd9c3e0d02b3c855f8fc25fb Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Sun, 23 Jan 2022 13:20:07 -0500 Subject: [PATCH 150/339] drm/amd/display: Retrieve MST Downstream Port Status Determine if DFP present and the type of downstream device based on dsc_aux Tested-by: Daniel Wheeler Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index b9a69b0cef23..e35977fda5c1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -604,6 +604,7 @@ struct amdgpu_dm_connector { #endif bool force_yuv420_output; struct dsc_preferred_settings dsc_settings; + union dp_downstream_port_present mst_downstream_port_present; /* Cached display modes */ struct drm_display_mode freesync_vid_base; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 23cc6a6fe70e..8e97d21bdf5c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -209,6 +209,25 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto return true; } + +bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnector) +{ + union dp_downstream_port_present ds_port_present; + + if (!aconnector->dsc_aux) + return false; + + if (drm_dp_dpcd_read(aconnector->dsc_aux, DP_DOWNSTREAMPORT_PRESENT, &ds_port_present, 1) < 0) { + DRM_INFO("Failed to read downstream_port_present 0x05 from DFP of branch device\n"); + return false; + } + + aconnector->mst_downstream_port_present = ds_port_present; + DRM_INFO("Downstream port present %d, type %d\n", + ds_port_present.fields.PORT_PRESENT, ds_port_present.fields.PORT_TYPE); + + return true; +} #endif static int dm_dp_mst_get_modes(struct drm_connector *connector) @@ -289,6 +308,10 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) if (!validate_dsc_caps_on_connector(aconnector)) memset(&aconnector->dc_sink->dsc_caps, 0, sizeof(aconnector->dc_sink->dsc_caps)); + + if (!retrieve_downstream_port_device(aconnector)) + memset(&aconnector->mst_downstream_port_present, + 0, sizeof(aconnector->mst_downstream_port_present)); #endif } } From 9cc370435cde6b672b6e2221115c2f535e8bd4ec Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Sun, 23 Jan 2022 13:20:08 -0500 Subject: [PATCH 151/339] drm/amd/display: Add DSC Enable for Synaptics Hub DSC sequence for non virtual dpcd synaptics hub Tested-by: Daniel Wheeler Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 48 +++++++++++++++++++ .../amd/display/include/ddc_service_types.h | 3 ++ 2 files changed, 51 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 8554c93c9fa9..75b5299b3576 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -39,6 +39,7 @@ #include "amdgpu_dm_mst_types.h" #include "dm_helpers.h" +#include "ddc_service_types.h" struct monitor_patch_info { unsigned int manufacturer_id; @@ -537,6 +538,7 @@ bool dm_helpers_submit_i2c( return result; } +#if defined(CONFIG_DRM_AMD_DC_DCN) static bool execute_synatpics_rc_command(struct drm_dp_aux *aux, bool is_write_cmd, unsigned char cmd, @@ -669,6 +671,43 @@ static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux) DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n"); } +static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst( + struct drm_dp_aux *aux, + const struct dc_stream_state *stream, + bool enable) +{ + uint8_t ret = 0; + + DC_LOG_DC("Configure DSC to non-virtual dpcd synaptics\n"); + + if (enable) { + /* When DSC is enabled on previous boot and reboot with the hub, + * there is a chance that Synaptics hub gets stuck during reboot sequence. + * Applying a workaround to reset Synaptics SDP fifo before enabling the first stream + */ + if (!stream->link->link_status.link_active && + memcmp(stream->link->dpcd_caps.branch_dev_name, + (int8_t *)SYNAPTICS_DEVICE_ID, 4) == 0) + apply_synaptics_fifo_reset_wa(aux); + + ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1); + DRM_INFO("Send DSC enable to synaptics\n"); + + } else { + /* Synaptics hub not support virtual dpcd, + * external monitor occur garbage while disable DSC, + * Disable DSC only when entire link status turn to false, + */ + if (!stream->link->link_status.link_active) { + ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1); + DRM_INFO("Send DSC disable to synaptics\n"); + } + } + + return ret; +} +#endif + bool dm_helpers_dp_write_dsc_enable( struct dc_context *ctx, const struct dc_stream_state *stream, @@ -687,7 +726,16 @@ bool dm_helpers_dp_write_dsc_enable( if (!aconnector->dsc_aux) return false; +#if defined(CONFIG_DRM_AMD_DC_DCN) + // apply w/a to synaptics + if (needs_dsc_aux_workaround(aconnector->dc_link) && + (aconnector->mst_downstream_port_present.byte & 0x7) != 0x3) + return write_dsc_enable_synaptics_non_virtual_dpcd_mst( + aconnector->dsc_aux, stream, enable_dsc); +#endif + ret = drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1); + DC_LOG_DC("Send DSC %s to MST RX\n", enable_dsc ? "enable" : "disable"); } if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) { diff --git a/drivers/gpu/drm/amd/display/include/ddc_service_types.h b/drivers/gpu/drm/amd/display/include/ddc_service_types.h index 57f92bd2814f..fb289a5c873a 100644 --- a/drivers/gpu/drm/amd/display/include/ddc_service_types.h +++ b/drivers/gpu/drm/amd/display/include/ddc_service_types.h @@ -123,4 +123,7 @@ struct av_sync_data { static const uint8_t DP_SINK_DEVICE_STR_ID_1[] = {7, 1, 8, 7, 3, 0}; static const uint8_t DP_SINK_DEVICE_STR_ID_2[] = {7, 1, 8, 7, 5, 0}; +/*MST Dock*/ +static const uint8_t SYNAPTICS_DEVICE_ID[] = "SYNA"; + #endif /* __DAL_DDC_SERVICE_TYPES_H__ */ From 5f2c1192eba42f6926253a1f2c9b18da05b3c31f Mon Sep 17 00:00:00 2001 From: Roy Chan Date: Sun, 23 Jan 2022 13:20:09 -0500 Subject: [PATCH 152/339] drm/amd/display: Support synchronized indirect reg access [Why] indirect register index/data pair may be used by multi-threads. when it happens, it would cause register access issue that is hard to trace. [How] Using cgs service, which provide a sync indirect reg access api. Tested-by: Daniel Wheeler Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Roy Chan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_helper.c | 60 +++++++++++++++++++ .../gpu/drm/amd/display/dc/inc/reg_helper.h | 34 +++++++++++ 2 files changed, 94 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index ab6bc5d79012..f43cce16bb6c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -588,6 +588,66 @@ uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx, return reg_val; } + +uint32_t generic_indirect_reg_update_ex_sync(const struct dc_context *ctx, + uint32_t index, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, + ...) +{ + uint32_t shift, mask, field_value; + int i = 1; + + va_list ap; + + va_start(ap, field_value1); + + reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t); + + reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); + i++; + } + + dm_write_index_reg(ctx, CGS_IND_REG__PCIE, index, reg_val); + va_end(ap); + + return reg_val; +} + +uint32_t generic_indirect_reg_get_sync(const struct dc_context *ctx, + uint32_t index, int n, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + ...) +{ + uint32_t shift, mask, *field_value; + uint32_t value = 0; + int i = 1; + + va_list ap; + + va_start(ap, field_value1); + + value = dm_read_index_reg(ctx, CGS_IND_REG__PCIE, index); + *field_value1 = get_reg_field_value_ex(value, mask1, shift1); + + while (i < n) { + shift = va_arg(ap, uint32_t); + mask = va_arg(ap, uint32_t); + field_value = va_arg(ap, uint32_t *); + + *field_value = get_reg_field_value_ex(value, mask, shift); + i++; + } + + va_end(ap); + + return value; +} + void reg_sequence_start_gather(const struct dc_context *ctx) { /* if reg sequence is supported and enabled, set flag to diff --git a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h index 2470405e996b..a402df225a76 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/reg_helper.h @@ -498,6 +498,40 @@ uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx, uint8_t shift1, uint32_t mask1, uint32_t field_value1, ...); +/* indirect register access + * underlying implementation determines which index/data pair to be used + * in a synchronous way + */ +#define IX_REG_SET_N_SYNC(index, n, initial_val, ...) \ + generic_indirect_reg_update_ex_sync(CTX, \ + IND_REG(index), \ + initial_val, \ + n, __VA_ARGS__) + +#define IX_REG_SET_2_SYNC(index, init_value, f1, v1, f2, v2) \ + IX_REG_SET_N_SYNC(index, 2, init_value, \ + FN(reg, f1), v1,\ + FN(reg, f2), v2) + +#define IX_REG_GET_N_SYNC(index, n, ...) \ + generic_indirect_reg_get_sync(CTX, \ + IND_REG(index), \ + n, __VA_ARGS__) + +#define IX_REG_GET_SYNC(index, field, val) \ + IX_REG_GET_N_SYNC(index, 1, \ + FN(data_reg_name, field), val) + +uint32_t generic_indirect_reg_get_sync(const struct dc_context *ctx, + uint32_t index, int n, + uint8_t shift1, uint32_t mask1, uint32_t *field_value1, + ...); + +uint32_t generic_indirect_reg_update_ex_sync(const struct dc_context *ctx, + uint32_t index, uint32_t reg_val, int n, + uint8_t shift1, uint32_t mask1, uint32_t field_value1, + ...); + /* register offload macros * * instead of MMIO to register directly, in some cases we want From 72b90723b3760c69721b04f59436f38cd215e2df Mon Sep 17 00:00:00 2001 From: Sung Joon Kim Date: Sun, 23 Jan 2022 13:20:11 -0500 Subject: [PATCH 153/339] drm/amd/display: remove PHY repeater count check for LTTPR mode [why] Due to bad hardware, the PHY repeater count in LTTPR cap is read as 0xFF in some monitors while the LTTPR is actually present. [how] Remove PHY repeater counter check when configuring LTTPR mode. Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Sung Joon Kim Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 062bdbadc781..538ace042961 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5069,9 +5069,8 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ - is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && + is_lttpr_present = (link->dpcd_caps.lttpr_caps.max_lane_count > 0 && link->dpcd_caps.lttpr_caps.phy_repeater_cnt < 0xff && - link->dpcd_caps.lttpr_caps.max_lane_count > 0 && link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); if (is_lttpr_present) { From 0c5a0bbb7379625eb2a5b6a931415c008b7a1a16 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Sun, 23 Jan 2022 13:20:12 -0500 Subject: [PATCH 154/339] drm/amd/display: Update VSC HDR infoPacket on TF change [why] OnSetSourceContentAttribute it does not trigger an update for the VSC with TF change. [how] In this call, create a new VSC infoPacket based on the new config, and allow DisplayTarget decide if an update and pursuant passive flip is necessary Tested-by: Daniel Wheeler Reviewed-by: Krunoslav Kovac Acked-by: Rodrigo Siqueira Signed-off-by: Reza Amini Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../amd/display/modules/inc/mod_info_packet.h | 3 ++- .../display/modules/info_packet/info_packet.c | 25 ++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c0ab23274f96..44f4d862a022 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6494,7 +6494,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) stream->use_vsc_sdp_for_colorimetry = true; } - mod_build_vsc_infopacket(stream, &stream->vsc_infopacket); + mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space); aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; } diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index 1ab813b4fd14..1d8b746b02f2 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -34,7 +34,8 @@ struct dc_info_packet; struct mod_vrr_params; void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet); + struct dc_info_packet *info_packet, + enum dc_color_space cs); void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet); diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 57f198de5e2c..b691aa45e84f 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -130,7 +130,8 @@ enum ColorimetryYCCDP { }; void mod_build_vsc_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet) + struct dc_info_packet *info_packet, + enum dc_color_space cs) { unsigned int vsc_packet_revision = vsc_packet_undefined; unsigned int i; @@ -331,13 +332,13 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, /* Set Colorimetry format based on pixel encoding */ switch (stream->timing.pixel_encoding) { case PIXEL_ENCODING_RGB: - if ((stream->output_color_space == COLOR_SPACE_SRGB) || - (stream->output_color_space == COLOR_SPACE_SRGB_LIMITED)) + if ((cs == COLOR_SPACE_SRGB) || + (cs == COLOR_SPACE_SRGB_LIMITED)) colorimetryFormat = ColorimetryRGB_DP_sRGB; - else if (stream->output_color_space == COLOR_SPACE_ADOBERGB) + else if (cs == COLOR_SPACE_ADOBERGB) colorimetryFormat = ColorimetryRGB_DP_AdobeRGB; - else if ((stream->output_color_space == COLOR_SPACE_2020_RGB_FULLRANGE) || - (stream->output_color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE)) + else if ((cs == COLOR_SPACE_2020_RGB_FULLRANGE) || + (cs == COLOR_SPACE_2020_RGB_LIMITEDRANGE)) colorimetryFormat = ColorimetryRGB_DP_ITU_R_BT2020RGB; break; @@ -347,13 +348,13 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, /* Note: xvYCC probably not supported correctly here on DP since colorspace translation * loses distinction between BT601 vs xvYCC601 in translation */ - if (stream->output_color_space == COLOR_SPACE_YCBCR601) + if (cs == COLOR_SPACE_YCBCR601) colorimetryFormat = ColorimetryYCC_DP_ITU601; - else if (stream->output_color_space == COLOR_SPACE_YCBCR709) + else if (cs == COLOR_SPACE_YCBCR709) colorimetryFormat = ColorimetryYCC_DP_ITU709; - else if (stream->output_color_space == COLOR_SPACE_ADOBERGB) + else if (cs == COLOR_SPACE_ADOBERGB) colorimetryFormat = ColorimetryYCC_DP_AdobeYCC; - else if (stream->output_color_space == COLOR_SPACE_2020_YCBCR) + else if (cs == COLOR_SPACE_2020_YCBCR) colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr; break; @@ -391,8 +392,8 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, } /* all YCbCr are always limited range */ - if ((stream->output_color_space == COLOR_SPACE_SRGB_LIMITED) || - (stream->output_color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) || + if ((cs == COLOR_SPACE_SRGB_LIMITED) || + (cs == COLOR_SPACE_2020_RGB_LIMITEDRANGE) || (pixelEncoding != 0x0)) { info_packet->sb[17] |= 0x80; /* DB17 bit 7 set to 1 for CEA timing. */ } From 5cef7e8e2fcc6f9e8d2134668848a31b15c523b8 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sun, 23 Jan 2022 13:20:13 -0500 Subject: [PATCH 155/339] drm/amd/display: [FW Promotion] Release 0.0.101.0 - Add Scr8 for GPINT messaging between driver and fw Tested-by: Daniel Wheeler Acked-by: Rodrigo Siqueira Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index e13d50abc281..3ef6a7a0c7b6 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x56a29f36 +#define DMUB_FW_VERSION_GIT_HASH 0x1288a7b7 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 100 +#define DMUB_FW_VERSION_REVISION 101 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -367,8 +367,9 @@ union dmub_fw_boot_options { /**< 1 if all root clock gating is enabled and low power memory is enabled*/ uint32_t power_optimization: 1; uint32_t diag_env: 1; /* 1 if diagnostic environment */ + uint32_t gpint_scratch8: 1; /* 1 if GPINT is in scratch8*/ - uint32_t reserved : 19; /**< reserved */ + uint32_t reserved : 18; /**< reserved */ } bits; /**< boot bits */ uint32_t all; /**< 32-bit access to bits */ }; @@ -644,6 +645,7 @@ enum dmub_cmd_type { * Command type used for OUTBOX1 notification enable */ DMUB_CMD__OUTBOX1_ENABLE = 71, + /** * Command type used for all idle optimization commands. */ @@ -656,6 +658,7 @@ enum dmub_cmd_type { * Command type used for all panel control commands. */ DMUB_CMD__PANEL_CNTL = 74, + /** * Command type used for interfacing with DPIA. */ From d52e77a3ffcf2da2be1a7892bc8fa67b0e907058 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Sun, 23 Jan 2022 13:20:14 -0500 Subject: [PATCH 156/339] drm/amd/display: Reset preferred training settings immediately [Why & How] In order to easily test ilr by immediately reset the preferred training settings, fix the code to disable skip_immediate_retrain. Tested-by: Daniel Wheeler Reviewed-by: Solomon Chiu Acked-by: Rodrigo Siqueira Signed-off-by: Wayne Lin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 12d437d9a0e4..aca725874bcf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2887,7 +2887,7 @@ static ssize_t edp_ilr_write(struct file *f, const char __user *buf, kfree(wr_buf); DRM_DEBUG_DRIVER("Invalid Input value. No HW will be programmed\n"); prefer_link_settings.use_link_rate_set = false; - dc_link_set_preferred_training_settings(dc, NULL, NULL, link, true); + dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false); return size; } From 53a35edfd0a767dbd04537596d95f56e94582f50 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 23 Jan 2022 13:20:15 -0500 Subject: [PATCH 157/339] drm/amd/display: 3.2.170 This version brings along the following fixes: - Z9 improvements - Clocks management adjustments - Code cleanup - Improve DSC and MST code Tested-by: Daniel Wheeler Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0dc183d6af5d..69cf78fe78cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.169" +#define DC_VER "3.2.170" #define MAX_SURFACES 3 #define MAX_PLANES 6 From d063e70c6acad14987242f266e9448669db4624e Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 23 Jan 2022 13:20:16 -0500 Subject: [PATCH 158/339] drm/amd/display: Remove unnecessary function definition Tested-by: Daniel Wheeler Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 5 ----- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h | 3 --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index dec8604a0612..ed0a0e5fd805 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -355,11 +355,6 @@ void dcn30_prepare_bandwidth(struct dc *dc, dcn20_prepare_bandwidth(dc, context); } -void dcn30_optimize_bandwidth(struct dc *dc, struct dc_state *context) -{ - dcn20_optimize_bandwidth(dc, context); -} - void dcn30_disable_writeback( struct dc *dc, unsigned int dwb_pipe_inst) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h index 357ee14711ad..73e7b690e82c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h @@ -50,9 +50,6 @@ void dcn30_disable_writeback( void dcn30_prepare_bandwidth(struct dc *dc, struct dc_state *context); -void dcn30_optimize_bandwidth(struct dc *dc, - struct dc_state *context); - bool dcn30_mmhubbub_warmup( struct dc *dc, unsigned int num_dwb, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 73a416cba563..bb347319de83 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -60,7 +60,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .interdependent_update_lock = dcn10_lock_all_pipes, .cursor_lock = dcn10_cursor_lock, .prepare_bandwidth = dcn20_prepare_bandwidth, - .optimize_bandwidth = dcn30_optimize_bandwidth, + .optimize_bandwidth = dcn20_optimize_bandwidth, .update_bandwidth = dcn20_update_bandwidth, .set_drr = dcn10_set_drr, .get_position = dcn10_get_position, From f6a3795d35c69bd34a556e1d93000057aed78599 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Sun, 23 Jan 2022 13:20:17 -0500 Subject: [PATCH 159/339] drm/amd/display: allow set dp drive setting when stream is not present [why] There is a change previously to disallow DM to set dp drive setings when stream is not present. The logic might not work well with DP PHY complaince scenario with a PHY test fixture attachment. We need to make the method allow DP link drive settings changes even without stream attached to it. [how] revert back to previous code in set drive setting function then add an empty link_resource structure, then assign link resource based on current link resource if link resource is allocated to the current pipe. Tested-by: Daniel Wheeler Reviewed-by: Wayne Lin Acked-by: Rodrigo Siqueira Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 30 ++++++++----------- drivers/gpu/drm/amd/display/dc/dc_link.h | 3 +- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 47cced994bfb..1e596f1ea494 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4455,22 +4455,17 @@ void dc_link_set_drive_settings(struct dc *dc, { int i; - struct pipe_ctx *pipe = NULL; - const struct link_resource *link_res; + struct link_resource link_res; - link_res = dc_link_get_cur_link_res(link); + for (i = 0; i < dc->link_count; i++) + if (dc->links[i] == link) + break; - for (i = 0; i < MAX_PIPES; i++) { - pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe->stream && pipe->stream->link) { - if (pipe->stream->link == link) - break; - } - } - if (pipe && link_res) - dc_link_dp_set_drive_settings(pipe->stream->link, link_res, lt_settings); - else + if (i >= dc->link_count) ASSERT_CRITICAL(false); + + dc_link_get_cur_link_res(link, &link_res); + dc_link_dp_set_drive_settings(dc->links[i], &link_res, lt_settings); } void dc_link_set_preferred_link_settings(struct dc *dc, @@ -4712,23 +4707,24 @@ uint32_t dc_bandwidth_in_kbps_from_timing( } -const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link) +void dc_link_get_cur_link_res(const struct dc_link *link, + struct link_resource *link_res) { int i; struct pipe_ctx *pipe = NULL; - const struct link_resource *link_res = NULL; + + memset(link_res, 0, sizeof(*link_res)); for (i = 0; i < MAX_PIPES; i++) { pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->stream && pipe->stream->link && pipe->top_pipe == NULL) { if (pipe->stream->link == link) { - link_res = &pipe->link_res; + *link_res = pipe->link_res; break; } } } - return link_res; } /** diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index b1c79b3f26aa..6c02244e7fe7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -459,7 +459,8 @@ bool dc_link_should_enable_fec(const struct dc_link *link); uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw); enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link); -const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link); +void dc_link_get_cur_link_res(const struct dc_link *link, + struct link_resource *link_res); /* take a snapshot of current link resource allocation state */ void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map); /* restore link resource allocation state from a snapshot */ From 0015cce5cf04d3bd7b2ae4f62d5cea5d35383e8c Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Sun, 23 Jan 2022 13:20:18 -0500 Subject: [PATCH 160/339] drm/amd/display: Fix disabling dccg clocks [How & Why] Updated procedure to match hardware programming guide. Tested-by: Daniel Wheeler Reviewed-by: Eric Yang Acked-by: Rodrigo Siqueira Signed-off-by: David Galiffi Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h | 7 +++ .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 44 ++++++++++++------- .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h | 1 + 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h index f98aba308028..493c47a3d06e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h @@ -183,8 +183,14 @@ type SYMCLK32_ROOT_SE1_GATE_DISABLE;\ type SYMCLK32_ROOT_SE2_GATE_DISABLE;\ type SYMCLK32_ROOT_SE3_GATE_DISABLE;\ + type SYMCLK32_SE0_GATE_DISABLE;\ + type SYMCLK32_SE1_GATE_DISABLE;\ + type SYMCLK32_SE2_GATE_DISABLE;\ + type SYMCLK32_SE3_GATE_DISABLE;\ type SYMCLK32_ROOT_LE0_GATE_DISABLE;\ type SYMCLK32_ROOT_LE1_GATE_DISABLE;\ + type SYMCLK32_LE0_GATE_DISABLE;\ + type SYMCLK32_LE1_GATE_DISABLE;\ type DPSTREAMCLK_ROOT_GATE_DISABLE;\ type DPSTREAMCLK_GATE_DISABLE;\ type HDMISTREAMCLK0_DTO_PHASE;\ @@ -233,6 +239,7 @@ struct dccg_registers { uint32_t DSCCLK2_DTO_PARAM; uint32_t DPSTREAMCLK_ROOT_GATE_DISABLE; uint32_t DPSTREAMCLK_GATE_DISABLE; + uint32_t DCCG_GATE_DISABLE_CNTL2; uint32_t DCCG_GATE_DISABLE_CNTL3; uint32_t HDMISTREAMCLK0_DTO_PARAM; uint32_t DCCG_GATE_DISABLE_CNTL4; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index ea4f8e06b07c..720bd35582b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -121,7 +121,8 @@ static void dccg31_enable_dpstreamclk(struct dccg *dccg, int otg_inst) return; } if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + DPSTREAMCLK_GATE_DISABLE, 1, DPSTREAMCLK_ROOT_GATE_DISABLE, 1); } @@ -130,8 +131,9 @@ static void dccg31_disable_dpstreamclk(struct dccg *dccg, int otg_inst) struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, - DPSTREAMCLK_ROOT_GATE_DISABLE, 0); + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + DPSTREAMCLK_ROOT_GATE_DISABLE, 0, + DPSTREAMCLK_GATE_DISABLE, 0); switch (otg_inst) { case 0: @@ -180,7 +182,8 @@ void dccg31_enable_symclk32_se( switch (hpo_se_inst) { case 0: if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE0_GATE_DISABLE, 1, SYMCLK32_ROOT_SE0_GATE_DISABLE, 1); REG_UPDATE_2(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, phyd32clk, @@ -188,7 +191,8 @@ void dccg31_enable_symclk32_se( break; case 1: if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE1_GATE_DISABLE, 1, SYMCLK32_ROOT_SE1_GATE_DISABLE, 1); REG_UPDATE_2(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, phyd32clk, @@ -196,7 +200,8 @@ void dccg31_enable_symclk32_se( break; case 2: if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE2_GATE_DISABLE, 1, SYMCLK32_ROOT_SE2_GATE_DISABLE, 1); REG_UPDATE_2(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, phyd32clk, @@ -204,7 +209,8 @@ void dccg31_enable_symclk32_se( break; case 3: if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE3_GATE_DISABLE, 1, SYMCLK32_ROOT_SE3_GATE_DISABLE, 1); REG_UPDATE_2(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, phyd32clk, @@ -229,7 +235,8 @@ void dccg31_disable_symclk32_se( SYMCLK32_SE0_SRC_SEL, 0, SYMCLK32_SE0_EN, 0); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE0_GATE_DISABLE, 0, SYMCLK32_ROOT_SE0_GATE_DISABLE, 0); break; case 1: @@ -237,7 +244,8 @@ void dccg31_disable_symclk32_se( SYMCLK32_SE1_SRC_SEL, 0, SYMCLK32_SE1_EN, 0); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE1_GATE_DISABLE, 0, SYMCLK32_ROOT_SE1_GATE_DISABLE, 0); break; case 2: @@ -245,7 +253,8 @@ void dccg31_disable_symclk32_se( SYMCLK32_SE2_SRC_SEL, 0, SYMCLK32_SE2_EN, 0); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE2_GATE_DISABLE, 0, SYMCLK32_ROOT_SE2_GATE_DISABLE, 0); break; case 3: @@ -253,7 +262,8 @@ void dccg31_disable_symclk32_se( SYMCLK32_SE3_SRC_SEL, 0, SYMCLK32_SE3_EN, 0); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_SE3_GATE_DISABLE, 0, SYMCLK32_ROOT_SE3_GATE_DISABLE, 0); break; default: @@ -275,7 +285,8 @@ void dccg31_enable_symclk32_le( switch (hpo_le_inst) { case 0: if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_LE0_GATE_DISABLE, 1, SYMCLK32_ROOT_LE0_GATE_DISABLE, 1); REG_UPDATE_2(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, phyd32clk, @@ -283,7 +294,8 @@ void dccg31_enable_symclk32_le( break; case 1: if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_LE1_GATE_DISABLE, 1, SYMCLK32_ROOT_LE1_GATE_DISABLE, 1); REG_UPDATE_2(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, phyd32clk, @@ -308,7 +320,8 @@ void dccg31_disable_symclk32_le( SYMCLK32_LE0_SRC_SEL, 0, SYMCLK32_LE0_EN, 0); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_LE0_GATE_DISABLE, 0, SYMCLK32_ROOT_LE0_GATE_DISABLE, 0); break; case 1: @@ -316,7 +329,8 @@ void dccg31_disable_symclk32_le( SYMCLK32_LE1_SRC_SEL, 0, SYMCLK32_LE1_EN, 0); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL3, + REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3, + SYMCLK32_LE1_GATE_DISABLE, 0, SYMCLK32_ROOT_LE1_GATE_DISABLE, 0); break; default: diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h index a013a32bbaf7..4039273872be 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h @@ -66,6 +66,7 @@ SR(DSCCLK1_DTO_PARAM),\ SR(DSCCLK2_DTO_PARAM),\ SR(DSCCLK_DTO_CTRL),\ + SR(DCCG_GATE_DISABLE_CNTL2),\ SR(DCCG_GATE_DISABLE_CNTL3),\ SR(HDMISTREAMCLK0_DTO_PARAM) From 05d6aea36a69e65b071e6ba897bf83a4aebaeab2 Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Sun, 23 Jan 2022 13:20:19 -0500 Subject: [PATCH 161/339] drm/amd/display: Disable physym clock [How & Why] Disable physym clock when it's not in use. Tested-by: Daniel Wheeler Reviewed-by: Eric Yang Acked-by: Rodrigo Siqueira Signed-off-by: David Galiffi Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h | 8 ++- .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 62 ++++++++++++++++--- .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h | 5 ++ 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h index 493c47a3d06e..b3c9a9724efd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h @@ -196,8 +196,12 @@ type HDMISTREAMCLK0_DTO_PHASE;\ type HDMISTREAMCLK0_DTO_MODULO;\ type HDMICHARCLK0_GATE_DISABLE;\ - type HDMICHARCLK0_ROOT_GATE_DISABLE; - + type HDMICHARCLK0_ROOT_GATE_DISABLE; \ + type PHYASYMCLK_GATE_DISABLE; \ + type PHYBSYMCLK_GATE_DISABLE; \ + type PHYCSYMCLK_GATE_DISABLE; \ + type PHYDSYMCLK_GATE_DISABLE; \ + type PHYESYMCLK_GATE_DISABLE; struct dccg_shift { DCCG_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index 720bd35582b0..287a1066b547 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -420,54 +420,89 @@ void dccg31_set_physymclk( /* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */ switch (phy_inst) { case 0: - if (force_enable) + if (force_enable) { REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, 1, PHYASYMCLK_FORCE_SRC_SEL, clk_src); - else + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYASYMCLK_GATE_DISABLE, 1); + } else { REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, 0, PHYASYMCLK_FORCE_SRC_SEL, 0); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYASYMCLK_GATE_DISABLE, 0); + } break; case 1: - if (force_enable) + if (force_enable) { REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, 1, PHYBSYMCLK_FORCE_SRC_SEL, clk_src); - else + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYBSYMCLK_GATE_DISABLE, 1); + } else { REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, 0, PHYBSYMCLK_FORCE_SRC_SEL, 0); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYBSYMCLK_GATE_DISABLE, 0); + } break; case 2: - if (force_enable) + if (force_enable) { REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, 1, PHYCSYMCLK_FORCE_SRC_SEL, clk_src); - else + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYCSYMCLK_GATE_DISABLE, 1); + } else { REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, 0, PHYCSYMCLK_FORCE_SRC_SEL, 0); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYCSYMCLK_GATE_DISABLE, 0); + } break; case 3: - if (force_enable) + if (force_enable) { REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_FORCE_EN, 1, PHYDSYMCLK_FORCE_SRC_SEL, clk_src); - else + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYDSYMCLK_GATE_DISABLE, 1); + } else { REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_FORCE_EN, 0, PHYDSYMCLK_FORCE_SRC_SEL, 0); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYDSYMCLK_GATE_DISABLE, 0); + } break; case 4: - if (force_enable) + if (force_enable) { REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_FORCE_EN, 1, PHYESYMCLK_FORCE_SRC_SEL, clk_src); - else + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYESYMCLK_GATE_DISABLE, 1); + } else { REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_FORCE_EN, 0, PHYESYMCLK_FORCE_SRC_SEL, 0); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, + PHYESYMCLK_GATE_DISABLE, 0); + } break; default: BREAK_TO_DEBUGGER(); @@ -629,6 +664,13 @@ void dccg31_init(struct dccg *dccg) dccg31_disable_dpstreamclk(dccg, 3); } + if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) { + dccg31_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false); + dccg31_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false); + dccg31_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false); + dccg31_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false); + dccg31_set_physymclk(dccg, 4, PHYSYMCLK_FORCE_SRC_SYMCLK, false); + } } static const struct dccg_funcs dccg31_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h index 4039273872be..269cabbea72a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h @@ -136,6 +136,11 @@ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_DTO_ENABLE, mask_sh),\ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_DTO_ENABLE, mask_sh),\ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_DTO_ENABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_GATE_DISABLE, mask_sh),\ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_ROOT_GATE_DISABLE, mask_sh),\ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, DPSTREAMCLK_GATE_DISABLE, mask_sh),\ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\ From 85b8f62b564120943cc0db1e754d6649037e6c7a Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Sun, 23 Jan 2022 13:20:20 -0500 Subject: [PATCH 162/339] drm/amd/display: fix zstate allow interface to PMFW [Why] psr_feature_enabled flag is dynamically updated, and sometimes when zstate allow status is determined the flag has not been set to true yet even on PSR enabled config, lid off/on is such a case, which will result in zstate disabled even though PSR is supported. [How] Check the supported PSR version and the PSR disable status instead. Tested-by: Daniel Wheeler Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Eric Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index d0a5c7afa265..fcf388b509db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3099,7 +3099,7 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0) return DCN_ZSTATE_SUPPORT_ALLOW; - else if (link->psr_settings.psr_feature_enabled) + else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !dc->debug.disable_psr) return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; else return DCN_ZSTATE_SUPPORT_DISALLOW; From b5d9a483685c37a480420cfe2d41a03d529bc0a5 Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Sun, 23 Jan 2022 13:20:21 -0500 Subject: [PATCH 163/339] drm/amd/display: add debug option for z9 disable interface [Why] To help triage issues and coordinate driver/bios release dependency [How] Only enable the new Z9 interface when debug option is set, otherwise treat Z10 only support case as Zstate disallowed. Tested-by: Daniel Wheeler Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Eric Yang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c | 6 +++++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c index 1c0415366216..9b4836350547 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c @@ -308,12 +308,16 @@ void dcn31_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr) void dcn31_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support) { - //TODO: Work with smu team to define optimization options. unsigned int msg_id, param; if (!clk_mgr->smu_present) return; + if (!clk_mgr->base.ctx->dc->debug.enable_z9_disable_interface && + (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY)) + support = DCN_ZSTATE_SUPPORT_DISALLOW; + + if (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY) param = 1; else diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 69cf78fe78cf..4f9dacd09856 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -703,6 +703,7 @@ struct dc_debug_options { int crb_alloc_policy_min_disp_count; #if defined(CONFIG_DRM_AMD_DC_DCN) bool disable_z10; + bool enable_z9_disable_interface; bool enable_sw_cntl_psr; union dpia_debug_options dpia_debug; #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 8d64187478e4..f9e312b20598 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1033,6 +1033,7 @@ static const struct dc_debug_options debug_defaults_drv = { .optimize_edp_link_rate = true, .enable_sw_cntl_psr = true, .apply_vendor_specific_lttpr_wa = true, + .enable_z9_disable_interface = false }; static const struct dc_debug_options debug_defaults_diags = { From f2bde8349c35d01d7c50456ea06a5c7d5e0e5ed0 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 24 Jan 2022 13:50:49 -0500 Subject: [PATCH 164/339] drm/amd/display: Call dc_stream_release for remove link enc assignment [Why] A porting error resulted in the stream assignment for the link being retained without being released - a memory leak. [How] Fix the porting error by adding back the dc_stream_release() intended as part of the original patch. Fixes: 0bb245558584 ("drm/amd/display: retain/release at proper places in link_enc assignment") Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index a380611b1e42..047c626a4a34 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -122,6 +122,7 @@ static void remove_link_enc_assignment( stream->link_enc = NULL; state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].eng_id = ENGINE_ID_UNKNOWN; state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].stream = NULL; + dc_stream_release(stream); break; } } From b9610edcfec216d7a2a5ea2c942734b3e5e26ffc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Jan 2022 09:23:47 -0500 Subject: [PATCH 165/339] drm/amdgpu/pm/smu7: drop message about VI performance levels Earlier chips only had two performance levels, but newer ones potentially had more. The message is harmless. Drop the message to avoid spamming the log. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1874 Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index cd99db0dc2be..a1e11037831a 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -3295,10 +3295,6 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, request_ps->classification.ui_label); data->mclk_ignore_signal = false; - PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2, - "VI should always have 2 performance levels", - ); - max_limits = adev->pm.ac_power ? &(hwmgr->dyn_state.max_clock_voltage_on_ac) : &(hwmgr->dyn_state.max_clock_voltage_on_dc); From 212021297eafe23b79ac117db9b5159d1df2ff30 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Jan 2022 09:31:38 -0500 Subject: [PATCH 166/339] drm/amdgpu: set APU flag based on IP discovery table Use the IP versions to set the APU flag when necessary. Reviewed-by: Aaron Liu Acked-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 8dd15a7b8dcc..eb4b7059633d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1259,6 +1259,19 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) return -EINVAL; } + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(9, 1, 0): + case IP_VERSION(9, 2, 2): + case IP_VERSION(9, 3, 0): + case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 3, 1): + case IP_VERSION(10, 3, 3): + adev->flags |= AMD_IS_APU; + break; + default: + break; + } + if (adev->ip_versions[XGMI_HWIP][0] == IP_VERSION(4, 8, 0)) adev->gmc.xgmi.supported = true; From 901e2be20dc55079997ea1885ea77fc72e6826e7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Jan 2022 13:42:30 -0500 Subject: [PATCH 167/339] drm/amdgpu: move PX checking into amdgpu_device_ip_early_init We need to set the APU flag from IP discovery before we evaluate this code. Acked-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 11 ----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5159c6dedc04..7cec3a0f61b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -2073,6 +2074,8 @@ out: */ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) { + struct drm_device *dev = adev_to_drm(adev); + struct pci_dev *parent; int i, r; amdgpu_device_enable_virtual_display(adev); @@ -2137,6 +2140,16 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) break; } + if (amdgpu_has_atpx() && + (amdgpu_is_atpx_hybrid() || + amdgpu_has_atpx_dgpu_power_cntl()) && + ((adev->flags & AMD_IS_APU) == 0) && + !pci_is_thunderbolt_attached(to_pci_dev(dev->dev))) + adev->flags |= AMD_IS_PX; + + parent = pci_upstream_bridge(adev->pdev); + adev->has_pr3 = parent ? pci_pr3_present(parent) : false; + amdgpu_amdkfd_device_probe(adev); adev->pm.pp_feature = amdgpu_pp_feature_mask; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index e5e69fcc3af3..36dedceb6ded 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -152,21 +152,10 @@ static void amdgpu_get_audio_func(struct amdgpu_device *adev) int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) { struct drm_device *dev; - struct pci_dev *parent; int r, acpi_status; dev = adev_to_drm(adev); - if (amdgpu_has_atpx() && - (amdgpu_is_atpx_hybrid() || - amdgpu_has_atpx_dgpu_power_cntl()) && - ((flags & AMD_IS_APU) == 0) && - !pci_is_thunderbolt_attached(to_pci_dev(dev->dev))) - flags |= AMD_IS_PX; - - parent = pci_upstream_bridge(adev->pdev); - adev->has_pr3 = parent ? pci_pr3_present(parent) : false; - /* amdgpu_device_init should report only fatal error * like memory allocation failure or iomapping failure, * or memory manager initialization failure, it must From d0d66b8c66d04363eff3a5b09da4074fc1dfc758 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Jan 2022 14:58:31 -0500 Subject: [PATCH 168/339] drm/amdgpu: move runtime pm init after drm and fbdev init Seems more logical to enable runtime pm at the end of the init sequence so we don't end up entering runtime suspend before init is finished. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 65 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 69 +------------------------ 2 files changed, 66 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 1a691a801928..4a5da4913d4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1946,6 +1946,22 @@ MODULE_DEVICE_TABLE(pci, pciidlist); static const struct drm_driver amdgpu_kms_driver; +static void amdgpu_get_audio_func(struct amdgpu_device *adev) +{ + struct pci_dev *p = NULL; + + p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), + adev->pdev->bus->number, 1); + if (p) { + pm_runtime_get_sync(&p->dev); + + pm_runtime_mark_last_busy(&p->dev); + pm_runtime_put_autosuspend(&p->dev); + + pci_dev_put(p); + } +} + static int amdgpu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2071,6 +2087,48 @@ retry_init: if (ret) DRM_ERROR("Creating debugfs files failed (%d).\n", ret); + if (adev->runpm) { + /* only need to skip on ATPX */ + if (amdgpu_device_supports_px(ddev)) + dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_NO_DIRECT_COMPLETE); + /* we want direct complete for BOCO */ + if (amdgpu_device_supports_boco(ddev)) + dev_pm_set_driver_flags(ddev->dev, DPM_FLAG_SMART_PREPARE | + DPM_FLAG_SMART_SUSPEND | + DPM_FLAG_MAY_SKIP_RESUME); + pm_runtime_use_autosuspend(ddev->dev); + pm_runtime_set_autosuspend_delay(ddev->dev, 5000); + + pm_runtime_allow(ddev->dev); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + /* + * For runpm implemented via BACO, PMFW will handle the + * timing for BACO in and out: + * - put ASIC into BACO state only when both video and + * audio functions are in D3 state. + * - pull ASIC out of BACO state when either video or + * audio function is in D0 state. + * Also, at startup, PMFW assumes both functions are in + * D0 state. + * + * So if snd driver was loaded prior to amdgpu driver + * and audio function was put into D3 state, there will + * be no PMFW-aware D-state transition(D0->D3) on runpm + * suspend. Thus the BACO will be not correctly kicked in. + * + * Via amdgpu_get_audio_func(), the audio dev is put + * into D0 state. Then there will be a PMFW-aware D-state + * transition(D0->D3) on runpm suspend. + */ + if (amdgpu_device_supports_baco(ddev) && + !(adev->flags & AMD_IS_APU) && + (adev->asic_type >= CHIP_NAVI10)) + amdgpu_get_audio_func(adev); + } + return 0; err_pci: @@ -2082,8 +2140,15 @@ static void amdgpu_pci_remove(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); + struct amdgpu_device *adev = drm_to_adev(dev); drm_dev_unplug(dev); + + if (adev->runpm) { + pm_runtime_get_sync(dev->dev); + pm_runtime_forbid(dev->dev); + } + amdgpu_driver_unload_kms(dev); /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 36dedceb6ded..c2cb345b1421 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -87,11 +87,6 @@ void amdgpu_driver_unload_kms(struct drm_device *dev) if (adev->rmmio == NULL) return; - if (adev->runpm) { - pm_runtime_get_sync(dev->dev); - pm_runtime_forbid(dev->dev); - } - if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_UNLOAD)) DRM_WARN("smart shift update failed\n"); @@ -124,22 +119,6 @@ void amdgpu_register_gpu_instance(struct amdgpu_device *adev) mutex_unlock(&mgpu_info.mutex); } -static void amdgpu_get_audio_func(struct amdgpu_device *adev) -{ - struct pci_dev *p = NULL; - - p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), - adev->pdev->bus->number, 1); - if (p) { - pm_runtime_get_sync(&p->dev); - - pm_runtime_mark_last_busy(&p->dev); - pm_runtime_put_autosuspend(&p->dev); - - pci_dev_put(p); - } -} - /** * amdgpu_driver_load_kms - Main load function for KMS. * @@ -207,58 +186,12 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) if (acpi_status) dev_dbg(dev->dev, "Error during ACPI methods call\n"); - if (adev->runpm) { - /* only need to skip on ATPX */ - if (amdgpu_device_supports_px(dev)) - dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE); - /* we want direct complete for BOCO */ - if (amdgpu_device_supports_boco(dev)) - dev_pm_set_driver_flags(dev->dev, DPM_FLAG_SMART_PREPARE | - DPM_FLAG_SMART_SUSPEND | - DPM_FLAG_MAY_SKIP_RESUME); - pm_runtime_use_autosuspend(dev->dev); - pm_runtime_set_autosuspend_delay(dev->dev, 5000); - - pm_runtime_allow(dev->dev); - - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); - - /* - * For runpm implemented via BACO, PMFW will handle the - * timing for BACO in and out: - * - put ASIC into BACO state only when both video and - * audio functions are in D3 state. - * - pull ASIC out of BACO state when either video or - * audio function is in D0 state. - * Also, at startup, PMFW assumes both functions are in - * D0 state. - * - * So if snd driver was loaded prior to amdgpu driver - * and audio function was put into D3 state, there will - * be no PMFW-aware D-state transition(D0->D3) on runpm - * suspend. Thus the BACO will be not correctly kicked in. - * - * Via amdgpu_get_audio_func(), the audio dev is put - * into D0 state. Then there will be a PMFW-aware D-state - * transition(D0->D3) on runpm suspend. - */ - if (amdgpu_device_supports_baco(dev) && - !(adev->flags & AMD_IS_APU) && - (adev->asic_type >= CHIP_NAVI10)) - amdgpu_get_audio_func(adev); - } - if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DRV_LOAD)) DRM_WARN("smart shift update failed\n"); out: - if (r) { - /* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */ - if (adev->rmmio && adev->runpm) - pm_runtime_put_noidle(dev->dev); + if (r) amdgpu_driver_unload_kms(dev); - } return r; } From 243c719e872a1322b22efccff80776353357b296 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Jan 2022 15:00:14 -0500 Subject: [PATCH 169/339] drm/amdgpu: handle BACO synchronization with secondary funcs Extend secondary function handling for runtime pm beyond audio to USB and UCSI. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 4a5da4913d4e..9c799645f2e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1946,19 +1946,25 @@ MODULE_DEVICE_TABLE(pci, pciidlist); static const struct drm_driver amdgpu_kms_driver; -static void amdgpu_get_audio_func(struct amdgpu_device *adev) +static void amdgpu_get_secondary_funcs(struct amdgpu_device *adev) { struct pci_dev *p = NULL; + int i; - p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), - adev->pdev->bus->number, 1); - if (p) { - pm_runtime_get_sync(&p->dev); - - pm_runtime_mark_last_busy(&p->dev); - pm_runtime_put_autosuspend(&p->dev); - - pci_dev_put(p); + /* 0 - GPU + * 1 - audio + * 2 - USB + * 3 - UCSI + */ + for (i = 1; i < 4; i++) { + p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), + adev->pdev->bus->number, i); + if (p) { + pm_runtime_get_sync(&p->dev); + pm_runtime_mark_last_busy(&p->dev); + pm_runtime_put_autosuspend(&p->dev); + pci_dev_put(p); + } } } @@ -2119,14 +2125,14 @@ retry_init: * be no PMFW-aware D-state transition(D0->D3) on runpm * suspend. Thus the BACO will be not correctly kicked in. * - * Via amdgpu_get_audio_func(), the audio dev is put + * Via amdgpu_get_secondary_funcs(), the audio dev is put * into D0 state. Then there will be a PMFW-aware D-state * transition(D0->D3) on runpm suspend. */ if (amdgpu_device_supports_baco(ddev) && !(adev->flags & AMD_IS_APU) && (adev->asic_type >= CHIP_NAVI10)) - amdgpu_get_audio_func(adev); + amdgpu_get_secondary_funcs(adev); } return 0; From 82c3a7a5edbf5f6feae9602d19567d2b5b55121f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 21 Jan 2022 11:18:44 -0500 Subject: [PATCH 170/339] drm/amdgpu: convert amdgpu_display_supported_domains() to IP versions Check IP versions rather than asic types. Acked-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 29 ++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 82011e75ed85..6cad39c31c58 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -510,19 +510,24 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev, case CHIP_STONEY: domain |= AMDGPU_GEM_DOMAIN_GTT; break; - case CHIP_RAVEN: - /* enable S/G on PCO and RV2 */ - if ((adev->apu_flags & AMD_APU_IS_RAVEN2) || - (adev->apu_flags & AMD_APU_IS_PICASSO)) - domain |= AMDGPU_GEM_DOMAIN_GTT; - break; - case CHIP_RENOIR: - case CHIP_VANGOGH: - case CHIP_YELLOW_CARP: - domain |= AMDGPU_GEM_DOMAIN_GTT; - break; - default: + switch (adev->ip_versions[DCE_HWIP][0]) { + case IP_VERSION(1, 0, 0): + case IP_VERSION(1, 0, 1): + /* enable S/G on PCO and RV2 */ + if ((adev->apu_flags & AMD_APU_IS_RAVEN2) || + (adev->apu_flags & AMD_APU_IS_PICASSO)) + domain |= AMDGPU_GEM_DOMAIN_GTT; + break; + case IP_VERSION(2, 1, 0): + case IP_VERSION(3, 0, 1): + case IP_VERSION(3, 1, 2): + case IP_VERSION(3, 1, 3): + domain |= AMDGPU_GEM_DOMAIN_GTT; + break; + default: + break; + } break; } } From 153a9529d7f372ce7ceb5eae7e2c312c0cd64d41 Mon Sep 17 00:00:00 2001 From: Zhou Qingyang Date: Tue, 25 Jan 2022 00:55:51 +0800 Subject: [PATCH 171/339] drm/amd/display/dc/calcs/dce_calcs: Fix a memleak in calculate_bandwidth() In calculate_bandwidth(), the tag free_sclk and free_yclk are reversed, which could lead to a memory leak of yclk. Fix this bug by changing the location of free_sclk and free_yclk. This bug was found by a static analyzer. Builds with 'make allyesconfig' show no new warnings, and our static analyzer no longer warns about this code. Fixes: 2be8989d0fc2 ("drm/amd/display/dc/calcs/dce_calcs: Move some large variables from the stack to the heap") Signed-off-by: Zhou Qingyang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c index 8f136db39f3e..0100a6053ab6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c @@ -2033,10 +2033,10 @@ static void calculate_bandwidth( kfree(surface_type); free_tiling_mode: kfree(tiling_mode); -free_yclk: - kfree(yclk); free_sclk: kfree(sclk); +free_yclk: + kfree(yclk); } /******************************************************************************* From 588a70177df3b1777484267584ef38ab2ca899a2 Mon Sep 17 00:00:00 2001 From: Zhou Qingyang Date: Tue, 25 Jan 2022 00:57:29 +0800 Subject: [PATCH 172/339] drm/amd/display: Fix a NULL pointer dereference in amdgpu_dm_connector_add_common_modes() In amdgpu_dm_connector_add_common_modes(), amdgpu_dm_create_common_mode() is assigned to mode and is passed to drm_mode_probed_add() directly after that. drm_mode_probed_add() passes &mode->head to list_add_tail(), and there is a dereference of it in list_add_tail() without recoveries, which could lead to NULL pointer dereference on failure of amdgpu_dm_create_common_mode(). Fix this by adding a NULL check of mode. This bug was found by a static analyzer. Builds with 'make allyesconfig' show no new warnings, and our static analyzer no longer warns about this code. Fixes: e7b07ceef2a6 ("drm/amd/display: Merge amdgpu_dm_types and amdgpu_dm") Signed-off-by: Zhou Qingyang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 44f4d862a022..e6ff40fdf18b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8138,6 +8138,9 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, mode = amdgpu_dm_create_common_mode(encoder, common_modes[i].name, common_modes[i].w, common_modes[i].h); + if (!mode) + continue; + drm_mode_probed_add(connector, mode); amdgpu_dm_connector->num_modes++; } From 94ca070cd3737dd5c3b98f615bd4cc950f82a597 Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Mon, 24 Jan 2022 01:23:35 +0100 Subject: [PATCH 173/339] drm/amd/display: Fix FP start/end for dcn30_internal_validate_bw. It calls populate_dml_pipes which uses doubles to initialize the scale_ratio_depth params. Mirrors the dcn20 logic. Signed-off-by: Bas Nieuwenhuizen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 602ec9a08549..8ca26383b568 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1878,7 +1878,6 @@ noinline bool dcn30_internal_validate_bw( dc->res_pool->funcs->update_soc_for_wm_a(dc, context); pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); - DC_FP_START(); if (!pipe_cnt) { out = true; goto validate_out; @@ -2104,7 +2103,6 @@ validate_fail: out = false; validate_out: - DC_FP_END(); return out; } @@ -2306,7 +2304,9 @@ bool dcn30_validate_bandwidth(struct dc *dc, BW_VAL_TRACE_COUNT(); + DC_FP_START(); out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); + DC_FP_END(); if (pipe_cnt == 0) goto validate_out; From 5e6d72c643e1262ff02e057620b9f87d7d81141a Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Mon, 24 Jan 2022 01:23:36 +0100 Subject: [PATCH 174/339] drm/amd/display: Wrap dcn301_calculate_wm_and_dlg for FPU. Mirrors the logic for dcn30. Cue lots of WARNs and some kernel panics without this fix. Signed-off-by: Bas Nieuwenhuizen Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 11 +++++++++++ .../gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c | 2 +- .../gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index b4001233867c..5d9637b07429 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -1380,6 +1380,17 @@ static void set_wm_ranges( pp_smu->nv_funcs.set_wm_ranges(&pp_smu->nv_funcs.pp_smu, &ranges); } +static void dcn301_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + DC_FP_START(); + dcn301_calculate_wm_and_dlg_fp(dc, context, pipes, pipe_cnt, vlevel); + DC_FP_END(); +} + static struct resource_funcs dcn301_res_pool_funcs = { .destroy = dcn301_destroy_resource_pool, .link_enc_create = dcn301_link_encoder_create, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c index 94c32832a0e7..0a7a33864973 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.c @@ -327,7 +327,7 @@ void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info) dcn3_01_soc.sr_exit_time_us = bb_info.dram_sr_exit_latency_100ns * 10; } -void dcn301_calculate_wm_and_dlg(struct dc *dc, +void dcn301_calculate_wm_and_dlg_fp(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h index fc7065d17842..774b0fdfc80b 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn301/dcn301_fpu.h @@ -34,7 +34,7 @@ void dcn301_fpu_set_wm_ranges(int i, void dcn301_fpu_init_soc_bounding_box(struct bp_soc_bb_info bb_info); -void dcn301_calculate_wm_and_dlg(struct dc *dc, +void dcn301_calculate_wm_and_dlg_fp(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt, From 430e6a0212b2a0eb1de5e9d47a016fa79edf3978 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Mon, 24 Jan 2022 12:18:12 -0800 Subject: [PATCH 175/339] drm/amd/pm: return -ENOTSUPP if there is no get_dpm_ultimate_freq function clang static analysis reports this represenative problem amdgpu_smu.c:144:18: warning: The left operand of '*' is a garbage value return clk_freq * 100; ~~~~~~~~ ^ If there is no get_dpm_ultimate_freq function, smu_get_dpm_freq_range returns success without setting the output min,max parameters. So return an -ENOTSUPP error. Fixes: e5ef784b1e17 ("drm/amd/powerplay: revise calling chain on retrieving frequency range") Signed-off-by: Tom Rix Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 5ace30434e60..264eb09ccfd5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -116,7 +116,7 @@ int smu_get_dpm_freq_range(struct smu_context *smu, uint32_t *min, uint32_t *max) { - int ret = 0; + int ret = -ENOTSUPP; if (!min && !max) return -EINVAL; From ee2016b4b5bb70483e1c06218e7b6288704284cb Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 19 Jan 2022 22:46:28 +0000 Subject: [PATCH 176/339] drm/radeon: remove redundant assignment to reg The pointer reg is being assigned a value that is not read, the exit path via label 'out' never accesses it. The assignment is redundant and can be removed. Cleans up clang scan build warning: drivers/gpu/drm/radeon/radeon_object.c:570:3: warning: Value stored to 'reg' is never read [deadcode.DeadStores] Reviewed-by: Nick Desaulniers Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 56ede9d63b12..87536d205593 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -567,7 +567,6 @@ int radeon_bo_get_surface_reg(struct radeon_bo *bo) return 0; if (bo->surface_reg >= 0) { - reg = &rdev->surface_regs[bo->surface_reg]; i = bo->surface_reg; goto out; } From e6f62afe9b2731b7a94b31fe59ef2c5134ad426b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 21 Jan 2022 17:23:43 -0800 Subject: [PATCH 177/339] drm/amd/display: don't use /** for non-kernel-doc comments Change a static function's comment from "/**" (indicating kernel-doc notation) to "/*" (indicating a regular C language comment). This prevents multiple kernel-doc warnings: drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:4343: warning: Function parameter or member 'max_supported_frl_bw_in_kbps' not described in 'intersect_frl_link_bw_support' drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:4343: warning: Function parameter or member 'hdmi_encoded_link_bw' not described in 'intersect_frl_link_bw_support' drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:4343: warning: expecting prototype for Return PCON's post FRL link training supported BW if its non(). Prototype was for intersect_frl_link_bw_support() instead Fixes: c022375ae095 ("drm/amd/display: Add DP-HDMI FRL PCON Support in DC") Reviewed-by: Harry Wentland Signed-off-by: Randy Dunlap Reported-by: kernel test robot Cc: Fangzhi Zuo Cc: Alex Deucher Cc: Nicholas Kazlauskas Cc: Harry Wentland Cc: Leo Li Cc: Rodrigo Siqueira Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 538ace042961..8cfc9a8197df 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4698,7 +4698,7 @@ uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw) return 0; } -/** +/* * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw. */ static uint32_t intersect_frl_link_bw_support( From d726d43c20e744bab1e346c1f77b7a71eff0c40c Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 25 Jan 2022 11:12:07 +0800 Subject: [PATCH 178/339] drm/amdgpu: convert to NBIO IP version checking Use IP versions rather than asic_type to differentiate IP version specific features. Signed-off-by: Tim Huang Reviewed-by: Aaron Liu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c | 44 ++++++++++++++++++-------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c index 3444332ea110..44f17bbfeb6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_2.c @@ -59,10 +59,15 @@ static u32 nbio_v7_2_get_rev_id(struct amdgpu_device *adev) { u32 tmp; - if (adev->asic_type == CHIP_YELLOW_CARP) + switch (adev->ip_versions[NBIO_HWIP][0]) { + case IP_VERSION(7, 2, 1): + case IP_VERSION(7, 5, 0): tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_YC); - else + break; + default: tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0); + break; + } tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK; tmp >>= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT; @@ -72,20 +77,25 @@ static u32 nbio_v7_2_get_rev_id(struct amdgpu_device *adev) static void nbio_v7_2_mc_access_enable(struct amdgpu_device *adev, bool enable) { - if (enable) - if (adev->asic_type == CHIP_YELLOW_CARP) + switch (adev->ip_versions[NBIO_HWIP][0]) { + case IP_VERSION(7, 2, 1): + case IP_VERSION(7, 5, 0): + if (enable) WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_YC, BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK | BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK); else + WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_YC, 0); + break; + default: + if (enable) WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, BIF_BX0_BIF_FB_EN__FB_READ_EN_MASK | BIF_BX0_BIF_FB_EN__FB_WRITE_EN_MASK); - else - if (adev->asic_type == CHIP_YELLOW_CARP) - WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN_YC, 0); else WREG32_SOC15(NBIO, 0, regBIF_BX0_BIF_FB_EN, 0); + break; + } } static u32 nbio_v7_2_get_memsize(struct amdgpu_device *adev) @@ -250,7 +260,9 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev { uint32_t def, data; - if (adev->asic_type == CHIP_YELLOW_CARP) { + switch (adev->ip_versions[NBIO_HWIP][0]) { + case IP_VERSION(7, 2, 1): + case IP_VERSION(7, 5, 0): def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) data |= PCIE_CNTL2__SLV_MEM_LS_EN_MASK; @@ -260,8 +272,8 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev if (def != data) WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2), data); - data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_TX_POWER_CTRL_1)); - def = data; + def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, + regBIF1_PCIE_TX_POWER_CTRL_1)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) data |= (BIF1_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK | BIF1_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK); @@ -272,7 +284,8 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev if (def != data) WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_TX_POWER_CTRL_1), data); - } else { + break; + default: def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS)) data |= (PCIE_CNTL2__SLV_MEM_LS_EN_MASK | @@ -285,6 +298,7 @@ static void nbio_v7_2_update_medium_grain_light_sleep(struct amdgpu_device *adev if (def != data) WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CNTL2), data); + break; } } @@ -352,7 +366,9 @@ const struct nbio_hdp_flush_reg nbio_v7_2_hdp_flush_reg = { static void nbio_v7_2_init_registers(struct amdgpu_device *adev) { uint32_t def, data; - if (adev->asic_type == CHIP_YELLOW_CARP) { + switch (adev->ip_versions[NBIO_HWIP][0]) { + case IP_VERSION(7, 2, 1): + case IP_VERSION(7, 5, 0): def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_MST_CTRL_3)); data = REG_SET_FIELD(data, BIF1_PCIE_MST_CTRL_3, CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1); @@ -361,7 +377,8 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev) if (def != data) WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regBIF1_PCIE_MST_CTRL_3), data); - } else { + break; + default: def = data = RREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CONFIG_CNTL)); data = REG_SET_FIELD(data, PCIE_CONFIG_CNTL, CI_SWUS_MAX_READ_REQUEST_SIZE_MODE, 1); @@ -370,6 +387,7 @@ static void nbio_v7_2_init_registers(struct amdgpu_device *adev) if (def != data) WREG32_PCIE_PORT(SOC15_REG_OFFSET(NBIO, 0, regPCIE_CONFIG_CNTL), data); + break; } if (amdgpu_sriov_vf(adev)) From 37d6b1506b80a5cf76238b6b00926070ab544058 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 25 Jan 2022 11:13:39 +0800 Subject: [PATCH 179/339] drm/amdgpu: convert to UVD IP version checking Use IP versions rather than asic_type to differentiate IP version specific features. Signed-off-by: Tim Huang Reviewed-by: Aaron Liu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index 01c242c5abc3..41a00851b6c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -50,11 +50,16 @@ static int jpeg_v3_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type != CHIP_YELLOW_CARP) { - u32 harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING); + u32 harvest; + switch (adev->ip_versions[UVD_HWIP][0]) { + case IP_VERSION(3, 1, 1): + break; + default: + harvest = RREG32_SOC15(JPEG, 0, mmCC_UVD_HARVESTING); if (harvest & CC_UVD_HARVESTING__UVD_DISABLE_MASK) return -ENOENT; + break; } adev->jpeg.num_jpeg_inst = 1; From 3b36f50d3a69ed720e4c464bc9c5fa2c3fadc750 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Tue, 25 Jan 2022 11:14:46 +0800 Subject: [PATCH 180/339] drm/amd/display: convert to DCE IP version checking Use IP versions rather than asic_type to differentiate IP version specific features. Signed-off-by: Tim Huang Reviewed-by: Aaron Liu Acked-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e6ff40fdf18b..84342f27ee64 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1119,14 +1119,12 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) for (i = 0; i < fb_info->num_fb; ++i) hw_params.fb[i] = &fb_info->fb[i]; - switch (adev->asic_type) { - case CHIP_YELLOW_CARP: - if (dc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_A0) { - hw_params.dpia_supported = true; + switch (adev->ip_versions[DCE_HWIP][0]) { + case IP_VERSION(3, 1, 3): /* Only for this asic hw internal rev B0 */ + hw_params.dpia_supported = true; #if defined(CONFIG_DRM_AMD_DC_DCN) - hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia; + hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia; #endif - } break; default: break; From 039cacd2393971fe11f855118eea6c83c8f506fa Mon Sep 17 00:00:00 2001 From: Victor Zhao Date: Mon, 24 Jan 2022 12:13:58 +0800 Subject: [PATCH 181/339] drm/amdgpu: add determine passthrough under arm64 add determine for passthrough mode under arm64 by reading CurrentEL register v2: squash in warning fix (Alex) Signed-off-by: Victor Zhao Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index c5edd84c1c12..645093610aa0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -294,8 +294,10 @@ struct amdgpu_video_codec_info; static inline bool is_virtual_machine(void) { -#ifdef CONFIG_X86 +#if defined(CONFIG_X86) return boot_cpu_has(X86_FEATURE_HYPERVISOR); +#elif defined(CONFIG_ARM64) + return !is_kernel_in_hyp_mode(); #else return false; #endif From 1790b649b01ba7e44af7c08ffcfc0eaa9d4f5ac6 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Fri, 21 Jan 2022 10:39:54 -0500 Subject: [PATCH 182/339] drm/amdkfd: enable heavy-weight TLB flush on Vega20 It is to meet the requirement for memory allocation optimization on MI50. Signed-off-by: Eric Huang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 337953af7c2f..26a593b3d7dc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1419,7 +1419,8 @@ err_unlock: static bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) { return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2) || (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1) && - dev->adev->sdma.instance[0].fw_version >= 18); + dev->adev->sdma.instance[0].fw_version >= 18) || + KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 0); } static int kfd_ioctl_map_memory_to_gpu(struct file *filep, From b6dca949b88ee69561fc4ed853ab7a2ae13d842f Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Sun, 23 Jan 2022 03:38:28 +0100 Subject: [PATCH 183/339] drm/amdgpu/display: Remove t_srx_delay_us. Unused. Convert the divisions into asserts on the divisor, to debug why it is zero. The divide by zero is suspected of causing kernel panics. While I have no idea where the zero is coming from I think this patch is a positive either way. Reviewed-by: Harry Wentland Signed-off-by: Bas Nieuwenhuizen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c | 1 - .../gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c | 2 -- .../drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c | 2 -- .../gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c | 2 -- .../gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c | 2 -- drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h | 1 - drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c | 3 --- drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c | 4 ---- 8 files changed, 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c index ec19678a0702..e447c74be713 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c @@ -503,7 +503,6 @@ static void dcn_bw_calc_rq_dlg_ttu( //input[in_idx].dout.output_standard; /*todo: soc->sr_enter_plus_exit_time??*/ - dlg_sys_param->t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; dml1_rq_dlg_get_rq_params(dml, rq_param, &input->pipe.src); dml1_extract_rq_regs(dml, rq_regs, rq_param); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 246071c72f6b..548cdef8a8ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -1576,8 +1576,6 @@ void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, &dlg_sys_param); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index 015e7f2c0b16..0fc9f3e3ffae 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -1577,8 +1577,6 @@ void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, &dlg_sys_param); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index 8bc27de4c104..618f4b682ab1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -1688,8 +1688,6 @@ void dml21_rq_dlg_get_dlg_reg( mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, &dlg_sys_param); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index aef854270054..747167083dea 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -1858,8 +1858,6 @@ void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, e2e_pipe_param, num_pipes); - dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency - / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated print__dlg_sys_params_st(mode_lib, &dlg_sys_param); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index d46a2733024c..8f9f1d607f7c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -546,7 +546,6 @@ struct _vcs_dpi_display_dlg_sys_params_st { double t_sr_wm_us; double t_extra_us; double mem_trip_us; - double t_srx_delay_us; double deepsleep_dcfclk_mhz; double total_flip_bw; unsigned int total_flip_bytes; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index 71ea503cb32f..412e75eb4704 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -141,9 +141,6 @@ void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _v dml_print("DML_RQ_DLG_CALC: t_urg_wm_us = %3.2f\n", dlg_sys_param->t_urg_wm_us); dml_print("DML_RQ_DLG_CALC: t_sr_wm_us = %3.2f\n", dlg_sys_param->t_sr_wm_us); dml_print("DML_RQ_DLG_CALC: t_extra_us = %3.2f\n", dlg_sys_param->t_extra_us); - dml_print( - "DML_RQ_DLG_CALC: t_srx_delay_us = %3.2f\n", - dlg_sys_param->t_srx_delay_us); dml_print( "DML_RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f\n", dlg_sys_param->deepsleep_dcfclk_mhz); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 59dc2c5b58dd..3df559c591f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -1331,10 +1331,6 @@ void dml1_rq_dlg_get_dlg_params( if (dual_plane) DTRACE("DLG: %s: swath_height_c = %d", __func__, swath_height_c); - DTRACE( - "DLG: %s: t_srx_delay_us = %3.2f", - __func__, - (double) dlg_sys_param->t_srx_delay_us); DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); From ac7c48c0cce00d03b3c95fddcccb0a45257e33e3 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 24 Jan 2022 16:40:44 -0500 Subject: [PATCH 184/339] drm/amdkfd: Don't take process mutex for svm ioctls SVM ioctls take proper svms->lock to handle race conditions, don't need take process mutex to serialize ioctls. This also fixes circular locking warning: WARNING: possible circular locking dependency detected Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((work_completion)(&svms->deferred_list_work)); lock(&process->mutex); lock((work_completion)(&svms->deferred_list_work)); lock(&process->mutex); *** DEADLOCK *** Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 26a593b3d7dc..214a2c67fba4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1847,13 +1847,9 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) if (!args->start_addr || !args->size) return -EINVAL; - mutex_lock(&p->mutex); - r = svm_ioctl(p, args->op, args->start_addr, args->size, args->nattr, args->attrs); - mutex_unlock(&p->mutex); - return r; } #else From 367c9b0f1b8750a704070e7ae85234d591290434 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Tue, 18 Jan 2022 12:15:24 -0500 Subject: [PATCH 185/339] drm/amdkfd: Ensure mm remain valid in svm deferred_list work svm_deferred_list work should continue to handle deferred_range_list which maybe split to child range to avoid child range leak, and remove ranges mmu interval notifier to avoid mm mm_count leak. So taking mm reference when adding range to deferred list, to ensure mm is valid in the scheduled deferred_list_work, and drop the mm referrence after range is handled. Signed-off-by: Philip Yang Reported-by: Ruili Ji Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 62 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index f2805ba74c80..225affcddbc1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1985,10 +1985,9 @@ svm_range_update_notifier_and_interval_tree(struct mm_struct *mm, } static void -svm_range_handle_list_op(struct svm_range_list *svms, struct svm_range *prange) +svm_range_handle_list_op(struct svm_range_list *svms, struct svm_range *prange, + struct mm_struct *mm) { - struct mm_struct *mm = prange->work_item.mm; - switch (prange->work_item.op) { case SVM_OP_NULL: pr_debug("NULL OP 0x%p prange 0x%p [0x%lx 0x%lx]\n", @@ -2071,34 +2070,41 @@ static void svm_range_deferred_list_work(struct work_struct *work) pr_debug("enter svms 0x%p\n", svms); p = container_of(svms, struct kfd_process, svms); - /* Avoid mm is gone when inserting mmu notifier */ - mm = get_task_mm(p->lead_thread); - if (!mm) { - pr_debug("svms 0x%p process mm gone\n", svms); - return; - } -retry: - mmap_write_lock(mm); - - /* Checking for the need to drain retry faults must be inside - * mmap write lock to serialize with munmap notifiers. - */ - if (unlikely(atomic_read(&svms->drain_pagefaults))) { - mmap_write_unlock(mm); - svm_range_drain_retry_fault(svms); - goto retry; - } spin_lock(&svms->deferred_list_lock); while (!list_empty(&svms->deferred_range_list)) { prange = list_first_entry(&svms->deferred_range_list, struct svm_range, deferred_list); - list_del_init(&prange->deferred_list); spin_unlock(&svms->deferred_list_lock); pr_debug("prange 0x%p [0x%lx 0x%lx] op %d\n", prange, prange->start, prange->last, prange->work_item.op); + mm = prange->work_item.mm; +retry: + mmap_write_lock(mm); + + /* Checking for the need to drain retry faults must be inside + * mmap write lock to serialize with munmap notifiers. + */ + if (unlikely(atomic_read(&svms->drain_pagefaults))) { + mmap_write_unlock(mm); + svm_range_drain_retry_fault(svms); + goto retry; + } + + /* Remove from deferred_list must be inside mmap write lock, for + * two race cases: + * 1. unmap_from_cpu may change work_item.op and add the range + * to deferred_list again, cause use after free bug. + * 2. svm_range_list_lock_and_flush_work may hold mmap write + * lock and continue because deferred_list is empty, but + * deferred_list work is actually waiting for mmap lock. + */ + spin_lock(&svms->deferred_list_lock); + list_del_init(&prange->deferred_list); + spin_unlock(&svms->deferred_list_lock); + mutex_lock(&svms->lock); mutex_lock(&prange->migrate_mutex); while (!list_empty(&prange->child_list)) { @@ -2109,19 +2115,20 @@ retry: pr_debug("child prange 0x%p op %d\n", pchild, pchild->work_item.op); list_del_init(&pchild->child_list); - svm_range_handle_list_op(svms, pchild); + svm_range_handle_list_op(svms, pchild, mm); } mutex_unlock(&prange->migrate_mutex); - svm_range_handle_list_op(svms, prange); + svm_range_handle_list_op(svms, prange, mm); mutex_unlock(&svms->lock); + mmap_write_unlock(mm); + + /* Pairs with mmget in svm_range_add_list_work */ + mmput(mm); spin_lock(&svms->deferred_list_lock); } spin_unlock(&svms->deferred_list_lock); - - mmap_write_unlock(mm); - mmput(mm); pr_debug("exit svms 0x%p\n", svms); } @@ -2139,6 +2146,9 @@ svm_range_add_list_work(struct svm_range_list *svms, struct svm_range *prange, prange->work_item.op = op; } else { prange->work_item.op = op; + + /* Pairs with mmput in deferred_list_work */ + mmget(mm); prange->work_item.mm = mm; list_add_tail(&prange->deferred_list, &prange->svms->deferred_range_list); From 6225bb3a88d22594aacea2485dc28ca12d596721 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 12 Jan 2022 11:50:50 -0500 Subject: [PATCH 186/339] drm/amdkfd: svm range restore work deadlock when process exit kfd_process_notifier_release flush svm_range_restore_work which calls svm_range_list_lock_and_flush_work to flush deferred_list work, but if deferred_list work mmput release the last user, it will call exit_mmap -> notifier_release, it is deadlock with below backtrace. Move flush svm_range_restore_work to kfd_process_wq_release to avoid deadlock. Then svm_range_restore_work take task->mm ref to avoid mm is gone while validating and mapping ranges to GPU. Workqueue: events svm_range_deferred_list_work [amdgpu] Call Trace: wait_for_completion+0x94/0x100 __flush_work+0x12a/0x1e0 __cancel_work_timer+0x10e/0x190 cancel_delayed_work_sync+0x13/0x20 kfd_process_notifier_release+0x98/0x2a0 [amdgpu] __mmu_notifier_release+0x74/0x1f0 exit_mmap+0x170/0x200 mmput+0x5d/0x130 svm_range_deferred_list_work+0x104/0x230 [amdgpu] process_one_work+0x220/0x3c0 Signed-off-by: Philip Yang Reported-by: Ruili Ji Tested-by: Ruili Ji Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 15 +++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index d1145da5348f..74f162887d3b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1150,7 +1150,6 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, cancel_delayed_work_sync(&p->eviction_work); cancel_delayed_work_sync(&p->restore_work); - cancel_delayed_work_sync(&p->svms.restore_work); mutex_lock(&p->mutex); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 225affcddbc1..1cf9041c9727 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1643,13 +1643,14 @@ static void svm_range_restore_work(struct work_struct *work) pr_debug("restore svm ranges\n"); - /* kfd_process_notifier_release destroys this worker thread. So during - * the lifetime of this thread, kfd_process and mm will be valid. - */ p = container_of(svms, struct kfd_process, svms); - mm = p->mm; - if (!mm) + + /* Keep mm reference when svm_range_validate_and_map ranges */ + mm = get_task_mm(p->lead_thread); + if (!mm) { + pr_debug("svms 0x%p process mm gone\n", svms); return; + } svm_range_list_lock_and_flush_work(svms, mm); mutex_lock(&svms->lock); @@ -1703,6 +1704,7 @@ static void svm_range_restore_work(struct work_struct *work) out_reschedule: mutex_unlock(&svms->lock); mmap_write_unlock(mm); + mmput(mm); /* If validation failed, reschedule another attempt */ if (evicted_ranges) { @@ -2840,6 +2842,8 @@ void svm_range_list_fini(struct kfd_process *p) pr_debug("pasid 0x%x svms 0x%p\n", p->pasid, &p->svms); + cancel_delayed_work_sync(&p->svms.restore_work); + /* Ensure list work is finished before process is destroyed */ flush_work(&p->svms.deferred_list_work); @@ -2850,7 +2854,6 @@ void svm_range_list_fini(struct kfd_process *p) atomic_inc(&p->svms.drain_pagefaults); svm_range_drain_retry_fault(&p->svms); - list_for_each_entry_safe(prange, next, &p->svms.list, list) { svm_range_unlink(prange); svm_range_remove_notifier(prange); From a154bf6eda9881aa3dd74cea83dcff6de3ce9680 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Tue, 25 Jan 2022 00:57:36 -0500 Subject: [PATCH 187/339] drm/amd/display: Add Missing HPO Stream Encoder Function Hook [Why] configure_dp_hpo_throttled_vcp_size() was missing promotion before, but it was covered by not calling the missing function hook in the old interface hpo_dp_link_encoder->funcs. Recent refactor replaces with new caller link_hwss->set_throttled_vcp_size which needs that hook, and that causes null ptr hang. Signed-off-by: Fangzhi Zuo Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c | 11 +++++++++++ .../display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h | 9 ++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index 5065904c7833..23621ff08c90 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -710,6 +710,16 @@ static void dcn31_hpo_dp_stream_enc_read_state( } } +static void dcn31_set_hblank_min_symbol_width( + struct hpo_dp_stream_encoder *enc, + uint16_t width) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + REG_SET(DP_SYM32_ENC_HBLANK_CONTROL, 0, + HBLANK_MINIMUM_SYMBOL_WIDTH, width); +} + static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = { .enable_stream = dcn31_hpo_dp_stream_enc_enable_stream, .dp_unblank = dcn31_hpo_dp_stream_enc_dp_unblank, @@ -725,6 +735,7 @@ static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = { .dp_audio_enable = dcn31_hpo_dp_stream_enc_audio_enable, .dp_audio_disable = dcn31_hpo_dp_stream_enc_audio_disable, .read_state = dcn31_hpo_dp_stream_enc_read_state, + .set_hblank_min_symbol_width = dcn31_set_hblank_min_symbol_width, }; void dcn31_hpo_dp_stream_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h index 70b94fc25304..7c77c71591a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h @@ -80,7 +80,8 @@ SRI(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id),\ SRI(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id),\ SRI(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id),\ - SRI(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id) + SRI(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \ + SRI(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id) #define DCN3_1_HPO_DP_STREAM_ENC_REGS \ uint32_t DP_STREAM_MAPPER_CONTROL0;\ @@ -116,7 +117,8 @@ uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL11;\ uint32_t DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL;\ uint32_t DP_SYM32_ENC_SDP_AUDIO_CONTROL0;\ - uint32_t DP_SYM32_ENC_VID_CRC_CONTROL + uint32_t DP_SYM32_ENC_VID_CRC_CONTROL;\ + uint32_t DP_SYM32_ENC_HBLANK_CONTROL #define DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\ @@ -202,7 +204,8 @@ type GSP_SOF_REFERENCE;\ type METADATA_PACKET_ENABLE;\ type CRC_ENABLE;\ - type CRC_CONT_MODE_ENABLE + type CRC_CONT_MODE_ENABLE;\ + type HBLANK_MINIMUM_SYMBOL_WIDTH struct dcn31_hpo_dp_stream_encoder_registers { From f4e2a66dae996b4fa2cc21b1904798ad1dc83049 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 24 Jan 2022 13:40:35 +0800 Subject: [PATCH 188/339] drm/amd/pm: correct the MGpuFanBoost support for Beige Goby The existing way cannot handle Beige Goby well as a different PPTable data structure(PPTable_beige_goby_t instead of PPTable_t) is used there. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 651fe748e423..dcd35c68e59b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3729,14 +3729,14 @@ static ssize_t sienna_cichlid_get_ecc_info(struct smu_context *smu, } static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) { - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *smc_pptable = table_context->driver_pptable; + uint16_t *mgpu_fan_boost_limit_rpm; + GET_PPTABLE_MEMBER(MGpuFanBoostLimitRpm, &mgpu_fan_boost_limit_rpm); /* * Skip the MGpuFanBoost setting for those ASICs * which do not support it */ - if (!smc_pptable->MGpuFanBoostLimitRpm) + if (*mgpu_fan_boost_limit_rpm == 0) return 0; return smu_cmn_send_smc_msg_with_param(smu, From 75513bf5d72cd1a81401866642f4a8052b2d4420 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 25 Jan 2022 16:09:00 +0800 Subject: [PATCH 189/339] drm/amd/pm: fix the deadlock observed on performance_level setting The sub-routine(amdgpu_gfx_off_ctrl) tried to obtain the lock adev->pm.mutex which was actually hold by amdgpu_dpm_force_performance_level. A deadlock happened then. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 50 ++++++++++------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index 5fc33893a68c..ef574c96b41c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -692,25 +692,16 @@ void amdgpu_dpm_set_power_state(struct amdgpu_device *adev, amdgpu_dpm_compute_clocks(adev); } -static enum amd_dpm_forced_level amdgpu_dpm_get_performance_level_locked(struct amdgpu_device *adev) +enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; enum amd_dpm_forced_level level; + mutex_lock(&adev->pm.mutex); if (pp_funcs->get_performance_level) level = pp_funcs->get_performance_level(adev->powerplay.pp_handle); else level = adev->pm.dpm.forced_level; - - return level; -} - -enum amd_dpm_forced_level amdgpu_dpm_get_performance_level(struct amdgpu_device *adev) -{ - enum amd_dpm_forced_level level; - - mutex_lock(&adev->pm.mutex); - level = amdgpu_dpm_get_performance_level_locked(adev); mutex_unlock(&adev->pm.mutex); return level; @@ -725,23 +716,16 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - int ret = 0; if (!pp_funcs->force_performance_level) return 0; - mutex_lock(&adev->pm.mutex); + if (adev->pm.dpm.thermal_active) + return -EINVAL; - if (adev->pm.dpm.thermal_active) { - ret = -EINVAL; - goto out; - } - - current_level = amdgpu_dpm_get_performance_level_locked(adev); - if (current_level == level) { - ret = 0; - goto out; - } + current_level = amdgpu_dpm_get_performance_level(adev); + if (current_level == level) + return 0; if (adev->asic_type == CHIP_RAVEN) { if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { @@ -755,10 +739,8 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, } if (!(current_level & profile_mode_mask) && - (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { - ret = -EINVAL; - goto out; - } + (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) + return -EINVAL; if (!(current_level & profile_mode_mask) && (level & profile_mode_mask)) { @@ -780,17 +762,19 @@ int amdgpu_dpm_force_performance_level(struct amdgpu_device *adev, AMD_PG_STATE_GATE); } + mutex_lock(&adev->pm.mutex); + if (pp_funcs->force_performance_level(adev->powerplay.pp_handle, - level)) - ret = -EINVAL; + level)) { + mutex_unlock(&adev->pm.mutex); + return -EINVAL; + } - if (!ret) - adev->pm.dpm.forced_level = level; + adev->pm.dpm.forced_level = level; -out: mutex_unlock(&adev->pm.mutex); - return ret; + return 0; } int amdgpu_dpm_get_pp_num_states(struct amdgpu_device *adev, From 7270e8957eb9aacf5914605d04865f3829a14bce Mon Sep 17 00:00:00 2001 From: "Tianci.Yin" Date: Tue, 25 Jan 2022 16:54:03 +0800 Subject: [PATCH 190/339] drm/amdgpu: Fix an error message in rmmod [why] In rmmod procedure, kfd sends cp a dequeue request, but the request does not get response, then an error message "cp queue pipe 4 queue 0 preemption failed" printed. [how] Performing kfd suspending after disabling gfxoff can fix it. Acked-by: Felix Kuehling Reviewed-by: Yang Wang Signed-off-by: Tianci.Yin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 7cec3a0f61b9..6ba57ad88640 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2721,11 +2721,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev) } } - amdgpu_amdkfd_suspend(adev, false); - amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); + amdgpu_amdkfd_suspend(adev, false); + /* Workaroud for ASICs need to disable SMC first */ amdgpu_device_smu_fini_early(adev); From fc6ea4bee130710a77ec16a86d2013e964602503 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 25 Jan 2022 10:51:49 -0500 Subject: [PATCH 191/339] drm/amdgpu: Wipe all VRAM on free when RAS is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On GPUs with RAS, poison can propagate between processes if VRAM is not cleared when it is freed or allocated. The reason is, that not all write accesses clear RAS poison. 32-byte writes by the SDMA engine do clear RAS poison. Clearing memory in the background when it is freed should avoid major performance impact. KFD has been doing this already for a long time. Signed-off-by: Felix Kuehling Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5661b82d84d4..ec29365d108d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -575,6 +575,9 @@ int amdgpu_bo_create(struct amdgpu_device *adev, if (!amdgpu_bo_support_uswc(bo->flags)) bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC; + if (adev->ras_enabled) + bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE; + bo->tbo.bdev = &adev->mman.bdev; if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA | AMDGPU_GEM_DOMAIN_GDS)) From 9a17696049889550ce76a987562e679535943c96 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 25 Jan 2022 15:49:47 -0600 Subject: [PATCH 192/339] display/amd: decrease message verbosity about watermarks table failure A number of BIOS versions have a problem with the watermarks table not being configured properly. This manifests as a very scary looking warning during resume from s0i3. This should be harmless in most cases and is well understood, so decrease the assertion to a clearer warning about the problem. Reviewed-by: Harry Wentland Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c index 9b4836350547..c5d7d075026f 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c @@ -120,7 +120,11 @@ static int dcn31_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, result = dcn31_smu_wait_for_response(clk_mgr, 10, 200000); if (result == VBIOSSMC_Result_Failed) { - ASSERT(0); + if (msg_id == VBIOSSMC_MSG_TransferTableDram2Smu && + param == TABLE_WATERMARKS) + DC_LOG_WARNING("Watermarks table not configured properly by SMU"); + else + ASSERT(0); REG_WRITE(MP1_SMN_C2PMSG_91, VBIOSSMC_Result_OK); return -1; } From 400013b268cb666a44c0827b136bfd4bb741b13d Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 19 Jan 2022 15:42:55 +0800 Subject: [PATCH 193/339] drm/amdgpu: add umc_fill_error_record to make code more simple Create common amdgpu_umc_fill_error_record function for all versions of UMC and clean up related codes. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 23 ++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 21 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h | 5 ++++ drivers/gpu/drm/amd/amdgpu/umc_v6_1.c | 18 +++---------- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 36 +++++-------------------- drivers/gpu/drm/amd/amdgpu/umc_v8_7.c | 36 +++++-------------------- 6 files changed, 46 insertions(+), 93 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d4e07d0acb66..e6324995fc54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -158,14 +158,9 @@ static int amdgpu_reserve_page_direct(struct amdgpu_device *adev, uint64_t addre } memset(&err_rec, 0x0, sizeof(struct eeprom_table_record)); - - err_rec.address = address; - err_rec.retired_page = address >> AMDGPU_GPU_PAGE_SHIFT; - err_rec.ts = (uint64_t)ktime_get_real_seconds(); - err_rec.err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_data.err_addr = &err_rec; - err_data.err_addr_cnt = 1; + amdgpu_umc_fill_error_record(&err_data, address, + (address >> AMDGPU_GPU_PAGE_SHIFT), 0, 0); if (amdgpu_bad_page_threshold != 0) { amdgpu_ras_add_bad_pages(adev, err_data.err_addr, @@ -2660,8 +2655,6 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb, dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d", umc_inst, ch_inst); - memset(&err_rec, 0x0, sizeof(struct eeprom_table_record)); - /* * Translate UMC channel address to Physical address */ @@ -2673,16 +2666,10 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb, ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(m->addr); - err_rec.address = m->addr; - err_rec.retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; - err_rec.ts = (uint64_t)ktime_get_real_seconds(); - err_rec.err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_rec.cu = 0; - err_rec.mem_channel = channel_index; - err_rec.mcumc_id = umc_inst; - + memset(&err_rec, 0x0, sizeof(struct eeprom_table_record)); err_data.err_addr = &err_rec; - err_data.err_addr_cnt = 1; + amdgpu_umc_fill_error_record(&err_data, m->addr, + retired_page, channel_index, umc_inst); if (amdgpu_bad_page_threshold != 0) { amdgpu_ras_add_bad_pages(adev, err_data.err_addr, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index b4c68c09e071..ff7805beda38 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -218,3 +218,24 @@ int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev, amdgpu_ras_interrupt_dispatch(adev, &ih_data); return 0; } + +void amdgpu_umc_fill_error_record(struct ras_err_data *err_data, + uint64_t err_addr, + uint64_t retired_page, + uint32_t channel_index, + uint32_t umc_inst) +{ + struct eeprom_table_record *err_rec = + &err_data->err_addr[err_data->err_addr_cnt]; + + err_rec->address = err_addr; + /* page frame address is saved */ + err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; + err_rec->ts = (uint64_t)ktime_get_real_seconds(); + err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; + err_rec->cu = 0; + err_rec->mem_channel = channel_index; + err_rec->mcumc_id = umc_inst; + + err_data->err_addr_cnt++; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 195740a6d97d..4db0526d0be4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -80,4 +80,9 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry); +void amdgpu_umc_fill_error_record(struct ras_err_data *err_data, + uint64_t err_addr, + uint64_t retired_page, + uint32_t channel_index, + uint32_t umc_inst); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c index 4776301972d4..939cb203f7ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_1.c @@ -300,7 +300,6 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev, { uint32_t lsb, mc_umc_status_addr; uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0; - struct eeprom_table_record *err_rec; uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; if (adev->asic_type == CHIP_ARCTURUS) { @@ -328,8 +327,6 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev, return; } - err_rec = &err_data->err_addr[err_data->err_addr_cnt]; - /* calculate error address if ue/ce error is detected */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || @@ -348,18 +345,9 @@ static void umc_v6_1_query_error_address(struct amdgpu_device *adev, /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) { - err_rec->address = err_addr; - /* page frame address is saved */ - err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; - err_rec->ts = (uint64_t)ktime_get_real_seconds(); - err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_rec->cu = 0; - err_rec->mem_channel = channel_index; - err_rec->mcumc_id = umc_inst; - - err_data->err_addr_cnt++; - } + == 1) + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); } /* clear umc status */ diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index f5a1ba7db75a..300dee9ec6b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -120,7 +120,6 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, uint32_t umc_inst) { uint64_t mc_umc_status, err_addr, retired_page; - struct eeprom_table_record *err_rec; uint32_t channel_index; uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); @@ -137,8 +136,6 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, if (!err_data->err_addr) return; - err_rec = &err_data->err_addr[err_data->err_addr_cnt]; - /* calculate error address if ue/ce error is detected */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || @@ -154,18 +151,9 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) { - err_rec->address = err_addr; - /* page frame address is saved */ - err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; - err_rec->ts = (uint64_t)ktime_get_real_seconds(); - err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_rec->cu = 0; - err_rec->mem_channel = channel_index; - err_rec->mcumc_id = umc_inst; - - err_data->err_addr_cnt++; - } + == 1) + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); } } @@ -345,7 +333,6 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev, { uint32_t mc_umc_status_addr; uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0; - struct eeprom_table_record *err_rec; uint32_t channel_index; mc_umc_status_addr = @@ -364,8 +351,6 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev, return; } - err_rec = &err_data->err_addr[err_data->err_addr_cnt]; - channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; @@ -384,18 +369,9 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev, /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) { - err_rec->address = err_addr; - /* page frame address is saved */ - err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; - err_rec->ts = (uint64_t)ktime_get_real_seconds(); - err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_rec->cu = 0; - err_rec->mem_channel = channel_index; - err_rec->mcumc_id = umc_inst; - - err_data->err_addr_cnt++; - } + == 1) + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); } /* clear umc status */ diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index d70417196662..de85a998ef99 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -121,7 +121,6 @@ static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, uint32_t umc_inst) { uint64_t mc_umc_status, err_addr, retired_page; - struct eeprom_table_record *err_rec; uint32_t channel_index; uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); @@ -138,8 +137,6 @@ static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, if (!err_data->err_addr) return; - err_rec = &err_data->err_addr[err_data->err_addr_cnt]; - /* calculate error address if ue/ce error is detected */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || @@ -155,18 +152,9 @@ static void umc_v8_7_ecc_info_query_error_address(struct amdgpu_device *adev, /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) { - err_rec->address = err_addr; - /* page frame address is saved */ - err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; - err_rec->ts = (uint64_t)ktime_get_real_seconds(); - err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_rec->cu = 0; - err_rec->mem_channel = channel_index; - err_rec->mcumc_id = umc_inst; - - err_data->err_addr_cnt++; - } + == 1) + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); } } @@ -344,7 +332,6 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev, { uint32_t lsb, mc_umc_status_addr; uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0; - struct eeprom_table_record *err_rec; uint32_t channel_index = adev->umc.channel_idx_tbl[umc_inst * adev->umc.channel_inst_num + ch_inst]; mc_umc_status_addr = @@ -363,8 +350,6 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev, return; } - err_rec = &err_data->err_addr[err_data->err_addr_cnt]; - /* calculate error address if ue/ce error is detected */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) == 1 || @@ -383,18 +368,9 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev, /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) { - err_rec->address = err_addr; - /* page frame address is saved */ - err_rec->retired_page = retired_page >> AMDGPU_GPU_PAGE_SHIFT; - err_rec->ts = (uint64_t)ktime_get_real_seconds(); - err_rec->err_type = AMDGPU_RAS_EEPROM_ERR_NON_RECOVERABLE; - err_rec->cu = 0; - err_rec->mem_channel = channel_index; - err_rec->mcumc_id = umc_inst; - - err_data->err_addr_cnt++; - } + == 1) + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); } /* clear umc status */ From 498d46fe7aa7eda5807352d62af133a2f432b814 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 19 Jan 2022 16:00:11 +0800 Subject: [PATCH 194/339] drm/amdgpu: increase bad page number for umc ras query One piece of umc normalizing address can be mapped to 16 pieces of physical address in each umc channel on ALDEBARAN. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/umc_v6_7.h | 4 ++++ 2 files changed, 6 insertions(+), 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 600ff658ab1b..4595027a8c63 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1213,7 +1213,8 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) adev->umc.ras = &umc_v6_1_ras; break; case IP_VERSION(6, 7, 0): - adev->umc.max_ras_err_cnt_per_query = UMC_V6_7_TOTAL_CHANNEL_NUM; + adev->umc.max_ras_err_cnt_per_query = + UMC_V6_7_TOTAL_CHANNEL_NUM * UMC_V6_7_BAD_PAGE_NUM_PER_CHANNEL; adev->umc.channel_inst_num = UMC_V6_7_CHANNEL_INSTANCE_NUM; adev->umc.umc_inst_num = UMC_V6_7_UMC_INSTANCE_NUM; adev->umc.channel_offs = UMC_V6_7_PER_CHANNEL_OFFSET; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h index 1f2edf625370..9adebcf98582 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h @@ -41,6 +41,10 @@ #define UMC_V6_7_CHANNEL_INSTANCE_NUM 8 /* total channel instances in one umc block */ #define UMC_V6_7_TOTAL_CHANNEL_NUM (UMC_V6_7_CHANNEL_INSTANCE_NUM * UMC_V6_7_UMC_INSTANCE_NUM) +/* one piece of normalizing address is mapped to 8 pieces of physical address */ +#define UMC_V6_7_NA_MAP_PA_NUM 8 +/* R14 bit shift should be considered, double the number */ +#define UMC_V6_7_BAD_PAGE_NUM_PER_CHANNEL (UMC_V6_7_NA_MAP_PA_NUM * 2) /* UMC regiser per channel offset */ #define UMC_V6_7_PER_CHANNEL_OFFSET 0x400 extern struct amdgpu_umc_ras umc_v6_7_ras; From e63fa4dcea2f7afcbf8f2d013dfae23a61a273d8 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 19 Jan 2022 17:00:09 +0800 Subject: [PATCH 195/339] drm/amdgpu: update algorithm of umc address conversion On ALDEBARAN, we need to traverse all column bits higher than BIT11(C4C3C2) in a row, the shift of R14 bit should be also taken into account. Retire all pages we find. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 41 +++++++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/umc_v6_7.h | 4 +++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 300dee9ec6b4..1ecba7b5df1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -119,7 +119,7 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, uint32_t ch_inst, uint32_t umc_inst) { - uint64_t mc_umc_status, err_addr, retired_page; + uint64_t mc_umc_status, err_addr, soc_pa, retired_page, column; uint32_t channel_index; uint32_t eccinfo_table_idx; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); @@ -145,15 +145,27 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); /* translate umc channel address to soc pa, 3 parts are included */ - retired_page = ADDR_OF_8KB_BLOCK(err_addr) | + soc_pa = ADDR_OF_8KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr); + /* clear [C4 C3 C2] in soc physical address */ + soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT); /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) - amdgpu_umc_fill_error_record(err_data, err_addr, + == 1) { + /* loop for all possibilities of [C4 C3 C2] */ + for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) { + retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT); + amdgpu_umc_fill_error_record(err_data, err_addr, retired_page, channel_index, umc_inst); + + /* shift R14 bit */ + retired_page ^= (0x1ULL << UMC_V6_7_PA_R14_BIT); + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); + } + } } } @@ -332,8 +344,9 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev, uint32_t umc_inst) { uint32_t mc_umc_status_addr; - uint64_t mc_umc_status, err_addr, retired_page, mc_umc_addrt0; uint32_t channel_index; + uint64_t mc_umc_status, mc_umc_addrt0; + uint64_t err_addr, soc_pa, retired_page, column; mc_umc_status_addr = SOC15_REG_OFFSET(UMC, 0, regMCA_UMC_UMC0_MCUMC_STATUST0); @@ -363,15 +376,27 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev, err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); /* translate umc channel address to soc pa, 3 parts are included */ - retired_page = ADDR_OF_8KB_BLOCK(err_addr) | + soc_pa = ADDR_OF_8KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr); + /* clear [C4 C3 C2] in soc physical address */ + soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT); /* we only save ue error information currently, ce is skipped */ if (REG_GET_FIELD(mc_umc_status, MCA_UMC_UMC0_MCUMC_STATUST0, UECC) - == 1) - amdgpu_umc_fill_error_record(err_data, err_addr, + == 1) { + /* loop for all possibilities of [C4 C3 C2] */ + for (column = 0; column < UMC_V6_7_NA_MAP_PA_NUM; column++) { + retired_page = soc_pa | (column << UMC_V6_7_PA_C2_BIT); + amdgpu_umc_fill_error_record(err_data, err_addr, retired_page, channel_index, umc_inst); + + /* shift R14 bit */ + retired_page ^= (0x1ULL << UMC_V6_7_PA_R14_BIT); + amdgpu_umc_fill_error_record(err_data, err_addr, + retired_page, channel_index, umc_inst); + } + } } /* clear umc status */ diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h index 9adebcf98582..b67677867b45 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h @@ -45,6 +45,10 @@ #define UMC_V6_7_NA_MAP_PA_NUM 8 /* R14 bit shift should be considered, double the number */ #define UMC_V6_7_BAD_PAGE_NUM_PER_CHANNEL (UMC_V6_7_NA_MAP_PA_NUM * 2) +/* The C2 bit in SOC physical address */ +#define UMC_V6_7_PA_C2_BIT 17 +/* The R14 bit in SOC physical address */ +#define UMC_V6_7_PA_R14_BIT 34 /* UMC regiser per channel offset */ #define UMC_V6_7_PER_CHANNEL_OFFSET 0x400 extern struct amdgpu_umc_ras umc_v6_7_ras; From bee7f8d09268dc80da0e841ca99d79f500d03b84 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 24 Jan 2022 16:41:40 +0800 Subject: [PATCH 196/339] drm/amdgpu: get hash bit for CH4 in umc channel index On ALDEBARAN, the umc channel bits are not original values, they are hashed. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/umc_v6_7.h | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 1ecba7b5df1c..47452b61b615 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -148,6 +148,10 @@ static void umc_v6_7_ecc_info_query_error_address(struct amdgpu_device *adev, soc_pa = ADDR_OF_8KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr); + + /* The umc channel bits are not original values, they are hashed */ + SET_CHANNEL_HASH(channel_index, soc_pa); + /* clear [C4 C3 C2] in soc physical address */ soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT); @@ -379,6 +383,10 @@ static void umc_v6_7_query_error_address(struct amdgpu_device *adev, soc_pa = ADDR_OF_8KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr); + + /* The umc channel bits are not original values, they are hashed */ + SET_CHANNEL_HASH(channel_index, soc_pa); + /* clear [C4 C3 C2] in soc physical address */ soc_pa &= ~(0x7ULL << UMC_V6_7_PA_C2_BIT); diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h index b67677867b45..fe41ed2f5945 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h @@ -45,12 +45,27 @@ #define UMC_V6_7_NA_MAP_PA_NUM 8 /* R14 bit shift should be considered, double the number */ #define UMC_V6_7_BAD_PAGE_NUM_PER_CHANNEL (UMC_V6_7_NA_MAP_PA_NUM * 2) +/* The CH4 bit in SOC physical address */ +#define UMC_V6_7_PA_CH4_BIT 12 /* The C2 bit in SOC physical address */ #define UMC_V6_7_PA_C2_BIT 17 /* The R14 bit in SOC physical address */ #define UMC_V6_7_PA_R14_BIT 34 /* UMC regiser per channel offset */ #define UMC_V6_7_PER_CHANNEL_OFFSET 0x400 + +/* XOR bit 20, 25, 34 of PA into CH4 bit (bit 12 of PA), + * hash bit is only effective when related setting is enabled + */ +#define CHANNEL_HASH(channel_idx, pa) (((channel_idx) >> 4) ^ \ + (((pa) >> 20) & 0x1ULL & adev->df.hash_status.hash_64k) ^ \ + (((pa) >> 25) & 0x1ULL & adev->df.hash_status.hash_2m) ^ \ + (((pa) >> 34) & 0x1ULL & adev->df.hash_status.hash_1g)) +#define SET_CHANNEL_HASH(channel_idx, pa) do { \ + (pa) &= ~(0x1ULL << UMC_V6_7_PA_CH4_BIT); \ + (pa) |= (CHANNEL_HASH(channel_idx, pa) << UMC_V6_7_PA_CH4_BIT); \ + } while (0) + extern struct amdgpu_umc_ras umc_v6_7_ras; extern const uint32_t umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM]; From 7367540b26214ba5f7236e0f212fd60ec6d07c3f Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Thu, 27 Jan 2022 10:48:41 +0800 Subject: [PATCH 197/339] drm/amd/display: Fix unused variable warning [Why] It will build failed with unused variable 'dc' with '-Werror=unused-variable'enabled when CONFIG_DRM_AMD_DC_DCN is not defined. Signed-off-by: Tim Huang Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Reviewed-by: Aaron Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 84342f27ee64..322333b1eb08 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1027,7 +1027,6 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) const unsigned char *fw_inst_const, *fw_bss_data; uint32_t i, fw_inst_const_size, fw_bss_data_size; bool has_hw_support; - struct dc *dc = adev->dm.dc; if (!dmub_srv) /* DMUB isn't supported on the ASIC. */ @@ -1123,7 +1122,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) case IP_VERSION(3, 1, 3): /* Only for this asic hw internal rev B0 */ hw_params.dpia_supported = true; #if defined(CONFIG_DRM_AMD_DC_DCN) - hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia; + hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia; #endif break; default: From 4e13b063d2e510b54e3ffc2e975315d08d14c5af Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Thu, 27 Jan 2022 09:40:44 +0800 Subject: [PATCH 198/339] drm/amdgpu: convert code name to ip version for athub Use IP version rather than codename for athub. Signed-off-by: Aaron Liu Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/athub_v1_0.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c index 3ea557864320..88642e7ecdf4 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c @@ -68,12 +68,13 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev, if (amdgpu_sriov_vf(adev)) return 0; - switch (adev->asic_type) { - case CHIP_VEGA10: - case CHIP_VEGA12: - case CHIP_VEGA20: - case CHIP_RAVEN: - case CHIP_RENOIR: + switch (adev->ip_versions[ATHUB_HWIP][0]) { + case IP_VERSION(9, 0, 0): + case IP_VERSION(9, 1, 0): + case IP_VERSION(9, 2, 0): + case IP_VERSION(9, 3, 0): + case IP_VERSION(9, 4, 0): + case IP_VERSION(1, 5, 0): athub_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); athub_update_medium_grain_light_sleep(adev, From f06d9e4eec7320f5a560e49ed652e785c8ab5c45 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Thu, 27 Jan 2022 09:30:33 +0800 Subject: [PATCH 199/339] drm/amdgpu: add 1.3.1/2.4.0 athub CG support This patch adds 1.3.1/2.4.0 athub clock gating support. Signed-off-by: Aaron Liu Reviewed-by: Alex Deucher Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/athub_v2_0.c | 1 + drivers/gpu/drm/amd/amdgpu/athub_v2_1.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c index ab6a07e5e8c4..a720436857b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_0.c @@ -78,6 +78,7 @@ int athub_v2_0_set_clockgating(struct amdgpu_device *adev, return 0; switch (adev->ip_versions[ATHUB_HWIP][0]) { + case IP_VERSION(1, 3, 1): case IP_VERSION(2, 0, 0): case IP_VERSION(2, 0, 2): athub_v2_0_update_medium_grain_clock_gating(adev, diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c index 2edefd10e56c..ad8e87d3d2cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v2_1.c @@ -74,6 +74,7 @@ int athub_v2_1_set_clockgating(struct amdgpu_device *adev, case IP_VERSION(2, 1, 0): case IP_VERSION(2, 1, 1): case IP_VERSION(2, 1, 2): + case IP_VERSION(2, 4, 0): athub_v2_1_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); athub_v2_1_update_medium_grain_light_sleep(adev, state == AMD_CG_STATE_GATE); break; From 2f60dd50769efcd6eedd0dc6b3f419cdd1f1f1fa Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Wed, 19 Jan 2022 20:20:53 -0500 Subject: [PATCH 200/339] drm/amd: Expose the FRU SMU I2C bus Expose both SMU I2C buses. Some boards use the same bus for both the RAS and FRU EEPROMs and others use different buses. This enables the additional I2C bus and sets the right buses to use for RAS and FRU EEPROM access. Cc: Roy Sun Co-developed-by: Alex Deucher Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 6 +- .../gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 14 ++-- drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 80 ++++++++++++------- drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h | 6 +- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 14 +++- .../amd/pm/powerplay/smumgr/vega20_smumgr.c | 4 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 4 +- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 4 +- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 69 +++++++++++----- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 68 +++++++++++----- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 69 +++++++++++----- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 44 +++++++--- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 4 +- 13 files changed, 272 insertions(+), 114 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 60e7e637eaa3..40180648be38 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -75,7 +75,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, { int ret, size; - ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr, buff, 1); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buff, 1); if (ret < 1) { DRM_WARN("FRU: Failed to get size field"); return ret; @@ -86,7 +86,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, */ size = buff[0] - I2C_PRODUCT_INFO_OFFSET; - ret = amdgpu_eeprom_read(&adev->pm.smu_i2c, addrptr + 1, buff, size); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buff, size); if (ret < 1) { DRM_WARN("FRU: Failed to get data field"); return ret; @@ -109,7 +109,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) offset = 0; /* If algo exists, it means that the i2c_adapter's initialized */ - if (!adev->pm.smu_i2c.algo) { + if (!adev->pm.fru_eeprom_i2c_bus || !adev->pm.fru_eeprom_i2c_bus->algo) { DRM_WARN("Cannot access FRU, EEPROM accessor not initialized"); return -ENODEV; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 05117eda105b..c09d047272b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -194,7 +194,7 @@ static int __write_table_header(struct amdgpu_ras_eeprom_control *control) /* i2c may be unstable in gpu reset */ down_read(&adev->reset_sem); - res = amdgpu_eeprom_write(&adev->pm.smu_i2c, + res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_header_offset, buf, RAS_TABLE_HEADER_SIZE); @@ -389,7 +389,7 @@ static int __amdgpu_ras_eeprom_write(struct amdgpu_ras_eeprom_control *control, /* i2c may be unstable in gpu reset */ down_read(&adev->reset_sem); buf_size = num * RAS_TABLE_RECORD_SIZE; - res = amdgpu_eeprom_write(&adev->pm.smu_i2c, + res = amdgpu_eeprom_write(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + RAS_INDEX_TO_OFFSET(control, fri), buf, buf_size); @@ -548,7 +548,7 @@ amdgpu_ras_eeprom_update_header(struct amdgpu_ras_eeprom_control *control) } down_read(&adev->reset_sem); - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_record_offset, buf, buf_size); @@ -644,7 +644,7 @@ static int __amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, /* i2c may be unstable in gpu reset */ down_read(&adev->reset_sem); buf_size = num * RAS_TABLE_RECORD_SIZE; - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + RAS_INDEX_TO_OFFSET(control, fri), buf, buf_size); @@ -1009,7 +1009,7 @@ static int __verify_ras_table_checksum(struct amdgpu_ras_eeprom_control *control return -ENOMEM; } - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_header_offset, buf, buf_size); @@ -1045,7 +1045,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, return 0; /* Verify i2c adapter is initialized */ - if (!adev->pm.smu_i2c.algo) + if (!adev->pm.ras_eeprom_i2c_bus || !adev->pm.ras_eeprom_i2c_bus->algo) return -ENOENT; if (!__get_eeprom_i2c_addr(adev, control)) @@ -1057,7 +1057,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, mutex_init(&control->ras_tbl_mutex); /* Read the table header from EEPROM address */ - res = amdgpu_eeprom_read(&adev->pm.smu_i2c, + res = amdgpu_eeprom_read(adev->pm.ras_eeprom_i2c_bus, control->i2c_address + control->ras_header_offset, buf, RAS_TABLE_HEADER_SIZE); if (res < RAS_TABLE_HEADER_SIZE) { diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c index 73ffa8fde3df..87acb089cfcc 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c @@ -26,6 +26,7 @@ #include "smu_v11_0_i2c.h" #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "soc15_common.h" #include #include @@ -43,11 +44,10 @@ #define I2C_X_RESTART BIT(31) -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_PWRMGT); reg = REG_SET_FIELD(reg, SMUIO_PWRMGT, i2c_clk_gate_en, en ? 1 : 0); @@ -75,7 +75,8 @@ static void smu_v11_0_i2c_set_clock_gating(struct i2c_adapter *control, bool en) static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; WREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_ENABLE, enable ? 1 : 0); @@ -100,7 +101,8 @@ static int smu_v11_0_i2c_enable(struct i2c_adapter *control, bool enable) static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* do */ { RREG32_SOC15(SMUIO, 0, mmCKSVII2C_IC_CLR_INTR); @@ -110,7 +112,8 @@ static void smu_v11_0_i2c_clear_status(struct i2c_adapter *control) static void smu_v11_0_i2c_configure(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t reg = 0; reg = REG_SET_FIELD(reg, CKSVII2C_IC_CON, IC_SLAVE_DISABLE, 1); @@ -131,7 +134,8 @@ static void smu_v11_0_i2c_configure(struct i2c_adapter *control) static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* * Standard mode speed, These values are taken from SMUIO MAS, @@ -154,7 +158,8 @@ static void smu_v11_0_i2c_set_clock(struct i2c_adapter *control) static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* The IC_TAR::IC_TAR field is 10-bits wide. * It takes a 7-bit or 10-bit addresses as an address, @@ -165,7 +170,8 @@ static void smu_v11_0_i2c_set_address(struct i2c_adapter *control, u16 address) static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t ret = I2C_OK; uint32_t reg, reg_c_tx_abrt_source; @@ -216,7 +222,8 @@ static uint32_t smu_v11_0_i2c_poll_tx_status(struct i2c_adapter *control) static uint32_t smu_v11_0_i2c_poll_rx_status(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t ret = I2C_OK; uint32_t reg_ic_status, reg_c_tx_abrt_source; @@ -262,7 +269,8 @@ static uint32_t smu_v11_0_i2c_transmit(struct i2c_adapter *control, u16 address, u8 *data, u32 numbytes, u32 i2c_flag) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; u32 bytes_sent, reg, ret = I2C_OK; unsigned long timeout_counter; @@ -360,7 +368,8 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, u16 address, u8 *data, u32 numbytes, u32 i2c_flag) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t bytes_received, ret = I2C_OK; bytes_received = 0; @@ -431,7 +440,8 @@ static uint32_t smu_v11_0_i2c_receive(struct i2c_adapter *control, static void smu_v11_0_i2c_abort(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; uint32_t reg = 0; /* Enable I2C engine; */ @@ -447,7 +457,8 @@ static void smu_v11_0_i2c_abort(struct i2c_adapter *control) static bool smu_v11_0_i2c_activity_done(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; const uint32_t IDLE_TIMEOUT = 1024; uint32_t timeout_count = 0; @@ -508,7 +519,8 @@ static void smu_v11_0_i2c_init(struct i2c_adapter *control) static void smu_v11_0_i2c_fini(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; u32 status, enable, en_stat; int res; @@ -543,7 +555,8 @@ static void smu_v11_0_i2c_fini(struct i2c_adapter *control) static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* Send PPSMC_MSG_RequestI2CBus */ if (!amdgpu_dpm_smu_i2c_bus_access(adev, true)) @@ -554,7 +567,8 @@ static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(control); + struct amdgpu_device *adev = smu_i2c->adev; /* Send PPSMC_MSG_ReleaseI2CBus */ if (!amdgpu_dpm_smu_i2c_bus_access(adev, false)) @@ -587,16 +601,17 @@ static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control, if (ret != I2C_OK) DRM_ERROR("WriteI2CData() - I2C error occurred :%x", ret); - + return ret; } static void lock_bus(struct i2c_adapter *i2c, unsigned int flags) { - struct amdgpu_device *adev = to_amdgpu_device(i2c); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c); + struct amdgpu_device *adev = smu_i2c->adev; - mutex_lock(&adev->pm.smu_i2c_mutex); + mutex_lock(&smu_i2c->mutex); if (!smu_v11_0_i2c_bus_lock(i2c)) DRM_ERROR("Failed to lock the bus from SMU"); else @@ -611,13 +626,14 @@ static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags) static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) { - struct amdgpu_device *adev = to_amdgpu_device(i2c); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c); + struct amdgpu_device *adev = smu_i2c->adev; if (!smu_v11_0_i2c_bus_unlock(i2c)) DRM_ERROR("Failed to unlock the bus from SMU"); else adev->pm.bus_locked = false; - mutex_unlock(&adev->pm.smu_i2c_mutex); + mutex_unlock(&smu_i2c->mutex); } static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = { @@ -706,19 +722,26 @@ static const struct i2c_adapter_quirks smu_v11_0_i2c_control_quirks = { .flags = I2C_AQ_NO_ZERO_LEN, }; -int smu_v11_0_i2c_control_init(struct i2c_adapter *control) +int smu_v11_0_i2c_control_init(struct amdgpu_device *adev) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0]; + struct i2c_adapter *control = &smu_i2c->adapter; int res; - mutex_init(&adev->pm.smu_i2c_mutex); + smu_i2c->adev = adev; + smu_i2c->port = 0; + mutex_init(&smu_i2c->mutex); control->owner = THIS_MODULE; control->class = I2C_CLASS_HWMON; control->dev.parent = &adev->pdev->dev; control->algo = &smu_v11_0_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0"); control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops; control->quirks = &smu_v11_0_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = NULL; res = i2c_add_adapter(control); if (res) @@ -727,9 +750,12 @@ int smu_v11_0_i2c_control_init(struct i2c_adapter *control) return res; } -void smu_v11_0_i2c_control_fini(struct i2c_adapter *control) +void smu_v11_0_i2c_control_fini(struct amdgpu_device *adev) { + struct i2c_adapter *control = adev->pm.ras_eeprom_i2c_bus; + i2c_del_adapter(control); + adev->pm.ras_eeprom_i2c_bus = NULL; } /* diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h index 44467c05f642..96ad14288a0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h @@ -26,9 +26,9 @@ #include -struct i2c_adapter; +struct amdgpu_device; -int smu_v11_0_i2c_control_init(struct i2c_adapter *control); -void smu_v11_0_i2c_control_fini(struct i2c_adapter *control); +int smu_v11_0_i2c_control_init(struct amdgpu_device *adev); +void smu_v11_0_i2c_control_fini(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index ba857ca75392..2766b88ecf96 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -284,6 +284,15 @@ enum ip_power_state { /* Used to mask smu debug modes */ #define SMU_DEBUG_HALT_ON_ERROR 0x1 +#define MAX_SMU_I2C_BUSES 2 + +struct amdgpu_smu_i2c_bus { + struct i2c_adapter adapter; + struct amdgpu_device *adev; + int port; + struct mutex mutex; +}; + struct amdgpu_pm { struct mutex mutex; u32 current_sclk; @@ -316,8 +325,9 @@ struct amdgpu_pm { uint32_t pp_feature; /* Used for I2C access to various EEPROMs on relevant ASICs */ - struct i2c_adapter smu_i2c; - struct mutex smu_i2c_mutex; + struct amdgpu_smu_i2c_bus smu_i2c[MAX_SMU_I2C_BUSES]; + struct i2c_adapter *ras_eeprom_i2c_bus; + struct i2c_adapter *fru_eeprom_i2c_bus; struct list_head pm_attr_list; atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM]; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c index 9ad26c285ecd..a5c95b180672 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c @@ -520,7 +520,7 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr) priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01; priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t); - ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c); + ret = smu_v11_0_i2c_control_init(adev); if (ret) goto err4; @@ -558,7 +558,7 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr) (struct vega20_smumgr *)(hwmgr->smu_backend); struct amdgpu_device *adev = hwmgr->adev; - smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c); + smu_v11_0_i2c_control_fini(adev); if (priv) { amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 264eb09ccfd5..9861d70a5dad 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -886,7 +886,7 @@ static int smu_smc_table_sw_init(struct smu_context *smu) if (ret) return ret; - ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); + ret = smu_i2c_init(smu); if (ret) return ret; @@ -897,7 +897,7 @@ static int smu_smc_table_sw_fini(struct smu_context *smu) { int ret; - smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); + smu_i2c_fini(smu); smu_free_dummy_read_table(smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 18f24db7d202..4c585241ef66 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -816,12 +816,12 @@ struct pptable_funcs { * other devices. The i2c's EEPROM also stores bad page tables on boards * with ECC. */ - int (*i2c_init)(struct smu_context *smu, struct i2c_adapter *control); + int (*i2c_init)(struct smu_context *smu); /** * @i2c_fini: Tear down i2c. */ - void (*i2c_fini)(struct smu_context *smu, struct i2c_adapter *control); + void (*i2c_fini)(struct smu_context *smu); /** * @get_unique_id: Get the GPU's unique id. Used for asset tracking. diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 2c78d04d5611..0cf385e8b4e9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -25,6 +25,7 @@ #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -45,6 +46,7 @@ #include #include "amdgpu_ras.h" #include "smu_cmn.h" +#include "amdgpu_dpm.h" /* * DO NOT use these for err/warn/info/debug messages. @@ -56,8 +58,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \ [smu_feature] = {1, (arcturus_feature)} @@ -2062,7 +2062,8 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -2074,7 +2075,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 0; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -2153,28 +2154,60 @@ static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int arcturus_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; + struct amdgpu_device *adev = smu->adev; + int res, i; - control->owner = THIS_MODULE; - control->class = I2C_CLASS_HWMON; - control->dev.parent = &adev->pdev->dev; - control->algo = &arcturus_i2c_algo; - control->quirks = &arcturus_i2c_control_quirks; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_HWMON; + control->dev.parent = &adev->pdev->dev; + control->algo = &arcturus_i2c_algo; + control->quirks = &arcturus_i2c_control_quirks; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + i2c_set_adapdata(control, smu_i2c); + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } + + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; + + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } return res; } -static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void arcturus_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static void arcturus_get_unique_id(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 84834c24a7e9..16a5d4d35981 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -27,6 +27,7 @@ #include #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -57,8 +58,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define FEATURE_MASK(feature) (1ULL << feature) #define SMC_DPM_FEATURE ( \ FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ @@ -2746,7 +2745,8 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu, static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -2758,7 +2758,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 0; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -2836,28 +2836,60 @@ static const struct i2c_adapter_quirks navi10_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int navi10_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; + struct amdgpu_device *adev = smu->adev; + int res, i; - control->owner = THIS_MODULE; - control->class = I2C_CLASS_HWMON; - control->dev.parent = &adev->pdev->dev; - control->algo = &navi10_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - control->quirks = &navi10_i2c_control_quirks; + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_HWMON; + control->dev.parent = &adev->pdev->dev; + control->algo = &navi10_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + control->quirks = &navi10_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } + + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; + + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } return res; } -static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void navi10_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index dcd35c68e59b..1c71ea97d06f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -27,6 +27,7 @@ #include #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -59,8 +60,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define FEATURE_MASK(feature) (1ULL << feature) #define SMC_DPM_FEATURE ( \ FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ @@ -3441,7 +3440,8 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -3453,7 +3453,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 1; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -3531,28 +3531,61 @@ static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int sienna_cichlid_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; + struct amdgpu_device *adev = smu->adev; + int res, i; - control->owner = THIS_MODULE; - control->class = I2C_CLASS_HWMON; - control->dev.parent = &adev->pdev->dev; - control->algo = &sienna_cichlid_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - control->quirks = &sienna_cichlid_i2c_control_quirks; + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_HWMON; + control->dev.parent = &adev->pdev->dev; + control->algo = &sienna_cichlid_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + control->quirks = &sienna_cichlid_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } + /* assign the buses used for the FRU EEPROM and RAS EEPROM */ + /* XXX ideally this would be something in a vbios data table */ + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } return res; } -static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void sienna_cichlid_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 8c02adbf446a..450049bcedcb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -25,6 +25,7 @@ #include #include "amdgpu.h" +#include "amdgpu_dpm.h" #include "amdgpu_smu.h" #include "atomfirmware.h" #include "amdgpu_atomfirmware.h" @@ -56,8 +57,6 @@ #undef pr_info #undef pr_debug -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - #define ALDEBARAN_FEA_MAP(smu_feature, aldebaran_feature) \ [smu_feature] = {1, (aldebaran_feature)} @@ -1465,7 +1464,8 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu) static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, int num_msgs) { - struct amdgpu_device *adev = to_amdgpu_device(i2c_adap); + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; struct smu_context *smu = adev->powerplay.pp_handle; struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *table = &smu_table->driver_table; @@ -1477,7 +1477,7 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, if (!req) return -ENOMEM; - req->I2CcontrollerPort = 0; + req->I2CcontrollerPort = smu_i2c->port; req->I2CSpeed = I2C_SPEED_FAST_400K; req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ dir = msg[0].flags & I2C_M_RD; @@ -1555,28 +1555,52 @@ static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = { .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, }; -static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +static int aldebaran_i2c_control_init(struct smu_context *smu) { - struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_device *adev = smu->adev; + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0]; + struct i2c_adapter *control = &smu_i2c->adapter; int res; + smu_i2c->adev = adev; + smu_i2c->port = 0; + mutex_init(&smu_i2c->mutex); control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; control->algo = &aldebaran_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0"); control->quirks = &aldebaran_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); res = i2c_add_adapter(control); - if (res) + if (res) { DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + + return 0; +Out_err: + i2c_del_adapter(control); return res; } -static void aldebaran_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +static void aldebaran_i2c_control_fini(struct smu_context *smu) { - i2c_del_adapter(control); + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } static void aldebaran_get_unique_id(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 59f9cfff3d61..a290b5789195 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -78,8 +78,8 @@ #define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu) #define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap) #define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src) -#define smu_i2c_init(smu, control) smu_ppt_funcs(i2c_init, 0, smu, control) -#define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) +#define smu_i2c_init(smu) smu_ppt_funcs(i2c_init, 0, smu) +#define smu_i2c_fini(smu) smu_ppt_funcs(i2c_fini, 0, smu) #define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) #define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) #define smu_get_asic_power_limits(smu, current, default, max) smu_ppt_funcs(get_power_limit, 0, smu, current, default, max) From 3ed893396b0132fa5a4d3fe3f9ba358678c6dba3 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 27 Jan 2022 13:49:30 -0500 Subject: [PATCH 201/339] drm/amd: Enable FRU EEPROM for Sienna Cichlid Enable the FRU EEPROM I2C bus for Sienna Cichlid server boards, for which it is enabled by checking the VBIOS version. Cc: Roy Sun Cc: Alex Deucher Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 40180648be38..ce5d5ee336a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -46,7 +46,7 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) return false; - /* VBIOS is of the format ###-DXXXYY-##. For SKU identification, + /* VBIOS is of the format ###-DXXXYYYY-##. For SKU identification, * we can use just the "DXXX" portion. If there were more models, we * could convert the 3 characters to a hex integer and use a switch * for ease/speed/readability. For now, 2 string comparisons are @@ -65,6 +65,12 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) case CHIP_ALDEBARAN: /* All Aldebaran SKUs have the FRU */ return true; + case CHIP_SIENNA_CICHLID: + if (strnstr(atom_ctx->vbios_version, "D603", + sizeof(atom_ctx->vbios_version))) + return true; + else + return false; default: return false; } From e281d5940ae7f2ceff99d5e001a69b5f0884d2f0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 27 Jan 2022 12:17:23 -0500 Subject: [PATCH 202/339] drm/amdgpu/swsmu/i2c: return an error if the SMU is not running Return an error if someone tries to use the i2c bus when the SMU is not running. Otherwise we can end up sending commands to the SMU which will either get ignored or could cause other issues depending on what state the GPU and SMU are in. Cc: Luben.Tuikov@amd.com Reviewed-by: Luben Tuikov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 3 +++ drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 3 +++ drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 3 +++ drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 3 +++ 4 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 0cf385e8b4e9..ee296441c5bc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2071,6 +2071,9 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, int i, j, r, c; u16 dir; + if (!adev->pm.dpm_enabled) + return -EBUSY; + req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 16a5d4d35981..4a86520d01c3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2754,6 +2754,9 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, int i, j, r, c; u16 dir; + if (!adev->pm.dpm_enabled) + return -EBUSY; + req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 1c71ea97d06f..22dd372b8d24 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -3449,6 +3449,9 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, int i, j, r, c; u16 dir; + if (!adev->pm.dpm_enabled) + return -EBUSY; + req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 450049bcedcb..ba4c9771ffc5 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1473,6 +1473,9 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap, int i, j, r, c; u16 dir; + if (!adev->pm.dpm_enabled) + return -EBUSY; + req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return -ENOMEM; From 8cda7a4f96e435be2fd074009d69521d973d7d31 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 7 Jan 2022 17:57:33 -0500 Subject: [PATCH 203/339] drm/amdgpu/UAPI: add new CTX OP to get/set stable pstates Add a new CTX ioctl operation to set stable pstates for profiling. When creating traces for tools like RGP or using SPM or doing performance profiling, it's required to enable a special stable profiling power state on the GPU. These profiling states set fixed clocks and disable certain other power features like powergating which may impact the results. Historically, these profiling pstates were enabled via sysfs, but this adds an interface to enable it via the CTX ioctl from the application. Since the power state is global only one application can set it at a time, so if multiple applications try and use it only the first will get it, the ioctl will return -EBUSY for others. The sysfs interface will override whatever has been set by this interface. Mesa MR: https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/207 v2: don't default r = 0; v3: rebase on Evan's PM cleanup Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 129 ++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + drivers/gpu/drm/amd/pm/amdgpu_pm.c | 5 + drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 3 + include/uapi/drm/amdgpu_drm.h | 17 ++- 6 files changed, 153 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 468003583b2a..2c929fa40379 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -237,6 +237,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter); ctx->init_priority = priority; ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET; + ctx->stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE; return 0; } @@ -255,6 +256,86 @@ static void amdgpu_ctx_fini_entity(struct amdgpu_ctx_entity *entity) kfree(entity); } +static int amdgpu_ctx_get_stable_pstate(struct amdgpu_ctx *ctx, + u32 *stable_pstate) +{ + struct amdgpu_device *adev = ctx->adev; + enum amd_dpm_forced_level current_level; + + if (!ctx) + return -EINVAL; + + current_level = amdgpu_dpm_get_performance_level(adev); + + switch (current_level) { + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_STANDARD; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_PEAK; + break; + default: + *stable_pstate = AMDGPU_CTX_STABLE_PSTATE_NONE; + break; + } + return 0; +} + +static int amdgpu_ctx_set_stable_pstate(struct amdgpu_ctx *ctx, + u32 stable_pstate) +{ + struct amdgpu_device *adev = ctx->adev; + enum amd_dpm_forced_level level; + int r; + + if (!ctx) + return -EINVAL; + + mutex_lock(&adev->pm.stable_pstate_ctx_lock); + if (adev->pm.stable_pstate_ctx && adev->pm.stable_pstate_ctx != ctx) { + r = -EBUSY; + goto done; + } + + switch (stable_pstate) { + case AMDGPU_CTX_STABLE_PSTATE_NONE: + level = AMD_DPM_FORCED_LEVEL_AUTO; + break; + case AMDGPU_CTX_STABLE_PSTATE_STANDARD: + level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD; + break; + case AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK: + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK; + break; + case AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK: + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK; + break; + case AMDGPU_CTX_STABLE_PSTATE_PEAK: + level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + break; + default: + r = -EINVAL; + goto done; + } + + r = amdgpu_dpm_force_performance_level(adev, level); + + if (level == AMD_DPM_FORCED_LEVEL_AUTO) + adev->pm.stable_pstate_ctx = NULL; + else + adev->pm.stable_pstate_ctx = ctx; +done: + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); + + return r; +} + static void amdgpu_ctx_fini(struct kref *ref) { struct amdgpu_ctx *ctx = container_of(ref, struct amdgpu_ctx, refcount); @@ -270,7 +351,7 @@ static void amdgpu_ctx_fini(struct kref *ref) ctx->entities[i][j] = NULL; } } - + amdgpu_ctx_set_stable_pstate(ctx, AMDGPU_CTX_STABLE_PSTATE_NONE); mutex_destroy(&ctx->lock); kfree(ctx); } @@ -467,11 +548,41 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, return 0; } + + +static int amdgpu_ctx_stable_pstate(struct amdgpu_device *adev, + struct amdgpu_fpriv *fpriv, uint32_t id, + bool set, u32 *stable_pstate) +{ + struct amdgpu_ctx *ctx; + struct amdgpu_ctx_mgr *mgr; + int r; + + if (!fpriv) + return -EINVAL; + + mgr = &fpriv->ctx_mgr; + mutex_lock(&mgr->lock); + ctx = idr_find(&mgr->ctx_handles, id); + if (!ctx) { + mutex_unlock(&mgr->lock); + return -EINVAL; + } + + if (set) + r = amdgpu_ctx_set_stable_pstate(ctx, *stable_pstate); + else + r = amdgpu_ctx_get_stable_pstate(ctx, stable_pstate); + + mutex_unlock(&mgr->lock); + return r; +} + int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { int r; - uint32_t id; + uint32_t id, stable_pstate; int32_t priority; union drm_amdgpu_ctx *args = data; @@ -500,6 +611,20 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, case AMDGPU_CTX_OP_QUERY_STATE2: r = amdgpu_ctx_query2(adev, fpriv, id, &args->out); break; + case AMDGPU_CTX_OP_GET_STABLE_PSTATE: + if (args->in.flags) + return -EINVAL; + r = amdgpu_ctx_stable_pstate(adev, fpriv, id, false, &stable_pstate); + args->out.pstate.flags = stable_pstate; + break; + case AMDGPU_CTX_OP_SET_STABLE_PSTATE: + if (args->in.flags & ~AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK) + return -EINVAL; + stable_pstate = args->in.flags & AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK; + if (stable_pstate > AMDGPU_CTX_STABLE_PSTATE_PEAK) + return -EINVAL; + r = amdgpu_ctx_stable_pstate(adev, fpriv, id, true, &stable_pstate); + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h index a44b8b8ed39c..142f2f87d44c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h @@ -53,6 +53,7 @@ struct amdgpu_ctx { atomic_t guilty; unsigned long ras_counter_ce; unsigned long ras_counter_ue; + uint32_t stable_pstate; }; struct amdgpu_ctx_mgr { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6ba57ad88640..660fb4085c97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3510,6 +3510,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, init_rwsem(&adev->reset_sem); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); + mutex_init(&adev->pm.stable_pstate_ctx_lock); amdgpu_device_init_apu_flags(adev); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 837a31a46596..d68e7132da2c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -336,11 +336,16 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } + mutex_lock(&adev->pm.stable_pstate_ctx_lock); if (amdgpu_dpm_force_performance_level(adev, level)) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); return -EINVAL; } + /* override whatever a user ctx may have set */ + adev->pm.stable_pstate_ctx = NULL; + mutex_unlock(&adev->pm.stable_pstate_ctx_lock); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 2766b88ecf96..5cc05110cdae 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -338,6 +338,9 @@ struct amdgpu_pm { uint32_t smu_debug_mask; bool pp_force_state_enabled; + + struct mutex stable_pstate_ctx_lock; + struct amdgpu_ctx *stable_pstate_ctx; }; u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index be4f9111f478..76b580d10a52 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -206,6 +206,8 @@ union drm_amdgpu_bo_list { #define AMDGPU_CTX_OP_FREE_CTX 2 #define AMDGPU_CTX_OP_QUERY_STATE 3 #define AMDGPU_CTX_OP_QUERY_STATE2 4 +#define AMDGPU_CTX_OP_GET_STABLE_PSTATE 5 +#define AMDGPU_CTX_OP_SET_STABLE_PSTATE 6 /* GPU reset status */ #define AMDGPU_CTX_NO_RESET 0 @@ -238,10 +240,18 @@ union drm_amdgpu_bo_list { #define AMDGPU_CTX_PRIORITY_HIGH 512 #define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023 +/* select a stable profiling pstate for perfmon tools */ +#define AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK 0xf +#define AMDGPU_CTX_STABLE_PSTATE_NONE 0 +#define AMDGPU_CTX_STABLE_PSTATE_STANDARD 1 +#define AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK 2 +#define AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK 3 +#define AMDGPU_CTX_STABLE_PSTATE_PEAK 4 + struct drm_amdgpu_ctx_in { /** AMDGPU_CTX_OP_* */ __u32 op; - /** For future use, no flags defined so far */ + /** Flags */ __u32 flags; __u32 ctx_id; /** AMDGPU_CTX_PRIORITY_* */ @@ -262,6 +272,11 @@ union drm_amdgpu_ctx_out { /** Reset status since the last call of the ioctl. */ __u32 reset_status; } state; + + struct { + __u32 flags; + __u32 _pad; + } pstate; }; union drm_amdgpu_ctx { From ded81d5b2b67e6e6fce0a1e8b73e4565a28dbfd8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 2 Dec 2021 11:02:23 -0500 Subject: [PATCH 204/339] drm/amdgpu: bump driver version for new CTX OP to set/get stable pstates So mesa and tools know when this is available. Mesa MR: https://gitlab.freedesktop.org/mesa/drm/-/merge_requests/207 Reviewed-by: Evan Quan 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 9c799645f2e7..f3cada3f743b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -98,9 +98,10 @@ * - 3.42.0 - Add 16bpc fixed point display support * - 3.43.0 - Add device hot plug/unplug support * - 3.44.0 - DCN3 supports DCC independent block settings: !64B && 128B, 64B && 128B + * - 3.45.0 - Add context ioctl stable pstate interface */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 44 +#define KMS_DRIVER_MINOR 45 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit; From 1ec5a44331af283b1cd3b0f0981cf65f0903ec8f Mon Sep 17 00:00:00 2001 From: tangmeng Date: Thu, 27 Jan 2022 15:12:39 +0800 Subject: [PATCH 205/339] drm/amd/amdgpu: fix spelling mistake "disbale" -> "disable" There is a spelling mistake. Fix it. Signed-off-by: tangmeng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c index aef9d059ae52..a642c04cf17d 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c @@ -544,7 +544,7 @@ static int xgpu_vi_mailbox_rcv_irq(struct amdgpu_device *adev, { int r; - /* trigger gpu-reset by hypervisor only if TDR disbaled */ + /* trigger gpu-reset by hypervisor only if TDR disabled */ if (!amdgpu_gpu_recovery) { /* see what event we get */ r = xgpu_vi_mailbox_rcv_msg(adev, IDH_FLR_NOTIFICATION); From c57f5ba2c8febe944ddebae53730667d5af179e5 Mon Sep 17 00:00:00 2001 From: huangqu Date: Wed, 26 Jan 2022 17:16:02 +0800 Subject: [PATCH 206/339] drm/amdgpu: Wrong order for config and counter_id parameters Wrong order for config and counter_id parameters was passed, when calling df_v3_6_pmc_set_deferred and df_v3_6_pmc_is_deferred functions. Signed-off-by: huangqu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index 43c5e3ec9a39..f4dfca013ec5 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c @@ -458,7 +458,7 @@ static int df_v3_6_pmc_add_cntr(struct amdgpu_device *adev, #define DEFERRED_ARM_MASK (1 << 31) static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev, - int counter_idx, uint64_t config, + uint64_t config, int counter_idx, bool is_deferred) { @@ -476,8 +476,8 @@ static int df_v3_6_pmc_set_deferred(struct amdgpu_device *adev, } static bool df_v3_6_pmc_is_deferred(struct amdgpu_device *adev, - int counter_idx, - uint64_t config) + uint64_t config, + int counter_idx) { return (df_v3_6_pmc_has_counter(adev, config, counter_idx) && (adev->df_perfmon_config_assign_mask[counter_idx] From f588a1bbfce781042196e68f8e200f08b3d9e8c4 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 11 Jan 2022 14:00:26 -0600 Subject: [PATCH 207/339] drm/amd: Warn users about potential s0ix problems On some OEM setups users can configure the BIOS for S3 or S2idle. When configured to S3 users can still choose 's2idle' in the kernel by using `/sys/power/mem_sleep`. Before commit 6dc8265f9803 ("drm/amdgpu: always reset the asic in suspend (v2)"), the GPU would crash. Now when configured this way, the system should resume but will use more power. As such, adjust the `amdpu_acpi_is_s0ix function` to warn users about potential power consumption issues during their first attempt at suspending. Reported-by: Bjoren Dasse Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1824 Reviewed-by: Alex Deucher Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 8 ++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 24 +++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 845c92dc73f6..65d2799f5a87 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1407,12 +1407,10 @@ int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_sta int amdgpu_acpi_pcie_notify_device_ready(struct amdgpu_device *adev); void amdgpu_acpi_get_backlight_caps(struct amdgpu_dm_backlight_caps *caps); -bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); void amdgpu_acpi_detect(void); #else static inline int amdgpu_acpi_init(struct amdgpu_device *adev) { return 0; } static inline void amdgpu_acpi_fini(struct amdgpu_device *adev) { } -static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } static inline void amdgpu_acpi_detect(void) { } static inline bool amdgpu_acpi_is_power_shift_control_supported(void) { return false; } static inline int amdgpu_acpi_power_shift_control(struct amdgpu_device *adev, @@ -1421,6 +1419,12 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev, enum amdgpu_ss ss_state) { return 0; } #endif +#if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) +bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); +#else +static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } +#endif + int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, uint64_t addr, struct amdgpu_bo **bo, struct amdgpu_bo_va_mapping **mapping); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 4811b0faafd9..b19d40751802 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1031,6 +1031,7 @@ void amdgpu_acpi_detect(void) } } +#if IS_ENABLED(CONFIG_SUSPEND) /** * amdgpu_acpi_is_s0ix_active * @@ -1040,11 +1041,24 @@ void amdgpu_acpi_detect(void) */ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { -#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND) - if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) { - if (adev->flags & AMD_IS_APU) - return pm_suspend_target_state == PM_SUSPEND_TO_IDLE; + if (!(adev->flags & AMD_IS_APU) || + (pm_suspend_target_state != PM_SUSPEND_TO_IDLE)) + return false; + + if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) { + dev_warn_once(adev->dev, + "Power consumption will be higher as BIOS has not been configured for suspend-to-idle.\n" + "To use suspend-to-idle change the sleep mode in BIOS setup.\n"); + return false; } -#endif + +#if !IS_ENABLED(CONFIG_AMD_PMC) + dev_warn_once(adev->dev, + "Power consumption will be higher as the kernel has not been compiled with CONFIG_AMD_PMC.\n"); return false; +#else + return true; +#endif /* CONFIG_AMD_PMC */ } + +#endif /* CONFIG_SUSPEND */ From 18b66ace6b3acb01b645d2fbbd571f66b2705c71 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 25 Jan 2022 21:35:09 -0600 Subject: [PATCH 208/339] drm/amd: add support to check whether the system is set to s3 This will be used to help make decisions on what to do in misconfigured systems. v2: squash in semicolon fix from Stephen Rothwell Signed-off-by: Mario Limonciello Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 65d2799f5a87..92f757c007d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1420,9 +1420,11 @@ static inline int amdgpu_acpi_smart_shift_update(struct drm_device *dev, #endif #if defined(CONFIG_ACPI) && defined(CONFIG_SUSPEND) +bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev); bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev); #else static inline bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) { return false; } +static inline bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) { return false; } #endif int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index b19d40751802..0e12315fa0cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -1032,6 +1032,19 @@ void amdgpu_acpi_detect(void) } #if IS_ENABLED(CONFIG_SUSPEND) +/** + * amdgpu_acpi_is_s3_active + * + * @adev: amdgpu_device_pointer + * + * returns true if supported, false if not. + */ +bool amdgpu_acpi_is_s3_active(struct amdgpu_device *adev) +{ + return !(adev->flags & AMD_IS_APU) || + (pm_suspend_target_state == PM_SUSPEND_MEM); +} + /** * amdgpu_acpi_is_s0ix_active * From d2a197a45daacd4ab3221161405768a6d1d11086 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 25 Jan 2022 21:37:57 -0600 Subject: [PATCH 209/339] drm/amd: Only run s3 or s0ix if system is configured properly This will cause misconfigured systems to not run the GPU suspend routines. * In APUs that are properly configured system will go into s2idle. * In APUs that are intended to be S3 but user selects s2idle the GPU will stay fully powered for the suspend. * In APUs that are intended to be s2idle and system misconfigured the GPU will stay fully powered for the suspend. * In systems that are intended to be s2idle, but AMD dGPU is also present, the dGPU will go through S3 Signed-off-by: Mario Limonciello Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index f3cada3f743b..4c43f9401f56 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2263,6 +2263,7 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work) static int amdgpu_pmops_prepare(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(drm_dev); /* Return a positive number here so * DPM_FLAG_SMART_SUSPEND works properly @@ -2271,6 +2272,13 @@ static int amdgpu_pmops_prepare(struct device *dev) return pm_runtime_suspended(dev) && pm_suspend_via_firmware(); + /* if we will not support s3 or s2i for the device + * then skip suspend + */ + if (!amdgpu_acpi_is_s0ix_active(adev) && + !amdgpu_acpi_is_s3_active(adev)) + return 1; + return 0; } From d2895ec4ca6c67c5a9c8ce74bd5deba76ea77f6c Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Fri, 28 Jan 2022 18:24:53 +0800 Subject: [PATCH 210/339] drm/amdgpu: fix a potential GPU hang on cyan skillfish We observed a GPU hang when querying GMC CG state(i.e., cat amdgpu_pm_info) on cyan skillfish. Acctually, cyan skillfish doesn't support any CG features. Just prevent it from accessing GMC CG registers. Signed-off-by: Lang Yu Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 73ab0eebe4e2..bddaf2417344 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -1156,6 +1156,9 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3)) + return; + adev->mmhub.funcs->get_clockgating(adev, flags); if (adev->ip_versions[ATHUB_HWIP][0] >= IP_VERSION(2, 1, 0)) From 6a77bce58c6b29167bce2f548559c75326bbaf03 Mon Sep 17 00:00:00 2001 From: Changcheng Deng Date: Fri, 28 Jan 2022 07:05:19 +0000 Subject: [PATCH 211/339] drm/amdgpu: remove duplicate include in 'amdgpu_device.c' 'linux/pci.h' included in 'amdgpu_device.c' is duplicated. Reported-by: Zeal Robot Signed-off-by: Changcheng Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 660fb4085c97..0b98d65056e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -56,7 +56,6 @@ #include "soc15.h" #include "nv.h" #include "bif/bif_4_1_d.h" -#include #include #include "amdgpu_vf_error.h" From f89154b6525c7ca394ca68adc90e6a0d5b3872fa Mon Sep 17 00:00:00 2001 From: Changcheng Deng Date: Fri, 28 Jan 2022 07:19:36 +0000 Subject: [PATCH 212/339] drm/amd/pm: remove duplicate include in 'arcturus_ppt.c' 'amdgpu_dpm.h' included in 'arcturus_ppt.c' is duplicated. Reported-by: Zeal Robot Signed-off-by: Changcheng Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index ee296441c5bc..709c32063ef7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -46,7 +46,6 @@ #include #include "amdgpu_ras.h" #include "smu_cmn.h" -#include "amdgpu_dpm.h" /* * DO NOT use these for err/warn/info/debug messages. From 1ca489fc60e2713a9acba4294c6fad66d85961b2 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 28 Jan 2022 17:35:02 +0000 Subject: [PATCH 213/339] drm/amd/display: fix spelling mistake: synatpics -> synaptics There are quite a few spelling mistakes in various function names and error messages. Fix these. Reviewed-by: Harry Wentland Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 75b5299b3576..db4ab01267e4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -539,7 +539,7 @@ bool dm_helpers_submit_i2c( } #if defined(CONFIG_DRM_AMD_DC_DCN) -static bool execute_synatpics_rc_command(struct drm_dp_aux *aux, +static bool execute_synaptics_rc_command(struct drm_dp_aux *aux, bool is_write_cmd, unsigned char cmd, unsigned int length, @@ -578,7 +578,7 @@ static bool execute_synatpics_rc_command(struct drm_dp_aux *aux, ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd)); if (ret < 0) { - DRM_ERROR(" execute_synatpics_rc_command - write cmd ..., err = %d\n", ret); + DRM_ERROR(" execute_synaptics_rc_command - write cmd ..., err = %d\n", ret); return false; } @@ -600,7 +600,7 @@ static bool execute_synatpics_rc_command(struct drm_dp_aux *aux, drm_dp_dpcd_read(aux, SYNAPTICS_RC_DATA, data, length); } - DC_LOG_DC(" execute_synatpics_rc_command - success = %d\n", success); + DC_LOG_DC(" execute_synaptics_rc_command - success = %d\n", success); return success; } @@ -618,54 +618,54 @@ static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux) data[3] = 'U'; data[4] = 'S'; - if (!execute_synatpics_rc_command(aux, true, 0x01, 5, 0, data)) + if (!execute_synaptics_rc_command(aux, true, 0x01, 5, 0, data)) return; // Step 3 and 4 - if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220998, data)) + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data)) return; data[0] &= (~(1 << 1)); // set bit 1 to 0 - if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220998, data)) + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data)) return; - if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) return; data[0] &= (~(1 << 1)); // set bit 1 to 0 - if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220D98, data)) + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220D98, data)) return; - if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x221198, data)) + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data)) return; data[0] &= (~(1 << 1)); // set bit 1 to 0 - if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x221198, data)) + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data)) return; // Step 3 and 5 - if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220998, data)) + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data)) return; data[0] |= (1 << 1); // set bit 1 to 1 - if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x220998, data)) + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data)) return; - if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data)) return; data[0] |= (1 << 1); // set bit 1 to 1 return; - if (!execute_synatpics_rc_command(aux, false, 0x31, 4, 0x221198, data)) + if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data)) return; data[0] |= (1 << 1); // set bit 1 to 1 - if (!execute_synatpics_rc_command(aux, true, 0x21, 4, 0x221198, data)) + if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data)) return; // Step 6 - if (!execute_synatpics_rc_command(aux, true, 0x02, 0, 0, NULL)) + if (!execute_synaptics_rc_command(aux, true, 0x02, 0, 0, NULL)) return; DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n"); From 90c44207cdd18091ac9aa7cab8a3e7b0ef00e847 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Fri, 28 Jan 2022 09:26:30 -0500 Subject: [PATCH 214/339] drm/amdkfd: Fix variable set but not used warning All warnings (new ones prefixed by >>): drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_svm.c: In function 'svm_range_deferred_list_work': >> drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_svm.c:2067:22: warning: variable 'p' set but not used [-Wunused-but-set-variable] 2067 | struct kfd_process *p; | Fixes: 367c9b0f1b8750 ("drm/amdkfd: Ensure mm remain valid in svm deferred_list work") Reported-by: kernel test robot Signed-off-by: Philip Yang Reviewed-By: Harish Kasiviswanathan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 1cf9041c9727..ffec25e642e2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -2066,13 +2066,10 @@ static void svm_range_deferred_list_work(struct work_struct *work) struct svm_range_list *svms; struct svm_range *prange; struct mm_struct *mm; - struct kfd_process *p; svms = container_of(work, struct svm_range_list, deferred_list_work); pr_debug("enter svms 0x%p\n", svms); - p = container_of(svms, struct kfd_process, svms); - spin_lock(&svms->deferred_list_lock); while (!list_empty(&svms->deferred_range_list)) { prange = list_first_entry(&svms->deferred_range_list, From 67ff4a72a0691b3c0998a875c3a90e1ea710b522 Mon Sep 17 00:00:00 2001 From: Agustin Gutierrez Date: Fri, 28 Jan 2022 17:51:53 -0500 Subject: [PATCH 215/339] drm/amd/display: Update watermark values for DCN301 [Why] There is underflow / visual corruption DCN301, for high bandwidth MST DSC configurations such as 2x1440p144 or 2x4k60. [How] Use up-to-date watermark values for DCN301. Reviewed-by: Zhan Liu Signed-off-by: Agustin Gutierrez Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 48005def1164..bc4ddc36fe58 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -570,32 +570,32 @@ static struct wm_table lpddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 7.95, - .sr_enter_plus_exit_time_us = 9, + .sr_exit_time_us = 13.5, + .sr_enter_plus_exit_time_us = 16.5, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 9.82, - .sr_enter_plus_exit_time_us = 11.196, + .sr_exit_time_us = 13.5, + .sr_enter_plus_exit_time_us = 16.5, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 9.89, - .sr_enter_plus_exit_time_us = 11.24, + .sr_exit_time_us = 13.5, + .sr_enter_plus_exit_time_us = 16.5, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 9.748, - .sr_enter_plus_exit_time_us = 11.102, + .sr_exit_time_us = 13.5, + .sr_enter_plus_exit_time_us = 16.5, .valid = true, }, } From a2170b4af62fd347c699ae3cd9ec0a8096466f9d Mon Sep 17 00:00:00 2001 From: yipechai Date: Sat, 29 Jan 2022 11:20:50 +0800 Subject: [PATCH 216/339] drm/amdgpu: Add judgement to avoid infinite loop 1. The infinite loop causing soft lock occurs on multiple amdgpu cards supporting ras feature. 2. This a workaround patch to fix 6492e1b07c03397f85bd6dc0e230ea6cd9394635. It is valid for multiple amdgpu cards of the same type. 3. The root cause is that each GPU card device has a separate .ras_list link header, but the instance and linked list node of each ras block are unique. When each device is initialized, each ras instance will repeatedly add link node to the device every time. In this way, only the .ras_list of the last initialized device is completely correct. the .ras_list->prev and .ras_list->next of the device initialzied before can still point to the correct ras instance, but the prev pointer and next pointer of the pointed ras instance both point to the last initialized device's .ras_ list instead of the beginning .ras_ list. When using list_for_each_entry_safe searches for non-existent Ras nodes on devices other than the last device, the last ras instance next pointer cannot always be equal to the beginning .ras_list, so that the loop cannot be terminated, the program enters a infinite loop. BTW: Since the data and initialization process of each card are the same, the link list between ras instances will not be destroyed every time the device is initialized. 4. The soft locked logs are as follows: [ 262.165690] CPU: 93 PID: 758 Comm: kworker/93:1 Tainted: G OE 5.13.0-27-generic #29~20.04.1-Ubuntu [ 262.165695] Hardware name: Supermicro AS -4124GS-TNR/H12DSG-O-CPU, BIOS T20200717143848 07/17/2020 [ 262.165698] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [ 262.165980] RIP: 0010:amdgpu_ras_get_ras_block+0x86/0xd0 [amdgpu] [ 262.166239] Code: 68 d8 4c 8d 71 d8 48 39 c3 74 54 49 8b 45 38 48 85 c0 74 32 44 89 fa 44 89 e6 4c 89 ef e8 82 e4 9b dc 85 c0 74 3c 49 8b 46 28 <49> 8d 56 28 4d 89 f5 48 83 e8 28 48 39 d3 74 25 49 89 c6 49 8b 45 [ 262.166243] RSP: 0018:ffffac908fa87d80 EFLAGS: 00000202 [ 262.166247] RAX: ffffffffc1394248 RBX: ffff91e4ab8d6e20 RCX: ffffffffc1394248 [ 262.166249] RDX: ffff91e4aa356e20 RSI: 000000000000000e RDI: ffff91e4ab8c0000 [ 262.166252] RBP: ffffac908fa87da8 R08: 0000000000000007 R09: 0000000000000001 [ 262.166254] R10: ffff91e4930b64ec R11: 0000000000000000 R12: 000000000000000e [ 262.166256] R13: ffff91e4aa356df8 R14: ffffffffc1394320 R15: 0000000000000003 [ 262.166258] FS: 0000000000000000(0000) GS:ffff92238fb40000(0000) knlGS:0000000000000000 [ 262.166261] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 262.166264] CR2: 00000001004865d0 CR3: 000000406d796000 CR4: 0000000000350ee0 [ 262.166267] Call Trace: [ 262.166272] amdgpu_ras_do_recovery+0x130/0x290 [amdgpu] [ 262.166529] ? psi_task_switch+0xd2/0x250 [ 262.166537] ? __switch_to+0x11d/0x460 [ 262.166542] ? __switch_to_asm+0x36/0x70 [ 262.166549] process_one_work+0x220/0x3c0 [ 262.166556] worker_thread+0x4d/0x3f0 [ 262.166560] ? process_one_work+0x3c0/0x3c0 [ 262.166563] kthread+0x12b/0x150 [ 262.166568] ? set_kthread_struct+0x40/0x40 [ 262.166571] ret_from_fork+0x22/0x30 Fixes: 6492e1b07c0339 ("drm/amdgpu: Unify ras block interface for each ras block") Signed-off-by: yipechai Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e6324995fc54..9d7c778c1a2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -879,6 +879,7 @@ static int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object *block_ static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_device *adev, enum amdgpu_ras_block block, uint32_t sub_block_index) { + int loop_cnt = 0; struct amdgpu_ras_block_object *obj, *tmp; if (block >= AMDGPU_RAS_BLOCK__LAST) @@ -895,6 +896,9 @@ static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_de if (amdgpu_ras_block_match_default(obj, block) == 0) return obj; } + + if (++loop_cnt >= AMDGPU_RAS_BLOCK__LAST) + break; } return NULL; From 889f84798c5b975125f5f7de910ed222ca8b2677 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 28 Jan 2022 11:57:18 +0530 Subject: [PATCH 217/339] drm/amdgpu: Fix uninitialized variable use warning Fix uninitialized variable use warning: variable 'reg_access_ctrl' is uninitialized when used here [-Wuninitialized] scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0; Fixes: 5d447e29670148 ("drm/amdgpu: add helper for rlcg indirect reg access") Reported-by: kernel test robot Signed-off-by: Lijo Lazar Reviewed-by: Alex Deucher Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 80c25176c993..c13765218919 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -875,6 +875,7 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v return 0; } + reg_access_ctrl = &adev->gfx.rlc.reg_access_ctrl; scratch_reg0 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg0; scratch_reg1 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg1; scratch_reg2 = (void __iomem *)adev->rmmio + 4 * reg_access_ctrl->scratch_reg2; From 274b924c3ed18f7d46d237810dd59d3bc89cb4b4 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 28 Jan 2022 23:14:07 +0800 Subject: [PATCH 218/339] drm/amdgpu: drop flood print in rlcg reg access function A lot of below message are outputed in SRIOV case. amdgpu: indirect registers access through rlcg is not supported Also drop redundant ret set, as it's initialized to be false already. Fixes: 29dbcac82f96d0 ("drm/amdgpu: add helper to query rlcg reg access flag") Signed-off-by: Guchun Chen Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index c13765218919..e1288901beb6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -849,9 +849,6 @@ static bool amdgpu_virt_get_rlcg_reg_access_flag(struct amdgpu_device *adev, } break; default: - dev_err(adev->dev, - "indirect registers access through rlcg is not supported\n"); - ret = false; break; } return ret; From 241a074fc1342b8f6a88af4b7bdc014692ebcde7 Mon Sep 17 00:00:00 2001 From: "Shen, George" Date: Fri, 28 Jan 2022 22:03:55 +0800 Subject: [PATCH 219/339] drm/amd/display: Add link enc null ptr check for cable ID (#2597) [Why] Certain configurations will result in link encoder to not be assigned to the link at the time we apply cable ID logic. We should skip it in those cases. [How] Check if link_enc is not null before applying cable ID. Tested-by: Daniel Wheeler Reviewed-by: Wenjing Liu Acked-by: Stylon Wang Signed-off-by: George Shen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 8cfc9a8197df..117183b5ab44 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -6327,7 +6327,12 @@ void dpcd_set_source_specific_data(struct dc_link *link) void dpcd_update_cable_id(struct dc_link *link) { - if (!link->link_enc->features.flags.bits.IS_UHBR10_CAPABLE || + struct link_encoder *link_enc = NULL; + + link_enc = link_enc_cfg_get_link_enc(link); + + if (!link_enc || + !link_enc->features.flags.bits.IS_UHBR10_CAPABLE || link->dprx_status.cable_id_updated) return; From d389eafa3f50944ca272e0ec865143a9fb948e78 Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Fri, 28 Jan 2022 22:03:56 +0800 Subject: [PATCH 220/339] drm/amd/display: Improve dce_aux_transfer_with_retries logging [Why + How] Payload reply is unknown and not handled in switch statement. Tested-by: Daniel Wheeler Reviewed-by: Anthony Koo Acked-by: Stylon Wang Signed-off-by: Wyatt Wood Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 6d42a9cc9916..74b05b3aef08 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -878,7 +878,7 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, default: DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, LOG_FLAG_Error_I2cAux, - "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case."); + "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case. Reply: %d", *payload->reply); goto fail; } break; From 219fa961e12497fe6beef478cc0de0da47b3a3e6 Mon Sep 17 00:00:00 2001 From: Paul Hsieh Date: Fri, 28 Jan 2022 22:03:57 +0800 Subject: [PATCH 221/339] drm/amd/display: watermark latencies is not enough on DCN31 [Why] The original latencies were causing underflow in some modes. Resolution: 2880x1620@60p when HDR enable [How] 1. Replace with the up-to-date watermark values based on new measurments 2. Correct the ddr_wm_table name to DDR5 on DCN31 Tested-by: Daniel Wheeler Reviewed-by: Aric Cyr Acked-by: Stylon Wang Signed-off-by: Paul Hsieh Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 66bd0261ead6..e17c9938cee5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -329,38 +329,38 @@ static struct clk_bw_params dcn31_bw_params = { }; -static struct wm_table ddr4_wm_table = { +static struct wm_table ddr5_wm_table = { .entries = { { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 6.09, - .sr_enter_plus_exit_time_us = 7.14, + .sr_exit_time_us = 9, + .sr_enter_plus_exit_time_us = 11, .valid = true, }, { .wm_inst = WM_B, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 10.12, - .sr_enter_plus_exit_time_us = 11.48, + .sr_exit_time_us = 9, + .sr_enter_plus_exit_time_us = 11, .valid = true, }, { .wm_inst = WM_C, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 10.12, - .sr_enter_plus_exit_time_us = 11.48, + .sr_exit_time_us = 9, + .sr_enter_plus_exit_time_us = 11, .valid = true, }, { .wm_inst = WM_D, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.72, - .sr_exit_time_us = 10.12, - .sr_enter_plus_exit_time_us = 11.48, + .sr_exit_time_us = 9, + .sr_enter_plus_exit_time_us = 11, .valid = true, }, } @@ -687,7 +687,7 @@ void dcn31_clk_mgr_construct( if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { dcn31_bw_params.wm_table = lpddr5_wm_table; } else { - dcn31_bw_params.wm_table = ddr4_wm_table; + dcn31_bw_params.wm_table = ddr5_wm_table; } /* Saved clocks configured at boot for debug purposes */ dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); From 88839870c3060a04a2e085ef1efccde4b0d1d440 Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" Date: Fri, 28 Jan 2022 22:03:58 +0800 Subject: [PATCH 222/339] drm/amd/display: add infoframe update sequence debug trace [Why] We find some of the driver sequence debug trace for infoframe update is missing so add it. [How] Add the missing sequence debug trace for infoframe update. Tested-by: Daniel Wheeler Reviewed-by: Martin Leung Acked-by: Stylon Wang Signed-off-by: Leo (Hanghong) Ma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0b8811ef3717..e1dee42652ba 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2713,6 +2713,9 @@ static void commit_planes_do_stream_update(struct dc *dc, stream_update->vsp_infopacket) { resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); } if (stream_update->hdr_static_metadata && From 702f8dd8319fa6e3fe9d90115426202e6ee5d06e Mon Sep 17 00:00:00 2001 From: Zhan Liu Date: Fri, 28 Jan 2022 22:03:59 +0800 Subject: [PATCH 223/339] drm/amd/display: revert "Reset fifo after enable otg" [Why] This change causes regression, that prevents some systems from lighting up internal displays. [How] Revert this patch until a new solution is ready. Tested-by: Daniel Wheeler Reviewed-by: Charlene Liu Acked-by: Stylon Wang Signed-off-by: Zhan Liu Signed-off-by: Alex Deucher --- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 5 ----- .../amd/display/dc/dcn10/dcn10_stream_encoder.c | 15 --------------- .../amd/display/dc/dcn10/dcn10_stream_encoder.h | 3 --- .../amd/display/dc/dcn20/dcn20_stream_encoder.c | 2 -- .../display/dc/dcn30/dcn30_dio_stream_encoder.c | 2 -- .../drm/amd/display/dc/inc/hw/stream_encoder.h | 4 ---- 6 files changed, 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 72dd41e7a7d6..f28d6c15a4e2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1567,11 +1567,6 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst); - if (dc_is_embedded_signal(pipe_ctx->stream->signal) && - pipe_ctx->stream_res.stream_enc->funcs->reset_fifo) - pipe_ctx->stream_res.stream_enc->funcs->reset_fifo( - pipe_ctx->stream_res.stream_enc); - if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index bf4436d7aaab..b0c08ee6bc2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -902,19 +902,6 @@ void enc1_stream_encoder_stop_dp_info_packets( } -void enc1_stream_encoder_reset_fifo( - struct stream_encoder *enc) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - /* set DIG_START to 0x1 to reset FIFO */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); - udelay(100); - - /* write 0 to take the FIFO out of reset */ - REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); -} - void enc1_stream_encoder_dp_blank( struct dc_link *link, struct stream_encoder *enc) @@ -1600,8 +1587,6 @@ static const struct stream_encoder_funcs dcn10_str_enc_funcs = { enc1_stream_encoder_send_immediate_sdp_message, .stop_dp_info_packets = enc1_stream_encoder_stop_dp_info_packets, - .reset_fifo = - enc1_stream_encoder_reset_fifo, .dp_blank = enc1_stream_encoder_dp_blank, .dp_unblank = diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index a146a41f68e9..687d7e4bf7ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -626,9 +626,6 @@ void enc1_stream_encoder_send_immediate_sdp_message( void enc1_stream_encoder_stop_dp_info_packets( struct stream_encoder *enc); -void enc1_stream_encoder_reset_fifo( - struct stream_encoder *enc); - void enc1_stream_encoder_dp_blank( struct dc_link *link, struct stream_encoder *enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index 8a70f92795c2..aab25ca8343a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -593,8 +593,6 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = { enc1_stream_encoder_send_immediate_sdp_message, .stop_dp_info_packets = enc1_stream_encoder_stop_dp_info_packets, - .reset_fifo = - enc1_stream_encoder_reset_fifo, .dp_blank = enc1_stream_encoder_dp_blank, .dp_unblank = diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index 8daa12730bc1..a04ca4a98392 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -789,8 +789,6 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = { enc3_stream_encoder_update_dp_info_packets, .stop_dp_info_packets = enc1_stream_encoder_stop_dp_info_packets, - .reset_fifo = - enc1_stream_encoder_reset_fifo, .dp_blank = enc1_stream_encoder_dp_blank, .dp_unblank = diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 36ec56524afd..678c2065e5e8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -164,10 +164,6 @@ struct stream_encoder_funcs { void (*stop_dp_info_packets)( struct stream_encoder *enc); - void (*reset_fifo)( - struct stream_encoder *enc - ); - void (*dp_blank)( struct dc_link *link, struct stream_encoder *enc); From 9d8033d6beca43e9d8eb952adfa8bf08642a357f Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:00 +0800 Subject: [PATCH 224/339] drm/amd/display: add setup/reset stream encoder to link_hwss [why] Factor setup/reset stream encoder to link hwss. Tested-by: Daniel Wheeler Acked-by: Wayne Lin Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 64 +++---- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 23 +-- .../drm/amd/display/dc/core/dc_link_hwss.c | 170 +++++++++++------- .../display/dc/dce110/dce110_hw_sequencer.c | 44 ++--- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 40 +---- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 24 ++- 6 files changed, 181 insertions(+), 184 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 1e596f1ea494..2c5d67abad3e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3441,7 +3441,7 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, struct link_mst_stream_allocation_table proposed_table = {0}; struct fixed31_32 avg_time_slots_per_mtp; const struct dc_link_settings empty_link_settings = {0}; - const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* slot X.Y for SST payload deallocate */ @@ -3450,9 +3450,11 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, dc_log_vcp_x_y(link, avg_time_slots_per_mtp); - link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->set_hblank_min_symbol_width) - link_hwss->set_hblank_min_symbol_width(pipe_ctx, + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, + avg_time_slots_per_mtp); + if (link_hwss->ext.set_hblank_min_symbol_width) + link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, &empty_link_settings, avg_time_slots_per_mtp); } @@ -3498,9 +3500,11 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, dc_log_vcp_x_y(link, avg_time_slots_per_mtp); - link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->set_hblank_min_symbol_width) - link_hwss->set_hblank_min_symbol_width(pipe_ctx, + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, + avg_time_slots_per_mtp); + if (link_hwss->ext.set_hblank_min_symbol_width) + link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, &link->cur_link_settings, avg_time_slots_per_mtp); } @@ -3526,7 +3530,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) struct fixed31_32 pbn_per_slot; int i; enum act_return_status ret; - const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ @@ -3634,9 +3638,10 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) dc_log_vcp_x_y(link, avg_time_slots_per_mtp); - link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->set_hblank_min_symbol_width) - link_hwss->set_hblank_min_symbol_width(pipe_ctx, + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->ext.set_hblank_min_symbol_width) + link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, &link->cur_link_settings, avg_time_slots_per_mtp); @@ -3655,7 +3660,7 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw struct dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; - const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* decrease throttled vcp size */ @@ -3663,9 +3668,10 @@ enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw pbn = get_pbn_from_bw_in_kbps(bw_in_kbps); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); - link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->set_hblank_min_symbol_width) - link_hwss->set_hblank_min_symbol_width(pipe_ctx, + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->ext.set_hblank_min_symbol_width) + link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, &link->cur_link_settings, avg_time_slots_per_mtp); @@ -3737,7 +3743,7 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t struct dp_mst_stream_allocation_table proposed_table = {0}; uint8_t i; enum act_return_status ret; - const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); /* notify immediate branch device table update */ @@ -3796,9 +3802,10 @@ enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t pbn_per_slot = get_pbn_per_slot(stream); avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot); - link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->set_hblank_min_symbol_width) - link_hwss->set_hblank_min_symbol_width(pipe_ctx, + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->ext.set_hblank_min_symbol_width) + link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, &link->cur_link_settings, avg_time_slots_per_mtp); @@ -3815,7 +3822,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0); int i; bool mst_mode = (link->type == dc_connection_mst_branch); - const struct link_hwss *link_hwss = dc_link_hwss_get(link, &pipe_ctx->link_res); + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); const struct dc_link_settings empty_link_settings = {0}; DC_LOGGER_INIT(link->ctx->logger); @@ -3834,9 +3841,10 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) */ /* slot X.Y */ - link_hwss->set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); - if (link_hwss->set_hblank_min_symbol_width) - link_hwss->set_hblank_min_symbol_width(pipe_ctx, + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); + if (link_hwss->ext.set_hblank_min_symbol_width) + link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx, &empty_link_settings, avg_time_slots_per_mtp); @@ -4004,8 +4012,8 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi struct fixed31_32 avg_time_slots_per_mtp; uint8_t req_slot_count = 0; uint8_t vc_id = 1; /// VC ID always 1 for SST - struct dc_link_settings link_settings = {0}; + const struct link_hwss *link_hwss = get_link_hwss(stream->link, &pipe_ctx->link_res); DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); decide_link_settings(stream, &link_settings); @@ -4066,12 +4074,8 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi pipe_ctx->link_res.hpo_dp_link_enc, &proposed_table); - pipe_ctx->link_res.hpo_dp_link_enc->funcs->set_throttled_vcp_size( - pipe_ctx->link_res.hpo_dp_link_enc, - pipe_ctx->stream_res.hpo_dp_stream_enc->inst, - avg_time_slots_per_mtp); - - + if (link_hwss->ext.set_throttled_vcp_size) + link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp); dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 117183b5ab44..f1082674bcbf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2700,26 +2700,15 @@ bool perform_link_training_with_retries( struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; enum dp_panel_mode panel_mode = dp_get_panel_mode(link); - struct link_encoder *link_enc; enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; struct dc_link_settings current_setting = *link_setting; + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); - /* Dynamically assigned link encoders associated with stream rather than - * link. - */ - if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_stream(link->ctx->dc, pipe_ctx->stream); - else - link_enc = link->link_enc; - - /* We need to do this before the link training to ensure the idle pattern in SST - * mode will be sent right after the link training - */ - if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) { - link_enc->funcs->connect_dig_be_to_fe(link_enc, - pipe_ctx->stream_res.stream_enc->id, true); - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); - } + if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) + /* We need to do this before the link training to ensure the idle + * pattern in SST mode will be sent right after the link training + */ + link_hwss->setup_stream_encoder(pipe_ctx); for (j = 0; j < attempts; ++j) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 5e9054fdb339..c26df0a78664 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -784,54 +784,8 @@ void disable_dp_hpo_output(struct dc_link *link, } } -void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct dc_stream_state *stream = pipe_ctx->stream; - struct dc *dc = pipe_ctx->stream->ctx->dc; - struct pipe_ctx *odm_pipe; - int odm_combine_num_segments = 1; - enum phyd32clk_clock_source phyd32clk; - - if (enable) { - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - odm_combine_num_segments++; - - dc->res_pool->dccg->funcs->set_dpstreamclk( - dc->res_pool->dccg, - DTBCLK0, - pipe_ctx->stream_res.tg->inst); - - phyd32clk = get_phyd32clk_src(stream->link); - dc->res_pool->dccg->funcs->enable_symclk32_se( - dc->res_pool->dccg, - pipe_ctx->stream_res.hpo_dp_stream_enc->inst, - phyd32clk); - - dc->res_pool->dccg->funcs->set_dtbclk_dto( - dc->res_pool->dccg, - pipe_ctx->stream_res.tg->inst, - stream->phy_pix_clk, - odm_combine_num_segments, - &stream->timing); - } else { - dc->res_pool->dccg->funcs->set_dtbclk_dto( - dc->res_pool->dccg, - pipe_ctx->stream_res.tg->inst, - 0, - 0, - &stream->timing); - dc->res_pool->dccg->funcs->disable_symclk32_se( - dc->res_pool->dccg, - pipe_ctx->stream_res.hpo_dp_stream_enc->inst); - dc->res_pool->dccg->funcs->set_dpstreamclk( - dc->res_pool->dccg, - REFCLK, - pipe_ctx->stream_res.tg->inst); - } -} - -static void set_dummy_throttled_vcp_size(struct pipe_ctx *pipe_ctx, - struct fixed31_32 throttled_vcp_size); +static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx); +static void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx); /************************* below goes to dio_link_hwss ************************/ static bool can_use_dio_link_hwss(const struct dc_link *link, @@ -850,8 +804,48 @@ static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, throttled_vcp_size); } +static struct link_encoder *get_dio_link_encoder(const struct dc_link *link) +{ + /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) + return link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); + else + return link->link_enc; +} + +static void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct link_encoder *link_enc = get_dio_link_encoder(pipe_ctx->stream->link); + + ASSERT(link_enc); + link_enc->funcs->connect_dig_be_to_fe(link_enc, + pipe_ctx->stream_res.stream_enc->id, true); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); +} + +static void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct link_encoder *link_enc = get_dio_link_encoder(pipe_ctx->stream->link); + + link_enc->funcs->connect_dig_be_to_fe( + link_enc, + pipe_ctx->stream_res.stream_enc->id, + false); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); + +} + static const struct link_hwss dio_link_hwss = { - .set_throttled_vcp_size = set_dio_throttled_vcp_size, + .setup_stream_encoder = setup_dio_stream_encoder, + .reset_stream_encoder = reset_dio_stream_encoder, + .ext = { + .set_throttled_vcp_size = set_dio_throttled_vcp_size, + }, }; /*********************** below goes to hpo_dp_link_hwss ***********************/ @@ -895,13 +889,57 @@ static void set_dp_hpo_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, hblank_min_symbol_width); } -static const struct link_hwss hpo_dp_link_hwss = { - .set_throttled_vcp_size = set_dp_hpo_throttled_vcp_size, +static int get_odm_segment_count(struct pipe_ctx *pipe_ctx) +{ + struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; + int count = 1; - /* function pointers below this point require check for NULL - * ********************************************************************* - */ - .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, + while (odm_pipe != NULL) { + count++; + odm_pipe = odm_pipe->next_odm_pipe; + } + + return count; +} + +static void setup_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc; + struct hpo_dp_link_encoder *link_enc = pipe_ctx->link_res.hpo_dp_link_enc; + struct dccg *dccg = dc->res_pool->dccg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + int odm_segment_count = get_odm_segment_count(pipe_ctx); + enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(pipe_ctx->stream->link); + + dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst); + dccg->funcs->enable_symclk32_se(dccg, stream_enc->inst, phyd32clk); + dccg->funcs->set_dtbclk_dto(dccg, tg->inst, pipe_ctx->stream->phy_pix_clk, + odm_segment_count, + &pipe_ctx->stream->timing); + stream_enc->funcs->enable_stream(stream_enc); + stream_enc->funcs->map_stream_to_link(stream_enc, stream_enc->inst, link_enc->inst); +} + +static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct hpo_dp_stream_encoder *stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc; + struct dccg *dccg = dc->res_pool->dccg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + + stream_enc->funcs->disable(stream_enc); + dccg->funcs->set_dtbclk_dto(dccg, tg->inst, 0, 0, &pipe_ctx->stream->timing); + dccg->funcs->disable_symclk32_se(dccg, stream_enc->inst); + dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst); +} +static const struct link_hwss hpo_dp_link_hwss = { + .setup_stream_encoder = setup_hpo_dp_stream_encoder, + .reset_stream_encoder = reset_hpo_dp_stream_encoder, + .ext = { + .set_throttled_vcp_size = set_dp_hpo_throttled_vcp_size, + .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, + }, }; /*********************** below goes to dpia_link_hwss *************************/ static bool can_use_dpia_link_hwss(const struct dc_link *link, @@ -912,21 +950,27 @@ static bool can_use_dpia_link_hwss(const struct dc_link *link, } static const struct link_hwss dpia_link_hwss = { - .set_throttled_vcp_size = set_dio_throttled_vcp_size, + .setup_stream_encoder = setup_dio_stream_encoder, + .reset_stream_encoder = reset_dio_stream_encoder, + .ext = { + .set_throttled_vcp_size = set_dio_throttled_vcp_size, + }, }; /*********************** below goes to link_hwss ******************************/ -static void set_dummy_throttled_vcp_size(struct pipe_ctx *pipe_ctx, - struct fixed31_32 throttled_vcp_size) +static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx) { - return; } -static const struct link_hwss dummy_link_hwss = { - .set_throttled_vcp_size = set_dummy_throttled_vcp_size, +static void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx) +{ +} +static const struct link_hwss virtual_link_hwss = { + .setup_stream_encoder = virtual_setup_stream_encoder, + .reset_stream_encoder = virtual_reset_stream_encoder, }; -const struct link_hwss *dc_link_hwss_get(const struct dc_link *link, +const struct link_hwss *get_link_hwss(const struct dc_link *link, const struct link_resource *link_res) { if (can_use_dp_hpo_link_hwss(link, link_res)) @@ -953,7 +997,7 @@ const struct link_hwss *dc_link_hwss_get(const struct dc_link *link, else if (can_use_dio_link_hwss(link, link_res)) return &dio_link_hwss; else - return &dummy_link_hwss; + return &virtual_link_hwss; } #undef DC_LOGGER diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f28d6c15a4e2..8c32b9cb3b49 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -667,17 +667,12 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct dc_link *link = pipe_ctx->stream->link; const struct dc *dc = link->dc; - + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); uint32_t active_total_with_borders; uint32_t early_control = 0; struct timing_generator *tg = pipe_ctx->stream_res.tg; - /* For MST, there are multiply stream go to only one link. - * connect DIG back_end to front_end while enable_stream and - * disconnect them during disable_stream - * BY this, it is logic clean to separate stream and link */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_res.stream_enc->id, true); + link_hwss->setup_stream_encoder(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); @@ -1178,7 +1173,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; struct dc *dc = pipe_ctx->stream->ctx->dc; - struct link_encoder *link_enc = NULL; + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) { pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( @@ -1196,34 +1191,17 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dc->hwss.disable_audio_stream(pipe_ctx); - /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ - if (link->ep_type == DISPLAY_ENDPOINT_PHY) - link_enc = link->link_enc; - else if (dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - ASSERT(link_enc); + link_hwss->reset_stream_encoder(pipe_ctx); if (is_dp_128b_132b_signal(pipe_ctx)) { - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable( - pipe_ctx->stream_res.hpo_dp_stream_enc); - setup_dp_hpo_stream(pipe_ctx, false); - /* TODO - DP2.0 HW: unmap stream from link encoder here */ - } else { - if (link_enc) - link_enc->funcs->connect_dig_be_to_fe( - link_enc, - pipe_ctx->stream_res.stream_enc->id, - false); + /* TODO: This looks like a bug to me as we are disabling HPO IO when + * we are just disabling a single HPO stream. Shouldn't we disable HPO + * HW control only when HPOs for all streams are disabled? + */ + if (pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control) + pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control( + pipe_ctx->stream->ctx->dc->hwseq, false); } - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); - -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dc->hwseq->funcs.setup_hpo_hw_control && is_dp_128b_132b_signal(pipe_ctx)) - dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, false); -#endif - } void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 4991e93e5308..013b94c41327 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2390,46 +2390,22 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) uint32_t active_total_with_borders; uint32_t early_control = 0; struct timing_generator *tg = pipe_ctx->stream_res.tg; - struct link_encoder *link_enc; + const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); + struct dc *dc = pipe_ctx->stream->ctx->dc; - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_stream(link->ctx->dc, pipe_ctx->stream); - else - link_enc = link->link_enc; - ASSERT(link_enc); - - /* For MST, there are multiply stream go to only one link. - * connect DIG back_end to front_end while enable_stream and - * disconnect them during disable_stream - * BY this, it is logic clean to separate stream and link - */ if (is_dp_128b_132b_signal(pipe_ctx)) { - if (pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control) - pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control( - pipe_ctx->stream->ctx->dc->hwseq, true); - setup_dp_hpo_stream(pipe_ctx, true); - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->enable_stream( - pipe_ctx->stream_res.hpo_dp_stream_enc); - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->map_stream_to_link( - pipe_ctx->stream_res.hpo_dp_stream_enc, - pipe_ctx->stream_res.hpo_dp_stream_enc->inst, - pipe_ctx->link_res.hpo_dp_link_enc->inst); + if (dc->hwseq->funcs.setup_hpo_hw_control) + dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, true); } - if (!is_dp_128b_132b_signal(pipe_ctx) && link_enc) - link_enc->funcs->connect_dig_be_to_fe( - link_enc, pipe_ctx->stream_res.stream_enc->id, true); - - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); + link_hwss->setup_stream_encoder(pipe_ctx); if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) { - if (link->dc->hwss.program_dmdata_engine) - link->dc->hwss.program_dmdata_engine(pipe_ctx); + if (dc->hwss.program_dmdata_engine) + dc->hwss.program_dmdata_engine(pipe_ctx); } - link->dc->hwss.update_info_frame(pipe_ctx); + dc->hwss.update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 5b361924ed8f..e9cad1c78b5e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -77,21 +77,27 @@ struct link_resource; struct fixed31_32; struct pipe_ctx; -struct link_hwss { - /* you must define a dummy implementation and assign the function to - * dummy_link_hwss if you don't want to check for NULL pointer - */ - void (*set_throttled_vcp_size)(struct pipe_ctx *pipe_ctx, - struct fixed31_32 throttled_vcp_size); - - /* function pointers below this point require check for NULL +struct link_hwss_ext { + /* function pointers below require check for NULL at all time * ********************************************************************* */ void (*set_hblank_min_symbol_width)(struct pipe_ctx *pipe_ctx, const struct dc_link_settings *link_settings, struct fixed31_32 throttled_vcp_size); + void (*set_throttled_vcp_size)(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size); }; -const struct link_hwss *dc_link_hwss_get(const struct dc_link *link, const struct link_resource *link_res); +struct link_hwss { + struct link_hwss_ext ext; + + /* function pointers below MUST be assigned to all types of link_hwss + * ********************************************************************* + */ + void (*setup_stream_encoder)(struct pipe_ctx *pipe_ctx); + void (*reset_stream_encoder)(struct pipe_ctx *pipe_ctx); +}; + +const struct link_hwss *get_link_hwss(const struct dc_link *link, const struct link_resource *link_res); #endif /* __DC_LINK_HWSS_H__ */ From 2426d71c52876a5558b40af06143688b3978ddb2 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:01 +0800 Subject: [PATCH 225/339] drm/amd/display: refactor destructive verify link cap sequence [how] 1. move decide det link training link resource before each link training. 2. move disable link for handling vbios case into set all streams dpms off for link sequence. 3. extract usbc hotplug workaround into its own wa function. 4. Minor syntax changes to improve code readability. Tested-by: Daniel Wheeler Acked-by: Wayne Lin Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 17 +-- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 140 +++++++----------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 22 ++- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 7 - drivers/gpu/drm/amd/display/dc/inc/resource.h | 7 +- 5 files changed, 86 insertions(+), 107 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2c5d67abad3e..c99e06afc769 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -893,6 +893,7 @@ static void set_all_streams_dpms_off_for_link(struct dc_link *link) struct pipe_ctx *pipe_ctx; struct dc_stream_update stream_update; bool dpms_off = true; + struct link_resource link_res = {0}; memset(&stream_update, 0, sizeof(stream_update)); stream_update.dpms_off = &dpms_off; @@ -907,33 +908,29 @@ static void set_all_streams_dpms_off_for_link(struct dc_link *link) link->ctx->dc->current_state); } } + + /* link can be also enabled by vbios. In this case it is not recorded + * in pipe_ctx. Disable link phy here to make sure it is completely off + */ + dp_disable_link_phy(link, &link_res, link->connector_signal); } static void verify_link_capability_destructive(struct dc_link *link, struct dc_sink *sink, enum dc_detect_reason reason) { - struct link_resource link_res = { 0 }; bool should_prepare_phy_clocks = should_prepare_phy_clocks_for_link_verification(link->dc, reason); if (should_prepare_phy_clocks) prepare_phy_clocks_for_destructive_link_verification(link->dc); - if (dc_is_dp_signal(link->local_sink->sink_signal)) { struct dc_link_settings known_limit_link_setting = dp_get_max_link_cap(link); - set_all_streams_dpms_off_for_link(link); - if (dp_get_link_encoding_format(&known_limit_link_setting) == - DP_128b_132b_ENCODING) - link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( - &link->dc->current_state->res_ctx, - link->dc->res_pool, - link); dp_verify_link_cap_with_retries( - link, &link_res, &known_limit_link_setting, + link, &known_limit_link_setting, LINK_TRAINING_MAX_VERIFY_RETRY); } else { ASSERT(0); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index f1082674bcbf..abec79e80eed 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -97,6 +97,12 @@ static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = { {LANE_COUNT_ONE, LINK_RATE_LOW}, }; +static const struct dc_link_settings fail_safe_link_settings = { + .lane_count = LANE_COUNT_ONE, + .link_rate = LINK_RATE_LOW, + .link_spread = LINK_SPREAD_DISABLED, +}; + static bool decide_fallback_link_setting( struct dc_link *link, struct dc_link_settings initial_link_settings, @@ -3182,25 +3188,22 @@ bool hpd_rx_irq_check_link_loss_status( return return_code; } -bool dp_verify_link_cap( +static bool dp_verify_link_cap( struct dc_link *link, - const struct link_resource *link_res, struct dc_link_settings *known_limit_link_setting, int *fail_count) { - struct dc_link_settings cur_link_setting = {0}; - struct dc_link_settings *cur = &cur_link_setting; + struct dc_link_settings cur_link_settings = {0}; struct dc_link_settings initial_link_settings = *known_limit_link_setting; - bool success; - bool skip_link_training; + bool success = false; bool skip_video_pattern; - enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; + enum clock_source_id dp_cs_id = get_clock_source_id(link); enum link_training_result status; union hpd_irq_data irq_data; + struct link_resource link_res; memset(&irq_data, 0, sizeof(irq_data)); - success = false; - skip_link_training = false; + cur_link_settings = initial_link_settings; /* Grant extended timeout request */ if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) { @@ -3209,100 +3212,72 @@ bool dp_verify_link_cap( core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); } - /* TODO implement override and monitor patch later */ - - /* try to train the link from high to low to - * find the physical link capability - */ - /* disable PHY done possible by BIOS, will be done by driver itself */ - dp_disable_link_phy(link, link_res, link->connector_signal); - - dp_cs_id = get_clock_source_id(link); - - cur_link_setting = initial_link_settings; - - /* Temporary Renoir-specific workaround for SWDEV-215184; - * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle, - * so add extra cycle of enabling and disabling the PHY before first link training. - */ - if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C && - link->dc->debug.usbc_combo_phy_reset_wa) { - dp_enable_link_phy(link, link_res, link->connector_signal, dp_cs_id, cur); - dp_disable_link_phy(link, link_res, link->connector_signal); - } - do { - skip_video_pattern = true; - - if (cur->link_rate == LINK_RATE_LOW) - skip_video_pattern = false; + if (!get_temp_dp_link_res(link, &link_res, &cur_link_settings)) + continue; + skip_video_pattern = cur_link_settings.link_rate != LINK_RATE_LOW; dp_enable_link_phy( link, - link_res, + &link_res, link->connector_signal, dp_cs_id, - cur); + &cur_link_settings); + status = dc_link_dp_perform_link_training( + link, + &link_res, + &cur_link_settings, + skip_video_pattern); - if (skip_link_training) + if (status == LINK_TRAINING_SUCCESS) { success = true; - else { - status = dc_link_dp_perform_link_training( - link, - link_res, - cur, - skip_video_pattern); - if (status == LINK_TRAINING_SUCCESS) - success = true; - else - (*fail_count)++; - } - - if (success) { - link->verified_link_cap = *cur; udelay(1000); - if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK) - if (hpd_rx_irq_check_link_loss_status( - link, - &irq_data)) - (*fail_count)++; + if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK && + hpd_rx_irq_check_link_loss_status( + link, + &irq_data)) + (*fail_count)++; + + } else { + (*fail_count)++; } - /* always disable the link before trying another - * setting or before returning we'll enable it later - * based on the actual mode we're driving - */ - dp_disable_link_phy(link, link_res, link->connector_signal); + dp_disable_link_phy(link, &link_res, link->connector_signal); } while (!success && decide_fallback_link_setting(link, - initial_link_settings, cur, status)); - - /* Link Training failed for all Link Settings - * (Lane Count is still unknown) - */ - if (!success) { - /* If all LT fails for all settings, - * set verified = failed safe (1 lane low) - */ - link->verified_link_cap.lane_count = LANE_COUNT_ONE; - link->verified_link_cap.link_rate = LINK_RATE_LOW; - - link->verified_link_cap.link_spread = - LINK_SPREAD_DISABLED; - } - + initial_link_settings, &cur_link_settings, status)); + link->verified_link_cap = success ? + cur_link_settings : fail_safe_link_settings; return success; } +static void apply_usbc_combo_phy_reset_wa(struct dc_link *link, + struct dc_link_settings *link_settings) +{ + /* Temporary Renoir-specific workaround PHY will sometimes be in bad + * state on hotplugging display from certain USB-C dongle, so add extra + * cycle of enabling and disabling the PHY before first link training. + */ + struct link_resource link_res = {0}; + enum clock_source_id dp_cs_id = get_clock_source_id(link); + + dp_enable_link_phy(link, &link_res, link->connector_signal, + dp_cs_id, link_settings); + dp_disable_link_phy(link, &link_res, link->connector_signal); +} + bool dp_verify_link_cap_with_retries( struct dc_link *link, - const struct link_resource *link_res, struct dc_link_settings *known_limit_link_setting, int attempts) { int i = 0; bool success = false; + if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C && + link->dc->debug.usbc_combo_phy_reset_wa) + apply_usbc_combo_phy_reset_wa(link, known_limit_link_setting); + for (i = 0; i < attempts; i++) { int fail_count = 0; enum dc_connection_type type = dc_connection_none; @@ -3310,12 +3285,9 @@ bool dp_verify_link_cap_with_retries( memset(&link->verified_link_cap, 0, sizeof(struct dc_link_settings)); if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) { - link->verified_link_cap.lane_count = LANE_COUNT_ONE; - link->verified_link_cap.link_rate = LINK_RATE_LOW; - link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED; + link->verified_link_cap = fail_safe_link_settings; break; - } else if (dp_verify_link_cap(link, link_res, - known_limit_link_setting, + } else if (dp_verify_link_cap(link, known_limit_link_setting, &fail_count) && fail_count == 0) { success = true; break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3aa6d347d73c..9af8794c5b24 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3187,9 +3187,9 @@ void get_audio_check(struct audio_info *aud_modes, } } -struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( +static struct hpo_dp_link_encoder *get_temp_hpo_dp_link_enc( const struct resource_context *res_ctx, - const struct resource_pool *pool, + const struct resource_pool *const pool, const struct dc_link *link) { struct hpo_dp_link_encoder *hpo_dp_link_enc = NULL; @@ -3206,6 +3206,24 @@ struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( return hpo_dp_link_enc; } +bool get_temp_dp_link_res(struct dc_link *link, + struct link_resource *link_res, + struct dc_link_settings *link_settings) +{ + const struct dc *dc = link->dc; + const struct resource_context *res_ctx = &dc->current_state->res_ctx; + + memset(link_res, 0, sizeof(*link_res)); + + if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { + link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx, + dc->res_pool, link); + if (!link_res->hpo_dp_link_enc) + return false; + } + return true; +} + void reset_syncd_pipes_from_disabled_pipes(struct dc *dc, struct dc_state *context) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 3ed2dbbf5642..67286950fe5a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -56,15 +56,8 @@ enum { struct dc_link_settings dp_get_max_link_cap(struct dc_link *link); -bool dp_verify_link_cap( - struct dc_link *link, - const struct link_resource *link_res, - struct dc_link_settings *known_limit_link_setting, - int *fail_count); - bool dp_verify_link_cap_with_retries( struct dc_link *link, - const struct link_resource *link_res, struct dc_link_settings *known_limit_link_setting, int attempts); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index ccb13dcb867b..a02887f644b0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -201,10 +201,9 @@ int get_num_mpc_splits(struct pipe_ctx *pipe); int get_num_odm_splits(struct pipe_ctx *pipe); -struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( - const struct resource_context *res_ctx, - const struct resource_pool *pool, - const struct dc_link *link); +bool get_temp_dp_link_res(struct dc_link *link, + struct link_resource *link_res, + struct dc_link_settings *link_settings); void reset_syncd_pipes_from_disabled_pipes(struct dc *dc, struct dc_state *context); From e8702d0b97dc9fa825715fb28f116c199bbebc87 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:02 +0800 Subject: [PATCH 226/339] drm/amd/display: add enable/disable dp link output to link_hwss [why] Factor enable/disable dp link output to link hwss. Tested-by: Daniel Wheeler Acked-by: Wayne Lin Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 6 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 256 +++++++++--------- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 8 + 3 files changed, 139 insertions(+), 131 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index c99e06afc769..cb6c91cd6e83 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4016,8 +4016,10 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi decide_link_settings(stream, &link_settings); stream->link->cur_link_settings = link_settings; - /* Enable clock, Configure lane count, and Enable Link Encoder*/ - enable_dp_hpo_output(stream->link, &pipe_ctx->link_res, &stream->link->cur_link_settings); + if (link_hwss->ext.enable_dp_link_output) + link_hwss->ext.enable_dp_link_output(stream->link, &pipe_ctx->link_res, + stream->signal, pipe_ctx->clock_source->id, + &link_settings); #ifdef DIAGS_BUILD /* Workaround for FPGA HPO capture DP link data: diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index c26df0a78664..364fa77b85f0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -76,19 +76,15 @@ void dp_enable_link_phy( enum clock_source_id clock_source, const struct dc_link_settings *link_settings) { - struct link_encoder *link_enc; struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; - struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); unsigned int i; - link_enc = link_enc_cfg_get_link_enc(link); - ASSERT(link_enc); - if (link->connector_signal == SIGNAL_TYPE_EDP) { link->dc->hwss.edp_power_control(link, true); link->dc->hwss.edp_wait_for_hpd_ready(link, true); @@ -126,21 +122,9 @@ void dp_enable_link_phy( if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); - if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { - enable_dp_hpo_output(link, link_res, link_settings); - } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { - if (dc_is_dp_sst_signal(signal)) { - link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); - } else { - link_enc->funcs->enable_dp_mst_output( - link_enc, - link_settings, - clock_source); - } - } + if (link_hwss->ext.enable_dp_link_output) + link_hwss->ext.enable_dp_link_output(link, link_res, signal, + clock_source, link_settings); if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); @@ -221,11 +205,7 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_ { struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; - struct hpo_dp_link_encoder *hpo_link_enc = link_res->hpo_dp_link_enc; - struct link_encoder *link_enc; - - link_enc = link_enc_cfg_get_link_enc(link); - ASSERT(link_enc); + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); @@ -234,20 +214,15 @@ void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_ if (link->dc->hwss.edp_backlight_control) link->dc->hwss.edp_backlight_control(link, false); - if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) - disable_dp_hpo_output(link, link_res, signal); - else - link_enc->funcs->disable_output(link_enc, signal); + if (link_hwss->ext.disable_dp_link_output) + link_hwss->ext.disable_dp_link_output(link, link_res, signal); link->dc->hwss.edp_power_control(link, false); } else { if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); - if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING && - hpo_link_enc) - disable_dp_hpo_output(link, link_res, signal); - else - link_enc->funcs->disable_output(link_enc, signal); + if (link_hwss->ext.disable_dp_link_output) + link_hwss->ext.disable_dp_link_output(link, link_res, signal); if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); @@ -702,88 +677,6 @@ static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) } } -void enable_dp_hpo_output(struct dc_link *link, - const struct link_resource *link_res, - const struct dc_link_settings *link_settings) -{ - const struct dc *dc = link->dc; - enum phyd32clk_clock_source phyd32clk; - - /* Enable PHY PLL at target bit rate - * UHBR10 = 10Gbps (SYMCLK32 = 312.5MHz) - * UBR13.5 = 13.5Gbps (SYMCLK32 = 421.875MHz) - * UHBR20 = 20Gbps (SYMCLK32 = 625MHz) - */ - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - switch (link_settings->link_rate) { - case LINK_RATE_UHBR10: - dm_set_phyd32clk(dc->ctx, 312500); - break; - case LINK_RATE_UHBR13_5: - dm_set_phyd32clk(dc->ctx, 412875); - break; - case LINK_RATE_UHBR20: - dm_set_phyd32clk(dc->ctx, 625000); - break; - default: - return; - } - } else { - /* DP2.0 HW: call transmitter control to enable PHY */ - link_res->hpo_dp_link_enc->funcs->enable_link_phy( - link_res->hpo_dp_link_enc, - link_settings, - link->link_enc->transmitter, - link->link_enc->hpd_source); - } - - /* DCCG muxing and DTBCLK DTO */ - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - dc->res_pool->dccg->funcs->set_physymclk( - dc->res_pool->dccg, - link->link_enc_hw_inst, - PHYSYMCLK_FORCE_SRC_PHYD32CLK, - true); - - phyd32clk = get_phyd32clk_src(link); - dc->res_pool->dccg->funcs->enable_symclk32_le( - dc->res_pool->dccg, - link_res->hpo_dp_link_enc->inst, - phyd32clk); - link_res->hpo_dp_link_enc->funcs->link_enable( - link_res->hpo_dp_link_enc, - link_settings->lane_count); - } -} - -void disable_dp_hpo_output(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal) -{ - const struct dc *dc = link->dc; - - link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc); - - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - dc->res_pool->dccg->funcs->disable_symclk32_le( - dc->res_pool->dccg, - link_res->hpo_dp_link_enc->inst); - - dc->res_pool->dccg->funcs->set_physymclk( - dc->res_pool->dccg, - link->link_enc_hw_inst, - PHYSYMCLK_FORCE_SRC_SYMCLK, - false); - - dm_set_phyd32clk(dc->ctx, 0); - } else { - /* DP2.0 HW: call transmitter control to disable PHY */ - link_res->hpo_dp_link_enc->funcs->disable_link_phy( - link_res->hpo_dp_link_enc, - signal); - } -} - static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx); static void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx); @@ -804,21 +697,10 @@ static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, throttled_vcp_size); } -static struct link_encoder *get_dio_link_encoder(const struct dc_link *link) -{ - /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) - return link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); - else - return link->link_enc; -} - static void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) { - struct link_encoder *link_enc = get_dio_link_encoder(pipe_ctx->stream->link); + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); - ASSERT(link_enc); link_enc->funcs->connect_dig_be_to_fe(link_enc, pipe_ctx->stream_res.stream_enc->id, true); if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -828,7 +710,7 @@ static void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) static void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) { - struct link_encoder *link_enc = get_dio_link_encoder(pipe_ctx->stream->link); + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); link_enc->funcs->connect_dig_be_to_fe( link_enc, @@ -840,11 +722,45 @@ static void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) } +static void enable_dio_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + if (dc_is_dp_sst_signal(signal)) + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); + else + link_enc->funcs->enable_dp_mst_output( + link_enc, + link_settings, + clock_source); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); +} + + +static void disable_dio_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + link_enc->funcs->disable_output(link_enc, signal); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); +} + static const struct link_hwss dio_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, + .enable_dp_link_output = enable_dio_dp_link_output, + .disable_dp_link_output = disable_dio_dp_link_output, }, }; @@ -933,12 +849,92 @@ static void reset_hpo_dp_stream_encoder(struct pipe_ctx *pipe_ctx) dccg->funcs->disable_symclk32_se(dccg, stream_enc->inst); dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst); } + +static void enable_hpo_dp_fpga_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + const struct dc *dc = link->dc; + enum phyd32clk_clock_source phyd32clk = get_phyd32clk_src(link); + int phyd32clk_freq_khz = link_settings->link_rate == LINK_RATE_UHBR10 ? 312500 : + link_settings->link_rate == LINK_RATE_UHBR13_5 ? 412875 : + link_settings->link_rate == LINK_RATE_UHBR20 ? 625000 : 0; + + dm_set_phyd32clk(dc->ctx, phyd32clk_freq_khz); + dc->res_pool->dccg->funcs->set_physymclk( + dc->res_pool->dccg, + link->link_enc_hw_inst, + PHYSYMCLK_FORCE_SRC_PHYD32CLK, + true); + dc->res_pool->dccg->funcs->enable_symclk32_le( + dc->res_pool->dccg, + link_res->hpo_dp_link_enc->inst, + phyd32clk); + link_res->hpo_dp_link_enc->funcs->link_enable( + link_res->hpo_dp_link_enc, + link_settings->lane_count); + +} + +static void enable_hpo_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment)) + enable_hpo_dp_fpga_link_output(link, link_res, signal, + clock_source, link_settings); + else + link_res->hpo_dp_link_enc->funcs->enable_link_phy( + link_res->hpo_dp_link_enc, + link_settings, + link->link_enc->transmitter, + link->link_enc->hpd_source); +} + + +static void disable_hpo_dp_fpga_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + const struct dc *dc = link->dc; + + link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc); + dc->res_pool->dccg->funcs->disable_symclk32_le( + dc->res_pool->dccg, + link_res->hpo_dp_link_enc->inst); + dc->res_pool->dccg->funcs->set_physymclk( + dc->res_pool->dccg, + link->link_enc_hw_inst, + PHYSYMCLK_FORCE_SRC_SYMCLK, + false); + dm_set_phyd32clk(dc->ctx, 0); +} + +static void disable_hpo_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + if (IS_FPGA_MAXIMUS_DC(link->dc->ctx->dce_environment)) { + disable_hpo_dp_fpga_link_output(link, link_res, signal); + } else { + link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc); + link_res->hpo_dp_link_enc->funcs->disable_link_phy( + link_res->hpo_dp_link_enc, signal); + } +} + static const struct link_hwss hpo_dp_link_hwss = { .setup_stream_encoder = setup_hpo_dp_stream_encoder, .reset_stream_encoder = reset_hpo_dp_stream_encoder, .ext = { .set_throttled_vcp_size = set_dp_hpo_throttled_vcp_size, .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, + .enable_dp_link_output = enable_hpo_dp_link_output, + .disable_dp_link_output = disable_hpo_dp_link_output, }, }; /*********************** below goes to dpia_link_hwss *************************/ @@ -954,6 +950,8 @@ static const struct link_hwss dpia_link_hwss = { .reset_stream_encoder = reset_dio_stream_encoder, .ext = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, + .enable_dp_link_output = enable_dio_dp_link_output, + .disable_dp_link_output = disable_dio_dp_link_output, }, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index e9cad1c78b5e..8fe20ee02d9e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -86,6 +86,14 @@ struct link_hwss_ext { struct fixed31_32 throttled_vcp_size); void (*set_throttled_vcp_size)(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size); + void (*enable_dp_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); + void (*disable_dp_link_output)(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); }; struct link_hwss { From b9d3d50adbc79c3131ff3c5ac35bb9a57442f08f Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:03 +0800 Subject: [PATCH 227/339] drm/amd/display: add set dp link test pattern to link_hwss [why] Factor set dp link test pattern to link_hwss. Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Stylon Wang Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 46 +++++++++++-------- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 3 ++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 364fa77b85f0..d5670d3b1a4b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -323,33 +323,16 @@ void dp_set_hw_test_pattern( uint8_t *custom_pattern, uint32_t custom_pattern_size) { + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); struct encoder_set_dp_phy_pattern_param pattern_param = {0}; - struct link_encoder *encoder; - enum dp_link_encoding link_encoding_format = dp_get_link_encoding_format(&link->cur_link_settings); - - encoder = link_enc_cfg_get_link_enc(link); - ASSERT(encoder); pattern_param.dp_phy_pattern = test_pattern; pattern_param.custom_pattern = custom_pattern; pattern_param.custom_pattern_size = custom_pattern_size; pattern_param.dp_panel_mode = dp_get_panel_mode(link); - switch (link_encoding_format) { - case DP_128b_132b_ENCODING: - link_res->hpo_dp_link_enc->funcs->set_link_test_pattern( - link_res->hpo_dp_link_enc, &pattern_param); - break; - case DP_8b_10b_ENCODING: - ASSERT(encoder); - encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); - break; - default: - DC_LOG_ERROR("%s: Unknown link encoding format.", __func__); - break; - } - - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); + if (link_hwss->ext.set_dp_link_test_pattern) + link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param); } #undef DC_LOGGER @@ -754,6 +737,17 @@ static void disable_dio_dp_link_output(struct dc_link *link, dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); } +static void set_dio_dp_link_test_pattern(struct dc_link *link, + const struct link_resource *link_res, + struct encoder_set_dp_phy_pattern_param *tp_params) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + ASSERT(link_enc); + link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); +} + static const struct link_hwss dio_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, @@ -761,6 +755,7 @@ static const struct link_hwss dio_link_hwss = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dio_dp_link_output, .disable_dp_link_output = disable_dio_dp_link_output, + .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, }, }; @@ -927,6 +922,15 @@ static void disable_hpo_dp_link_output(struct dc_link *link, } } +static void set_hpo_dp_link_test_pattern(struct dc_link *link, + const struct link_resource *link_res, + struct encoder_set_dp_phy_pattern_param *tp_params) +{ + link_res->hpo_dp_link_enc->funcs->set_link_test_pattern( + link_res->hpo_dp_link_enc, tp_params); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); +} + static const struct link_hwss hpo_dp_link_hwss = { .setup_stream_encoder = setup_hpo_dp_stream_encoder, .reset_stream_encoder = reset_hpo_dp_stream_encoder, @@ -935,6 +939,7 @@ static const struct link_hwss hpo_dp_link_hwss = { .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, .enable_dp_link_output = enable_hpo_dp_link_output, .disable_dp_link_output = disable_hpo_dp_link_output, + .set_dp_link_test_pattern = set_hpo_dp_link_test_pattern, }, }; /*********************** below goes to dpia_link_hwss *************************/ @@ -952,6 +957,7 @@ static const struct link_hwss dpia_link_hwss = { .set_throttled_vcp_size = set_dio_throttled_vcp_size, .enable_dp_link_output = enable_dio_dp_link_output, .disable_dp_link_output = disable_dio_dp_link_output, + .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, }, }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 8fe20ee02d9e..ce9762aa58c9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -94,6 +94,9 @@ struct link_hwss_ext { void (*disable_dp_link_output)(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); + void (*set_dp_link_test_pattern)(struct dc_link *link, + const struct link_resource *link_res, + struct encoder_set_dp_phy_pattern_param *tp_params); }; struct link_hwss { From 8788e0668f4fd8815f82c982879252aebfa708db Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:04 +0800 Subject: [PATCH 228/339] drm/amd/display: add set dp lane settings to link_hwss [why] Factor set dp lane settings to link_hwss. v2: fix statement with no effect warning (Alex) Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Stylon Wang Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 40 ++++++++++++++----- .../drm/amd/display/dc/dce/dce_link_encoder.c | 17 ++++---- .../drm/amd/display/dc/dce/dce_link_encoder.h | 3 +- .../amd/display/dc/dcn10/dcn10_link_encoder.c | 18 ++++----- .../amd/display/dc/dcn10/dcn10_link_encoder.h | 3 +- .../drm/amd/display/dc/inc/hw/link_encoder.h | 3 +- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 4 ++ .../display/dc/virtual/virtual_link_encoder.c | 3 +- 8 files changed, 59 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index d5670d3b1a4b..3b7ab2ca34c6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -295,22 +295,16 @@ void dp_set_hw_lane_settings( const struct link_training_settings *link_settings, uint32_t offset) { - struct link_encoder *encoder = link->link_enc; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset)) return; - /* call Encoder to set lane settings */ - if (dp_get_link_encoding_format(&link_settings->link_settings) == - DP_128b_132b_ENCODING) { - link_res->hpo_dp_link_enc->funcs->set_ffe( - link_res->hpo_dp_link_enc, + if (link_hwss->ext.set_dp_lane_settings) + link_hwss->ext.set_dp_lane_settings(link, link_res, &link_settings->link_settings, - link_settings->lane_settings[0].FFE_PRESET.raw); - } else if (dp_get_link_encoding_format(&link_settings->link_settings) - == DP_8b_10b_ENCODING) { - encoder->funcs->dp_set_lane_settings(encoder, link_settings); - } + link_settings->hw_lane_settings); + memmove(link->cur_lane_setting, link_settings->lane_settings, sizeof(link->cur_lane_setting)); @@ -748,6 +742,16 @@ static void set_dio_dp_link_test_pattern(struct dc_link *link, dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); } +static void set_dio_dp_lane_settings(struct dc_link *link, + const struct link_resource *link_res, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings); +} + static const struct link_hwss dio_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, @@ -756,6 +760,7 @@ static const struct link_hwss dio_link_hwss = { .enable_dp_link_output = enable_dio_dp_link_output, .disable_dp_link_output = disable_dio_dp_link_output, .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, + .set_dp_lane_settings = set_dio_dp_lane_settings, }, }; @@ -931,6 +936,17 @@ static void set_hpo_dp_link_test_pattern(struct dc_link *link, dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); } +static void set_hpo_dp_lane_settings(struct dc_link *link, + const struct link_resource *link_res, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) +{ + link_res->hpo_dp_link_enc->funcs->set_ffe( + link_res->hpo_dp_link_enc, + link_settings, + lane_settings[0].FFE_PRESET.raw); +} + static const struct link_hwss hpo_dp_link_hwss = { .setup_stream_encoder = setup_hpo_dp_stream_encoder, .reset_stream_encoder = reset_hpo_dp_stream_encoder, @@ -940,6 +956,7 @@ static const struct link_hwss hpo_dp_link_hwss = { .enable_dp_link_output = enable_hpo_dp_link_output, .disable_dp_link_output = disable_hpo_dp_link_output, .set_dp_link_test_pattern = set_hpo_dp_link_test_pattern, + .set_dp_lane_settings = set_hpo_dp_lane_settings, }, }; /*********************** below goes to dpia_link_hwss *************************/ @@ -958,6 +975,7 @@ static const struct link_hwss dpia_link_hwss = { .enable_dp_link_output = enable_dio_dp_link_output, .disable_dp_link_output = disable_dio_dp_link_output, .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, + .set_dp_lane_settings = set_dio_dp_lane_settings, }, }; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index f1c61d5aee6c..0bc41414481e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c @@ -1325,7 +1325,8 @@ void dce110_link_encoder_disable_output( void dce110_link_encoder_dp_set_lane_settings( struct link_encoder *enc, - const struct link_training_settings *link_settings) + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) { struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); union dpcd_training_lane_set training_lane_set = { { 0 } }; @@ -1340,26 +1341,26 @@ void dce110_link_encoder_dp_set_lane_settings( cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; cntl.transmitter = enc110->base.transmitter; cntl.connector_obj_id = enc110->base.connector; - cntl.lanes_number = link_settings->link_settings.lane_count; + cntl.lanes_number = link_settings->lane_count; cntl.hpd_sel = enc110->base.hpd_source; - cntl.pixel_clock = link_settings->link_settings.link_rate * + cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (lane = 0; lane < link_settings->link_settings.lane_count; lane++) { + for (lane = 0; lane < link_settings->lane_count; lane++) { /* translate lane settings */ training_lane_set.bits.VOLTAGE_SWING_SET = - link_settings->lane_settings[lane].VOLTAGE_SWING; + lane_settings[lane].VOLTAGE_SWING; training_lane_set.bits.PRE_EMPHASIS_SET = - link_settings->lane_settings[lane].PRE_EMPHASIS; + lane_settings[lane].PRE_EMPHASIS; /* post cursor 2 setting only applies to HBR2 link rate */ - if (link_settings->link_settings.link_rate == LINK_RATE_HIGH2) { + if (link_settings->link_rate == LINK_RATE_HIGH2) { /* this is passed to VBIOS * to program post cursor 2 level */ training_lane_set.bits.POST_CURSOR2_SET = - link_settings->lane_settings[lane].POST_CURSOR2; + lane_settings[lane].POST_CURSOR2; } cntl.lane_select = lane; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index fc6ade824c23..261c70e01e33 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -279,7 +279,8 @@ void dce110_link_encoder_disable_output( /* set DP lane settings */ void dce110_link_encoder_dp_set_lane_settings( struct link_encoder *enc, - const struct link_training_settings *link_settings); + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); void dce110_link_encoder_dp_set_phy_pattern( struct link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index f4b34c110eae..ca39361f71c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -1101,7 +1101,8 @@ void dcn10_link_encoder_disable_output( void dcn10_link_encoder_dp_set_lane_settings( struct link_encoder *enc, - const struct link_training_settings *link_settings) + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) { struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); union dpcd_training_lane_set training_lane_set = { { 0 } }; @@ -1116,26 +1117,25 @@ void dcn10_link_encoder_dp_set_lane_settings( cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; cntl.transmitter = enc10->base.transmitter; cntl.connector_obj_id = enc10->base.connector; - cntl.lanes_number = link_settings->link_settings.lane_count; + cntl.lanes_number = link_settings->lane_count; cntl.hpd_sel = enc10->base.hpd_source; - cntl.pixel_clock = link_settings->link_settings.link_rate * - LINK_RATE_REF_FREQ_IN_KHZ; + cntl.pixel_clock = link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (lane = 0; lane < link_settings->link_settings.lane_count; lane++) { + for (lane = 0; lane < link_settings->lane_count; lane++) { /* translate lane settings */ training_lane_set.bits.VOLTAGE_SWING_SET = - link_settings->lane_settings[lane].VOLTAGE_SWING; + lane_settings[lane].VOLTAGE_SWING; training_lane_set.bits.PRE_EMPHASIS_SET = - link_settings->lane_settings[lane].PRE_EMPHASIS; + lane_settings[lane].PRE_EMPHASIS; /* post cursor 2 setting only applies to HBR2 link rate */ - if (link_settings->link_settings.link_rate == LINK_RATE_HIGH2) { + if (link_settings->link_rate == LINK_RATE_HIGH2) { /* this is passed to VBIOS * to program post cursor 2 level */ training_lane_set.bits.POST_CURSOR2_SET = - link_settings->lane_settings[lane].POST_CURSOR2; + lane_settings[lane].POST_CURSOR2; } cntl.lane_select = lane; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index c337588231ff..663aac0a164a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -581,7 +581,8 @@ void dcn10_link_encoder_disable_output( /* set DP lane settings */ void dcn10_link_encoder_dp_set_lane_settings( struct link_encoder *enc, - const struct link_training_settings *link_settings); + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); void dcn10_link_encoder_dp_set_phy_pattern( struct link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 101444c6f145..2013a70603ae 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -162,7 +162,8 @@ struct link_encoder_funcs { void (*disable_output)(struct link_encoder *link_enc, enum signal_type signal); void (*dp_set_lane_settings)(struct link_encoder *enc, - const struct link_training_settings *link_settings); + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); void (*dp_set_phy_pattern)(struct link_encoder *enc, const struct encoder_set_dp_phy_pattern_param *para); void (*update_mst_stream_allocation_table)( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index ce9762aa58c9..3400e75685aa 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -97,6 +97,10 @@ struct link_hwss_ext { void (*set_dp_link_test_pattern)(struct dc_link *link, const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params); + void (*set_dp_lane_settings)(struct dc_link *link, + const struct link_resource *link_res, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); }; struct link_hwss { diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 348e9a600a72..df8bc44bc4be 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c @@ -63,7 +63,8 @@ static void virtual_link_encoder_disable_output( static void virtual_link_encoder_dp_set_lane_settings( struct link_encoder *enc, - const struct link_training_settings *link_settings) {} + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) {} static void virtual_link_encoder_dp_set_phy_pattern( struct link_encoder *enc, From dfabe59797799bb500897ab4064f8a76aae4026a Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:05 +0800 Subject: [PATCH 229/339] drm/amd/display: temporarly move non link_hwss code to dc_link_dp [why] Clean up dc_link_hwss file in the preparation of breaking it down to file for each encoder type. We temporarly move the original dp link functions in link_hwss back to dc_link_dp. We will break dc_link_dp down after link_hwss is in good shape. Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Stylon Wang Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 613 ++++++++++++++++ .../drm/amd/display/dc/core/dc_link_hwss.c | 653 +----------------- drivers/gpu/drm/amd/display/dc/dc_link.h | 4 +- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 1 + .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 40 ++ .../gpu/drm/amd/display/dc/inc/link_dpcd.h | 2 +- .../gpu/drm/amd/display/dc/inc/link_hwss.h | 54 +- 7 files changed, 681 insertions(+), 686 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index abec79e80eed..51347e1d3d95 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -27,6 +27,7 @@ #include "dm_helpers.h" #include "opp.h" #include "dsc.h" +#include "clk_mgr.h" #include "resource.h" #include "inc/core_types.h" @@ -6713,3 +6714,615 @@ void dc_link_dp_clear_rx_status(struct dc_link *link) { memset(&link->dprx_status, 0, sizeof(link->dprx_status)); } + +void dp_receiver_power_ctrl(struct dc_link *link, bool on) +{ + uint8_t state; + + state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; + + if (link->sync_lt_in_progress) + return; + + core_link_write_dpcd(link, DP_SET_POWER, &state, + sizeof(state)); + +} + +void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) +{ + if (link != NULL && link->dc->debug.enable_driver_sequence_debug) + core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, + &dp_test_mode, sizeof(dp_test_mode)); +} + + +static uint8_t convert_to_count(uint8_t lttpr_repeater_count) +{ + switch (lttpr_repeater_count) { + case 0x80: // 1 lttpr repeater + return 1; + case 0x40: // 2 lttpr repeaters + return 2; + case 0x20: // 3 lttpr repeaters + return 3; + case 0x10: // 4 lttpr repeaters + return 4; + case 0x08: // 5 lttpr repeaters + return 5; + case 0x04: // 6 lttpr repeaters + return 6; + case 0x02: // 7 lttpr repeaters + return 7; + case 0x01: // 8 lttpr repeaters + return 8; + default: + break; + } + return 0; // invalid value +} + +static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset) +{ + return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset); +} + +void dp_enable_link_phy( + struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + struct pipe_ctx *pipes = + link->dc->current_state->res_ctx.pipe_ctx; + struct clock_source *dp_cs = + link->dc->res_pool->dp_clock_source; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + unsigned int i; + + if (link->connector_signal == SIGNAL_TYPE_EDP) { + link->dc->hwss.edp_power_control(link, true); + link->dc->hwss.edp_wait_for_hpd_ready(link, true); + } + + /* If the current pixel clock source is not DTO(happens after + * switching from HDMI passive dongle to DP on the same connector), + * switch the pixel clock source to DTO. + */ + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + pipes[i].stream->link == link) { + if (pipes[i].clock_source != NULL && + pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + pipes[i].clock_source = dp_cs; + pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz = + pipes[i].stream->timing.pix_clk_100hz; + pipes[i].clock_source->funcs->program_pix_clk( + pipes[i].clock_source, + &pipes[i].stream_res.pix_clk_params, + &pipes[i].pll_settings); + } + } + } + + link->cur_link_settings = *link_settings; + + if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { + if (dc->clk_mgr->funcs->notify_link_rate_change) + dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); + } + + if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->lock_phy(dmcu); + + if (link_hwss->ext.enable_dp_link_output) + link_hwss->ext.enable_dp_link_output(link, link_res, signal, + clock_source, link_settings); + + if (dmcu != NULL && dmcu->funcs->unlock_phy) + dmcu->funcs->unlock_phy(dmcu); + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); + dp_receiver_power_ctrl(link, true); +} + +void edp_add_delay_for_T9(struct dc_link *link) +{ + if (link->local_sink && + link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0) + udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000); +} + +bool edp_receiver_ready_T9(struct dc_link *link) +{ + unsigned int tries = 0; + unsigned char sinkstatus = 0; + unsigned char edpRev = 0; + enum dc_status result = DC_OK; + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); + + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + if (result == DC_OK && edpRev >= DP_EDP_12) { + do { + sinkstatus = 1; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 0) + break; + if (result != DC_OK) + break; + udelay(100); //MAx T9 + } while (++tries < 50); + } + + return result; +} +bool edp_receiver_ready_T7(struct dc_link *link) +{ + unsigned char sinkstatus = 0; + unsigned char edpRev = 0; + enum dc_status result = DC_OK; + + /* use absolute time stamp to constrain max T7*/ + unsigned long long enter_timestamp = 0; + unsigned long long finish_timestamp = 0; + unsigned long long time_taken_in_ns = 0; + + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); + + if (result == DC_OK && edpRev >= DP_EDP_12) { + /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ + enter_timestamp = dm_get_timestamp(link->ctx); + do { + sinkstatus = 0; + result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); + if (sinkstatus == 1) + break; + if (result != DC_OK) + break; + udelay(25); + finish_timestamp = dm_get_timestamp(link->ctx); + time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); + } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms + } + + if (link->local_sink && + link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0) + udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000); + + return result; +} + +void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res, + enum signal_type signal) +{ + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + + if (!link->wa_flags.dp_keep_receiver_powered) + dp_receiver_power_ctrl(link, false); + + if (signal == SIGNAL_TYPE_EDP) { + if (link->dc->hwss.edp_backlight_control) + link->dc->hwss.edp_backlight_control(link, false); + if (link_hwss->ext.disable_dp_link_output) + link_hwss->ext.disable_dp_link_output(link, link_res, signal); + link->dc->hwss.edp_power_control(link, false); + } else { + if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->lock_phy(dmcu); + if (link_hwss->ext.disable_dp_link_output) + link_hwss->ext.disable_dp_link_output(link, link_res, signal); + if (dmcu != NULL && dmcu->funcs->unlock_phy) + dmcu->funcs->unlock_phy(dmcu); + } + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); + + /* Clear current link setting.*/ + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); + + if (dc->clk_mgr->funcs->notify_link_rate_change) + dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); +} + +void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res, + enum signal_type signal) +{ + /* MST disable link only when no stream use the link */ + if (link->mst_stream_alloc_table.stream_count > 0) + return; + + dp_disable_link_phy(link, link_res, signal); + + /* set the sink to SST mode after disabling the link */ + dp_enable_mst_on_sink(link, false); +} + +bool dp_set_hw_training_pattern( + struct dc_link *link, + const struct link_resource *link_res, + enum dc_dp_training_pattern pattern, + uint32_t offset) +{ + enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; + + switch (pattern) { + case DP_TRAINING_PATTERN_SEQUENCE_1: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; + break; + case DP_TRAINING_PATTERN_SEQUENCE_2: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; + break; + case DP_TRAINING_PATTERN_SEQUENCE_3: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; + break; + case DP_TRAINING_PATTERN_SEQUENCE_4: + test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; + break; + case DP_128b_132b_TPS1: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE; + break; + case DP_128b_132b_TPS2: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE; + break; + default: + break; + } + + dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0); + + return true; +} + +void dp_set_hw_lane_settings( + struct dc_link *link, + const struct link_resource *link_res, + const struct link_training_settings *link_settings, + uint32_t offset) +{ + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + + if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset)) + return; + + if (link_hwss->ext.set_dp_lane_settings) + link_hwss->ext.set_dp_lane_settings(link, link_res, + &link_settings->link_settings, + link_settings->hw_lane_settings); + + memmove(link->cur_lane_setting, + link_settings->hw_lane_settings, + sizeof(link->cur_lane_setting)); +} + +void dp_set_hw_test_pattern( + struct dc_link *link, + const struct link_resource *link_res, + enum dp_test_pattern test_pattern, + uint8_t *custom_pattern, + uint32_t custom_pattern_size) +{ + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + struct encoder_set_dp_phy_pattern_param pattern_param = {0}; + + pattern_param.dp_phy_pattern = test_pattern; + pattern_param.custom_pattern = custom_pattern; + pattern_param.custom_pattern_size = custom_pattern_size; + pattern_param.dp_panel_mode = dp_get_panel_mode(link); + + if (link_hwss->ext.set_dp_link_test_pattern) + link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param); +} + +void dp_retrain_link_dp_test(struct dc_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern) +{ + struct pipe_ctx *pipes = + &link->dc->current_state->res_ctx.pipe_ctx[0]; + unsigned int i; + + + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream != NULL && + !pipes[i].top_pipe && !pipes[i].prev_odm_pipe && + pipes[i].stream->link != NULL && + pipes[i].stream_res.stream_enc != NULL && + pipes[i].stream->link == link) { + udelay(100); + + pipes[i].stream_res.stream_enc->funcs->dp_blank(link, + pipes[i].stream_res.stream_enc); + + /* disable any test pattern that might be active */ + dp_set_hw_test_pattern(link, &pipes[i].link_res, + DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); + + dp_receiver_power_ctrl(link, false); + + link->dc->hwss.disable_stream(&pipes[i]); + if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only) + (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio); + + if (link->link_enc) + link->link_enc->funcs->disable_output( + link->link_enc, + SIGNAL_TYPE_DISPLAY_PORT); + + /* Clear current link setting. */ + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); + + perform_link_training_with_retries( + link_setting, + skip_video_pattern, + LINK_TRAINING_ATTEMPTS, + &pipes[i], + SIGNAL_TYPE_DISPLAY_PORT, + false); + + link->dc->hwss.enable_stream(&pipes[i]); + + link->dc->hwss.unblank_stream(&pipes[i], + link_setting); + + if (pipes[i].stream_res.audio) { + /* notify audio driver for + * audio modes of monitor */ + pipes[i].stream_res.audio->funcs->az_enable( + pipes[i].stream_res.audio); + + /* un-mute audio */ + /* TODO: audio should be per stream rather than + * per link */ + pipes[i].stream_res.stream_enc->funcs-> + audio_mute_control( + pipes[i].stream_res.stream_enc, false); + } + } + } +} + +#undef DC_LOGGER +#define DC_LOGGER \ + dsc->ctx->logger +static void dsc_optc_config_log(struct display_stream_compressor *dsc, + struct dsc_optc_config *config) +{ + uint32_t precision = 1 << 28; + uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision; + uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision; + uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod; + + /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC + * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is + * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal + */ + ll_bytes_per_pix_fraq *= 10000000; + ll_bytes_per_pix_fraq /= precision; + + DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)", + config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq); + DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444); + DC_LOG_DSC("\tslice_width %d", config->slice_width); +} + +bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dc_stream_state *stream = pipe_ctx->stream; + bool result = false; + + if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + result = true; + else + result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable); + return result; +} + +/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first, + * i.e. after dp_enable_dsc_on_rx() had been called + */ +void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dc_stream_state *stream = pipe_ctx->stream; + struct pipe_ctx *odm_pipe; + int opp_cnt = 1; + + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + opp_cnt++; + + if (enable) { + struct dsc_config dsc_cfg; + struct dsc_optc_config dsc_optc_cfg; + enum optc_dsc_mode optc_dsc_mode; + + /* Enable DSC hw block */ + dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; + dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; + dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; + dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; + dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; + ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0); + dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; + + dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); + dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { + struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; + + odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg); + odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst); + } + dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt; + dsc_cfg.pic_width *= opp_cnt; + + optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; + + /* Enable DSC in encoder */ + if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) + && !is_dp_128b_132b_signal(pipe_ctx)) { + DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); + dsc_optc_config_log(dsc, &dsc_optc_cfg); + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, + optc_dsc_mode, + dsc_optc_cfg.bytes_per_pixel, + dsc_optc_cfg.slice_width); + + /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */ + } + + /* Enable DSC in OPTC */ + DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst); + dsc_optc_config_log(dsc, &dsc_optc_cfg); + pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, + optc_dsc_mode, + dsc_optc_cfg.bytes_per_pixel, + dsc_optc_cfg.slice_width); + } else { + /* disable DSC in OPTC */ + pipe_ctx->stream_res.tg->funcs->set_dsc_config( + pipe_ctx->stream_res.tg, + OPTC_DSC_DISABLED, 0, 0); + + /* disable DSC in stream encoder */ + if (dc_is_dp_signal(stream->signal)) { + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + false, + NULL, + true); + else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( + pipe_ctx->stream_res.stream_enc, + OPTC_DSC_DISABLED, 0, 0); + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL, true); + } + } + + /* disable DSC block */ + pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc); + } +} + +bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + bool result = false; + + if (!pipe_ctx->stream->timing.flags.DSC) + goto out; + if (!dsc) + goto out; + + if (enable) { + { + dp_set_dsc_on_stream(pipe_ctx, true); + result = true; + } + } else { + dp_set_dsc_on_rx(pipe_ctx, false); + dp_set_dsc_on_stream(pipe_ctx, false); + result = true; + } +out: + return result; +} + +/* + * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled; + * hence PPS info packet update need to use frame update instead of immediate update. + * Added parameter immediate_update for this purpose. + * The decision to use frame update is hard-coded in function dp_update_dsc_config(), + * which is the only place where a "false" would be passed in for param immediate_update. + * + * immediate_update is only applicable when DSC is enabled. + */ +bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + struct dc_stream_state *stream = pipe_ctx->stream; + + if (!pipe_ctx->stream->timing.flags.DSC || !dsc) + return false; + + if (enable) { + struct dsc_config dsc_cfg; + uint8_t dsc_packed_pps[128]; + + memset(&dsc_cfg, 0, sizeof(dsc_cfg)); + memset(dsc_packed_pps, 0, 128); + + /* Enable DSC hw block */ + dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; + dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; + dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; + dsc_cfg.color_depth = stream->timing.display_color_depth; + dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; + dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; + + DC_LOG_DSC(" "); + dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); + if (dc_is_dp_signal(stream->signal)) { + DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + true, + &dsc_packed_pps[0], + immediate_update); + else + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, + true, + &dsc_packed_pps[0], + immediate_update); + } + } else { + /* disable DSC PPS in stream encoder */ + if (dc_is_dp_signal(stream->signal)) { + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + false, + NULL, + true); + else + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL, true); + } + } + + return true; +} + + +bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) +{ + struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; + + if (!pipe_ctx->stream->timing.flags.DSC) + return false; + if (!dsc) + return false; + + dp_set_dsc_on_stream(pipe_ctx, true); + dp_set_dsc_pps_sdp(pipe_ctx, true, false); + return true; +} + +#undef DC_LOGGER +#define DC_LOGGER \ + link->ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 3b7ab2ca34c6..96414f99c671 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -1,640 +1,11 @@ /* Copyright 2015 Advanced Micro Devices, Inc. */ - -#include "dm_services.h" -#include "dc.h" -#include "inc/core_types.h" -#include "include/ddc_service_types.h" -#include "include/i2caux_interface.h" #include "link_hwss.h" -#include "hw_sequencer.h" -#include "dc_link_dp.h" -#include "dc_link_ddc.h" #include "dm_helpers.h" -#include "dpcd_defs.h" -#include "dsc.h" -#include "resource.h" -#include "link_enc_cfg.h" -#include "clk_mgr.h" -#include "inc/link_dpcd.h" +#include "core_types.h" #include "dccg.h" - -static uint8_t convert_to_count(uint8_t lttpr_repeater_count) -{ - switch (lttpr_repeater_count) { - case 0x80: // 1 lttpr repeater - return 1; - case 0x40: // 2 lttpr repeaters - return 2; - case 0x20: // 3 lttpr repeaters - return 3; - case 0x10: // 4 lttpr repeaters - return 4; - case 0x08: // 5 lttpr repeaters - return 5; - case 0x04: // 6 lttpr repeaters - return 6; - case 0x02: // 7 lttpr repeaters - return 7; - case 0x01: // 8 lttpr repeaters - return 8; - default: - break; - } - return 0; // invalid value -} - -static inline bool is_immediate_downstream(struct dc_link *link, uint32_t offset) -{ - return (convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == offset); -} - -void dp_receiver_power_ctrl(struct dc_link *link, bool on) -{ - uint8_t state; - - state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3; - - if (link->sync_lt_in_progress) - return; - - core_link_write_dpcd(link, DP_SET_POWER, &state, - sizeof(state)); -} - -void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) -{ - if (link != NULL && link->dc->debug.enable_driver_sequence_debug) - core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, - &dp_test_mode, sizeof(dp_test_mode)); -} - -void dp_enable_link_phy( - struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal, - enum clock_source_id clock_source, - const struct dc_link_settings *link_settings) -{ - struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - struct pipe_ctx *pipes = - link->dc->current_state->res_ctx.pipe_ctx; - struct clock_source *dp_cs = - link->dc->res_pool->dp_clock_source; - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - unsigned int i; - - if (link->connector_signal == SIGNAL_TYPE_EDP) { - link->dc->hwss.edp_power_control(link, true); - link->dc->hwss.edp_wait_for_hpd_ready(link, true); - } - - /* If the current pixel clock source is not DTO(happens after - * switching from HDMI passive dongle to DP on the same connector), - * switch the pixel clock source to DTO. - */ - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream != NULL && - pipes[i].stream->link == link) { - if (pipes[i].clock_source != NULL && - pipes[i].clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { - pipes[i].clock_source = dp_cs; - pipes[i].stream_res.pix_clk_params.requested_pix_clk_100hz = - pipes[i].stream->timing.pix_clk_100hz; - pipes[i].clock_source->funcs->program_pix_clk( - pipes[i].clock_source, - &pipes[i].stream_res.pix_clk_params, - &pipes[i].pll_settings); - } - } - } - - link->cur_link_settings = *link_settings; - - if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { - /* TODO - DP2.0 HW: notify link rate change here */ - } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { - if (dc->clk_mgr->funcs->notify_link_rate_change) - dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); - } - - if (dmcu != NULL && dmcu->funcs->lock_phy) - dmcu->funcs->lock_phy(dmcu); - - if (link_hwss->ext.enable_dp_link_output) - link_hwss->ext.enable_dp_link_output(link, link_res, signal, - clock_source, link_settings); - - if (dmcu != NULL && dmcu->funcs->unlock_phy) - dmcu->funcs->unlock_phy(dmcu); - - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); - dp_receiver_power_ctrl(link, true); -} - -void edp_add_delay_for_T9(struct dc_link *link) -{ - if (link->local_sink && - link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0) - udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000); -} - -bool edp_receiver_ready_T9(struct dc_link *link) -{ - unsigned int tries = 0; - unsigned char sinkstatus = 0; - unsigned char edpRev = 0; - enum dc_status result; - - result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); - - /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ - if (result == DC_OK && edpRev >= DP_EDP_12) { - do { - sinkstatus = 1; - result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); - if (sinkstatus == 0) - break; - if (result != DC_OK) - break; - udelay(100); //MAx T9 - } while (++tries < 50); - } - - return result; -} -bool edp_receiver_ready_T7(struct dc_link *link) -{ - unsigned char sinkstatus = 0; - unsigned char edpRev = 0; - enum dc_status result; - - /* use absolute time stamp to constrain max T7*/ - unsigned long long enter_timestamp = 0; - unsigned long long finish_timestamp = 0; - unsigned long long time_taken_in_ns = 0; - - result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); - - if (result == DC_OK && edpRev >= DP_EDP_12) { - /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ - enter_timestamp = dm_get_timestamp(link->ctx); - do { - sinkstatus = 0; - result = core_link_read_dpcd(link, DP_SINK_STATUS, &sinkstatus, sizeof(sinkstatus)); - if (sinkstatus == 1) - break; - if (result != DC_OK) - break; - udelay(25); - finish_timestamp = dm_get_timestamp(link->ctx); - time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp, enter_timestamp); - } while (time_taken_in_ns < 50 * 1000000); //MAx T7 is 50ms - } - - if (link->local_sink && - link->local_sink->edid_caps.panel_patch.extra_t7_ms > 0) - udelay(link->local_sink->edid_caps.panel_patch.extra_t7_ms * 1000); - - return result; -} - -void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res, - enum signal_type signal) -{ - struct dc *dc = link->ctx->dc; - struct dmcu *dmcu = dc->res_pool->dmcu; - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - - if (!link->wa_flags.dp_keep_receiver_powered) - dp_receiver_power_ctrl(link, false); - - if (signal == SIGNAL_TYPE_EDP) { - if (link->dc->hwss.edp_backlight_control) - link->dc->hwss.edp_backlight_control(link, false); - - if (link_hwss->ext.disable_dp_link_output) - link_hwss->ext.disable_dp_link_output(link, link_res, signal); - link->dc->hwss.edp_power_control(link, false); - } else { - if (dmcu != NULL && dmcu->funcs->lock_phy) - dmcu->funcs->lock_phy(dmcu); - - if (link_hwss->ext.disable_dp_link_output) - link_hwss->ext.disable_dp_link_output(link, link_res, signal); - - if (dmcu != NULL && dmcu->funcs->unlock_phy) - dmcu->funcs->unlock_phy(dmcu); - } - - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); - - /* Clear current link setting.*/ - memset(&link->cur_link_settings, 0, - sizeof(link->cur_link_settings)); - - if (dc->clk_mgr->funcs->notify_link_rate_change) - dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); -} - -void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res, - enum signal_type signal) -{ - /* MST disable link only when no stream use the link */ - if (link->mst_stream_alloc_table.stream_count > 0) - return; - - dp_disable_link_phy(link, link_res, signal); - - /* set the sink to SST mode after disabling the link */ - dp_enable_mst_on_sink(link, false); -} - -bool dp_set_hw_training_pattern( - struct dc_link *link, - const struct link_resource *link_res, - enum dc_dp_training_pattern pattern, - uint32_t offset) -{ - enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED; - - switch (pattern) { - case DP_TRAINING_PATTERN_SEQUENCE_1: - test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1; - break; - case DP_TRAINING_PATTERN_SEQUENCE_2: - test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2; - break; - case DP_TRAINING_PATTERN_SEQUENCE_3: - test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3; - break; - case DP_TRAINING_PATTERN_SEQUENCE_4: - test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; - break; - case DP_128b_132b_TPS1: - test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE; - break; - case DP_128b_132b_TPS2: - test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE; - break; - default: - break; - } - - dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0); - - return true; -} - -#define DC_LOGGER \ - link->ctx->logger -void dp_set_hw_lane_settings( - struct dc_link *link, - const struct link_resource *link_res, - const struct link_training_settings *link_settings, - uint32_t offset) -{ - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - - if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset)) - return; - - if (link_hwss->ext.set_dp_lane_settings) - link_hwss->ext.set_dp_lane_settings(link, link_res, - &link_settings->link_settings, - link_settings->hw_lane_settings); - - memmove(link->cur_lane_setting, - link_settings->lane_settings, - sizeof(link->cur_lane_setting)); -} - -void dp_set_hw_test_pattern( - struct dc_link *link, - const struct link_resource *link_res, - enum dp_test_pattern test_pattern, - uint8_t *custom_pattern, - uint32_t custom_pattern_size) -{ - const struct link_hwss *link_hwss = get_link_hwss(link, link_res); - struct encoder_set_dp_phy_pattern_param pattern_param = {0}; - - pattern_param.dp_phy_pattern = test_pattern; - pattern_param.custom_pattern = custom_pattern; - pattern_param.custom_pattern_size = custom_pattern_size; - pattern_param.dp_panel_mode = dp_get_panel_mode(link); - - if (link_hwss->ext.set_dp_link_test_pattern) - link_hwss->ext.set_dp_link_test_pattern(link, link_res, &pattern_param); -} -#undef DC_LOGGER - -void dp_retrain_link_dp_test(struct dc_link *link, - struct dc_link_settings *link_setting, - bool skip_video_pattern) -{ - struct pipe_ctx *pipes = - &link->dc->current_state->res_ctx.pipe_ctx[0]; - unsigned int i; - - for (i = 0; i < MAX_PIPES; i++) { - if (pipes[i].stream != NULL && - !pipes[i].top_pipe && !pipes[i].prev_odm_pipe && - pipes[i].stream->link != NULL && - pipes[i].stream_res.stream_enc != NULL && - pipes[i].stream->link == link) { - udelay(100); - - pipes[i].stream_res.stream_enc->funcs->dp_blank(link, - pipes[i].stream_res.stream_enc); - - /* disable any test pattern that might be active */ - dp_set_hw_test_pattern(link, &pipes[i].link_res, - DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); - - dp_receiver_power_ctrl(link, false); - - link->dc->hwss.disable_stream(&pipes[i]); - if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only) - (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio); - - if (link->link_enc) - link->link_enc->funcs->disable_output( - link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT); - - /* Clear current link setting. */ - memset(&link->cur_link_settings, 0, - sizeof(link->cur_link_settings)); - - perform_link_training_with_retries( - link_setting, - skip_video_pattern, - LINK_TRAINING_ATTEMPTS, - &pipes[i], - SIGNAL_TYPE_DISPLAY_PORT, - false); - - link->dc->hwss.enable_stream(&pipes[i]); - - link->dc->hwss.unblank_stream(&pipes[i], - link_setting); - - if (pipes[i].stream_res.audio) { - /* notify audio driver for - * audio modes of monitor */ - pipes[i].stream_res.audio->funcs->az_enable( - pipes[i].stream_res.audio); - - /* un-mute audio */ - /* TODO: audio should be per stream rather than - * per link */ - pipes[i].stream_res.stream_enc->funcs-> - audio_mute_control( - pipes[i].stream_res.stream_enc, false); - } - } - } -} - -#define DC_LOGGER \ - dsc->ctx->logger -static void dsc_optc_config_log(struct display_stream_compressor *dsc, - struct dsc_optc_config *config) -{ - uint32_t precision = 1 << 28; - uint32_t bytes_per_pixel_int = config->bytes_per_pixel / precision; - uint32_t bytes_per_pixel_mod = config->bytes_per_pixel % precision; - uint64_t ll_bytes_per_pix_fraq = bytes_per_pixel_mod; - - /* 7 fractional digits decimal precision for bytes per pixel is enough because DSC - * bits per pixel precision is 1/16th of a pixel, which means bytes per pixel precision is - * 1/16/8 = 1/128 of a byte, or 0.0078125 decimal - */ - ll_bytes_per_pix_fraq *= 10000000; - ll_bytes_per_pix_fraq /= precision; - - DC_LOG_DSC("\tbytes_per_pixel 0x%08x (%d.%07d)", - config->bytes_per_pixel, bytes_per_pixel_int, (uint32_t)ll_bytes_per_pix_fraq); - DC_LOG_DSC("\tis_pixel_format_444 %d", config->is_pixel_format_444); - DC_LOG_DSC("\tslice_width %d", config->slice_width); -} - -bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct dc *dc = pipe_ctx->stream->ctx->dc; - struct dc_stream_state *stream = pipe_ctx->stream; - bool result = false; - - if (dc_is_virtual_signal(stream->signal) || IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - result = true; - else - result = dm_helpers_dp_write_dsc_enable(dc->ctx, stream, enable); - return result; -} - -/* The stream with these settings can be sent (unblanked) only after DSC was enabled on RX first, - * i.e. after dp_enable_dsc_on_rx() had been called - */ -void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - struct dc *dc = pipe_ctx->stream->ctx->dc; - struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe; - int opp_cnt = 1; - - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - opp_cnt++; - - if (enable) { - struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; - enum optc_dsc_mode optc_dsc_mode; - - /* Enable DSC hw block */ - dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0); - dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt; - - dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg); - dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { - struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc; - - odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg); - odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst); - } - dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt; - dsc_cfg.pic_width *= opp_cnt; - - optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; - - /* Enable DSC in encoder */ - if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) - && !is_dp_128b_132b_signal(pipe_ctx)) { - DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); - dsc_optc_config_log(dsc, &dsc_optc_cfg); - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, - optc_dsc_mode, - dsc_optc_cfg.bytes_per_pixel, - dsc_optc_cfg.slice_width); - - /* PPS SDP is set elsewhere because it has to be done after DIG FE is connected to DIG BE */ - } - - /* Enable DSC in OPTC */ - DC_LOG_DSC("Setting optc DSC config for tg instance %d:", pipe_ctx->stream_res.tg->inst); - dsc_optc_config_log(dsc, &dsc_optc_cfg); - pipe_ctx->stream_res.tg->funcs->set_dsc_config(pipe_ctx->stream_res.tg, - optc_dsc_mode, - dsc_optc_cfg.bytes_per_pixel, - dsc_optc_cfg.slice_width); - } else { - /* disable DSC in OPTC */ - pipe_ctx->stream_res.tg->funcs->set_dsc_config( - pipe_ctx->stream_res.tg, - OPTC_DSC_DISABLED, 0, 0); - - /* disable DSC in stream encoder */ - if (dc_is_dp_signal(stream->signal)) { - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.hpo_dp_stream_enc, - false, - NULL, - true); - else if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( - pipe_ctx->stream_res.stream_enc, - OPTC_DSC_DISABLED, 0, 0); - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL, true); - } - } - - /* disable DSC block */ - pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc); - for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) - odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc); - } -} - -bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - bool result = false; - - if (!pipe_ctx->stream->timing.flags.DSC) - goto out; - if (!dsc) - goto out; - - if (enable) { - { - dp_set_dsc_on_stream(pipe_ctx, true); - result = true; - } - } else { - dp_set_dsc_on_rx(pipe_ctx, false); - dp_set_dsc_on_stream(pipe_ctx, false); - result = true; - } -out: - return result; -} - -/* - * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled; - * hence PPS info packet update need to use frame update instead of immediate update. - * Added parameter immediate_update for this purpose. - * The decision to use frame update is hard-coded in function dp_update_dsc_config(), - * which is the only place where a "false" would be passed in for param immediate_update. - * - * immediate_update is only applicable when DSC is enabled. - */ -bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - struct dc_stream_state *stream = pipe_ctx->stream; - - if (!pipe_ctx->stream->timing.flags.DSC || !dsc) - return false; - - if (enable) { - struct dsc_config dsc_cfg; - uint8_t dsc_packed_pps[128]; - - memset(&dsc_cfg, 0, sizeof(dsc_cfg)); - memset(dsc_packed_pps, 0, 128); - - /* Enable DSC hw block */ - dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; - dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; - dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; - dsc_cfg.color_depth = stream->timing.display_color_depth; - dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false; - dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg; - - DC_LOG_DSC(" "); - dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); - if (dc_is_dp_signal(stream->signal)) { - DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.hpo_dp_stream_enc, - true, - &dsc_packed_pps[0], - immediate_update); - else - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, - true, - &dsc_packed_pps[0], - immediate_update); - } - } else { - /* disable DSC PPS in stream encoder */ - if (dc_is_dp_signal(stream->signal)) { - if (is_dp_128b_132b_signal(pipe_ctx)) - pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.hpo_dp_stream_enc, - false, - NULL, - true); - else - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL, true); - } - } - - return true; -} - - -bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) -{ - struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; - - if (!pipe_ctx->stream->timing.flags.DSC) - return false; - if (!dsc) - return false; - - dp_set_dsc_on_stream(pipe_ctx, true); - dp_set_dsc_pps_sdp(pipe_ctx, true, false); - return true; -} - -#undef DC_LOGGER -#define DC_LOGGER \ - link->ctx->logger +#include "link_enc_cfg.h" +#include "dc_link_dp.h" static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) { @@ -774,8 +145,10 @@ static bool can_use_dp_hpo_link_hwss(const struct dc_link *link, static void set_dp_hpo_throttled_vcp_size(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size) { - struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; - struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc; + struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = + pipe_ctx->stream_res.hpo_dp_stream_enc; + struct hpo_dp_link_encoder *hpo_dp_link_encoder = + pipe_ctx->link_res.hpo_dp_link_enc; hpo_dp_link_encoder->funcs->set_throttled_vcp_size(hpo_dp_link_encoder, hpo_dp_stream_encoder->inst, @@ -786,17 +159,21 @@ static void set_dp_hpo_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, const struct dc_link_settings *link_settings, struct fixed31_32 throttled_vcp_size) { - struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; + struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = + pipe_ctx->stream_res.hpo_dp_stream_enc; struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct fixed31_32 h_blank_in_ms, time_slot_in_ms, mtp_cnt_per_h_blank; - uint32_t link_bw_in_kbps = dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings); + uint32_t link_bw_in_kbps = + dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings); uint16_t hblank_min_symbol_width = 0; if (link_bw_in_kbps > 0) { - h_blank_in_ms = dc_fixpt_div(dc_fixpt_from_int(timing->h_total-timing->h_addressable), + h_blank_in_ms = dc_fixpt_div(dc_fixpt_from_int( + timing->h_total - timing->h_addressable), dc_fixpt_from_fraction(timing->pix_clk_100hz, 10)); time_slot_in_ms = dc_fixpt_from_fraction(32 * 4, link_bw_in_kbps); - mtp_cnt_per_h_blank = dc_fixpt_div(h_blank_in_ms, dc_fixpt_mul_int(time_slot_in_ms, 64)); + mtp_cnt_per_h_blank = dc_fixpt_div(h_blank_in_ms, + dc_fixpt_mul_int(time_slot_in_ms, 64)); hblank_min_symbol_width = dc_fixpt_floor( dc_fixpt_mul(mtp_cnt_per_h_blank, throttled_vcp_size)); } diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 6c02244e7fe7..e7ead9e25318 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -465,6 +465,8 @@ void dc_link_get_cur_link_res(const struct dc_link *link, void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map); /* restore link resource allocation state from a snapshot */ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map); - void dc_link_dp_clear_rx_status(struct dc_link *link); +struct gpio *get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service); #endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 013b94c41327..20a9cbb7c0a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -55,6 +55,7 @@ #include "inc/link_dpcd.h" #include "dpcd_defs.h" #include "inc/link_enc_cfg.h" +#include "link_hwss.h" #define DC_LOGGER_INIT(logger) diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 67286950fe5a..477c4d9a972f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -218,4 +218,44 @@ bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx); bool dp_retrieve_lttpr_cap(struct dc_link *link); void edp_panel_backlight_power_on(struct dc_link *link); +void dp_receiver_power_ctrl(struct dc_link *link, bool on); +void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); +void dp_enable_link_phy( + struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); +void edp_add_delay_for_T9(struct dc_link *link); +bool edp_receiver_ready_T9(struct dc_link *link); +bool edp_receiver_ready_T7(struct dc_link *link); + +void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res, + enum signal_type signal); + +void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res, + enum signal_type signal); + +bool dp_set_hw_training_pattern( + struct dc_link *link, + const struct link_resource *link_res, + enum dc_dp_training_pattern pattern, + uint32_t offset); + +void dp_set_hw_lane_settings( + struct dc_link *link, + const struct link_resource *link_res, + const struct link_training_settings *link_settings, + uint32_t offset); + +void dp_set_hw_test_pattern( + struct dc_link *link, + const struct link_resource *link_res, + enum dp_test_pattern test_pattern, + uint8_t *custom_pattern, + uint32_t custom_pattern_size); + +void dp_retrain_link_dp_test(struct dc_link *link, + struct dc_link_settings *link_setting, + bool skip_video_pattern); #endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h b/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h index 3f12b1600d2a..d561f86d503c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_dpcd.h @@ -27,7 +27,7 @@ #define __LINK_DPCD_H__ #include #include -#include +#include enum dc_status core_link_read_dpcd( struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 3400e75685aa..43c6c0e0ddd9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -26,56 +26,18 @@ #ifndef __DC_LINK_HWSS_H__ #define __DC_LINK_HWSS_H__ -struct gpio *get_hpd_gpio(struct dc_bios *dcb, - struct graphics_object_id link_id, - struct gpio_service *gpio_service); - -void dp_enable_link_phy( - struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal, - enum clock_source_id clock_source, - const struct dc_link_settings *link_settings); - -void dp_receiver_power_ctrl(struct dc_link *link, bool on); -void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); -void edp_add_delay_for_T9(struct dc_link *link); -bool edp_receiver_ready_T9(struct dc_link *link); -bool edp_receiver_ready_T7(struct dc_link *link); - -void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res, - enum signal_type signal); - -void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res, - enum signal_type signal); - -bool dp_set_hw_training_pattern( - struct dc_link *link, - const struct link_resource *link_res, - enum dc_dp_training_pattern pattern, - uint32_t offset); - -void dp_set_hw_lane_settings( - struct dc_link *link, - const struct link_resource *link_res, - const struct link_training_settings *link_settings, - uint32_t offset); - -void dp_set_hw_test_pattern( - struct dc_link *link, - const struct link_resource *link_res, - enum dp_test_pattern test_pattern, - uint8_t *custom_pattern, - uint32_t custom_pattern_size); - -void dp_retrain_link_dp_test(struct dc_link *link, - struct dc_link_settings *link_setting, - bool skip_video_pattern); +/* include basic type headers only */ +#include "os_types.h" +#include "dc_dp_types.h" +#include "signal_types.h" +#include "grph_object_id.h" +#include "fixed31_32.h" +/* forward declare dc core types */ struct dc_link; struct link_resource; -struct fixed31_32; struct pipe_ctx; +struct encoder_set_dp_phy_pattern_param; struct link_hwss_ext { /* function pointers below require check for NULL at all time From 2750caffa7a9ae82824d7ac3ab0fee65181c4126 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:06 +0800 Subject: [PATCH 230/339] drm/amd/display: move get_link_hwss to dc_resource [why] Isolate the way to obtain link_hwss from the actual implemenation of link_hwss. So the caller can call link_hwss without knowing the implementation detail of link_hwss. Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Stylon Wang Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 51 ++++++++++++------- .../gpu/drm/amd/display/dc/core/dc_resource.c | 33 ++++++++++++ .../gpu/drm/amd/display/dc/inc/link_hwss.h | 17 ++++++- drivers/gpu/drm/amd/display/dc/inc/resource.h | 3 ++ 4 files changed, 85 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 96414f99c671..dab532cf52b9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -29,12 +29,6 @@ static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx); static void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx); /************************* below goes to dio_link_hwss ************************/ -static bool can_use_dio_link_hwss(const struct dc_link *link, - const struct link_resource *link_res) -{ - return link->link_enc != NULL; -} - static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size) { @@ -135,14 +129,19 @@ static const struct link_hwss dio_link_hwss = { }, }; -/*********************** below goes to hpo_dp_link_hwss ***********************/ -static bool can_use_dp_hpo_link_hwss(const struct dc_link *link, +bool can_use_dio_link_hwss(const struct dc_link *link, const struct link_resource *link_res) { - return link_res->hpo_dp_link_enc != NULL; + return link->link_enc != NULL; } -static void set_dp_hpo_throttled_vcp_size(struct pipe_ctx *pipe_ctx, +const struct link_hwss *get_dio_link_hwss(void) +{ + return &dio_link_hwss; +} + +/*********************** below goes to hpo_dp_link_hwss ***********************/ +static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size) { struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = @@ -155,7 +154,7 @@ static void set_dp_hpo_throttled_vcp_size(struct pipe_ctx *pipe_ctx, throttled_vcp_size); } -static void set_dp_hpo_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, +static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, const struct dc_link_settings *link_settings, struct fixed31_32 throttled_vcp_size) { @@ -328,22 +327,27 @@ static const struct link_hwss hpo_dp_link_hwss = { .setup_stream_encoder = setup_hpo_dp_stream_encoder, .reset_stream_encoder = reset_hpo_dp_stream_encoder, .ext = { - .set_throttled_vcp_size = set_dp_hpo_throttled_vcp_size, - .set_hblank_min_symbol_width = set_dp_hpo_hblank_min_symbol_width, + .set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size, + .set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width, .enable_dp_link_output = enable_hpo_dp_link_output, .disable_dp_link_output = disable_hpo_dp_link_output, .set_dp_link_test_pattern = set_hpo_dp_link_test_pattern, .set_dp_lane_settings = set_hpo_dp_lane_settings, }, }; -/*********************** below goes to dpia_link_hwss *************************/ -static bool can_use_dpia_link_hwss(const struct dc_link *link, + +bool can_use_hpo_dp_link_hwss(const struct dc_link *link, const struct link_resource *link_res) { - return link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign; + return link_res->hpo_dp_link_enc != NULL; } +const struct link_hwss *get_hpo_dp_link_hwss(void) +{ + return &hpo_dp_link_hwss; +} + +/*********************** below goes to dpia_link_hwss *************************/ static const struct link_hwss dpia_link_hwss = { .setup_stream_encoder = setup_dio_stream_encoder, .reset_stream_encoder = reset_dio_stream_encoder, @@ -356,7 +360,18 @@ static const struct link_hwss dpia_link_hwss = { }, }; -/*********************** below goes to link_hwss ******************************/ +bool can_use_dpia_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign; +} + +const struct link_hwss *get_dpia_link_hwss(void) +{ + return &dpia_link_hwss; +} +/*********************** below goes to virtual_link_hwss ******************************/ static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx) { } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9af8794c5b24..19e06331169d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3310,3 +3310,36 @@ uint8_t resource_transmitter_to_phy_idx(const struct dc *dc, enum transmitter tr #endif return phy_idx; } + +const struct link_hwss *get_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + /* Link_hwss is only accessible by getter function instead of accessing + * by pointers in dc with the intent to protect against breaking polymorphism. + */ + if (can_use_hpo_dp_link_hwss(link, link_res)) + /* TODO: some assumes that if decided link settings is 128b/132b + * channel coding format hpo_dp_link_enc should be used. + * Others believe that if hpo_dp_link_enc is available in link + * resource then hpo_dp_link_enc must be used. This bound between + * hpo_dp_link_enc != NULL and decided link settings is loosely coupled + * with a premise that both hpo_dp_link_enc pointer and decided link + * settings are determined based on single policy function like + * "decide_link_settings" from upper layer. This "convention" + * cannot be maintained and enforced at current level. + * Therefore a refactor is due so we can enforce a strong bound + * between those two parameters at this level. + * + * To put it simple, we want to make enforcement at low level so that + * we will not return link hwss if caller plans to do 8b/10b + * with an hpo encoder. Or we can return a very dummy one that doesn't + * do work for all functions + */ + return get_hpo_dp_link_hwss(); + else if (can_use_dpia_link_hwss(link, link_res)) + return get_dpia_link_hwss(); + else if (can_use_dio_link_hwss(link, link_res)) + return get_dio_link_hwss(); + else + return get_virtual_link_hwss(); +} diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index 43c6c0e0ddd9..fd4bfa22eda8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -75,6 +75,21 @@ struct link_hwss { void (*reset_stream_encoder)(struct pipe_ctx *pipe_ctx); }; -const struct link_hwss *get_link_hwss(const struct dc_link *link, const struct link_resource *link_res); + +/*********************** below goes to virtual_link_hwss **********************/ +const struct link_hwss *get_virtual_link_hwss(void); +/*********************** below goes to dpia_link_hwss *************************/ +bool can_use_dpia_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); +const struct link_hwss *get_dpia_link_hwss(void); +/*********************** below goes to hpo_dp_link_hwss ***********************/ +bool can_use_hpo_dp_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); +const struct link_hwss *get_hpo_dp_link_hwss(void); +/************************* below goes to dio_link_hwss ************************/ +bool can_use_dio_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); +const struct link_hwss *get_dio_link_hwss(void); #endif /* __DC_LINK_HWSS_H__ */ + diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index a02887f644b0..63ed28cbf873 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -213,4 +213,7 @@ void check_syncd_pipes_for_disabled_master_pipe(struct dc *dc, uint8_t disabled_master_pipe_idx); uint8_t resource_transmitter_to_phy_idx(const struct dc *dc, enum transmitter transmitter); +const struct link_hwss *get_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); + #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ From fd24926676801dd68afa1f39647a858cf4f6ae50 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 28 Jan 2022 22:04:07 +0800 Subject: [PATCH 231/339] drm/amd/display: move link_hwss to link folder and break down to files [why] Move link_hwss to its own folder as part of DC LIB and break it down to separate file one for each type of backend for code isolation. Tested-by: Daniel Wheeler Reviewed-by: Jun Lei Acked-by: Stylon Wang Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/Makefile | 4 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 1 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 4 + .../gpu/drm/amd/display/dc/inc/core_types.h | 1 + .../gpu/drm/amd/display/dc/inc/link_hwss.h | 18 -- drivers/gpu/drm/amd/display/dc/link/Makefile | 30 +++ .../drm/amd/display/dc/link/link_hwss_dio.c | 137 +++++++++++ .../drm/amd/display/dc/link/link_hwss_dio.h | 53 +++++ .../drm/amd/display/dc/link/link_hwss_dpia.c | 51 +++++ .../drm/amd/display/dc/link/link_hwss_dpia.h | 34 +++ .../link_hwss_hpo_dp.c} | 213 ++---------------- .../amd/display/dc/link/link_hwss_hpo_dp.h | 35 +++ .../amd/display/dc/link/link_hwss_hpo_frl.c | 43 ++++ .../amd/display/dc/link/link_hwss_hpo_frl.h | 34 +++ .../gpu/drm/amd/display/dc/virtual/Makefile | 2 +- .../display/dc/virtual/virtual_link_hwss.c | 43 ++++ .../display/dc/virtual/virtual_link_hwss.h | 34 +++ 17 files changed, 528 insertions(+), 209 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/link/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h rename drivers/gpu/drm/amd/display/dc/{core/dc_link_hwss.c => link/link_hwss_hpo_dp.c} (54%) create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c create mode 100644 drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c create mode 100644 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.h diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index a4ef8f314307..0aaf394b73ff 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -23,7 +23,7 @@ # Makefile for Display Core (dc) component. # -DC_LIBS = basics bios clk_mgr dce dml gpio irq virtual +DC_LIBS = basics bios dml clk_mgr dce gpio irq link virtual ifdef CONFIG_DRM_AMD_DC_DCN DC_LIBS += dcn20 @@ -58,7 +58,7 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ -dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ +dc_surface.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ dc_link_enc_cfg.o dc_link_dpia.o dc_link_dpcd.o ifdef CONFIG_DRM_AMD_DC_DCN diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 51347e1d3d95..65ebfbcf3019 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -6842,6 +6842,7 @@ bool edp_receiver_ready_T9(struct dc_link *link) unsigned char sinkstatus = 0; unsigned char edpRev = 0; enum dc_status result = DC_OK; + result = core_link_read_dpcd(link, DP_EDP_DPCD_REV, &edpRev, sizeof(edpRev)); /* start from eDP version 1.2, SINK_STAUS indicate the sink is ready.*/ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 19e06331169d..e82aa0559bdf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -43,6 +43,10 @@ #include "dpcd_defs.h" #include "link_enc_cfg.h" #include "dc_link_dp.h" +#include "virtual/virtual_link_hwss.h" +#include "link/link_hwss_dio.h" +#include "link/link_hwss_dpia.h" +#include "link/link_hwss_hpo_dp.h" #if defined(CONFIG_DRM_AMD_DC_SI) #include "dce60/dce60_resource.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index e90123b0ee0e..951c9b60917d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -54,6 +54,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #ifdef CONFIG_DRM_AMD_DC_HDCP #include "dm_cp_psp.h" #endif +#include "link_hwss.h" /************ link *****************/ struct link_init_data { diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index fd4bfa22eda8..3b3090e3d327 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -27,7 +27,6 @@ #define __DC_LINK_HWSS_H__ /* include basic type headers only */ -#include "os_types.h" #include "dc_dp_types.h" #include "signal_types.h" #include "grph_object_id.h" @@ -74,22 +73,5 @@ struct link_hwss { void (*setup_stream_encoder)(struct pipe_ctx *pipe_ctx); void (*reset_stream_encoder)(struct pipe_ctx *pipe_ctx); }; - - -/*********************** below goes to virtual_link_hwss **********************/ -const struct link_hwss *get_virtual_link_hwss(void); -/*********************** below goes to dpia_link_hwss *************************/ -bool can_use_dpia_link_hwss(const struct dc_link *link, - const struct link_resource *link_res); -const struct link_hwss *get_dpia_link_hwss(void); -/*********************** below goes to hpo_dp_link_hwss ***********************/ -bool can_use_hpo_dp_link_hwss(const struct dc_link *link, - const struct link_resource *link_res); -const struct link_hwss *get_hpo_dp_link_hwss(void); -/************************* below goes to dio_link_hwss ************************/ -bool can_use_dio_link_hwss(const struct dc_link *link, - const struct link_resource *link_res); -const struct link_hwss *get_dio_link_hwss(void); - #endif /* __DC_LINK_HWSS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile new file mode 100644 index 000000000000..c4a69ba7cb62 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/Makefile @@ -0,0 +1,30 @@ +# +# Copyright 2022 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# Makefile for the link sub-component of DAL. +# It abstracts the control and status of back end pipe such as DIO, HPO, DPIA, +# PHY, HPD, DDC and etc). + +LINK = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o + +AMD_DAL_LINK = $(addprefix $(AMDDALPATH)/dc/link/,$(LINK)) + +AMD_DISPLAY_FILES += $(AMD_DAL_LINK) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c new file mode 100644 index 000000000000..0f845113a6aa --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c @@ -0,0 +1,137 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "link_hwss_dio.h" +#include "core_types.h" +#include "dc_link_dp.h" +#include "link_enc_cfg.h" + +void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size) +{ + struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; + + stream_encoder->funcs->set_throttled_vcp_size( + stream_encoder, + throttled_vcp_size); +} + +void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + + link_enc->funcs->connect_dig_be_to_fe(link_enc, + pipe_ctx->stream_res.stream_enc->id, true); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); +} + +void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); + + link_enc->funcs->connect_dig_be_to_fe( + link_enc, + pipe_ctx->stream_res.stream_enc->id, + false); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); + +} + +void enable_dio_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + if (dc_is_dp_sst_signal(signal)) + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); + else + link_enc->funcs->enable_dp_mst_output( + link_enc, + link_settings, + clock_source); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); +} + +void disable_dio_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + link_enc->funcs->disable_output(link_enc, signal); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); +} + +void set_dio_dp_link_test_pattern(struct dc_link *link, + const struct link_resource *link_res, + struct encoder_set_dp_phy_pattern_param *tp_params) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); +} + +void set_dio_dp_lane_settings(struct dc_link *link, + const struct link_resource *link_res, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) +{ + struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); + + link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings); +} + +static const struct link_hwss dio_link_hwss = { + .setup_stream_encoder = setup_dio_stream_encoder, + .reset_stream_encoder = reset_dio_stream_encoder, + .ext = { + .set_throttled_vcp_size = set_dio_throttled_vcp_size, + .enable_dp_link_output = enable_dio_dp_link_output, + .disable_dp_link_output = disable_dio_dp_link_output, + .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, + .set_dp_lane_settings = set_dio_dp_lane_settings, + }, +}; + +bool can_use_dio_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link->link_enc != NULL; +} + +const struct link_hwss *get_dio_link_hwss(void) +{ + return &dio_link_hwss; +} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h new file mode 100644 index 000000000000..680df20b1fa3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h @@ -0,0 +1,53 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __LINK_HWSS_DIO_H__ +#define __LINK_HWSS_DIO_H__ + +#include "link_hwss.h" + +const struct link_hwss *get_dio_link_hwss(void); +bool can_use_dio_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); +void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, + struct fixed31_32 throttled_vcp_size); +void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx); +void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx); +void enable_dio_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal, + enum clock_source_id clock_source, + const struct dc_link_settings *link_settings); +void disable_dio_dp_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); +void set_dio_dp_link_test_pattern(struct dc_link *link, + const struct link_resource *link_res, + struct encoder_set_dp_phy_pattern_param *tp_params); +void set_dio_dp_lane_settings(struct dc_link *link, + const struct link_resource *link_res, + const struct dc_link_settings *link_settings, + const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]); + +#endif /* __LINK_HWSS_DIO_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c new file mode 100644 index 000000000000..35b206225201 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c @@ -0,0 +1,51 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "link_hwss_dpia.h" +#include "core_types.h" +#include "link_hwss_dio.h" + +static const struct link_hwss dpia_link_hwss = { + .setup_stream_encoder = setup_dio_stream_encoder, + .reset_stream_encoder = reset_dio_stream_encoder, + .ext = { + .set_throttled_vcp_size = set_dio_throttled_vcp_size, + .enable_dp_link_output = enable_dio_dp_link_output, + .disable_dp_link_output = disable_dio_dp_link_output, + .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, + .set_dp_lane_settings = set_dio_dp_lane_settings, + }, +}; + +bool can_use_dpia_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign; +} + +const struct link_hwss *get_dpia_link_hwss(void) +{ + return &dpia_link_hwss; +} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h new file mode 100644 index 000000000000..ad16ec5d9bb7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.h @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __LINK_HWSS_DPIA_H__ +#define __LINK_HWSS_DPIA_H__ + +#include "link_hwss.h" + +const struct link_hwss *get_dpia_link_hwss(void); +bool can_use_dpia_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); + +#endif /* __LINK_HWSS_DPIA_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c similarity index 54% rename from drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c rename to drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c index dab532cf52b9..74919491675f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c @@ -1,10 +1,31 @@ -/* Copyright 2015 Advanced Micro Devices, Inc. */ - -#include "link_hwss.h" +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "link_hwss_hpo_dp.h" #include "dm_helpers.h" #include "core_types.h" #include "dccg.h" -#include "link_enc_cfg.h" #include "dc_link_dp.h" static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) @@ -25,122 +46,6 @@ static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) } } -static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx); -static void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx); - -/************************* below goes to dio_link_hwss ************************/ -static void set_dio_throttled_vcp_size(struct pipe_ctx *pipe_ctx, - struct fixed31_32 throttled_vcp_size) -{ - struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc; - - stream_encoder->funcs->set_throttled_vcp_size( - stream_encoder, - throttled_vcp_size); -} - -static void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) -{ - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); - - link_enc->funcs->connect_dig_be_to_fe(link_enc, - pipe_ctx->stream_res.stream_enc->id, true); - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(pipe_ctx->stream->link, - DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); -} - -static void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) -{ - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); - - link_enc->funcs->connect_dig_be_to_fe( - link_enc, - pipe_ctx->stream_res.stream_enc->id, - false); - if (dc_is_dp_signal(pipe_ctx->stream->signal)) - dp_source_sequence_trace(pipe_ctx->stream->link, - DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); - -} - -static void enable_dio_dp_link_output(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal, - enum clock_source_id clock_source, - const struct dc_link_settings *link_settings) -{ - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); - - if (dc_is_dp_sst_signal(signal)) - link_enc->funcs->enable_dp_output( - link_enc, - link_settings, - clock_source); - else - link_enc->funcs->enable_dp_mst_output( - link_enc, - link_settings, - clock_source); - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); -} - - -static void disable_dio_dp_link_output(struct dc_link *link, - const struct link_resource *link_res, - enum signal_type signal) -{ - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); - - link_enc->funcs->disable_output(link_enc, signal); - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); -} - -static void set_dio_dp_link_test_pattern(struct dc_link *link, - const struct link_resource *link_res, - struct encoder_set_dp_phy_pattern_param *tp_params) -{ - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); - - ASSERT(link_enc); - link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); - dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); -} - -static void set_dio_dp_lane_settings(struct dc_link *link, - const struct link_resource *link_res, - const struct dc_link_settings *link_settings, - const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) -{ - struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); - - link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings); -} - -static const struct link_hwss dio_link_hwss = { - .setup_stream_encoder = setup_dio_stream_encoder, - .reset_stream_encoder = reset_dio_stream_encoder, - .ext = { - .set_throttled_vcp_size = set_dio_throttled_vcp_size, - .enable_dp_link_output = enable_dio_dp_link_output, - .disable_dp_link_output = disable_dio_dp_link_output, - .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, - .set_dp_lane_settings = set_dio_dp_lane_settings, - }, -}; - -bool can_use_dio_link_hwss(const struct dc_link *link, - const struct link_resource *link_res) -{ - return link->link_enc != NULL; -} - -const struct link_hwss *get_dio_link_hwss(void) -{ - return &dio_link_hwss; -} - -/*********************** below goes to hpo_dp_link_hwss ***********************/ static void set_hpo_dp_throttled_vcp_size(struct pipe_ctx *pipe_ctx, struct fixed31_32 throttled_vcp_size) { @@ -347,71 +252,3 @@ const struct link_hwss *get_hpo_dp_link_hwss(void) return &hpo_dp_link_hwss; } -/*********************** below goes to dpia_link_hwss *************************/ -static const struct link_hwss dpia_link_hwss = { - .setup_stream_encoder = setup_dio_stream_encoder, - .reset_stream_encoder = reset_dio_stream_encoder, - .ext = { - .set_throttled_vcp_size = set_dio_throttled_vcp_size, - .enable_dp_link_output = enable_dio_dp_link_output, - .disable_dp_link_output = disable_dio_dp_link_output, - .set_dp_link_test_pattern = set_dio_dp_link_test_pattern, - .set_dp_lane_settings = set_dio_dp_lane_settings, - }, -}; - -bool can_use_dpia_link_hwss(const struct dc_link *link, - const struct link_resource *link_res) -{ - return link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign; -} - -const struct link_hwss *get_dpia_link_hwss(void) -{ - return &dpia_link_hwss; -} -/*********************** below goes to virtual_link_hwss ******************************/ -static void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx) -{ -} - -static void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx) -{ -} -static const struct link_hwss virtual_link_hwss = { - .setup_stream_encoder = virtual_setup_stream_encoder, - .reset_stream_encoder = virtual_reset_stream_encoder, -}; - -const struct link_hwss *get_link_hwss(const struct dc_link *link, - const struct link_resource *link_res) -{ - if (can_use_dp_hpo_link_hwss(link, link_res)) - /* TODO: some assumes that if decided link settings is 128b/132b - * channel coding format hpo_dp_link_enc should be used. - * Others believe that if hpo_dp_link_enc is available in link - * resource then hpo_dp_link_enc must be used. This bound between - * hpo_dp_link_enc != NULL and decided link settings is loosely coupled - * with a premise that both hpo_dp_link_enc pointer and decided link - * settings are determined based on single policy function like - * "decide_link_settings" from upper layer. This "convention" - * cannot be maintained and enforced at current level. - * Therefore a refactor is due so we can enforce a strong bound - * between those two parameters at this level. - * - * To put it simple, we want to make enforcement at low level so that - * we will not return link hwss if caller plans to do 8b/10b - * with an hpo encoder. Or we can return a very dummy one that doesn't - * do work for all functions - */ - return &hpo_dp_link_hwss; - else if (can_use_dpia_link_hwss(link, link_res)) - return &dpia_link_hwss; - else if (can_use_dio_link_hwss(link, link_res)) - return &dio_link_hwss; - else - return &virtual_link_hwss; -} - -#undef DC_LOGGER diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h new file mode 100644 index 000000000000..57d447ec27b8 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.h @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __LINK_HWSS_HPO_DP_H__ +#define __LINK_HWSS_HPO_DP_H__ + +#include "link_hwss.h" + +bool can_use_hpo_dp_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); +const struct link_hwss *get_hpo_dp_link_hwss(void); + + +#endif /* __LINK_HWSS_HPO_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c new file mode 100644 index 000000000000..9df273ca699b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.c @@ -0,0 +1,43 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#include "link_hwss_hpo_frl.h" +#include "core_types.h" +#include "virtual/virtual_link_hwss.h" + +static const struct link_hwss hpo_frl_link_hwss = { + .setup_stream_encoder = virtual_setup_stream_encoder, + .reset_stream_encoder = virtual_reset_stream_encoder, +}; + +bool can_use_hpo_frl_link_hwss(const struct dc_link *link, + const struct link_resource *link_res) +{ + return link_res->hpo_frl_link_enc != NULL; +} + +const struct link_hwss *get_hpo_frl_link_hwss(void) +{ + return &hpo_frl_link_hwss; +} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h new file mode 100644 index 000000000000..ea8d9760132f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_frl.h @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __LINK_HWSS_HPO_FRL_H__ +#define __LINK_HWSS_HPO_FRL_H__ + +#include "link_hwss.h" + +bool can_use_hpo_frl_link_hwss(const struct dc_link *link, + const struct link_resource *link_res); +const struct link_hwss *get_hpo_frl_link_hwss(void); + +#endif /* __LINK_HWSS_HPO_FRL_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/virtual/Makefile b/drivers/gpu/drm/amd/display/dc/virtual/Makefile index 07326d244d50..931facd4dab5 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/Makefile +++ b/drivers/gpu/drm/amd/display/dc/virtual/Makefile @@ -23,7 +23,7 @@ # Makefile for the virtual sub-component of DAL. # It provides the control and status of HW CRTC block. -VIRTUAL = virtual_link_encoder.o virtual_stream_encoder.o +VIRTUAL = virtual_link_encoder.o virtual_stream_encoder.o virtual_link_hwss.o AMD_DAL_VIRTUAL = $(addprefix $(AMDDALPATH)/dc/virtual/,$(VIRTUAL)) diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c new file mode 100644 index 000000000000..525eba2a3354 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.c @@ -0,0 +1,43 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "virtual_link_hwss.h" + +void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx) +{ +} + +void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx) +{ +} +static const struct link_hwss virtual_link_hwss = { + .setup_stream_encoder = virtual_setup_stream_encoder, + .reset_stream_encoder = virtual_reset_stream_encoder, +}; + +const struct link_hwss *get_virtual_link_hwss(void) +{ + return &virtual_link_hwss; +} diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.h b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.h new file mode 100644 index 000000000000..e6bcb4bb0f3a --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_hwss.h @@ -0,0 +1,34 @@ +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_VIRTUAL_LINK_HWSS_H__ +#define __DC_VIRTUAL_LINK_HWSS_H__ + +#include "core_types.h" + +void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx); +void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx); +const struct link_hwss *get_virtual_link_hwss(void); + +#endif /* __DC_VIRTUAL_LINK_HWSS_H__ */ From 2412d339b30e66f86d9430aec26f5c6a44908b15 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 28 Jan 2022 22:04:08 +0800 Subject: [PATCH 232/339] drm/amd/display: [FW Promotion] Release 0.0.102.0 - Correct number of reserved bits in cmd_lock_hw - Extend bits of hw_lock_client to allow for more clients Tested-by: Daniel Wheeler Acked-by: Stylon Wang Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 3ef6a7a0c7b6..d6589db40f42 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x1288a7b7 +#define DMUB_FW_VERSION_GIT_HASH 0xab0ae3c8 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 101 +#define DMUB_FW_VERSION_REVISION 102 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -524,7 +524,7 @@ union dmub_inbox0_cmd_lock_hw { uint32_t command_code: 8; /* NOTE: Must be have enough bits to match: enum hw_lock_client */ - uint32_t hw_lock_client: 1; + uint32_t hw_lock_client: 2; /* NOTE: Below fields must match with: struct dmub_hw_lock_inst_flags */ uint32_t otg_inst: 3; @@ -539,7 +539,7 @@ union dmub_inbox0_cmd_lock_hw { uint32_t lock: 1; /**< Lock */ uint32_t should_release: 1; /**< Release */ - uint32_t reserved: 8; /**< Reserved for extending more clients, HW, etc. */ + uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */ } bits; uint32_t all; }; From 05f8c2a87aa01d1000cf148213560117e39a48f6 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Fri, 28 Jan 2022 22:04:09 +0800 Subject: [PATCH 233/339] drm/amd/display: 3.2.171 This version brings along following fixes: - DC refactor and bug fixes for DP links - Bug fixes for DP2 - Fix regressions causing display not light up - Improved debug trace - Improved DP AUX transfer - Updated watermark latencies to fix underflows in some modes Tested-by: Daniel Wheeler Acked-by: Stylon Wang Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4f9dacd09856..69d264dd69a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.170" +#define DC_VER "3.2.171" #define MAX_SURFACES 3 #define MAX_PLANES 6 From bd682a788c1f4fbefe17b3ee9e0e3debdefeec6d Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Fri, 28 Jan 2022 22:04:10 +0800 Subject: [PATCH 234/339] drm/amd/display: Trigger DP2 Sequence With Uncertified Cable DP2 sequence is triggered only if VESA certified cable is detected. Force DP2 sequence with uncertified cable for testing purpose. Tested-by: Daniel Wheeler Reviewed-by: Wenjing Liu Acked-by: Stylon Wang Signed-off-by: Fangzhi Zuo Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index aca725874bcf..bdea177fae55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -3431,6 +3431,30 @@ static int dp_force_sst_get(void *data, u64 *val) } DEFINE_DEBUGFS_ATTRIBUTE(dp_set_mst_en_for_sst_ops, dp_force_sst_get, dp_force_sst_set, "%llu\n"); + +/* + * Force DP2 sequence without VESA certified cable. + * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dp_ignore_cable_id + */ +static int dp_ignore_cable_id_set(void *data, u64 val) +{ + struct amdgpu_device *adev = data; + + adev->dm.dc->debug.ignore_cable_id = val; + + return 0; +} + +static int dp_ignore_cable_id_get(void *data, u64 *val) +{ + struct amdgpu_device *adev = data; + + *val = adev->dm.dc->debug.ignore_cable_id; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(dp_ignore_cable_id_ops, dp_ignore_cable_id_get, + dp_ignore_cable_id_set, "%llu\n"); #endif /* @@ -3549,6 +3573,8 @@ void dtn_debugfs_init(struct amdgpu_device *adev) #if defined(CONFIG_DRM_AMD_DC_DCN) debugfs_create_file("amdgpu_dm_dp_set_mst_en_for_sst", 0644, root, adev, &dp_set_mst_en_for_sst_ops); + debugfs_create_file("amdgpu_dm_dp_ignore_cable_id", 0644, root, adev, + &dp_ignore_cable_id_ops); #endif debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev, From dd4dabe4b3c2425878a49ae8d5817d5c5958c6db Mon Sep 17 00:00:00 2001 From: Yang Li Date: Sat, 29 Jan 2022 09:04:13 +0800 Subject: [PATCH 235/339] drm/amd/display: clean up some inconsistent indenting Eliminate the follow smatch warning: drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c:2246 dp_perform_8b_10b_link_training() warn: inconsistent indenting Reviewed-by: Harry Wentland Reported-by: Abaci Robot Signed-off-by: Yang Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 65ebfbcf3019..05ab3468329e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2250,11 +2250,11 @@ static enum link_training_result dp_perform_8b_10b_link_training( if (status == LINK_TRAINING_SUCCESS) { status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX); - if (status == LINK_TRAINING_SUCCESS) { - status = perform_channel_equalization_sequence(link, - link_res, - lt_settings, - DPRX); + if (status == LINK_TRAINING_SUCCESS) { + status = perform_channel_equalization_sequence(link, + link_res, + lt_settings, + DPRX); } } From 33413ef964b8cdbb25a23aaf0b4aa8f0a330c4cf Mon Sep 17 00:00:00 2001 From: Aun-Ali Zaidi Date: Sat, 29 Jan 2022 05:49:55 +0000 Subject: [PATCH 236/339] drm/amd/display: Force link_rate as LINK_RATE_RBR2 for 2018 15" Apple Retina panels The eDP link rate reported by the DP_MAX_LINK_RATE dpcd register (0xa) is contradictory to the highest rate supported reported by EDID (0xc = LINK_RATE_RBR2). The effects of this compounded with commit '4a8ca46bae8a ("drm/amd/display: Default max bpc to 16 for eDP")' results in no display modes being found and a dark panel. For now, simply force the maximum supported link rate for the eDP attached 2018 15" Apple Retina panels. Additionally, we must also check the firmware revision since the device ID reported by the DPCD is identical to that of the more capable 16,1, incorrectly quirking it. We also use said firmware check to quirk the refreshed 15,1 models with Vega graphics as they use a slightly newer firmware version. Tested-by: Aun-Ali Zaidi Reviewed-by: Harry Wentland Signed-off-by: Aun-Ali Zaidi Signed-off-by: Aditya Garg Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 05ab3468329e..18fe8f77821a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5280,6 +5280,26 @@ static bool retrieve_link_cap(struct dc_link *link) dp_hw_fw_revision.ieee_fw_rev, sizeof(dp_hw_fw_revision.ieee_fw_rev)); + /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */ + { + uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 }; + uint8_t fwrev_mbp_2018[] = { 7, 4 }; + uint8_t fwrev_mbp_2018_vega[] = { 8, 4 }; + + /* We also check for the firmware revision as 16,1 models have an + * identical device id and are incorrectly quirked otherwise. + */ + if ((link->dpcd_caps.sink_dev_id == 0x0010fa) && + !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018, + sizeof(str_mbp_2018)) && + (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018, + sizeof(fwrev_mbp_2018)) || + !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega, + sizeof(fwrev_mbp_2018_vega)))) { + link->reported_link_cap.link_rate = LINK_RATE_RBR2; + } + } + memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps)); memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); From fcd6b0e270a9dd849981df34051ee6dcbdbb1c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 28 Jan 2022 13:21:10 +0100 Subject: [PATCH 237/339] drm/amdgpu: fix logic inversion in check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We probably never trigger this, but the logic inside the check is inverted. Signed-off-by: Christian König Reviewed-by: Felix Kuehling 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 74d8b721bd7d..4b2920af1209 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1941,7 +1941,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, unsigned i; int r; - if (direct_submit && !ring->sched.ready) { + if (!direct_submit && !ring->sched.ready) { DRM_ERROR("Trying to move memory with ring turned off.\n"); return -EINVAL; } From e0a4459d45425fabd5f020a2117d350c5a07477b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 31 Jan 2022 14:20:57 +0100 Subject: [PATCH 238/339] drm/amdgpu: lower BUG_ON into WARN_ON for AMDGPU_PL_PREEMPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That should never happen, but make sure that we only warn instead of crash. Signed-off-by: Christian König Reviewed-by: Felix Kuehling 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 4b2920af1209..7b43a0b30102 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -199,7 +199,9 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, BUG_ON(adev->mman.buffer_funcs->copy_max_bytes < AMDGPU_GTT_MAX_TRANSFER_SIZE * 8); - BUG_ON(mem->mem_type == AMDGPU_PL_PREEMPT); + + if (WARN_ON(mem->mem_type == AMDGPU_PL_PREEMPT)) + return -EINVAL; /* Map only what can't be accessed directly */ if (!tmz && mem->start != AMDGPU_BO_INVALID_OFFSET) { From 6927913d700749a4b9550f87f294778df2a7faa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 31 Jan 2022 13:42:52 +0100 Subject: [PATCH 239/339] drm/amdgpu: rework GART copy window handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of limiting the size before we call the mapping function let the function itself limit the size. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 49 ++++++++++++------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7b43a0b30102..a630dc42b934 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -171,10 +171,10 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, * @bo: buffer object to map * @mem: memory object to map * @mm_cur: range to map - * @num_pages: number of pages to map * @window: which GART window to use * @ring: DMA ring to use for the copy * @tmz: if we should setup a TMZ enabled mapping + * @size: in number of bytes to map, out number of bytes mapped * @addr: resulting address inside the MC address space * * Setup one of the GART windows to access a specific piece of memory or return @@ -183,15 +183,14 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, struct ttm_resource *mem, struct amdgpu_res_cursor *mm_cur, - unsigned num_pages, unsigned window, - struct amdgpu_ring *ring, bool tmz, - uint64_t *addr) + unsigned window, struct amdgpu_ring *ring, + bool tmz, uint64_t *size, uint64_t *addr) { struct amdgpu_device *adev = ring->adev; - struct amdgpu_job *job; - unsigned num_dw, num_bytes; - struct dma_fence *fence; + unsigned offset, num_pages, num_dw, num_bytes; uint64_t src_addr, dst_addr; + struct dma_fence *fence; + struct amdgpu_job *job; void *cpu_addr; uint64_t flags; unsigned int i; @@ -210,10 +209,22 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, return 0; } + + /* + * If start begins at an offset inside the page, then adjust the size + * and addr accordingly + */ + offset = mm_cur->start & ~PAGE_MASK; + + num_pages = PFN_UP(*size + offset); + num_pages = min_t(uint32_t, num_pages, AMDGPU_GTT_MAX_TRANSFER_SIZE); + + *size = min(*size, (uint64_t)num_pages * PAGE_SIZE - offset); + *addr = adev->gmc.gart_start; *addr += (u64)window * AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GPU_PAGE_SIZE; - *addr += mm_cur->start & ~PAGE_MASK; + *addr += offset; num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8); num_bytes = num_pages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE; @@ -294,9 +305,6 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, struct dma_resv *resv, struct dma_fence **f) { - const uint32_t GTT_MAX_BYTES = (AMDGPU_GTT_MAX_TRANSFER_SIZE * - AMDGPU_GPU_PAGE_SIZE); - struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; struct amdgpu_res_cursor src_mm, dst_mm; struct dma_fence *fence = NULL; @@ -312,29 +320,20 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, mutex_lock(&adev->mman.gtt_window_lock); while (src_mm.remaining) { - uint32_t src_page_offset = src_mm.start & ~PAGE_MASK; - uint32_t dst_page_offset = dst_mm.start & ~PAGE_MASK; + uint64_t from, to, cur_size; struct dma_fence *next; - uint32_t cur_size; - uint64_t from, to; - /* Copy size cannot exceed GTT_MAX_BYTES. So if src or dst - * begins at an offset, then adjust the size accordingly - */ - cur_size = max(src_page_offset, dst_page_offset); - cur_size = min(min3(src_mm.size, dst_mm.size, size), - (uint64_t)(GTT_MAX_BYTES - cur_size)); + /* Never copy more than 256MiB at once to avoid a timeout */ + cur_size = min3(src_mm.size, dst_mm.size, 256ULL << 20); /* Map src to window 0 and dst to window 1. */ r = amdgpu_ttm_map_buffer(src->bo, src->mem, &src_mm, - PFN_UP(cur_size + src_page_offset), - 0, ring, tmz, &from); + 0, ring, tmz, &cur_size, &from); if (r) goto error; r = amdgpu_ttm_map_buffer(dst->bo, dst->mem, &dst_mm, - PFN_UP(cur_size + dst_page_offset), - 1, ring, tmz, &to); + 1, ring, tmz, &cur_size, &to); if (r) goto error; From 22f7cc7524081bb2bfb2720e43ab9889e2ed5b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 28 Jan 2022 15:59:15 +0100 Subject: [PATCH 240/339] drm/amdgpu: restructure amdgpu_fill_buffer v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We ran into the problem that clearing really larger buffer (60GiB) caused an SDMA timeout. Restructure the function to use the dst window instead of mapping the whole buffer into the GART and then fill only 2MiB/256MiB chunks at a time. v2: rebase on restructured window map. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 189 +++++++++++++----------- 1 file changed, 106 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a630dc42b934..7cac4a69ba32 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -392,8 +392,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, (abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) { struct dma_fence *wipe_fence = NULL; - r = amdgpu_fill_buffer(ttm_to_amdgpu_bo(bo), AMDGPU_POISON, - NULL, &wipe_fence); + r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence); if (r) { goto error; } else if (wipe_fence) { @@ -1926,19 +1925,51 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; } +static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev, + bool direct_submit, + unsigned int num_dw, + struct dma_resv *resv, + bool vm_needs_flush, + struct amdgpu_job **job) +{ + enum amdgpu_ib_pool_type pool = direct_submit ? + AMDGPU_IB_POOL_DIRECT : + AMDGPU_IB_POOL_DELAYED; + int r; + + r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, pool, job); + if (r) + return r; + + if (vm_needs_flush) { + (*job)->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gmc.pdb0_bo ? + adev->gmc.pdb0_bo : + adev->gart.bo); + (*job)->vm_needs_flush = true; + } + if (resv) { + r = amdgpu_sync_resv(adev, &(*job)->sync, resv, + AMDGPU_SYNC_ALWAYS, + AMDGPU_FENCE_OWNER_UNDEFINED); + if (r) { + DRM_ERROR("sync failed (%d).\n", r); + amdgpu_job_free(*job); + return r; + } + } + return 0; +} + int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, struct dma_fence **fence, bool direct_submit, bool vm_needs_flush, bool tmz) { - enum amdgpu_ib_pool_type pool = direct_submit ? AMDGPU_IB_POOL_DIRECT : - AMDGPU_IB_POOL_DELAYED; struct amdgpu_device *adev = ring->adev; - struct amdgpu_job *job; - - uint32_t max_bytes; unsigned num_loops, num_dw; + struct amdgpu_job *job; + uint32_t max_bytes; unsigned i; int r; @@ -1950,26 +1981,11 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, max_bytes = adev->mman.buffer_funcs->copy_max_bytes; num_loops = DIV_ROUND_UP(byte_count, max_bytes); num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->copy_num_dw, 8); - - r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, pool, &job); + r = amdgpu_ttm_prepare_job(adev, direct_submit, num_dw, + resv, vm_needs_flush, &job); if (r) return r; - if (vm_needs_flush) { - job->vm_pd_addr = amdgpu_gmc_pd_addr(adev->gmc.pdb0_bo ? - adev->gmc.pdb0_bo : adev->gart.bo); - job->vm_needs_flush = true; - } - if (resv) { - r = amdgpu_sync_resv(adev, &job->sync, resv, - AMDGPU_SYNC_ALWAYS, - AMDGPU_FENCE_OWNER_UNDEFINED); - if (r) { - DRM_ERROR("sync failed (%d).\n", r); - goto error_free; - } - } - for (i = 0; i < num_loops; i++) { uint32_t cur_size_in_bytes = min(byte_count, max_bytes); @@ -1999,77 +2015,35 @@ error_free: return r; } -int amdgpu_fill_buffer(struct amdgpu_bo *bo, - uint32_t src_data, - struct dma_resv *resv, - struct dma_fence **fence) +static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data, + uint64_t dst_addr, uint32_t byte_count, + struct dma_resv *resv, + struct dma_fence **fence, + bool vm_needs_flush) { - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes; - struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; - - struct amdgpu_res_cursor cursor; + struct amdgpu_device *adev = ring->adev; unsigned int num_loops, num_dw; - uint64_t num_bytes; - struct amdgpu_job *job; + uint32_t max_bytes; + unsigned int i; int r; - if (!adev->mman.buffer_funcs_enabled) { - DRM_ERROR("Trying to clear memory with ring turned off.\n"); - return -EINVAL; - } - - if (bo->tbo.resource->mem_type == AMDGPU_PL_PREEMPT) { - DRM_ERROR("Trying to clear preemptible memory.\n"); - return -EINVAL; - } - - if (bo->tbo.resource->mem_type == TTM_PL_TT) { - r = amdgpu_ttm_alloc_gart(&bo->tbo); - if (r) - return r; - } - - num_bytes = bo->tbo.resource->num_pages << PAGE_SHIFT; - num_loops = 0; - - amdgpu_res_first(bo->tbo.resource, 0, num_bytes, &cursor); - while (cursor.remaining) { - num_loops += DIV_ROUND_UP_ULL(cursor.size, max_bytes); - amdgpu_res_next(&cursor, cursor.size); - } - num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw; - - /* for IB padding */ - num_dw += 64; - - r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, AMDGPU_IB_POOL_DELAYED, - &job); + max_bytes = adev->mman.buffer_funcs->fill_max_bytes; + num_loops = DIV_ROUND_UP_ULL(byte_count, max_bytes); + num_dw = ALIGN(num_loops * adev->mman.buffer_funcs->fill_num_dw, 8); + r = amdgpu_ttm_prepare_job(adev, false, num_dw, resv, vm_needs_flush, + &job); if (r) return r; - if (resv) { - r = amdgpu_sync_resv(adev, &job->sync, resv, - AMDGPU_SYNC_ALWAYS, - AMDGPU_FENCE_OWNER_UNDEFINED); - if (r) { - DRM_ERROR("sync failed (%d).\n", r); - goto error_free; - } - } + for (i = 0; i < num_loops; i++) { + uint32_t cur_size = min(byte_count, max_bytes); - amdgpu_res_first(bo->tbo.resource, 0, num_bytes, &cursor); - while (cursor.remaining) { - uint32_t cur_size = min_t(uint64_t, cursor.size, max_bytes); - uint64_t dst_addr = cursor.start; - - dst_addr += amdgpu_ttm_domain_start(adev, - bo->tbo.resource->mem_type); amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data, dst_addr, cur_size); - amdgpu_res_next(&cursor, cur_size); + dst_addr += cur_size; + byte_count -= cur_size; } amdgpu_ring_pad_ib(ring, &job->ibs[0]); @@ -2086,6 +2060,55 @@ error_free: return r; } +int amdgpu_fill_buffer(struct amdgpu_bo *bo, + uint32_t src_data, + struct dma_resv *resv, + struct dma_fence **f) +{ + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; + struct dma_fence *fence = NULL; + struct amdgpu_res_cursor dst; + int r; + + if (!adev->mman.buffer_funcs_enabled) { + DRM_ERROR("Trying to clear memory with ring turned off.\n"); + return -EINVAL; + } + + amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &dst); + + mutex_lock(&adev->mman.gtt_window_lock); + while (dst.remaining) { + struct dma_fence *next; + uint64_t cur_size, to; + + /* Never fill more than 256MiB at once to avoid timeouts */ + cur_size = min(dst.size, 256ULL << 20); + + r = amdgpu_ttm_map_buffer(&bo->tbo, bo->tbo.resource, &dst, + 1, ring, false, &cur_size, &to); + if (r) + goto error; + + r = amdgpu_ttm_fill_mem(ring, src_data, to, cur_size, resv, + &next, true); + if (r) + goto error; + + dma_fence_put(fence); + fence = next; + + amdgpu_res_next(&dst, cur_size); + } +error: + mutex_unlock(&adev->mman.gtt_window_lock); + if (f) + *f = dma_fence_get(fence); + dma_fence_put(fence); + return r; +} + /** * amdgpu_ttm_evict_resources - evict memory buffers * @adev: amdgpu device object From 9308a49d8ee2f0f372fb7f18b8f4a97d9ec676c7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 25 Jan 2022 21:46:58 -0600 Subject: [PATCH 241/339] drm/amd: avoid suspend on dGPUs w/ s2idle support when runtime PM enabled dGPUs connected to Intel systems configured for suspend to idle will not have the power rails cut at suspend and resetting the GPU may lead to problematic behaviors. Fixes: e25443d2765f4 ("drm/amdgpu: add a dev_pm_ops prepare callback (v2)") Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1879 Reviewed-by: Alex Deucher Signed-off-by: Mario Limonciello Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 4c43f9401f56..78063d01c9db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -2269,8 +2269,7 @@ static int amdgpu_pmops_prepare(struct device *dev) * DPM_FLAG_SMART_SUSPEND works properly */ if (amdgpu_device_supports_boco(drm_dev)) - return pm_runtime_suspended(dev) && - pm_suspend_via_firmware(); + return pm_runtime_suspended(dev); /* if we will not support s3 or s2i for the device * then skip suspend From 4f860edecdafeb2e5fb29fecc6428090997936fe Mon Sep 17 00:00:00 2001 From: Somalapuram Amaranath Date: Mon, 17 Jan 2022 13:19:10 +0530 Subject: [PATCH 242/339] drm/amdgpu: limit the number of dst address in trace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit trace_amdgpu_vm_update_ptes trace unable to log when nptes too large Signed-off-by: Somalapuram Amaranath Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h | 5 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index d855cb53c7e0..a48b34d4ce31 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -358,11 +358,10 @@ TRACE_EVENT(amdgpu_vm_update_ptes, } ), TP_printk("pid:%u vm_ctx:0x%llx start:0x%010llx end:0x%010llx," - " flags:0x%llx, incr:%llu, dst:\n%s%s", __entry->pid, + " flags:0x%llx, incr:%llu, dst:\n%s", __entry->pid, __entry->vm_ctx, __entry->start, __entry->end, __entry->flags, __entry->incr, __print_array( - __get_dynamic_array(dst), min(__entry->nptes, 32u), 8), - __entry->nptes > 32 ? "..." : "") + __get_dynamic_array(dst), __entry->nptes, 8)) ); TRACE_EVENT(amdgpu_vm_set_ptes, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b37fc7d7d2c7..4017bcf75e1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1634,7 +1634,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, nptes = max(nptes, 1u); trace_amdgpu_vm_update_ptes(params, frag_start, upd_end, - nptes, dst, incr, upd_flags, + min(nptes, 32u), dst, incr, upd_flags, vm->task_info.pid, vm->immediate.fence_context); amdgpu_vm_update_flags(params, to_amdgpu_bo_vm(pt), From 5d64f9bbb6281a5a89a2266b9d39daa1fca1d6b4 Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Sat, 4 Dec 2021 00:23:52 -0500 Subject: [PATCH 243/339] amdgpu/pm: Implement new API function "emit" that accepts buffer base and write offset (v3) Rewrote patchset to order patches as (API, hw impl, usecase) - added API for new power management function emit_clk_levels This function should duplicate the functionality of print_clk_levels, but this solution passes the buffer base and write offset down the stack. - new powerplay function emit_clock_levels, implemented by smu_emit_ppclk_levels() This function parallels the implementation of smu_print_ppclk_levels and calls emit_clk_levels, and allows the returns of errors - new helper function smu_convert_to_smuclk called by smu_print_ppclk_levels and smu_emit_ppclk_levels Signed-off-by: Darren Powell Reviewed-By: Evan Quan Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 21 ++++++++++ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 ++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 42 ++++++++++++++++--- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 14 +++++++ 5 files changed, 77 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 387120099493..a4c267f15959 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -321,6 +321,7 @@ struct amd_pm_funcs { int (*get_fan_speed_pwm)(void *handle, u32 *speed); int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); + int (*emit_clock_levels)(void *handle, enum pp_clock_type type, char *buf, int *offset); int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); int (*get_sclk_od)(void *handle); int (*set_sclk_od)(void *handle, uint32_t value); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index ef574c96b41c..1d63f1e8884c 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -890,6 +890,27 @@ int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, return ret; } +int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, + enum pp_clock_type type, + char *buf, + int *offset) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + int ret = 0; + + if (!pp_funcs->emit_clock_levels) + return -ENOENT; + + mutex_lock(&adev->pm.mutex); + ret = pp_funcs->emit_clock_levels(adev->powerplay.pp_handle, + type, + buf, + offset); + mutex_unlock(&adev->pm.mutex); + + return ret; +} + int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, uint64_t ppfeature_masks) { diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 5cc05110cdae..1ed0ef898eb0 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -441,6 +441,10 @@ int amdgpu_dpm_odn_edit_dpm_table(struct amdgpu_device *adev, int amdgpu_dpm_print_clock_levels(struct amdgpu_device *adev, enum pp_clock_type type, char *buf); +int amdgpu_dpm_emit_clock_levels(struct amdgpu_device *adev, + enum pp_clock_type type, + char *buf, + int *offset); int amdgpu_dpm_set_ppfeature_status(struct amdgpu_device *adev, uint64_t ppfeature_masks); int amdgpu_dpm_get_ppfeature_status(struct amdgpu_device *adev, char *buf); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 9861d70a5dad..af368aa1fd0a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2216,11 +2216,8 @@ static int smu_print_smuclk_levels(struct smu_context *smu, enum smu_clk_type cl return ret; } -static int smu_print_ppclk_levels(void *handle, - enum pp_clock_type type, - char *buf) +static enum smu_clk_type smu_convert_to_smuclk(enum pp_clock_type type) { - struct smu_context *smu = handle; enum smu_clk_type clk_type; switch (type) { @@ -2253,12 +2250,46 @@ static int smu_print_ppclk_levels(void *handle, case OD_CCLK: clk_type = SMU_OD_CCLK; break; default: - return -EINVAL; + clk_type = SMU_CLK_COUNT; break; } + return clk_type; +} + +static int smu_print_ppclk_levels(void *handle, + enum pp_clock_type type, + char *buf) +{ + struct smu_context *smu = handle; + enum smu_clk_type clk_type; + + clk_type = smu_convert_to_smuclk(type); + if (clk_type == SMU_CLK_COUNT) + return -EINVAL; + return smu_print_smuclk_levels(smu, clk_type, buf); } +static int smu_emit_ppclk_levels(void *handle, enum pp_clock_type type, char *buf, int *offset) +{ + struct smu_context *smu = handle; + enum smu_clk_type clk_type; + int ret = 0; + + clk_type = smu_convert_to_smuclk(type); + if (clk_type == SMU_CLK_COUNT) + return -EINVAL; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->emit_clk_levels) + ret = -ENOENT; + + return smu->ppt_funcs->emit_clk_levels(smu, clk_type, buf, offset); + +} + static int smu_od_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, long *input, uint32_t size) @@ -2824,6 +2855,7 @@ static const struct amd_pm_funcs swsmu_pm_funcs = { .get_fan_speed_pwm = smu_get_fan_speed_pwm, .force_clock_level = smu_force_ppclk_levels, .print_clock_levels = smu_print_ppclk_levels, + .emit_clock_levels = smu_emit_ppclk_levels, .force_performance_level = smu_force_performance_level, .read_sensor = smu_read_sensor, .get_performance_level = smu_get_performance_level, diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 4c585241ef66..79c7cb1a92d7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -605,9 +605,23 @@ struct pptable_funcs { * to buffer. Star current level. * * Used for sysfs interfaces. + * Return: Number of characters written to the buffer */ int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf); + /** + * @emit_clk_levels: Print DPM clock levels for a clock domain + * to buffer using sysfs_emit_at. Star current level. + * + * Used for sysfs interfaces. + * &buf: sysfs buffer + * &offset: offset within buffer to start printing, which is updated by the + * function. + * + * Return: 0 on Success or Negative to indicate an error occurred. + */ + int (*emit_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf, int *offset); + /** * @force_clk_levels: Set a range of allowed DPM levels for a clock * domain. From 7e2ec174945fa98048b39baf2a87973eddca3241 Mon Sep 17 00:00:00 2001 From: Magali Lemes Date: Wed, 2 Feb 2022 18:38:56 -0300 Subject: [PATCH 244/339] drm/amd/display: Use NULL pointer instead of plain integer Assigning 0L to a pointer variable caused the following warning: drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dsc/rc_calc_fpu.c:71:40: warning: Using plain integer as NULL pointer In order to remove this warning, this commit assigns a NULL pointer to the pointer variable that caused this issue. Reported-by: kernel test robot Signed-off-by: Magali Lemes Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c index ec636d06e18c..ef75eb7d5adc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c @@ -68,7 +68,7 @@ static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc, int sel = table_hash(mode, bpc, max_min); int table_size = 0; int index; - const struct qp_entry *table = 0L; + const struct qp_entry *table = NULL; // alias enum enum { min = DAL_MM_MIN, max = DAL_MM_MAX }; From 2d022081b333a7f15ba27607696d4a41a7a2b5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 1 Feb 2022 16:21:04 +0100 Subject: [PATCH 245/339] drm/amdgpu: add some lockdep checks to the VM code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever a bo_va structure is added or removed the VM and eventually added BO should be locked. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Felix Kuehling Acked-by: Daniel Vetter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 4017bcf75e1f..5a67ac0b6b7a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2244,6 +2244,8 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, { struct amdgpu_bo_va *bo_va; + dma_resv_assert_held(vm->root.bo->tbo.base.resv); + bo_va = kzalloc(sizeof(struct amdgpu_bo_va), GFP_KERNEL); if (bo_va == NULL) { return NULL; @@ -2257,6 +2259,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, if (!bo) return bo_va; + dma_resv_assert_held(bo->tbo.base.resv); if (amdgpu_dmabuf_is_xgmi_accessible(adev, bo)) { bo_va->is_xgmi = true; /* Power up XGMI if it can be potentially used */ @@ -2651,7 +2654,10 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, struct amdgpu_vm *vm = bo_va->base.vm; struct amdgpu_vm_bo_base **base; + dma_resv_assert_held(vm->root.bo->tbo.base.resv); + if (bo) { + dma_resv_assert_held(bo->tbo.base.resv); if (bo->tbo.base.resv == vm->root.bo->tbo.base.resv) vm->bulk_moveable = false; From e56694f718f0f6694c18d7595e61533a2663335e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 1 Feb 2022 16:25:52 +0100 Subject: [PATCH 246/339] drm/amdgpu: rename amdgpu_vm_bo_rmv to _del MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some people complained about the name and this matches much more Linux naming conventions for object functions. Signed-off-by: Christian König Reviewed-by: Alex Deucher Reviewed-by: Felix Kuehling Acked-by: Daniel Vetter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5df387c4d7fb..5d00a6878ef2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -778,7 +778,7 @@ unwind: continue; if (attachment[i]->bo_va) { amdgpu_bo_reserve(bo[i], true); - amdgpu_vm_bo_rmv(adev, attachment[i]->bo_va); + amdgpu_vm_bo_del(adev, attachment[i]->bo_va); amdgpu_bo_unreserve(bo[i]); list_del(&attachment[i]->list); } @@ -795,7 +795,7 @@ static void kfd_mem_detach(struct kfd_mem_attachment *attachment) pr_debug("\t remove VA 0x%llx in entry %p\n", attachment->va, attachment); - amdgpu_vm_bo_rmv(attachment->adev, attachment->bo_va); + amdgpu_vm_bo_del(attachment->adev, attachment->bo_va); drm_gem_object_put(&bo->tbo.base); list_del(&attachment->list); kfree(attachment); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c index da21e60bb827..c6d4d41c4393 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_csa.c @@ -98,7 +98,7 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (r) { DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r); - amdgpu_vm_bo_rmv(adev, *bo_va); + amdgpu_vm_bo_del(adev, *bo_va); ttm_eu_backoff_reservation(&ticket, &list); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index c0d8f40a5b45..bab6500728cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -222,7 +222,7 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj, if (!bo_va || --bo_va->ref_count) goto out_unlock; - amdgpu_vm_bo_rmv(adev, bo_va); + amdgpu_vm_bo_del(adev, bo_va); if (!amdgpu_vm_ready(vm)) goto out_unlock; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c2cb345b1421..d1970f37bc88 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1188,12 +1188,12 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL) amdgpu_vce_free_handles(adev, file_priv); - amdgpu_vm_bo_rmv(adev, fpriv->prt_va); + amdgpu_vm_bo_del(adev, fpriv->prt_va); if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { /* TODO: how to handle reserve failure */ BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true)); - amdgpu_vm_bo_rmv(adev, fpriv->csa_va); + amdgpu_vm_bo_del(adev, fpriv->csa_va); fpriv->csa_va = NULL; amdgpu_bo_unreserve(adev->virt.csa_obj); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 5a67ac0b6b7a..e0a2f5211b73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2637,7 +2637,7 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket) } /** - * amdgpu_vm_bo_rmv - remove a bo to a specific vm + * amdgpu_vm_bo_del - remove a bo from a specific vm * * @adev: amdgpu_device pointer * @bo_va: requested bo_va @@ -2646,7 +2646,7 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket) * * Object have to be reserved! */ -void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, +void amdgpu_vm_bo_del(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va) { struct amdgpu_bo_va_mapping *mapping, *next; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 85fcfb8c5efd..a40a6a993bb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -435,7 +435,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *amdgpu_vm_bo_lookup_mapping(struct amdgpu_vm *vm, uint64_t addr); void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket); -void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, +void amdgpu_vm_bo_del(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va); void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, uint32_t fragment_size_default, unsigned max_level, From afa37315917bbc9e71a4359f921eb887470c008c Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 17:05:12 -0500 Subject: [PATCH 247/339] drm/amdgpu: Print once if RAS unsupported MESA polls for errors every 2-3 seconds. Printing with dev_info() causes the dmesg log to fill up with the same message, e.g, [18028.206676] amdgpu 0000:0b:00.0: amdgpu: df doesn't config ras function. Make it dev_dbg_once(), as it isn't something correctible during boot or thereafter, so printing just once is sufficient. Also sanitize the message. Cc: Alex Deucher Cc: Hawking Zhang Cc: John Clements Cc: Tao Zhou Cc: yipechai Fixes: 8b0fb0e967c1 ("drm/amdgpu: Modify gfx block to fit for the unified ras block data and ops") Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 9d7c778c1a2d..e440a5268ace 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -952,8 +952,8 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, } else { block_obj = amdgpu_ras_get_ras_block(adev, info->head.block, 0); if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function.\n", - get_ras_block_str(&info->head)); + dev_dbg_once(adev->dev, "%s doesn't config RAS function\n", + get_ras_block_str(&info->head)); return -EINVAL; } @@ -1028,8 +1028,8 @@ int amdgpu_ras_reset_error_status(struct amdgpu_device *adev, return -EINVAL; if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function.\n", - ras_block_str(block)); + dev_dbg_once(adev->dev, "%s doesn't config RAS function\n", + ras_block_str(block)); return -EINVAL; } @@ -1066,8 +1066,8 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, return -EINVAL; if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function.\n", - get_ras_block_str(&info->head)); + dev_dbg_once(adev->dev, "%s doesn't config RAS function\n", + get_ras_block_str(&info->head)); return -EINVAL; } @@ -1717,8 +1717,8 @@ static void amdgpu_ras_error_status_query(struct amdgpu_device *adev, info->head.sub_block_index); if (!block_obj || !block_obj->hw_ops) { - dev_info(adev->dev, "%s doesn't config ras function.\n", - get_ras_block_str(&info->head)); + dev_dbg_once(adev->dev, "%s doesn't config RAS function\n", + get_ras_block_str(&info->head)); return; } From 3698807094ecae945436921325f5c309d1123f11 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 24 Aug 2021 16:13:41 -0400 Subject: [PATCH 248/339] drm/amdkfd: CRIU Introduce Checkpoint-Restore APIs Checkpoint-Restore in userspace (CRIU) is a powerful tool that can snapshot a running process and later restore it on same or a remote machine but expects the processes that have a device file (e.g. GPU) associated with them, provide necessary driver support to assist CRIU and its extensible plugin interface. Thus, In order to support the Checkpoint-Restore of any ROCm process, the AMD Radeon Open Compute Kernel driver, needs to provide a set of new APIs that provide necessary VRAM metadata and its contents to a userspace component (CRIU plugin) that can store it in form of image files. This introduces some new ioctls which will be used to checkpoint-Restore any KFD bound user process. KFD only allows ioctl calls from the same process that opened the KFD file descriptor. Since these ioctls are expected to be called from a KFD criu plugin which has elevated ptrace attached privileges and CAP_CHECKPOINT_RESTORE capabilities attached with the file descriptors so modify KFD to allow such calls. (API redesigned by David Yat Sin) Suggested-by: Felix Kuehling Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 98 +++++++++++++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 65 +++++++++++++++- include/uapi/linux/kfd_ioctl.h | 81 +++++++++++++++++++- 3 files changed, 241 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 214a2c67fba4..90e6d9e335a5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include "kfd_priv.h" @@ -1859,6 +1860,75 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) } #endif +static int criu_checkpoint(struct file *filep, + struct kfd_process *p, + struct kfd_ioctl_criu_args *args) +{ + return 0; +} + +static int criu_restore(struct file *filep, + struct kfd_process *p, + struct kfd_ioctl_criu_args *args) +{ + return 0; +} + +static int criu_unpause(struct file *filep, + struct kfd_process *p, + struct kfd_ioctl_criu_args *args) +{ + return 0; +} + +static int criu_resume(struct file *filep, + struct kfd_process *p, + struct kfd_ioctl_criu_args *args) +{ + return 0; +} + +static int criu_process_info(struct file *filep, + struct kfd_process *p, + struct kfd_ioctl_criu_args *args) +{ + return 0; +} + +static int kfd_ioctl_criu(struct file *filep, struct kfd_process *p, void *data) +{ + struct kfd_ioctl_criu_args *args = data; + int ret; + + dev_dbg(kfd_device, "CRIU operation: %d\n", args->op); + switch (args->op) { + case KFD_CRIU_OP_PROCESS_INFO: + ret = criu_process_info(filep, p, args); + break; + case KFD_CRIU_OP_CHECKPOINT: + ret = criu_checkpoint(filep, p, args); + break; + case KFD_CRIU_OP_UNPAUSE: + ret = criu_unpause(filep, p, args); + break; + case KFD_CRIU_OP_RESTORE: + ret = criu_restore(filep, p, args); + break; + case KFD_CRIU_OP_RESUME: + ret = criu_resume(filep, p, args); + break; + default: + dev_dbg(kfd_device, "Unsupported CRIU operation:%d\n", args->op); + ret = -EINVAL; + break; + } + + if (ret) + dev_dbg(kfd_device, "CRIU operation:%d err:%d\n", args->op, ret); + + return ret; +} + #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ .cmd_drv = 0, .name = #ioctl} @@ -1962,6 +2032,10 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_XNACK_MODE, kfd_ioctl_set_xnack_mode, 0), + + AMDKFD_IOCTL_DEF(AMDKFD_IOC_CRIU_OP, + kfd_ioctl_criu, KFD_IOC_FLAG_CHECKPOINT_RESTORE), + }; #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) @@ -1976,6 +2050,7 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) char *kdata = NULL; unsigned int usize, asize; int retcode = -EINVAL; + bool ptrace_attached = false; if (nr >= AMDKFD_CORE_IOCTL_COUNT) goto err_i1; @@ -2001,7 +2076,15 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) * processes need to create their own KFD device context. */ process = filep->private_data; - if (process->lead_thread != current->group_leader) { + + rcu_read_lock(); + if ((ioctl->flags & KFD_IOC_FLAG_CHECKPOINT_RESTORE) && + ptrace_parent(process->lead_thread) == current) + ptrace_attached = true; + rcu_read_unlock(); + + if (process->lead_thread != current->group_leader + && !ptrace_attached) { dev_dbg(kfd_device, "Using KFD FD in wrong process\n"); retcode = -EBADF; goto err_i1; @@ -2016,6 +2099,19 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) goto err_i1; } + /* + * Versions of docker shipped in Ubuntu 18.xx and 20.xx do not support + * CAP_CHECKPOINT_RESTORE, so we also allow access if CAP_SYS_ADMIN as CAP_SYS_ADMIN is a + * more priviledged access. + */ + if (unlikely(ioctl->flags & KFD_IOC_FLAG_CHECKPOINT_RESTORE)) { + if (!capable(CAP_CHECKPOINT_RESTORE) && + !capable(CAP_SYS_ADMIN)) { + retcode = -EACCES; + goto err_i1; + } + } + if (cmd & (IOC_IN | IOC_OUT)) { if (asize <= sizeof(stack_kdata)) { kdata = stack_kdata; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index ea68f3b3a4e9..f928878196ef 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -121,7 +121,26 @@ */ #define KFD_QUEUE_DOORBELL_MIRROR_OFFSET 512 - +/** + * enum kfd_ioctl_flags - KFD ioctl flags + * Various flags that can be set in &amdkfd_ioctl_desc.flags to control how + * userspace can use a given ioctl. + */ +enum kfd_ioctl_flags { + /* + * @KFD_IOC_FLAG_CHECKPOINT_RESTORE: + * Certain KFD ioctls such as AMDKFD_IOC_CRIU_OP can potentially + * perform privileged operations and load arbitrary data into MQDs and + * eventually HQD registers when the queue is mapped by HWS. In order to + * prevent this we should perform additional security checks. + * + * This is equivalent to callers with the CHECKPOINT_RESTORE capability. + * + * Note: Since earlier versions of docker do not support CHECKPOINT_RESTORE, + * we also allow ioctls with SYS_ADMIN capability. + */ + KFD_IOC_FLAG_CHECKPOINT_RESTORE = BIT(0), +}; /* * Kernel module parameter to specify maximum number of supported queues per * device @@ -1006,6 +1025,50 @@ void kfd_process_set_trap_handler(struct qcm_process_device *qpd, uint64_t tba_addr, uint64_t tma_addr); +/* CRIU */ +/* + * Need to increment KFD_CRIU_PRIV_VERSION each time a change is made to any of the CRIU private + * structures: + * kfd_criu_process_priv_data + * kfd_criu_device_priv_data + * kfd_criu_bo_priv_data + * kfd_criu_queue_priv_data + * kfd_criu_event_priv_data + * kfd_criu_svm_range_priv_data + */ + +#define KFD_CRIU_PRIV_VERSION 1 + +struct kfd_criu_process_priv_data { + uint32_t version; +}; + +struct kfd_criu_device_priv_data { + /* For future use */ + uint64_t reserved; +}; + +struct kfd_criu_bo_priv_data { + uint64_t reserved; +}; + +struct kfd_criu_svm_range_priv_data { + uint32_t object_type; + uint32_t reserved; +}; + +struct kfd_criu_queue_priv_data { + uint32_t object_type; + uint32_t reserved; +}; + +struct kfd_criu_event_priv_data { + uint32_t object_type; + uint32_t reserved; +}; + +/* CRIU - End */ + /* Queue Context Management */ int init_queue(struct queue **q, const struct queue_properties *properties); void uninit_queue(struct queue *q); diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index af96af174dc4..49429a6c42fc 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -468,6 +468,82 @@ struct kfd_ioctl_smi_events_args { __u32 anon_fd; /* from KFD */ }; +/************************************************************************************************** + * CRIU IOCTLs (Checkpoint Restore In Userspace) + * + * When checkpointing a process, the userspace application will perform: + * 1. PROCESS_INFO op to determine current process information. This pauses execution and evicts + * all the queues. + * 2. CHECKPOINT op to checkpoint process contents (BOs, queues, events, svm-ranges) + * 3. UNPAUSE op to un-evict all the queues + * + * When restoring a process, the CRIU userspace application will perform: + * + * 1. RESTORE op to restore process contents + * 2. RESUME op to start the process + * + * Note: Queues are forced into an evicted state after a successful PROCESS_INFO. User + * application needs to perform an UNPAUSE operation after calling PROCESS_INFO. + */ + +enum kfd_criu_op { + KFD_CRIU_OP_PROCESS_INFO, + KFD_CRIU_OP_CHECKPOINT, + KFD_CRIU_OP_UNPAUSE, + KFD_CRIU_OP_RESTORE, + KFD_CRIU_OP_RESUME, +}; + +/** + * kfd_ioctl_criu_args - Arguments perform CRIU operation + * @devices: [in/out] User pointer to memory location for devices information. + * This is an array of type kfd_criu_device_bucket. + * @bos: [in/out] User pointer to memory location for BOs information + * This is an array of type kfd_criu_bo_bucket. + * @priv_data: [in/out] User pointer to memory location for private data + * @priv_data_size: [in/out] Size of priv_data in bytes + * @num_devices: [in/out] Number of GPUs used by process. Size of @devices array. + * @num_bos [in/out] Number of BOs used by process. Size of @bos array. + * @num_objects: [in/out] Number of objects used by process. Objects are opaque to + * user application. + * @pid: [in/out] PID of the process being checkpointed + * @op [in] Type of operation (kfd_criu_op) + * + * Return: 0 on success, -errno on failure + */ +struct kfd_ioctl_criu_args { + __u64 devices; /* Used during ops: CHECKPOINT, RESTORE */ + __u64 bos; /* Used during ops: CHECKPOINT, RESTORE */ + __u64 priv_data; /* Used during ops: CHECKPOINT, RESTORE */ + __u64 priv_data_size; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 num_devices; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 num_bos; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 num_objects; /* Used during ops: PROCESS_INFO, RESTORE */ + __u32 pid; /* Used during ops: PROCESS_INFO, RESUME */ + __u32 op; +}; + +struct kfd_criu_device_bucket { + __u32 user_gpu_id; + __u32 actual_gpu_id; + __u32 drm_fd; + __u32 pad; +}; + +struct kfd_criu_bo_bucket { + __u64 addr; + __u64 size; + __u64 offset; + __u64 restored_offset; /* During restore, updated offset for BO */ + __u32 gpu_id; /* This is the user_gpu_id */ + __u32 alloc_flags; + __u32 dmabuf_fd; + __u32 pad; +}; + +/* CRIU IOCTLs - END */ +/**************************************************************************************************/ + /* Register offset inside the remapped mmio page */ enum kfd_mmio_remap { @@ -742,7 +818,10 @@ struct kfd_ioctl_set_xnack_mode_args { #define AMDKFD_IOC_SET_XNACK_MODE \ AMDKFD_IOWR(0x21, struct kfd_ioctl_set_xnack_mode_args) +#define AMDKFD_IOC_CRIU_OP \ + AMDKFD_IOWR(0x22, struct kfd_ioctl_criu_args) + #define AMDKFD_COMMAND_START 0x01 -#define AMDKFD_COMMAND_END 0x22 +#define AMDKFD_COMMAND_END 0x23 #endif From f185381b64814bb483416e4dd83d85891018a7c5 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 24 Aug 2021 16:14:51 -0400 Subject: [PATCH 249/339] drm/amdkfd: CRIU Implement KFD process_info ioctl This IOCTL op is expected to be called as a precursor to the actual Checkpoint operation. This does the basic discovery into the target process seized by CRIU and relays the information to the userspace that utilizes it to start the Checkpoint operation via another dedicated IOCTL op. The process_info IOCTL op determines the number of GPUs, buffer objects that are associated with the target process, its process id in caller's namespace since /proc/pid/mem interface maybe used to drain the contents of the discovered buffer objects in userspace and getpid returns the pid of CRIU dumper process. Also the pid of a process inside a container might be different than its global pid so return the ns pid. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: David Yat Sin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 56 +++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 90e6d9e335a5..29443419bbf0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1860,6 +1860,42 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) } #endif +uint32_t get_process_num_bos(struct kfd_process *p) +{ + uint32_t num_of_bos = 0; + int i; + + /* Run over all PDDs of the process */ + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; + void *mem; + int id; + + idr_for_each_entry(&pdd->alloc_idr, mem, id) { + struct kgd_mem *kgd_mem = (struct kgd_mem *)mem; + + if ((uint64_t)kgd_mem->va > pdd->gpuvm_base) + num_of_bos++; + } + } + return num_of_bos; +} + +static void criu_get_process_object_info(struct kfd_process *p, + uint32_t *num_bos, + uint64_t *objs_priv_size) +{ + uint64_t priv_size; + + *num_bos = get_process_num_bos(p); + + if (objs_priv_size) { + priv_size = sizeof(struct kfd_criu_process_priv_data); + priv_size += *num_bos * sizeof(struct kfd_criu_bo_priv_data); + *objs_priv_size = priv_size; + } +} + static int criu_checkpoint(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) @@ -1892,7 +1928,25 @@ static int criu_process_info(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) { - return 0; + int ret = 0; + + mutex_lock(&p->mutex); + + if (!p->n_pdds) { + pr_err("No pdd for given process\n"); + ret = -ENODEV; + goto err_unlock; + } + + args->pid = task_pid_nr_ns(p->lead_thread, + task_active_pid_ns(p->lead_thread)); + + criu_get_process_object_info(p, &args->num_bos, &args->priv_data_size); + + dev_dbg(kfd_device, "Num of bos:%u\n", args->num_bos); +err_unlock: + mutex_unlock(&p->mutex); + return ret; } static int kfd_ioctl_criu(struct file *filep, struct kfd_process *p, void *data) From 5ccbb057c0a1282b39192a346f963fa989ddbc92 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Mon, 30 Nov 2020 18:26:22 -0500 Subject: [PATCH 250/339] drm/amdkfd: CRIU Implement KFD checkpoint ioctl This adds support to discover the buffer objects that belong to a process being checkpointed. The data corresponding to these buffer objects is returned to user space plugin running under criu master context which then stores this info to recreate these buffer objects during a restore operation. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 11 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 2 + drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 177 +++++++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +- 6 files changed, 213 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index ac841ae8f5cc..395ba9566afe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -297,6 +297,7 @@ int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev, struct tile_config *config); void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset); +bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem); #if IS_ENABLED(CONFIG_HSA_AMD) void amdgpu_amdkfd_gpuvm_init_mem_limits(void); void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5d00a6878ef2..5cf4bedca1d6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -2629,3 +2629,14 @@ int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev, return 0; } + +bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem) +{ + struct kfd_mem_attachment *entry; + + list_for_each_entry(entry, &mem->attachments, list) { + if (entry->is_mapped && entry->adev == adev) + return true; + } + return false; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7cac4a69ba32..41d6f604813d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1136,6 +1136,26 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev, return ttm_pool_free(&adev->mman.bdev.pool, ttm); } +/** + * amdgpu_ttm_tt_get_userptr - Return the userptr GTT ttm_tt for the current + * task + * + * @tbo: The ttm_buffer_object that contains the userptr + * @user_addr: The returned value + */ +int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo, + uint64_t *user_addr) +{ + struct amdgpu_ttm_tt *gtt; + + if (!tbo->ttm) + return -EINVAL; + + gtt = (void *)tbo->ttm; + *user_addr = gtt->userptr; + return 0; +} + /** * amdgpu_ttm_tt_set_userptr - Initialize userptr GTT ttm_tt for the current * task diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 0efc31e3a457..0e4ecc77db3f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -181,6 +181,8 @@ static inline bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm) #endif void amdgpu_ttm_tt_set_user_pages(struct ttm_tt *ttm, struct page **pages); +int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo, + uint64_t *user_addr); int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo, uint64_t addr, uint32_t flags); bool amdgpu_ttm_tt_has_userptr(struct ttm_tt *ttm); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 29443419bbf0..17a937b7139f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1860,6 +1860,29 @@ static int kfd_ioctl_svm(struct file *filep, struct kfd_process *p, void *data) } #endif +static int criu_checkpoint_process(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_offset) +{ + struct kfd_criu_process_priv_data process_priv; + int ret; + + memset(&process_priv, 0, sizeof(process_priv)); + + process_priv.version = KFD_CRIU_PRIV_VERSION; + + ret = copy_to_user(user_priv_data + *priv_offset, + &process_priv, sizeof(process_priv)); + + if (ret) { + pr_err("Failed to copy process information to user\n"); + ret = -EFAULT; + } + + *priv_offset += sizeof(process_priv); + return ret; +} + uint32_t get_process_num_bos(struct kfd_process *p) { uint32_t num_of_bos = 0; @@ -1881,6 +1904,117 @@ uint32_t get_process_num_bos(struct kfd_process *p) return num_of_bos; } +static int criu_checkpoint_bos(struct kfd_process *p, + uint32_t num_bos, + uint8_t __user *user_bos, + uint8_t __user *user_priv_data, + uint64_t *priv_offset) +{ + struct kfd_criu_bo_bucket *bo_buckets; + struct kfd_criu_bo_priv_data *bo_privs; + int ret = 0, pdd_index, bo_index = 0, id; + void *mem; + + bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), GFP_KERNEL); + if (!bo_buckets) { + ret = -ENOMEM; + goto exit; + } + + bo_privs = kvzalloc(num_bos * sizeof(*bo_privs), GFP_KERNEL); + if (!bo_privs) { + ret = -ENOMEM; + goto exit; + } + + for (pdd_index = 0; pdd_index < p->n_pdds; pdd_index++) { + struct kfd_process_device *pdd = p->pdds[pdd_index]; + struct amdgpu_bo *dumper_bo; + struct kgd_mem *kgd_mem; + + idr_for_each_entry(&pdd->alloc_idr, mem, id) { + struct kfd_criu_bo_bucket *bo_bucket; + struct kfd_criu_bo_priv_data *bo_priv; + int i, dev_idx = 0; + + if (!mem) { + ret = -ENOMEM; + goto exit; + } + + kgd_mem = (struct kgd_mem *)mem; + dumper_bo = kgd_mem->bo; + + if ((uint64_t)kgd_mem->va <= pdd->gpuvm_base) + continue; + + bo_bucket = &bo_buckets[bo_index]; + bo_priv = &bo_privs[bo_index]; + + bo_bucket->addr = (uint64_t)kgd_mem->va; + bo_bucket->size = amdgpu_bo_size(dumper_bo); + bo_bucket->gpu_id = pdd->dev->id; + bo_bucket->alloc_flags = (uint32_t)kgd_mem->alloc_flags; + bo_priv->idr_handle = id; + + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { + ret = amdgpu_ttm_tt_get_userptr(&dumper_bo->tbo, + &bo_priv->user_addr); + if (ret) { + pr_err("Failed to obtain user address for user-pointer bo\n"); + goto exit; + } + } + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) + bo_bucket->offset = KFD_MMAP_TYPE_DOORBELL | + KFD_MMAP_GPU_ID(pdd->dev->id); + else if (bo_bucket->alloc_flags & + KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) + bo_bucket->offset = KFD_MMAP_TYPE_MMIO | + KFD_MMAP_GPU_ID(pdd->dev->id); + else + bo_bucket->offset = amdgpu_bo_mmap_offset(dumper_bo); + + for (i = 0; i < p->n_pdds; i++) { + if (amdgpu_amdkfd_bo_mapped_to_dev(p->pdds[i]->dev->adev, kgd_mem)) + bo_priv->mapped_gpuids[dev_idx++] = p->pdds[i]->dev->id; + } + + pr_debug("bo_size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n" + "gpu_id = 0x%x alloc_flags = 0x%x idr_handle = 0x%x", + bo_bucket->size, + bo_bucket->addr, + bo_bucket->offset, + bo_bucket->gpu_id, + bo_bucket->alloc_flags, + bo_priv->idr_handle); + bo_index++; + } + } + + ret = copy_to_user(user_bos, bo_buckets, num_bos * sizeof(*bo_buckets)); + if (ret) { + pr_err("Failed to copy BO information to user\n"); + ret = -EFAULT; + goto exit; + } + + ret = copy_to_user(user_priv_data + *priv_offset, bo_privs, num_bos * sizeof(*bo_privs)); + if (ret) { + pr_err("Failed to copy BO priv information to user\n"); + ret = -EFAULT; + goto exit; + } + + *priv_offset += num_bos * sizeof(*bo_privs); + +exit: + + kvfree(bo_buckets); + kvfree(bo_privs); + return ret; +} + static void criu_get_process_object_info(struct kfd_process *p, uint32_t *num_bos, uint64_t *objs_priv_size) @@ -1900,7 +2034,48 @@ static int criu_checkpoint(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) { - return 0; + int ret; + uint32_t num_bos; + uint64_t priv_size, priv_offset = 0; + + if (!args->bos || !args->priv_data) + return -EINVAL; + + mutex_lock(&p->mutex); + + if (!p->n_pdds) { + pr_err("No pdd for given process\n"); + ret = -ENODEV; + goto exit_unlock; + } + + criu_get_process_object_info(p, &num_bos, &priv_size); + + if (num_bos != args->num_bos || + priv_size != args->priv_data_size) { + + ret = -EINVAL; + goto exit_unlock; + } + + /* each function will store private data inside priv_data and adjust priv_offset */ + ret = criu_checkpoint_process(p, (uint8_t __user *)args->priv_data, &priv_offset); + if (ret) + goto exit_unlock; + + ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, + (uint8_t __user *)args->priv_data, &priv_offset); + if (ret) + goto exit_unlock; + +exit_unlock: + mutex_unlock(&p->mutex); + if (ret) + pr_err("Failed to dump CRIU ret:%d\n", ret); + else + pr_debug("CRIU dump ret:%d\n", ret); + + return ret; } static int criu_restore(struct file *filep, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f928878196ef..a4d08b6b2e6b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1049,7 +1049,9 @@ struct kfd_criu_device_priv_data { }; struct kfd_criu_bo_priv_data { - uint64_t reserved; + uint64_t user_addr; + uint32_t idr_handle; + uint32_t mapped_gpuids[MAX_GPU_INSTANCE]; }; struct kfd_criu_svm_range_priv_data { From 73fa13b6a5112b59d09e58b8075973769a15814c Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 1 Dec 2020 12:36:46 -0500 Subject: [PATCH 251/339] drm/amdkfd: CRIU Implement KFD restore ioctl This implements the KFD CRIU Restore ioctl that lays the basic foundation for the CRIU restore operation. It provides support to create the buffer objects corresponding to the checkpointed image. This ioctl creates various types of buffer objects such as VRAM, MMIO, Doorbell, GTT based on the date sent from the userspace plugin. The data mostly contains the previously checkpointed KFD images from some KFD processs. While restoring a criu process, attach old IDR values to newly created BOs. This also adds the minimal gpu mapping support for a single gpu checkpoint restore use case. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 298 ++++++++++++++++++++++- 1 file changed, 297 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 17a937b7139f..342fc56b1940 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2078,11 +2078,307 @@ exit_unlock: return ret; } +static int criu_restore_process(struct kfd_process *p, + struct kfd_ioctl_criu_args *args, + uint64_t *priv_offset, + uint64_t max_priv_data_size) +{ + int ret = 0; + struct kfd_criu_process_priv_data process_priv; + + if (*priv_offset + sizeof(process_priv) > max_priv_data_size) + return -EINVAL; + + ret = copy_from_user(&process_priv, + (void __user *)(args->priv_data + *priv_offset), + sizeof(process_priv)); + if (ret) { + pr_err("Failed to copy process private information from user\n"); + ret = -EFAULT; + goto exit; + } + *priv_offset += sizeof(process_priv); + + if (process_priv.version != KFD_CRIU_PRIV_VERSION) { + pr_err("Invalid CRIU API version (checkpointed:%d current:%d)\n", + process_priv.version, KFD_CRIU_PRIV_VERSION); + return -EINVAL; + } + +exit: + return ret; +} + +static int criu_restore_bos(struct kfd_process *p, + struct kfd_ioctl_criu_args *args, + uint64_t *priv_offset, + uint64_t max_priv_data_size) +{ + struct kfd_criu_bo_bucket *bo_buckets; + struct kfd_criu_bo_priv_data *bo_privs; + bool flush_tlbs = false; + int ret = 0, j = 0; + uint32_t i; + + if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size) + return -EINVAL; + + bo_buckets = kvmalloc_array(args->num_bos, sizeof(*bo_buckets), GFP_KERNEL); + if (!bo_buckets) + return -ENOMEM; + + ret = copy_from_user(bo_buckets, (void __user *)args->bos, + args->num_bos * sizeof(*bo_buckets)); + if (ret) { + pr_err("Failed to copy BOs information from user\n"); + ret = -EFAULT; + goto exit; + } + + bo_privs = kvmalloc_array(args->num_bos, sizeof(*bo_privs), GFP_KERNEL); + if (!bo_privs) { + ret = -ENOMEM; + goto exit; + } + + ret = copy_from_user(bo_privs, (void __user *)args->priv_data + *priv_offset, + args->num_bos * sizeof(*bo_privs)); + if (ret) { + pr_err("Failed to copy BOs information from user\n"); + ret = -EFAULT; + goto exit; + } + *priv_offset += args->num_bos * sizeof(*bo_privs); + + /* Create and map new BOs */ + for (i = 0; i < args->num_bos; i++) { + struct kfd_criu_bo_bucket *bo_bucket; + struct kfd_criu_bo_priv_data *bo_priv; + struct kfd_dev *dev; + struct kfd_process_device *pdd; + void *mem; + u64 offset; + int idr_handle; + + bo_bucket = &bo_buckets[i]; + bo_priv = &bo_privs[i]; + + dev = kfd_device_by_id(bo_bucket->gpu_id); + if (!dev) { + ret = -EINVAL; + pr_err("Failed to get pdd\n"); + goto exit; + } + pdd = kfd_get_process_device_data(dev, p); + if (!pdd) { + ret = -EINVAL; + pr_err("Failed to get pdd\n"); + goto exit; + } + + pr_debug("kfd restore ioctl - bo_bucket[%d]:\n", i); + pr_debug("size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n" + "gpu_id = 0x%x alloc_flags = 0x%x\n" + "idr_handle = 0x%x\n", + bo_bucket->size, + bo_bucket->addr, + bo_bucket->offset, + bo_bucket->gpu_id, + bo_bucket->alloc_flags, + bo_priv->idr_handle); + + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { + pr_debug("restore ioctl: KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL\n"); + if (bo_bucket->size != kfd_doorbell_process_slice(dev)) { + ret = -EINVAL; + goto exit; + } + offset = kfd_get_process_doorbells(pdd); + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { + /* MMIO BOs need remapped bus address */ + pr_debug("restore ioctl :KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP\n"); + if (bo_bucket->size != PAGE_SIZE) { + pr_err("Invalid page size\n"); + ret = -EINVAL; + goto exit; + } + offset = dev->adev->rmmio_remap.bus_addr; + if (!offset) { + pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n"); + ret = -ENOMEM; + goto exit; + } + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { + offset = bo_priv->user_addr; + } + + /* Create the BO */ + ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(dev->adev, + bo_bucket->addr, + bo_bucket->size, + pdd->drm_priv, + (struct kgd_mem **) &mem, + &offset, + bo_bucket->alloc_flags); + if (ret) { + pr_err("Could not create the BO\n"); + ret = -ENOMEM; + goto exit; + } + pr_debug("New BO created: size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n", + bo_bucket->size, bo_bucket->addr, offset); + + /* Restore previuos IDR handle */ + pr_debug("Restoring old IDR handle for the BO"); + idr_handle = idr_alloc(&pdd->alloc_idr, mem, + bo_priv->idr_handle, + bo_priv->idr_handle + 1, GFP_KERNEL); + + if (idr_handle < 0) { + pr_err("Could not allocate idr\n"); + amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, + (struct kgd_mem *)mem, + pdd->drm_priv, NULL); + + ret = -ENOMEM; + goto exit; + } + + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) + bo_bucket->restored_offset = KFD_MMAP_TYPE_DOORBELL | + KFD_MMAP_GPU_ID(pdd->dev->id); + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_MMIO_REMAP) { + bo_bucket->restored_offset = KFD_MMAP_TYPE_MMIO | + KFD_MMAP_GPU_ID(pdd->dev->id); + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) { + bo_bucket->restored_offset = offset; + pr_debug("updating offset for GTT\n"); + } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + bo_bucket->restored_offset = offset; + /* Update the VRAM usage count */ + WRITE_ONCE(pdd->vram_usage, pdd->vram_usage + bo_bucket->size); + pr_debug("updating offset for VRAM\n"); + } + + /* now map these BOs to GPU/s */ + for (j = 0; j < p->n_pdds; j++) { + struct kfd_dev *peer; + struct kfd_process_device *peer_pdd; + bool table_freed = false; + + if (!bo_priv->mapped_gpuids[j]) + break; + + peer = kfd_device_by_id(bo_priv->mapped_gpuids[j]); + if (!peer) { + pr_debug("Getting device by id failed for 0x%x\n", pdd->dev->id); + ret = -EINVAL; + goto exit; + } + + peer_pdd = kfd_bind_process_to_device(peer, p); + if (IS_ERR(peer_pdd)) { + ret = PTR_ERR(peer_pdd); + goto exit; + } + pr_debug("map mem in restore ioctl -> 0x%llx\n", + ((struct kgd_mem *)mem)->va); + ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, + (struct kgd_mem *)mem, peer_pdd->drm_priv, &table_freed); + if (ret) { + pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); + goto exit; + } + if (table_freed) + flush_tlbs = true; + } + + ret = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, + (struct kgd_mem *) mem, true); + if (ret) { + pr_debug("Sync memory failed, wait interrupted by user signal\n"); + goto exit; + } + + pr_debug("map memory was successful for the BO\n"); + } /* done */ + + if (flush_tlbs) { + /* Flush TLBs after waiting for the page table updates to complete */ + for (j = 0; j < p->n_pdds; j++) { + struct kfd_dev *peer; + struct kfd_process_device *pdd = p->pdds[j]; + struct kfd_process_device *peer_pdd; + + peer = kfd_device_by_id(pdd->dev->id); + if (WARN_ON_ONCE(!peer)) + continue; + peer_pdd = kfd_get_process_device_data(peer, p); + if (WARN_ON_ONCE(!peer_pdd)) + continue; + kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); + } + } + + /* Copy only the buckets back so user can read bo_buckets[N].restored_offset */ + ret = copy_to_user((void __user *)args->bos, + bo_buckets, + (args->num_bos * sizeof(*bo_buckets))); + if (ret) + ret = -EFAULT; + +exit: + kvfree(bo_buckets); + kvfree(bo_privs); + return ret; +} + static int criu_restore(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) { - return 0; + uint64_t priv_offset = 0; + int ret = 0; + + pr_debug("CRIU restore (num_devices:%u num_bos:%u num_objects:%u priv_data_size:%llu)\n", + args->num_devices, args->num_bos, args->num_objects, args->priv_data_size); + + if (!args->bos || !args->devices || !args->priv_data || !args->priv_data_size || + !args->num_devices || !args->num_bos) + return -EINVAL; + + mutex_lock(&p->mutex); + + /* + * Set the process to evicted state to avoid running any new queues before all the memory + * mappings are ready. + */ + ret = kfd_process_evict_queues(p); + if (ret) + goto exit_unlock; + + /* Each function will adjust priv_offset based on how many bytes they consumed */ + ret = criu_restore_process(p, args, &priv_offset, args->priv_data_size); + if (ret) + goto exit_unlock; + + ret = criu_restore_bos(p, args, &priv_offset, args->priv_data_size); + if (ret) + goto exit_unlock; + + if (priv_offset != args->priv_data_size) { + pr_err("Invalid private data size\n"); + ret = -EINVAL; + } + +exit_unlock: + mutex_unlock(&p->mutex); + if (ret) + pr_err("Failed to restore CRIU ret:%d\n", ret); + else + pr_debug("CRIU restore successful\n"); + + return ret; } static int criu_unpause(struct file *filep, From 011bbb03024f5a22dc04eba370f9296f0cb83502 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Mon, 11 Jan 2021 13:27:50 -0500 Subject: [PATCH 252/339] drm/amdkfd: CRIU Implement KFD resume ioctl This adds support to create userptr BOs on restore and introduces a new ioctl op to restart memory notifiers for the restored userptr BOs. When doing CRIU restore MMU notifications can happen anytime after we call amdgpu_mn_register. Prevent MMU notifications until we reach stage-4 of the restore process i.e. criu_resume ioctl op is received, and the process is ready to be resumed. This ioctl is different from other KFD CRIU ioctls since its called by CRIU master restore process for all the target processes being resumed by CRIU. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 6 ++- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 53 +++++++++++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 41 ++++++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 35 ++++++++++-- 5 files changed, 122 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 395ba9566afe..4cb14c2fe53f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -131,6 +131,7 @@ struct amdkfd_process_info { atomic_t evicted_bos; struct delayed_work restore_userptr_work; struct pid *pid; + bool block_mmu_notifications; }; int amdgpu_amdkfd_init(void); @@ -268,7 +269,7 @@ uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv); int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( struct amdgpu_device *adev, uint64_t va, uint64_t size, void *drm_priv, struct kgd_mem **mem, - uint64_t *offset, uint32_t flags); + uint64_t *offset, uint32_t flags, bool criu_resume); int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv, uint64_t *size); @@ -298,6 +299,9 @@ int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev, void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset); bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem); +void amdgpu_amdkfd_block_mmu_notifications(void *p); +int amdgpu_amdkfd_criu_resume(void *p); + #if IS_ENABLED(CONFIG_HSA_AMD) void amdgpu_amdkfd_gpuvm_init_mem_limits(void); void amdgpu_amdkfd_gpuvm_destroy_cb(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5cf4bedca1d6..2e00c3fb4bd3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -842,7 +842,8 @@ static void remove_kgd_mem_from_kfd_bo_list(struct kgd_mem *mem, * * Returns 0 for success, negative errno for errors. */ -static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr) +static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr, + bool criu_resume) { struct amdkfd_process_info *process_info = mem->process_info; struct amdgpu_bo *bo = mem->bo; @@ -864,6 +865,18 @@ static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr) goto out; } + if (criu_resume) { + /* + * During a CRIU restore operation, the userptr buffer objects + * will be validated in the restore_userptr_work worker at a + * later stage when it is scheduled by another ioctl called by + * CRIU master process for the target pid for restore. + */ + atomic_inc(&mem->invalid); + mutex_unlock(&process_info->lock); + return 0; + } + ret = amdgpu_ttm_tt_get_user_pages(bo, bo->tbo.ttm->pages); if (ret) { pr_err("%s: Failed to get user pages: %d\n", __func__, ret); @@ -1452,10 +1465,39 @@ uint64_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *drm_priv) return avm->pd_phys_addr; } +void amdgpu_amdkfd_block_mmu_notifications(void *p) +{ + struct amdkfd_process_info *pinfo = (struct amdkfd_process_info *)p; + + mutex_lock(&pinfo->lock); + WRITE_ONCE(pinfo->block_mmu_notifications, true); + mutex_unlock(&pinfo->lock); +} + +int amdgpu_amdkfd_criu_resume(void *p) +{ + int ret = 0; + struct amdkfd_process_info *pinfo = (struct amdkfd_process_info *)p; + + mutex_lock(&pinfo->lock); + pr_debug("scheduling work\n"); + atomic_inc(&pinfo->evicted_bos); + if (!READ_ONCE(pinfo->block_mmu_notifications)) { + ret = -EINVAL; + goto out_unlock; + } + WRITE_ONCE(pinfo->block_mmu_notifications, false); + schedule_delayed_work(&pinfo->restore_userptr_work, 0); + +out_unlock: + mutex_unlock(&pinfo->lock); + return ret; +} + int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( struct amdgpu_device *adev, uint64_t va, uint64_t size, void *drm_priv, struct kgd_mem **mem, - uint64_t *offset, uint32_t flags) + uint64_t *offset, uint32_t flags, bool criu_resume) { struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); enum ttm_bo_type bo_type = ttm_bo_type_device; @@ -1558,7 +1600,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr); if (user_addr) { - ret = init_user_pages(*mem, user_addr); + pr_debug("creating userptr BO for user_addr = %llu\n", user_addr); + ret = init_user_pages(*mem, user_addr, criu_resume); if (ret) goto allocate_init_user_pages_failed; } else if (flags & (KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL | @@ -2062,6 +2105,10 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, int evicted_bos; int r = 0; + /* Do not process MMU notifications until stage-4 IOCTL is received */ + if (READ_ONCE(process_info->block_mmu_notifications)) + return 0; + atomic_inc(&mem->invalid); evicted_bos = atomic_inc_return(&process_info->evicted_bos); if (evicted_bos == 1) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 342fc56b1940..95fc5668195c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1324,7 +1324,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( dev->adev, args->va_addr, args->size, pdd->drm_priv, (struct kgd_mem **) &mem, &offset, - flags); + flags, false); if (err) goto err_unlock; @@ -2116,6 +2116,7 @@ static int criu_restore_bos(struct kfd_process *p, { struct kfd_criu_bo_bucket *bo_buckets; struct kfd_criu_bo_priv_data *bo_privs; + const bool criu_resume = true; bool flush_tlbs = false; int ret = 0, j = 0; uint32_t i; @@ -2123,6 +2124,9 @@ static int criu_restore_bos(struct kfd_process *p, if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size) return -EINVAL; + /* Prevent MMU notifications until stage-4 IOCTL (CRIU_RESUME) is received */ + amdgpu_amdkfd_block_mmu_notifications(p->kgd_process_info); + bo_buckets = kvmalloc_array(args->num_bos, sizeof(*bo_buckets), GFP_KERNEL); if (!bo_buckets) return -ENOMEM; @@ -2211,7 +2215,6 @@ static int criu_restore_bos(struct kfd_process *p, } else if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_USERPTR) { offset = bo_priv->user_addr; } - /* Create the BO */ ret = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(dev->adev, bo_bucket->addr, @@ -2219,7 +2222,8 @@ static int criu_restore_bos(struct kfd_process *p, pdd->drm_priv, (struct kgd_mem **) &mem, &offset, - bo_bucket->alloc_flags); + bo_bucket->alloc_flags, + criu_resume); if (ret) { pr_err("Could not create the BO\n"); ret = -ENOMEM; @@ -2239,7 +2243,6 @@ static int criu_restore_bos(struct kfd_process *p, amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, (struct kgd_mem *)mem, pdd->drm_priv, NULL); - ret = -ENOMEM; goto exit; } @@ -2392,7 +2395,35 @@ static int criu_resume(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) { - return 0; + struct kfd_process *target = NULL; + struct pid *pid = NULL; + int ret = 0; + + pr_debug("Inside %s, target pid for criu restore: %d\n", __func__, + args->pid); + + pid = find_get_pid(args->pid); + if (!pid) { + pr_err("Cannot find pid info for %i\n", args->pid); + return -ESRCH; + } + + pr_debug("calling kfd_lookup_process_by_pid\n"); + target = kfd_lookup_process_by_pid(pid); + + put_pid(pid); + + if (!target) { + pr_debug("Cannot find process info for %i\n", args->pid); + return -ESRCH; + } + + mutex_lock(&target->mutex); + ret = amdgpu_amdkfd_criu_resume(target->kgd_process_info); + mutex_unlock(&target->mutex); + + kfd_unref_process(target); + return ret; } static int criu_process_info(struct file *filep, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a4d08b6b2e6b..9b347247055c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -951,6 +951,7 @@ void *kfd_process_device_translate_handle(struct kfd_process_device *p, int handle); void kfd_process_device_remove_obj_handle(struct kfd_process_device *pdd, int handle); +struct kfd_process *kfd_lookup_process_by_pid(struct pid *pid); /* PASIDs */ int kfd_pasid_init(void); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 74f162887d3b..b3198e186622 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -64,7 +64,8 @@ static struct workqueue_struct *kfd_process_wq; */ static struct workqueue_struct *kfd_restore_wq; -static struct kfd_process *find_process(const struct task_struct *thread); +static struct kfd_process *find_process(const struct task_struct *thread, + bool ref); static void kfd_process_ref_release(struct kref *ref); static struct kfd_process *create_process(const struct task_struct *thread); static int kfd_process_init_cwsr_apu(struct kfd_process *p, struct file *filep); @@ -715,7 +716,8 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd, int err; err = amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(kdev->adev, gpu_va, size, - pdd->drm_priv, mem, NULL, flags); + pdd->drm_priv, mem, NULL, + flags, false); if (err) goto err_alloc_mem; @@ -816,7 +818,7 @@ struct kfd_process *kfd_create_process(struct file *filep) mutex_lock(&kfd_processes_mutex); /* A prior open of /dev/kfd could have already created the process. */ - process = find_process(thread); + process = find_process(thread, false); if (process) { pr_debug("Process already found\n"); } else { @@ -884,7 +886,7 @@ struct kfd_process *kfd_get_process(const struct task_struct *thread) if (thread->group_leader->mm != thread->mm) return ERR_PTR(-EINVAL); - process = find_process(thread); + process = find_process(thread, false); if (!process) return ERR_PTR(-EINVAL); @@ -903,13 +905,16 @@ static struct kfd_process *find_process_by_mm(const struct mm_struct *mm) return NULL; } -static struct kfd_process *find_process(const struct task_struct *thread) +static struct kfd_process *find_process(const struct task_struct *thread, + bool ref) { struct kfd_process *p; int idx; idx = srcu_read_lock(&kfd_processes_srcu); p = find_process_by_mm(thread->mm); + if (p && ref) + kref_get(&p->ref); srcu_read_unlock(&kfd_processes_srcu, idx); return p; @@ -920,6 +925,26 @@ void kfd_unref_process(struct kfd_process *p) kref_put(&p->ref, kfd_process_ref_release); } +/* This increments the process->ref counter. */ +struct kfd_process *kfd_lookup_process_by_pid(struct pid *pid) +{ + struct task_struct *task = NULL; + struct kfd_process *p = NULL; + + if (!pid) { + task = current; + get_task_struct(task); + } else { + task = get_pid_task(pid, PIDTYPE_PID); + } + + if (task) { + p = find_process(task, true); + put_task_struct(task); + } + + return p; +} static void kfd_process_device_free_bos(struct kfd_process_device *pdd) { From cd9f79103003599e58f9f394c07cb4045883a51e Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 16 Aug 2021 10:39:39 -0400 Subject: [PATCH 253/339] drm/amdkfd: CRIU Implement KFD unpause operation Introducing UNPAUSE op. After CRIU amdgpu plugin performs a PROCESS_INFO op the queues will be stay in an evicted state. Once the plugin is done draining BO contents, it is safe to perform an UNPAUSE op for the queues to resume. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 37 +++++++++++++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 ++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 95fc5668195c..6af6deeda523 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2049,6 +2049,14 @@ static int criu_checkpoint(struct file *filep, goto exit_unlock; } + /* Confirm all process queues are evicted */ + if (!p->queues_paused) { + pr_err("Cannot dump process when queues are not in evicted state\n"); + /* CRIU plugin did not call op PROCESS_INFO before checkpointing */ + ret = -EINVAL; + goto exit_unlock; + } + criu_get_process_object_info(p, &num_bos, &priv_size); if (num_bos != args->num_bos || @@ -2388,7 +2396,24 @@ static int criu_unpause(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) { - return 0; + int ret; + + mutex_lock(&p->mutex); + + if (!p->queues_paused) { + mutex_unlock(&p->mutex); + return -EINVAL; + } + + ret = kfd_process_restore_queues(p); + if (ret) + pr_err("Failed to unpause queues ret:%d\n", ret); + else + p->queues_paused = false; + + mutex_unlock(&p->mutex); + + return ret; } static int criu_resume(struct file *filep, @@ -2440,6 +2465,12 @@ static int criu_process_info(struct file *filep, goto err_unlock; } + ret = kfd_process_evict_queues(p); + if (ret) + goto err_unlock; + + p->queues_paused = true; + args->pid = task_pid_nr_ns(p->lead_thread, task_active_pid_ns(p->lead_thread)); @@ -2447,6 +2478,10 @@ static int criu_process_info(struct file *filep, dev_dbg(kfd_device, "Num of bos:%u\n", args->num_bos); err_unlock: + if (ret) { + kfd_process_restore_queues(p); + p->queues_paused = false; + } mutex_unlock(&p->mutex); return ret; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 9b347247055c..677f21447112 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -877,6 +877,8 @@ struct kfd_process { bool xnack_enabled; atomic_t poison; + /* Queues are in paused stated because we are in the process of doing a CRIU checkpoint */ + bool queues_paused; }; #define KFD_PROCESS_TABLE_SIZE 5 /* bits: 32 entries */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index b3198e186622..0649064b8e95 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1384,6 +1384,7 @@ static struct kfd_process *create_process(const struct task_struct *thread) process->mm = thread->mm; process->lead_thread = thread->group_leader; process->n_pdds = 0; + process->queues_paused = false; INIT_DELAYED_WORK(&process->eviction_work, evict_process_worker); INIT_DELAYED_WORK(&process->restore_work, restore_process_worker); process->last_restore_timestamp = get_jiffies_64(); From 626f7b3190b4c07917f0262162cb7fef7272c34d Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 25 Jan 2021 10:13:48 -0500 Subject: [PATCH 254/339] drm/amdkfd: CRIU add queues support Add support to existing CRIU ioctl's to save number of queues and queue properties for each queue during checkpoint and re-create queues on restore. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 110 ++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 43 +++- .../amd/amdkfd/kfd_process_queue_manager.c | 208 ++++++++++++++++++ 3 files changed, 353 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 6af6deeda523..d049f9cbbc79 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2015,19 +2015,36 @@ exit: return ret; } -static void criu_get_process_object_info(struct kfd_process *p, - uint32_t *num_bos, - uint64_t *objs_priv_size) +static int criu_get_process_object_info(struct kfd_process *p, + uint32_t *num_bos, + uint32_t *num_objects, + uint64_t *objs_priv_size) { + int ret; uint64_t priv_size; + uint32_t num_queues, num_events, num_svm_ranges; + uint64_t queues_priv_data_size; *num_bos = get_process_num_bos(p); + ret = kfd_process_get_queue_info(p, &num_queues, &queues_priv_data_size); + if (ret) + return ret; + + num_events = 0; /* TODO: Implement Events */ + num_svm_ranges = 0; /* TODO: Implement SVM-Ranges */ + + *num_objects = num_queues + num_events + num_svm_ranges; + if (objs_priv_size) { priv_size = sizeof(struct kfd_criu_process_priv_data); priv_size += *num_bos * sizeof(struct kfd_criu_bo_priv_data); + priv_size += queues_priv_data_size; + /* TODO: Add Events priv size */ + /* TODO: Add SVM ranges priv size */ *objs_priv_size = priv_size; } + return 0; } static int criu_checkpoint(struct file *filep, @@ -2035,7 +2052,7 @@ static int criu_checkpoint(struct file *filep, struct kfd_ioctl_criu_args *args) { int ret; - uint32_t num_bos; + uint32_t num_bos, num_objects; uint64_t priv_size, priv_offset = 0; if (!args->bos || !args->priv_data) @@ -2057,9 +2074,12 @@ static int criu_checkpoint(struct file *filep, goto exit_unlock; } - criu_get_process_object_info(p, &num_bos, &priv_size); + ret = criu_get_process_object_info(p, &num_bos, &num_objects, &priv_size); + if (ret) + goto exit_unlock; if (num_bos != args->num_bos || + num_objects != args->num_objects || priv_size != args->priv_data_size) { ret = -EINVAL; @@ -2076,6 +2096,17 @@ static int criu_checkpoint(struct file *filep, if (ret) goto exit_unlock; + if (num_objects) { + ret = kfd_criu_checkpoint_queues(p, (uint8_t __user *)args->priv_data, + &priv_offset); + if (ret) + goto exit_unlock; + + /* TODO: Dump Events */ + + /* TODO: Dump SVM-Ranges */ + } + exit_unlock: mutex_unlock(&p->mutex); if (ret) @@ -2344,6 +2375,62 @@ exit: return ret; } +static int criu_restore_objects(struct file *filep, + struct kfd_process *p, + struct kfd_ioctl_criu_args *args, + uint64_t *priv_offset, + uint64_t max_priv_data_size) +{ + int ret = 0; + uint32_t i; + + BUILD_BUG_ON(offsetof(struct kfd_criu_queue_priv_data, object_type)); + BUILD_BUG_ON(offsetof(struct kfd_criu_event_priv_data, object_type)); + BUILD_BUG_ON(offsetof(struct kfd_criu_svm_range_priv_data, object_type)); + + for (i = 0; i < args->num_objects; i++) { + uint32_t object_type; + + if (*priv_offset + sizeof(object_type) > max_priv_data_size) { + pr_err("Invalid private data size\n"); + return -EINVAL; + } + + ret = get_user(object_type, (uint32_t __user *)(args->priv_data + *priv_offset)); + if (ret) { + pr_err("Failed to copy private information from user\n"); + goto exit; + } + + switch (object_type) { + case KFD_CRIU_OBJECT_TYPE_QUEUE: + ret = kfd_criu_restore_queue(p, (uint8_t __user *)args->priv_data, + priv_offset, max_priv_data_size); + if (ret) + goto exit; + break; + case KFD_CRIU_OBJECT_TYPE_EVENT: + /* TODO: Implement Events */ + *priv_offset += sizeof(struct kfd_criu_event_priv_data); + if (ret) + goto exit; + break; + case KFD_CRIU_OBJECT_TYPE_SVM_RANGE: + /* TODO: Implement SVM range */ + *priv_offset += sizeof(struct kfd_criu_svm_range_priv_data); + if (ret) + goto exit; + break; + default: + pr_err("Invalid object type:%u at index:%d\n", object_type, i); + ret = -EINVAL; + goto exit; + } + } +exit: + return ret; +} + static int criu_restore(struct file *filep, struct kfd_process *p, struct kfd_ioctl_criu_args *args) @@ -2377,6 +2464,10 @@ static int criu_restore(struct file *filep, if (ret) goto exit_unlock; + ret = criu_restore_objects(filep, p, args, &priv_offset, args->priv_data_size); + if (ret) + goto exit_unlock; + if (priv_offset != args->priv_data_size) { pr_err("Invalid private data size\n"); ret = -EINVAL; @@ -2474,9 +2565,14 @@ static int criu_process_info(struct file *filep, args->pid = task_pid_nr_ns(p->lead_thread, task_active_pid_ns(p->lead_thread)); - criu_get_process_object_info(p, &args->num_bos, &args->priv_data_size); + ret = criu_get_process_object_info(p, &args->num_bos, &args->num_objects, + &args->priv_data_size); + if (ret) + goto err_unlock; + + dev_dbg(kfd_device, "Num of bos:%u objects:%u priv_data_size:%lld\n", + args->num_bos, args->num_objects, args->priv_data_size); - dev_dbg(kfd_device, "Num of bos:%u\n", args->num_bos); err_unlock: if (ret) { kfd_process_restore_queues(p); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 677f21447112..41aa7b150a96 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1057,6 +1057,16 @@ struct kfd_criu_bo_priv_data { uint32_t mapped_gpuids[MAX_GPU_INSTANCE]; }; +/* + * The first 4 bytes of kfd_criu_queue_priv_data, kfd_criu_event_priv_data, + * kfd_criu_svm_range_priv_data is the object type + */ +enum kfd_criu_object_type { + KFD_CRIU_OBJECT_TYPE_QUEUE, + KFD_CRIU_OBJECT_TYPE_EVENT, + KFD_CRIU_OBJECT_TYPE_SVM_RANGE, +}; + struct kfd_criu_svm_range_priv_data { uint32_t object_type; uint32_t reserved; @@ -1064,7 +1074,26 @@ struct kfd_criu_svm_range_priv_data { struct kfd_criu_queue_priv_data { uint32_t object_type; - uint32_t reserved; + uint64_t q_address; + uint64_t q_size; + uint64_t read_ptr_addr; + uint64_t write_ptr_addr; + uint64_t doorbell_off; + uint64_t eop_ring_buffer_address; + uint64_t ctx_save_restore_area_address; + uint32_t gpu_id; + uint32_t type; + uint32_t format; + uint32_t q_id; + uint32_t priority; + uint32_t q_percent; + uint32_t doorbell_id; + uint32_t is_gws; + uint32_t sdma_id; + uint32_t eop_ring_buffer_size; + uint32_t ctx_save_restore_area_size; + uint32_t ctl_stack_size; + uint32_t mqd_size; }; struct kfd_criu_event_priv_data { @@ -1072,6 +1101,18 @@ struct kfd_criu_event_priv_data { uint32_t reserved; }; +int kfd_process_get_queue_info(struct kfd_process *p, + uint32_t *num_queues, + uint64_t *priv_data_sizes); + +int kfd_criu_checkpoint_queues(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset); + +int kfd_criu_restore_queue(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size); /* CRIU - End */ /* Queue Context Management */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 5e5c84a8e1ef..38d3217f0f67 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -497,6 +497,214 @@ int pqm_get_wave_state(struct process_queue_manager *pqm, save_area_used_size); } +int kfd_process_get_queue_info(struct kfd_process *p, + uint32_t *num_queues, + uint64_t *priv_data_sizes) +{ + struct queue *q; + int i; + + *num_queues = 0; + + /* Run over all PDDs of the process */ + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; + + list_for_each_entry(q, &pdd->qpd.queues_list, list) { + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || + q->properties.type == KFD_QUEUE_TYPE_SDMA || + q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { + + *num_queues = *num_queues + 1; + } else { + pr_err("Unsupported queue type (%d)\n", q->properties.type); + return -EOPNOTSUPP; + } + } + } + *priv_data_sizes = *num_queues * sizeof(struct kfd_criu_queue_priv_data); + + return 0; +} + +static void criu_dump_queue(struct kfd_process_device *pdd, + struct queue *q, + struct kfd_criu_queue_priv_data *q_data) +{ + q_data->gpu_id = pdd->dev->id; + q_data->type = q->properties.type; + q_data->format = q->properties.format; + q_data->q_id = q->properties.queue_id; + q_data->q_address = q->properties.queue_address; + q_data->q_size = q->properties.queue_size; + q_data->priority = q->properties.priority; + q_data->q_percent = q->properties.queue_percent; + q_data->read_ptr_addr = (uint64_t)q->properties.read_ptr; + q_data->write_ptr_addr = (uint64_t)q->properties.write_ptr; + q_data->doorbell_id = q->doorbell_id; + + q_data->sdma_id = q->sdma_id; + + q_data->eop_ring_buffer_address = + q->properties.eop_ring_buffer_address; + + q_data->eop_ring_buffer_size = q->properties.eop_ring_buffer_size; + + q_data->ctx_save_restore_area_address = + q->properties.ctx_save_restore_area_address; + + q_data->ctx_save_restore_area_size = + q->properties.ctx_save_restore_area_size; + + pr_debug("Dumping Queue: gpu_id:%x queue_id:%u\n", q_data->gpu_id, q_data->q_id); +} + +static int criu_dump_queues_device(struct kfd_process_device *pdd, + uint8_t __user *user_priv, + unsigned int *q_index, + uint64_t *queues_priv_data_offset) +{ + struct kfd_criu_queue_priv_data *q_data; + struct queue *q; + int ret = 0; + + q_data = kzalloc(sizeof(*q_data), GFP_KERNEL); + if (!q_data) + return -ENOMEM; + + list_for_each_entry(q, &pdd->qpd.queues_list, list) { + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE && + q->properties.type != KFD_QUEUE_TYPE_SDMA && + q->properties.type != KFD_QUEUE_TYPE_SDMA_XGMI) { + + pr_err("Unsupported queue type (%d)\n", q->properties.type); + ret = -EOPNOTSUPP; + break; + } + + criu_dump_queue(pdd, q, q_data); + + ret = copy_to_user(user_priv + *queues_priv_data_offset, q_data, sizeof(*q_data)); + if (ret) { + ret = -EFAULT; + break; + } + *queues_priv_data_offset += sizeof(*q_data); + *q_index = *q_index + 1; + } + + kfree(q_data); + + return ret; +} + +int kfd_criu_checkpoint_queues(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset) +{ + int ret = 0, pdd_index, q_index = 0; + + for (pdd_index = 0; pdd_index < p->n_pdds; pdd_index++) { + struct kfd_process_device *pdd = p->pdds[pdd_index]; + + /* + * criu_dump_queues_device will copy data to user and update q_index and + * queues_priv_data_offset + */ + ret = criu_dump_queues_device(pdd, user_priv_data, &q_index, priv_data_offset); + if (ret) + break; + } + + return ret; +} + +static void set_queue_properties_from_criu(struct queue_properties *qp, + struct kfd_criu_queue_priv_data *q_data) +{ + qp->is_interop = false; + qp->is_gws = q_data->is_gws; + qp->queue_percent = q_data->q_percent; + qp->priority = q_data->priority; + qp->queue_address = q_data->q_address; + qp->queue_size = q_data->q_size; + qp->read_ptr = (uint32_t *) q_data->read_ptr_addr; + qp->write_ptr = (uint32_t *) q_data->write_ptr_addr; + qp->eop_ring_buffer_address = q_data->eop_ring_buffer_address; + qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size; + qp->ctx_save_restore_area_address = q_data->ctx_save_restore_area_address; + qp->ctx_save_restore_area_size = q_data->ctx_save_restore_area_size; + qp->ctl_stack_size = q_data->ctl_stack_size; + qp->type = q_data->type; + qp->format = q_data->format; +} + +int kfd_criu_restore_queue(struct kfd_process *p, + uint8_t __user *user_priv_ptr, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size) +{ + struct kfd_criu_queue_priv_data *q_data; + struct kfd_process_device *pdd; + struct kfd_dev *dev; + struct queue_properties qp; + unsigned int queue_id; + + int ret = 0; + + if (*priv_data_offset + sizeof(*q_data) > max_priv_data_size) + return -EINVAL; + + q_data = kmalloc(sizeof(*q_data), GFP_KERNEL); + if (!q_data) + return -ENOMEM; + + ret = copy_from_user(q_data, user_priv_ptr + *priv_data_offset, sizeof(*q_data)); + if (ret) { + ret = -EFAULT; + goto exit; + } + + *priv_data_offset += sizeof(*q_data); + + dev = kfd_device_by_id(q_data->gpu_id); + if (!dev) { + pr_err("Could not get kfd_dev from gpu_id = 0x%x\n", + q_data->gpu_id); + + ret = -EINVAL; + goto exit; + } + + pdd = kfd_get_process_device_data(dev, p); + if (!pdd) { + pr_err("Failed to get pdd\n"); + ret = -EFAULT; + return ret; + } + + memset(&qp, 0, sizeof(qp)); + set_queue_properties_from_criu(&qp, q_data); + + print_queue_properties(&qp); + + ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, NULL); + if (ret) { + pr_err("Failed to create new queue err:%d\n", ret); + ret = -EINVAL; + } + +exit: + if (ret) + pr_err("Failed to create queue (%d)\n", ret); + else + pr_debug("Queue id %d was restored successfully\n", queue_id); + + kfree(q_data); + + return ret; +} + #if defined(CONFIG_DEBUG_FS) int pqm_debugfs_mqds(struct seq_file *m, void *data) From 8668dfc30d3eee695233ce83944abaf5546a5017 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 25 Jan 2021 11:03:31 -0500 Subject: [PATCH 255/339] drm/amdkfd: CRIU restore queue ids When re-creating queues during CRIU restore, restore the queue with the same queue id value used during CRIU dump. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: David Yat Sin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 + .../amd/amdkfd/kfd_process_queue_manager.c | 37 +++++++++++++++---- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index d049f9cbbc79..d35911550792 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -311,7 +311,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, p->pasid, dev->id); - err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, + err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, NULL, &doorbell_offset_in_process); if (err != 0) goto err_create_queue; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c index 1e30717b5253..0c50e67e2b51 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c @@ -185,7 +185,7 @@ static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev) properties.type = KFD_QUEUE_TYPE_DIQ; status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL, - &properties, &qid, NULL); + &properties, &qid, NULL, NULL); if (status) { pr_err("Failed to create DIQ\n"); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 41aa7b150a96..59125d8f16a7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -461,6 +461,7 @@ enum KFD_QUEUE_PRIORITY { * it's user mode or kernel mode queue. * */ + struct queue_properties { enum kfd_queue_type type; enum kfd_queue_format format; @@ -1156,6 +1157,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, struct file *f, struct queue_properties *properties, unsigned int *qid, + const struct kfd_criu_queue_priv_data *q_data, uint32_t *p_doorbell_offset_in_process); int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid); int pqm_update_queue_properties(struct process_queue_manager *pqm, unsigned int qid, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 38d3217f0f67..75bad4381421 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -42,6 +42,20 @@ static inline struct process_queue_node *get_queue_by_qid( return NULL; } +static int assign_queue_slot_by_qid(struct process_queue_manager *pqm, + unsigned int qid) +{ + if (qid >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) + return -EINVAL; + + if (__test_and_set_bit(qid, pqm->queue_slot_bitmap)) { + pr_err("Cannot create new queue because requested qid(%u) is in use\n", qid); + return -ENOSPC; + } + + return 0; +} + static int find_available_queue_slot(struct process_queue_manager *pqm, unsigned int *qid) { @@ -193,6 +207,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, struct file *f, struct queue_properties *properties, unsigned int *qid, + const struct kfd_criu_queue_priv_data *q_data, uint32_t *p_doorbell_offset_in_process) { int retval; @@ -224,7 +239,12 @@ int pqm_create_queue(struct process_queue_manager *pqm, if (pdd->qpd.queue_count >= max_queues) return -ENOSPC; - retval = find_available_queue_slot(pqm, qid); + if (q_data) { + retval = assign_queue_slot_by_qid(pqm, q_data->q_id); + *qid = q_data->q_id; + } else + retval = find_available_queue_slot(pqm, qid); + if (retval != 0) return retval; @@ -527,7 +547,7 @@ int kfd_process_get_queue_info(struct kfd_process *p, return 0; } -static void criu_dump_queue(struct kfd_process_device *pdd, +static void criu_checkpoint_queue(struct kfd_process_device *pdd, struct queue *q, struct kfd_criu_queue_priv_data *q_data) { @@ -559,7 +579,7 @@ static void criu_dump_queue(struct kfd_process_device *pdd, pr_debug("Dumping Queue: gpu_id:%x queue_id:%u\n", q_data->gpu_id, q_data->q_id); } -static int criu_dump_queues_device(struct kfd_process_device *pdd, +static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, uint8_t __user *user_priv, unsigned int *q_index, uint64_t *queues_priv_data_offset) @@ -582,7 +602,8 @@ static int criu_dump_queues_device(struct kfd_process_device *pdd, break; } - criu_dump_queue(pdd, q, q_data); + criu_checkpoint_queue(pdd, q, q_data); + q_data->object_type = KFD_CRIU_OBJECT_TYPE_QUEUE; ret = copy_to_user(user_priv + *queues_priv_data_offset, q_data, sizeof(*q_data)); if (ret) { @@ -608,10 +629,12 @@ int kfd_criu_checkpoint_queues(struct kfd_process *p, struct kfd_process_device *pdd = p->pdds[pdd_index]; /* - * criu_dump_queues_device will copy data to user and update q_index and + * criu_checkpoint_queues_device will copy data to user and update q_index and * queues_priv_data_offset */ - ret = criu_dump_queues_device(pdd, user_priv_data, &q_index, priv_data_offset); + ret = criu_checkpoint_queues_device(pdd, user_priv_data, &q_index, + priv_data_offset); + if (ret) break; } @@ -688,7 +711,7 @@ int kfd_criu_restore_queue(struct kfd_process *p, print_queue_properties(&qp); - ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, NULL); + ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, NULL); if (ret) { pr_err("Failed to create new queue err:%d\n", ret); ret = -EINVAL; From 2485c12c980a36bb9e23ababb07d73c4ac6a45af Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 25 Jan 2021 11:29:30 -0500 Subject: [PATCH 256/339] drm/amdkfd: CRIU restore sdma id for queues When re-creating queues during CRIU restore, restore the queue with the same sdma id value used during CRIU dump. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 48 ++++++++++++++----- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 3 +- .../amd/amdkfd/kfd_process_queue_manager.c | 4 +- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 4b6814949aad..15fa2dc6dcba 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -58,7 +58,7 @@ static inline void deallocate_hqd(struct device_queue_manager *dqm, struct queue *q); static int allocate_hqd(struct device_queue_manager *dqm, struct queue *q); static int allocate_sdma_queue(struct device_queue_manager *dqm, - struct queue *q); + struct queue *q, const uint32_t *restore_sdma_id); static void kfd_process_hw_exception(struct work_struct *work); static inline @@ -299,7 +299,8 @@ static void deallocate_vmid(struct device_queue_manager *dqm, static int create_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q, - struct qcm_process_device *qpd) + struct qcm_process_device *qpd, + const struct kfd_criu_queue_priv_data *qd) { struct mqd_manager *mqd_mgr; int retval; @@ -339,7 +340,7 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, q->pipe, q->queue); } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA || q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { - retval = allocate_sdma_queue(dqm, q); + retval = allocate_sdma_queue(dqm, q, qd ? &qd->sdma_id : NULL); if (retval) goto deallocate_vmid; dqm->asic_ops.init_sdma_vm(dqm, q, qpd); @@ -1034,7 +1035,7 @@ static void pre_reset(struct device_queue_manager *dqm) } static int allocate_sdma_queue(struct device_queue_manager *dqm, - struct queue *q) + struct queue *q, const uint32_t *restore_sdma_id) { int bit; @@ -1044,9 +1045,21 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm, return -ENOMEM; } - bit = __ffs64(dqm->sdma_bitmap); - dqm->sdma_bitmap &= ~(1ULL << bit); - q->sdma_id = bit; + if (restore_sdma_id) { + /* Re-use existing sdma_id */ + if (!(dqm->sdma_bitmap & (1ULL << *restore_sdma_id))) { + pr_err("SDMA queue already in use\n"); + return -EBUSY; + } + dqm->sdma_bitmap &= ~(1ULL << *restore_sdma_id); + q->sdma_id = *restore_sdma_id; + } else { + /* Find first available sdma_id */ + bit = __ffs64(dqm->sdma_bitmap); + dqm->sdma_bitmap &= ~(1ULL << bit); + q->sdma_id = bit; + } + q->properties.sdma_engine_id = q->sdma_id % kfd_get_num_sdma_engines(dqm->dev); q->properties.sdma_queue_id = q->sdma_id / @@ -1056,9 +1069,19 @@ static int allocate_sdma_queue(struct device_queue_manager *dqm, pr_err("No more XGMI SDMA queue to allocate\n"); return -ENOMEM; } - bit = __ffs64(dqm->xgmi_sdma_bitmap); - dqm->xgmi_sdma_bitmap &= ~(1ULL << bit); - q->sdma_id = bit; + if (restore_sdma_id) { + /* Re-use existing sdma_id */ + if (!(dqm->xgmi_sdma_bitmap & (1ULL << *restore_sdma_id))) { + pr_err("SDMA queue already in use\n"); + return -EBUSY; + } + dqm->xgmi_sdma_bitmap &= ~(1ULL << *restore_sdma_id); + q->sdma_id = *restore_sdma_id; + } else { + bit = __ffs64(dqm->xgmi_sdma_bitmap); + dqm->xgmi_sdma_bitmap &= ~(1ULL << bit); + q->sdma_id = bit; + } /* sdma_engine_id is sdma id including * both PCIe-optimized SDMAs and XGMI- * optimized SDMAs. The calculation below @@ -1288,7 +1311,8 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, } static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, - struct qcm_process_device *qpd) + struct qcm_process_device *qpd, + const struct kfd_criu_queue_priv_data *qd) { int retval; struct mqd_manager *mqd_mgr; @@ -1303,7 +1327,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, if (q->properties.type == KFD_QUEUE_TYPE_SDMA || q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { dqm_lock(dqm); - retval = allocate_sdma_queue(dqm, q); + retval = allocate_sdma_queue(dqm, q, qd ? &qd->sdma_id : NULL); dqm_unlock(dqm); if (retval) goto out; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index e145e4deb53a..76cc5e2a9733 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -88,7 +88,8 @@ struct device_process_node { struct device_queue_manager_ops { int (*create_queue)(struct device_queue_manager *dqm, struct queue *q, - struct qcm_process_device *qpd); + struct qcm_process_device *qpd, + const struct kfd_criu_queue_priv_data *qd); int (*destroy_queue)(struct device_queue_manager *dqm, struct qcm_process_device *qpd, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 75bad4381421..8afe6879b861 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -272,7 +272,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd); + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data); print_queue(q); break; @@ -292,7 +292,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd); + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data); print_queue(q); break; case KFD_QUEUE_TYPE_DIQ: From 5bb6a8fa75fcfda93592bee0a4910420ceab15f3 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 25 Jan 2021 12:01:19 -0500 Subject: [PATCH 257/339] drm/amdkfd: CRIU restore queue doorbell id When re-creating queues during CRIU restore, restore the queue with the same doorbell id value used during CRIU dump. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 58 +++++++++++++------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 15fa2dc6dcba..13317d2c8959 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -144,7 +144,13 @@ static void decrement_queue_count(struct device_queue_manager *dqm, dqm->active_cp_queue_count--; } -static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) +/* + * Allocate a doorbell ID to this queue. + * If doorbell_id is passed in, make sure requested ID is valid then allocate it. + */ +static int allocate_doorbell(struct qcm_process_device *qpd, + struct queue *q, + uint32_t const *restore_id) { struct kfd_dev *dev = qpd->dqm->dev; @@ -152,6 +158,10 @@ static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) /* On pre-SOC15 chips we need to use the queue ID to * preserve the user mode ABI. */ + + if (restore_id && *restore_id != q->properties.queue_id) + return -EINVAL; + q->doorbell_id = q->properties.queue_id; } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA || q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { @@ -160,25 +170,37 @@ static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) * The doobell index distance between RLC (2*i) and (2*i+1) * for a SDMA engine is 512. */ - uint32_t *idx_offset = - dev->shared_resources.sdma_doorbell_idx; - q->doorbell_id = idx_offset[q->properties.sdma_engine_id] - + (q->properties.sdma_queue_id & 1) - * KFD_QUEUE_DOORBELL_MIRROR_OFFSET - + (q->properties.sdma_queue_id >> 1); + uint32_t *idx_offset = dev->shared_resources.sdma_doorbell_idx; + uint32_t valid_id = idx_offset[q->properties.sdma_engine_id] + + (q->properties.sdma_queue_id & 1) + * KFD_QUEUE_DOORBELL_MIRROR_OFFSET + + (q->properties.sdma_queue_id >> 1); + + if (restore_id && *restore_id != valid_id) + return -EINVAL; + q->doorbell_id = valid_id; } else { - /* For CP queues on SOC15 reserve a free doorbell ID */ - unsigned int found; + /* For CP queues on SOC15 */ + if (restore_id) { + /* make sure that ID is free */ + if (__test_and_set_bit(*restore_id, qpd->doorbell_bitmap)) + return -EINVAL; - found = find_first_zero_bit(qpd->doorbell_bitmap, - KFD_MAX_NUM_OF_QUEUES_PER_PROCESS); - if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) { - pr_debug("No doorbells available"); - return -EBUSY; + q->doorbell_id = *restore_id; + } else { + /* or reserve a free doorbell ID */ + unsigned int found; + + found = find_first_zero_bit(qpd->doorbell_bitmap, + KFD_MAX_NUM_OF_QUEUES_PER_PROCESS); + if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) { + pr_debug("No doorbells available"); + return -EBUSY; + } + set_bit(found, qpd->doorbell_bitmap); + q->doorbell_id = found; } - set_bit(found, qpd->doorbell_bitmap); - q->doorbell_id = found; } q->properties.doorbell_off = @@ -346,7 +368,7 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, dqm->asic_ops.init_sdma_vm(dqm, q, qpd); } - retval = allocate_doorbell(qpd, q); + retval = allocate_doorbell(qpd, q, qd ? &qd->doorbell_id : NULL); if (retval) goto out_deallocate_hqd; @@ -1333,7 +1355,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, goto out; } - retval = allocate_doorbell(qpd, q); + retval = allocate_doorbell(qpd, q, qd ? &qd->doorbell_id : NULL); if (retval) goto out_deallocate_sdma_queue; From 42c6c48214b726c30918e8dc80e2168607d13ae4 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 25 Jan 2021 12:50:14 -0500 Subject: [PATCH 258/339] drm/amdkfd: CRIU checkpoint and restore queue mqds Checkpoint contents of queue MQD's on CRIU dump and restore them during CRIU restore. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c | 2 +- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 73 +++++++- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 12 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h | 7 + .../gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c | 70 ++++++++ .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c | 71 ++++++++ .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 71 ++++++++ .../gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 72 ++++++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 + .../amd/amdkfd/kfd_process_queue_manager.c | 157 ++++++++++++++++-- 11 files changed, 516 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index d35911550792..999672602252 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -311,7 +311,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, p->pasid, dev->id); - err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, NULL, + err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, NULL, NULL, &doorbell_offset_in_process); if (err != 0) goto err_create_queue; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c index 0c50e67e2b51..3a5303ebcabf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c @@ -185,7 +185,7 @@ static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev) properties.type = KFD_QUEUE_TYPE_DIQ; status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL, - &properties, &qid, NULL, NULL); + &properties, &qid, NULL, NULL, NULL); if (status) { pr_err("Failed to create DIQ\n"); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 13317d2c8959..42933610d4e1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -322,7 +322,8 @@ static void deallocate_vmid(struct device_queue_manager *dqm, static int create_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, - const struct kfd_criu_queue_priv_data *qd) + const struct kfd_criu_queue_priv_data *qd, + const void *restore_mqd) { struct mqd_manager *mqd_mgr; int retval; @@ -381,8 +382,14 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, retval = -ENOMEM; goto out_deallocate_doorbell; } - mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, - &q->gart_mqd_addr, &q->properties); + + if (qd) + mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr, + &q->properties, restore_mqd); + else + mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, + &q->gart_mqd_addr, &q->properties); + if (q->properties.is_active) { if (!dqm->sched_running) { WARN_ONCE(1, "Load non-HWS mqd while stopped\n"); @@ -1334,7 +1341,8 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, - const struct kfd_criu_queue_priv_data *qd) + const struct kfd_criu_queue_priv_data *qd, + const void *restore_mqd) { int retval; struct mqd_manager *mqd_mgr; @@ -1380,8 +1388,13 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, * updates the is_evicted flag but is a no-op otherwise. */ q->properties.is_evicted = !!qpd->evicted; - mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, - &q->gart_mqd_addr, &q->properties); + + if (qd) + mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr, + &q->properties, restore_mqd); + else + mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, + &q->gart_mqd_addr, &q->properties); list_add(&q->list, &qpd->queues_list); qpd->queue_count++; @@ -1784,6 +1797,50 @@ static int get_wave_state(struct device_queue_manager *dqm, ctl_stack_used_size, save_area_used_size); } +static void get_queue_checkpoint_info(struct device_queue_manager *dqm, + const struct queue *q, + u32 *mqd_size) +{ + struct mqd_manager *mqd_mgr; + enum KFD_MQD_TYPE mqd_type = + get_mqd_type_from_queue_type(q->properties.type); + + dqm_lock(dqm); + mqd_mgr = dqm->mqd_mgrs[mqd_type]; + *mqd_size = mqd_mgr->mqd_size; + + dqm_unlock(dqm); +} + +static int checkpoint_mqd(struct device_queue_manager *dqm, + const struct queue *q, + void *mqd) +{ + struct mqd_manager *mqd_mgr; + int r = 0; + enum KFD_MQD_TYPE mqd_type = + get_mqd_type_from_queue_type(q->properties.type); + + dqm_lock(dqm); + + if (q->properties.is_active || !q->device->cwsr_enabled) { + r = -EINVAL; + goto dqm_unlock; + } + + mqd_mgr = dqm->mqd_mgrs[mqd_type]; + if (!mqd_mgr->checkpoint_mqd) { + r = -EOPNOTSUPP; + goto dqm_unlock; + } + + mqd_mgr->checkpoint_mqd(mqd_mgr, q->mqd, mqd); + +dqm_unlock: + dqm_unlock(dqm); + return r; +} + static int process_termination_cpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { @@ -1961,6 +2018,8 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) dqm->ops.restore_process_queues = restore_process_queues_cpsch; dqm->ops.get_wave_state = get_wave_state; dqm->ops.reset_queues = reset_queues_cpsch; + dqm->ops.get_queue_checkpoint_info = get_queue_checkpoint_info; + dqm->ops.checkpoint_mqd = checkpoint_mqd; break; case KFD_SCHED_POLICY_NO_HWS: /* initialize dqm for no cp scheduling */ @@ -1980,6 +2039,8 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) dqm->ops.restore_process_queues = restore_process_queues_nocpsch; dqm->ops.get_wave_state = get_wave_state; + dqm->ops.get_queue_checkpoint_info = get_queue_checkpoint_info; + dqm->ops.checkpoint_mqd = checkpoint_mqd; break; default: pr_err("Invalid scheduling policy %d\n", dqm->sched_policy); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 76cc5e2a9733..fb6aa2a1ca0f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -83,13 +83,17 @@ struct device_process_node { * control stack, if kept in the MQD, to the given userspace address. * * @reset_queues: reset queues which consume RAS poison + * @get_queue_checkpoint_info: Retrieves queue size information for CRIU checkpoint. + * + * @checkpoint_mqd: checkpoint queue MQD contents for CRIU. */ struct device_queue_manager_ops { int (*create_queue)(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, - const struct kfd_criu_queue_priv_data *qd); + const struct kfd_criu_queue_priv_data *qd, + const void *restore_mqd); int (*destroy_queue)(struct device_queue_manager *dqm, struct qcm_process_device *qpd, @@ -140,6 +144,12 @@ struct device_queue_manager_ops { int (*reset_queues)(struct device_queue_manager *dqm, uint16_t pasid); + void (*get_queue_checkpoint_info)(struct device_queue_manager *dqm, + const struct queue *q, u32 *mqd_size); + + int (*checkpoint_mqd)(struct device_queue_manager *dqm, + const struct queue *q, + void *mqd); }; struct device_queue_manager_asic_ops { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h index 965e17c5dbb4..cebb2877a505 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h @@ -100,6 +100,13 @@ struct mqd_manager { u32 *ctl_stack_used_size, u32 *save_area_used_size); + void (*checkpoint_mqd)(struct mqd_manager *mm, void *mqd, void *mqd_dst); + + void (*restore_mqd)(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *p, + const void *mqd_src); + #if defined(CONFIG_DEBUG_FS) int (*debugfs_show_mqd)(struct seq_file *m, void *data); #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c index e9a8e21e144e..83117209bc15 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c @@ -280,6 +280,72 @@ static int destroy_mqd(struct mqd_manager *mm, void *mqd, pipe_id, queue_id); } +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct cik_mqd *m; + + m = get_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct cik_mqd)); +} + +static void restore_mqd(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct cik_mqd *m; + + m = (struct cik_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + m->cp_hqd_pq_doorbell_control = DOORBELL_OFFSET(qp->doorbell_off); + + pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", + m->cp_hqd_pq_doorbell_control); + + qp->is_active = 0; +} + +static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct cik_sdma_rlc_registers *m; + + m = get_sdma_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct cik_sdma_rlc_registers)); +} + +static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct cik_sdma_rlc_registers *m; + + m = (struct cik_sdma_rlc_registers *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + m->sdma_rlc_doorbell = + qp->doorbell_off << SDMA0_RLC0_DOORBELL__OFFSET__SHIFT; + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + qp->is_active = 0; +} + /* * preempt type here is ignored because there is only one way * to preempt sdma queue @@ -394,6 +460,8 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, mqd->update_mqd = update_mqd; mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; + mqd->checkpoint_mqd = checkpoint_mqd; + mqd->restore_mqd = restore_mqd; mqd->mqd_size = sizeof(struct cik_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -434,6 +502,8 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, mqd->update_mqd = update_mqd_sdma; mqd->destroy_mqd = destroy_mqd_sdma; mqd->is_occupied = is_occupied_sdma; + mqd->checkpoint_mqd = checkpoint_mqd_sdma; + mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct cik_sdma_rlc_registers); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd_sdma; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c index d74d8a6ac27a..4ddf5b45c42a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c @@ -285,6 +285,41 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd, return 0; } +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct v10_compute_mqd *m; + + m = get_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct v10_compute_mqd)); +} + +static void restore_mqd(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct v10_compute_mqd *m; + + m = (struct v10_compute_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + m->cp_hqd_pq_doorbell_control = + qp->doorbell_off << + CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT; + pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", + m->cp_hqd_pq_doorbell_control); + + qp->is_active = 0; +} + static void init_mqd_hiq(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *q) @@ -373,6 +408,38 @@ static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); } +static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct v10_sdma_mqd *m; + + m = get_sdma_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct v10_sdma_mqd)); +} + +static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct v10_sdma_mqd *m; + + m = (struct v10_sdma_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + m->sdmax_rlcx_doorbell_offset = + qp->doorbell_off << SDMA0_RLC0_DOORBELL_OFFSET__OFFSET__SHIFT; + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + qp->is_active = 0; +} + #if defined(CONFIG_DEBUG_FS) static int debugfs_show_mqd(struct seq_file *m, void *data) @@ -417,6 +484,8 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, mqd->is_occupied = is_occupied; mqd->mqd_size = sizeof(struct v10_compute_mqd); mqd->get_wave_state = get_wave_state; + mqd->checkpoint_mqd = checkpoint_mqd; + mqd->restore_mqd = restore_mqd; #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; #endif @@ -460,6 +529,8 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, mqd->update_mqd = update_mqd_sdma; mqd->destroy_mqd = destroy_mqd_sdma; mqd->is_occupied = is_occupied_sdma; + mqd->checkpoint_mqd = checkpoint_mqd_sdma; + mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct v10_sdma_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd_sdma; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index 326eb2285029..18ad7669eedf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -340,6 +340,41 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd, return 0; } +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct v9_mqd *m; + + m = get_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct v9_mqd)); +} + +static void restore_mqd(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct v9_mqd *m; + + m = (struct v9_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + m->cp_hqd_pq_doorbell_control = + qp->doorbell_off << + CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT; + pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", + m->cp_hqd_pq_doorbell_control); + + qp->is_active = 0; +} + static void init_mqd_hiq(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *q) @@ -428,6 +463,38 @@ static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); } +static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct v9_sdma_mqd *m; + + m = get_sdma_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct v9_sdma_mqd)); +} + +static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct v9_sdma_mqd *m; + + m = (struct v9_sdma_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + m->sdmax_rlcx_doorbell_offset = + qp->doorbell_off << SDMA0_RLC0_DOORBELL_OFFSET__OFFSET__SHIFT; + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + qp->is_active = 0; +} + #if defined(CONFIG_DEBUG_FS) static int debugfs_show_mqd(struct seq_file *m, void *data) @@ -470,6 +537,8 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; mqd->get_wave_state = get_wave_state; + mqd->checkpoint_mqd = checkpoint_mqd; + mqd->restore_mqd = restore_mqd; mqd->mqd_size = sizeof(struct v9_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -510,6 +579,8 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, mqd->update_mqd = update_mqd_sdma; mqd->destroy_mqd = destroy_mqd_sdma; mqd->is_occupied = is_occupied_sdma; + mqd->checkpoint_mqd = checkpoint_mqd_sdma; + mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct v9_sdma_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd_sdma; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c index d456e950ce1d..9fdc67b60bb4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c @@ -306,6 +306,42 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd, return 0; } +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct vi_mqd *m; + + m = get_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct vi_mqd)); +} + +static void restore_mqd(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct vi_mqd *m; + + m = (struct vi_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + m->cp_hqd_pq_doorbell_control = + qp->doorbell_off << + CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT; + pr_debug("cp_hqd_pq_doorbell_control 0x%x\n", + m->cp_hqd_pq_doorbell_control); + + qp->is_active = 0; +} + + static void init_mqd_hiq(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *q) @@ -399,6 +435,38 @@ static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); } +static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +{ + struct vi_sdma_mqd *m; + + m = get_sdma_mqd(mqd); + + memcpy(mqd_dst, m, sizeof(struct vi_sdma_mqd)); +} + +static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, + struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, + struct queue_properties *qp, + const void *mqd_src) +{ + uint64_t addr; + struct vi_sdma_mqd *m; + + m = (struct vi_sdma_mqd *) mqd_mem_obj->cpu_ptr; + addr = mqd_mem_obj->gpu_addr; + + memcpy(m, mqd_src, sizeof(*m)); + + m->sdmax_rlcx_doorbell = + qp->doorbell_off << SDMA0_RLC0_DOORBELL__OFFSET__SHIFT; + + *mqd = m; + if (gart_addr) + *gart_addr = addr; + + qp->is_active = 0; +} + #if defined(CONFIG_DEBUG_FS) static int debugfs_show_mqd(struct seq_file *m, void *data) @@ -441,6 +509,8 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; mqd->get_wave_state = get_wave_state; + mqd->checkpoint_mqd = checkpoint_mqd; + mqd->restore_mqd = restore_mqd; mqd->mqd_size = sizeof(struct vi_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -481,6 +551,8 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, mqd->update_mqd = update_mqd_sdma; mqd->destroy_mqd = destroy_mqd_sdma; mqd->is_occupied = is_occupied_sdma; + mqd->checkpoint_mqd = checkpoint_mqd_sdma; + mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct vi_sdma_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd_sdma; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 59125d8f16a7..1c62abe0dbd5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1158,6 +1158,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, struct queue_properties *properties, unsigned int *qid, const struct kfd_criu_queue_priv_data *q_data, + const void *restore_mqd, uint32_t *p_doorbell_offset_in_process); int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid); int pqm_update_queue_properties(struct process_queue_manager *pqm, unsigned int qid, @@ -1180,6 +1181,10 @@ int amdkfd_fence_wait_timeout(uint64_t *fence_addr, uint64_t fence_value, unsigned int timeout_ms); +int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm, + unsigned int qid, + u32 *mqd_size); + /* Packet Manager */ #define KFD_FENCE_COMPLETED (100) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 8afe6879b861..844917c1c346 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -208,6 +208,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, struct queue_properties *properties, unsigned int *qid, const struct kfd_criu_queue_priv_data *q_data, + const void *restore_mqd, uint32_t *p_doorbell_offset_in_process) { int retval; @@ -272,7 +273,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data); + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data, restore_mqd); print_queue(q); break; @@ -292,7 +293,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data); + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data, restore_mqd); print_queue(q); break; case KFD_QUEUE_TYPE_DIQ: @@ -517,12 +518,25 @@ int pqm_get_wave_state(struct process_queue_manager *pqm, save_area_used_size); } +static int get_queue_data_sizes(struct kfd_process_device *pdd, struct queue *q, uint32_t *mqd_size) +{ + int ret; + + ret = pqm_get_queue_checkpoint_info(&pdd->process->pqm, q->properties.queue_id, mqd_size); + if (ret) + pr_err("Failed to get queue dump info (%d)\n", ret); + + return ret; +} + int kfd_process_get_queue_info(struct kfd_process *p, uint32_t *num_queues, uint64_t *priv_data_sizes) { + uint32_t extra_data_sizes = 0; struct queue *q; int i; + int ret; *num_queues = 0; @@ -534,23 +548,53 @@ int kfd_process_get_queue_info(struct kfd_process *p, if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || q->properties.type == KFD_QUEUE_TYPE_SDMA || q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { - + uint32_t mqd_size; *num_queues = *num_queues + 1; + + ret = get_queue_data_sizes(pdd, q, &mqd_size); + if (ret) + return ret; + + extra_data_sizes += mqd_size; } else { pr_err("Unsupported queue type (%d)\n", q->properties.type); return -EOPNOTSUPP; } } } - *priv_data_sizes = *num_queues * sizeof(struct kfd_criu_queue_priv_data); + *priv_data_sizes = extra_data_sizes + + (*num_queues * sizeof(struct kfd_criu_queue_priv_data)); return 0; } -static void criu_checkpoint_queue(struct kfd_process_device *pdd, +static int pqm_checkpoint_mqd(struct process_queue_manager *pqm, unsigned int qid, void *mqd) +{ + struct process_queue_node *pqn; + + pqn = get_queue_by_qid(pqm, qid); + if (!pqn) { + pr_debug("amdkfd: No queue %d exists for operation\n", qid); + return -EFAULT; + } + + if (!pqn->q->device->dqm->ops.checkpoint_mqd) { + pr_err("amdkfd: queue dumping not supported on this device\n"); + return -EOPNOTSUPP; + } + + return pqn->q->device->dqm->ops.checkpoint_mqd(pqn->q->device->dqm, pqn->q, mqd); +} + +static int criu_checkpoint_queue(struct kfd_process_device *pdd, struct queue *q, struct kfd_criu_queue_priv_data *q_data) { + uint8_t *mqd; + int ret; + + mqd = (void *)(q_data + 1); + q_data->gpu_id = pdd->dev->id; q_data->type = q->properties.type; q_data->format = q->properties.format; @@ -576,7 +620,14 @@ static void criu_checkpoint_queue(struct kfd_process_device *pdd, q_data->ctx_save_restore_area_size = q->properties.ctx_save_restore_area_size; + ret = pqm_checkpoint_mqd(&pdd->process->pqm, q->properties.queue_id, mqd); + if (ret) { + pr_err("Failed checkpoint queue_mqd (%d)\n", ret); + return ret; + } + pr_debug("Dumping Queue: gpu_id:%x queue_id:%u\n", q_data->gpu_id, q_data->q_id); + return ret; } static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, @@ -584,15 +635,16 @@ static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, unsigned int *q_index, uint64_t *queues_priv_data_offset) { - struct kfd_criu_queue_priv_data *q_data; + unsigned int q_private_data_size = 0; + uint8_t *q_private_data = NULL; /* Local buffer to store individual queue private data */ struct queue *q; int ret = 0; - q_data = kzalloc(sizeof(*q_data), GFP_KERNEL); - if (!q_data) - return -ENOMEM; - list_for_each_entry(q, &pdd->qpd.queues_list, list) { + struct kfd_criu_queue_priv_data *q_data; + uint64_t q_data_size; + uint32_t mqd_size; + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE && q->properties.type != KFD_QUEUE_TYPE_SDMA && q->properties.type != KFD_QUEUE_TYPE_SDMA_XGMI) { @@ -602,19 +654,46 @@ static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, break; } - criu_checkpoint_queue(pdd, q, q_data); + ret = get_queue_data_sizes(pdd, q, &mqd_size); + if (ret) + break; + + q_data_size = sizeof(*q_data) + mqd_size; + + /* Increase local buffer space if needed */ + if (q_private_data_size < q_data_size) { + kfree(q_private_data); + + q_private_data = kzalloc(q_data_size, GFP_KERNEL); + if (!q_private_data) { + ret = -ENOMEM; + break; + } + q_private_data_size = q_data_size; + } + + q_data = (struct kfd_criu_queue_priv_data *)q_private_data; + + /* data stored in this order: priv_data, mqd */ + q_data->mqd_size = mqd_size; + + ret = criu_checkpoint_queue(pdd, q, q_data); + if (ret) + break; + q_data->object_type = KFD_CRIU_OBJECT_TYPE_QUEUE; - ret = copy_to_user(user_priv + *queues_priv_data_offset, q_data, sizeof(*q_data)); + ret = copy_to_user(user_priv + *queues_priv_data_offset, + q_data, q_data_size); if (ret) { ret = -EFAULT; break; } - *queues_priv_data_offset += sizeof(*q_data); + *queues_priv_data_offset += q_data_size; *q_index = *q_index + 1; } - kfree(q_data); + kfree(q_private_data); return ret; } @@ -668,11 +747,12 @@ int kfd_criu_restore_queue(struct kfd_process *p, uint64_t max_priv_data_size) { struct kfd_criu_queue_priv_data *q_data; + uint8_t *mqd, *q_extra_data = NULL; struct kfd_process_device *pdd; - struct kfd_dev *dev; + uint64_t q_extra_data_size; struct queue_properties qp; unsigned int queue_id; - + struct kfd_dev *dev; int ret = 0; if (*priv_data_offset + sizeof(*q_data) > max_priv_data_size) @@ -689,6 +769,26 @@ int kfd_criu_restore_queue(struct kfd_process *p, } *priv_data_offset += sizeof(*q_data); + q_extra_data_size = q_data->mqd_size; + + if (*priv_data_offset + q_extra_data_size > max_priv_data_size) { + ret = -EINVAL; + goto exit; + } + + q_extra_data = kmalloc(q_extra_data_size, GFP_KERNEL); + if (!q_extra_data) { + ret = -ENOMEM; + goto exit; + } + + ret = copy_from_user(q_extra_data, user_priv_ptr + *priv_data_offset, q_extra_data_size); + if (ret) { + ret = -EFAULT; + goto exit; + } + + *priv_data_offset += q_extra_data_size; dev = kfd_device_by_id(q_data->gpu_id); if (!dev) { @@ -705,13 +805,15 @@ int kfd_criu_restore_queue(struct kfd_process *p, ret = -EFAULT; return ret; } + /* data stored in this order: mqd */ + mqd = q_extra_data; memset(&qp, 0, sizeof(qp)); set_queue_properties_from_criu(&qp, q_data); print_queue_properties(&qp); - ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, NULL); + ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, mqd, NULL); if (ret) { pr_err("Failed to create new queue err:%d\n", ret); ret = -EINVAL; @@ -728,6 +830,27 @@ exit: return ret; } +int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm, + unsigned int qid, + uint32_t *mqd_size) +{ + struct process_queue_node *pqn; + + pqn = get_queue_by_qid(pqm, qid); + if (!pqn) { + pr_debug("amdkfd: No queue %d exists for operation\n", qid); + return -EFAULT; + } + + if (!pqn->q->device->dqm->ops.get_queue_checkpoint_info) { + pr_err("amdkfd: queue dumping not supported on this device\n"); + return -EOPNOTSUPP; + } + + pqn->q->device->dqm->ops.get_queue_checkpoint_info(pqn->q->device->dqm, pqn->q, mqd_size); + return 0; +} + #if defined(CONFIG_DEBUG_FS) int pqm_debugfs_mqds(struct seq_file *m, void *data) From 3a9822d7bd623be9000cef8101ecf8479fa53f2c Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 25 Jan 2021 14:09:32 -0500 Subject: [PATCH 259/339] drm/amdkfd: CRIU checkpoint and restore queue control stack Checkpoint contents of queue control stacks on CRIU dump and restore them during CRIU restore. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c | 2 +- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 22 ++++--- .../drm/amd/amdkfd/kfd_device_queue_manager.h | 9 ++- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h | 11 +++- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c | 13 ++-- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c | 14 +++-- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 29 +++++++-- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 22 +++++-- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 +- .../amd/amdkfd/kfd_process_queue_manager.c | 62 +++++++++++++------ 11 files changed, 138 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 999672602252..608214ea634d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -311,7 +311,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, p->pasid, dev->id); - err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, NULL, NULL, + err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id, NULL, NULL, NULL, &doorbell_offset_in_process); if (err != 0) goto err_create_queue; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c index 3a5303ebcabf..8eca9ed3ab36 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c @@ -185,7 +185,7 @@ static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev) properties.type = KFD_QUEUE_TYPE_DIQ; status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL, - &properties, &qid, NULL, NULL, NULL); + &properties, &qid, NULL, NULL, NULL, NULL); if (status) { pr_err("Failed to create DIQ\n"); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 42933610d4e1..63b3c7af681b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -323,7 +323,7 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, const struct kfd_criu_queue_priv_data *qd, - const void *restore_mqd) + const void *restore_mqd, const void *restore_ctl_stack) { struct mqd_manager *mqd_mgr; int retval; @@ -385,7 +385,8 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, if (qd) mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr, - &q->properties, restore_mqd); + &q->properties, restore_mqd, restore_ctl_stack, + qd->ctl_stack_size); else mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr, &q->properties); @@ -1342,7 +1343,7 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, const struct kfd_criu_queue_priv_data *qd, - const void *restore_mqd) + const void *restore_mqd, const void *restore_ctl_stack) { int retval; struct mqd_manager *mqd_mgr; @@ -1391,7 +1392,8 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, if (qd) mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr, - &q->properties, restore_mqd); + &q->properties, restore_mqd, restore_ctl_stack, + qd->ctl_stack_size); else mqd_mgr->init_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr, &q->properties); @@ -1799,7 +1801,8 @@ static int get_wave_state(struct device_queue_manager *dqm, static void get_queue_checkpoint_info(struct device_queue_manager *dqm, const struct queue *q, - u32 *mqd_size) + u32 *mqd_size, + u32 *ctl_stack_size) { struct mqd_manager *mqd_mgr; enum KFD_MQD_TYPE mqd_type = @@ -1808,13 +1811,18 @@ static void get_queue_checkpoint_info(struct device_queue_manager *dqm, dqm_lock(dqm); mqd_mgr = dqm->mqd_mgrs[mqd_type]; *mqd_size = mqd_mgr->mqd_size; + *ctl_stack_size = 0; + + if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE && mqd_mgr->get_checkpoint_info) + mqd_mgr->get_checkpoint_info(mqd_mgr, q->mqd, ctl_stack_size); dqm_unlock(dqm); } static int checkpoint_mqd(struct device_queue_manager *dqm, const struct queue *q, - void *mqd) + void *mqd, + void *ctl_stack) { struct mqd_manager *mqd_mgr; int r = 0; @@ -1834,7 +1842,7 @@ static int checkpoint_mqd(struct device_queue_manager *dqm, goto dqm_unlock; } - mqd_mgr->checkpoint_mqd(mqd_mgr, q->mqd, mqd); + mqd_mgr->checkpoint_mqd(mqd_mgr, q->mqd, mqd, ctl_stack); dqm_unlock: dqm_unlock(dqm); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index fb6aa2a1ca0f..a7d2e3323977 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -93,7 +93,8 @@ struct device_queue_manager_ops { struct queue *q, struct qcm_process_device *qpd, const struct kfd_criu_queue_priv_data *qd, - const void *restore_mqd); + const void *restore_mqd, + const void *restore_ctl_stack); int (*destroy_queue)(struct device_queue_manager *dqm, struct qcm_process_device *qpd, @@ -145,11 +146,13 @@ struct device_queue_manager_ops { int (*reset_queues)(struct device_queue_manager *dqm, uint16_t pasid); void (*get_queue_checkpoint_info)(struct device_queue_manager *dqm, - const struct queue *q, u32 *mqd_size); + const struct queue *q, u32 *mqd_size, + u32 *ctl_stack_size); int (*checkpoint_mqd)(struct device_queue_manager *dqm, const struct queue *q, - void *mqd); + void *mqd, + void *ctl_stack); }; struct device_queue_manager_asic_ops { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h index cebb2877a505..23486a23df84 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h @@ -100,12 +100,19 @@ struct mqd_manager { u32 *ctl_stack_used_size, u32 *save_area_used_size); - void (*checkpoint_mqd)(struct mqd_manager *mm, void *mqd, void *mqd_dst); + void (*get_checkpoint_info)(struct mqd_manager *mm, void *mqd, uint32_t *ctl_stack_size); + + void (*checkpoint_mqd)(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst); void (*restore_mqd)(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *p, - const void *mqd_src); + const void *mqd_src, + const void *ctl_stack_src, + const u32 ctl_stack_size); #if defined(CONFIG_DEBUG_FS) int (*debugfs_show_mqd)(struct seq_file *m, void *data); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c index 83117209bc15..96e3303fa27c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c @@ -280,7 +280,7 @@ static int destroy_mqd(struct mqd_manager *mm, void *mqd, pipe_id, queue_id); } -static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) { struct cik_mqd *m; @@ -292,7 +292,8 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) static void restore_mqd(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; struct cik_mqd *m; @@ -314,7 +315,10 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd, qp->is_active = 0; } -static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void checkpoint_mqd_sdma(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst) { struct cik_sdma_rlc_registers *m; @@ -326,7 +330,8 @@ static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; struct cik_sdma_rlc_registers *m; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c index 4ddf5b45c42a..0cc8679c24fa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c @@ -285,7 +285,7 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd, return 0; } -static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) { struct v10_compute_mqd *m; @@ -297,7 +297,8 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) static void restore_mqd(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; struct v10_compute_mqd *m; @@ -408,7 +409,10 @@ static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); } -static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void checkpoint_mqd_sdma(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst) { struct v10_sdma_mqd *m; @@ -420,7 +424,9 @@ static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, + const u32 ctl_stack_size) { uint64_t addr; struct v10_sdma_mqd *m; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index 18ad7669eedf..87da4329dbf2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -340,22 +340,34 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd, return 0; } -static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size) +{ + struct v9_mqd *m = get_mqd(mqd); + + *ctl_stack_size = m->cp_hqd_cntl_stack_size; +} + +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) { struct v9_mqd *m; + /* Control stack is located one page after MQD. */ + void *ctl_stack = (void *)((uintptr_t)mqd + PAGE_SIZE); m = get_mqd(mqd); memcpy(mqd_dst, m, sizeof(struct v9_mqd)); + memcpy(ctl_stack_dst, ctl_stack, m->cp_hqd_cntl_stack_size); } static void restore_mqd(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, u32 ctl_stack_size) { uint64_t addr; struct v9_mqd *m; + void *ctl_stack; m = (struct v9_mqd *) mqd_mem_obj->cpu_ptr; addr = mqd_mem_obj->gpu_addr; @@ -366,6 +378,10 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd, if (gart_addr) *gart_addr = addr; + /* Control stack is located one page after MQD. */ + ctl_stack = (void *)((uintptr_t)*mqd + PAGE_SIZE); + memcpy(ctl_stack, ctl_stack_src, ctl_stack_size); + m->cp_hqd_pq_doorbell_control = qp->doorbell_off << CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT; @@ -463,7 +479,10 @@ static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); } -static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void checkpoint_mqd_sdma(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst) { struct v9_sdma_mqd *m; @@ -475,7 +494,8 @@ static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; struct v9_sdma_mqd *m; @@ -537,6 +557,7 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; mqd->get_wave_state = get_wave_state; + mqd->get_checkpoint_info = get_checkpoint_info; mqd->checkpoint_mqd = checkpoint_mqd; mqd->restore_mqd = restore_mqd; mqd->mqd_size = sizeof(struct v9_mqd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c index 9fdc67b60bb4..137b208135a0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c @@ -306,7 +306,13 @@ static int get_wave_state(struct mqd_manager *mm, void *mqd, return 0; } -static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void get_checkpoint_info(struct mqd_manager *mm, void *mqd, u32 *ctl_stack_size) +{ + /* Control stack is stored in user mode */ + *ctl_stack_size = 0; +} + +static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) { struct vi_mqd *m; @@ -318,7 +324,8 @@ static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst) static void restore_mqd(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; struct vi_mqd *m; @@ -341,7 +348,6 @@ static void restore_mqd(struct mqd_manager *mm, void **mqd, qp->is_active = 0; } - static void init_mqd_hiq(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *q) @@ -435,7 +441,10 @@ static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); } -static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst) +static void checkpoint_mqd_sdma(struct mqd_manager *mm, + void *mqd, + void *mqd_dst, + void *ctl_stack_dst) { struct vi_sdma_mqd *m; @@ -447,7 +456,8 @@ static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, struct queue_properties *qp, - const void *mqd_src) + const void *mqd_src, + const void *ctl_stack_src, const u32 ctl_stack_size) { uint64_t addr; struct vi_sdma_mqd *m; @@ -469,6 +479,7 @@ static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, #if defined(CONFIG_DEBUG_FS) + static int debugfs_show_mqd(struct seq_file *m, void *data) { seq_hex_dump(m, " ", DUMP_PREFIX_OFFSET, 32, 4, @@ -509,6 +520,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, mqd->destroy_mqd = destroy_mqd; mqd->is_occupied = is_occupied; mqd->get_wave_state = get_wave_state; + mqd->get_checkpoint_info = get_checkpoint_info; mqd->checkpoint_mqd = checkpoint_mqd; mqd->restore_mqd = restore_mqd; mqd->mqd_size = sizeof(struct vi_mqd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 1c62abe0dbd5..03242975078a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1159,6 +1159,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, unsigned int *qid, const struct kfd_criu_queue_priv_data *q_data, const void *restore_mqd, + const void *restore_ctl_stack, uint32_t *p_doorbell_offset_in_process); int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid); int pqm_update_queue_properties(struct process_queue_manager *pqm, unsigned int qid, @@ -1183,8 +1184,8 @@ int amdkfd_fence_wait_timeout(uint64_t *fence_addr, int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm, unsigned int qid, - u32 *mqd_size); - + u32 *mqd_size, + u32 *ctl_stack_size); /* Packet Manager */ #define KFD_FENCE_COMPLETED (100) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 844917c1c346..bd89dd0ca83e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -209,6 +209,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, unsigned int *qid, const struct kfd_criu_queue_priv_data *q_data, const void *restore_mqd, + const void *restore_ctl_stack, uint32_t *p_doorbell_offset_in_process) { int retval; @@ -273,7 +274,8 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data, restore_mqd); + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data, + restore_mqd, restore_ctl_stack); print_queue(q); break; @@ -293,7 +295,8 @@ int pqm_create_queue(struct process_queue_manager *pqm, goto err_create_queue; pqn->q = q; pqn->kq = NULL; - retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data, restore_mqd); + retval = dev->dqm->ops.create_queue(dev->dqm, q, &pdd->qpd, q_data, + restore_mqd, restore_ctl_stack); print_queue(q); break; case KFD_QUEUE_TYPE_DIQ: @@ -518,11 +521,17 @@ int pqm_get_wave_state(struct process_queue_manager *pqm, save_area_used_size); } -static int get_queue_data_sizes(struct kfd_process_device *pdd, struct queue *q, uint32_t *mqd_size) +static int get_queue_data_sizes(struct kfd_process_device *pdd, + struct queue *q, + uint32_t *mqd_size, + uint32_t *ctl_stack_size) { int ret; - ret = pqm_get_queue_checkpoint_info(&pdd->process->pqm, q->properties.queue_id, mqd_size); + ret = pqm_get_queue_checkpoint_info(&pdd->process->pqm, + q->properties.queue_id, + mqd_size, + ctl_stack_size); if (ret) pr_err("Failed to get queue dump info (%d)\n", ret); @@ -548,14 +557,15 @@ int kfd_process_get_queue_info(struct kfd_process *p, if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || q->properties.type == KFD_QUEUE_TYPE_SDMA || q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI) { - uint32_t mqd_size; + uint32_t mqd_size, ctl_stack_size; + *num_queues = *num_queues + 1; - ret = get_queue_data_sizes(pdd, q, &mqd_size); + ret = get_queue_data_sizes(pdd, q, &mqd_size, &ctl_stack_size); if (ret) return ret; - extra_data_sizes += mqd_size; + extra_data_sizes += mqd_size + ctl_stack_size; } else { pr_err("Unsupported queue type (%d)\n", q->properties.type); return -EOPNOTSUPP; @@ -568,7 +578,10 @@ int kfd_process_get_queue_info(struct kfd_process *p, return 0; } -static int pqm_checkpoint_mqd(struct process_queue_manager *pqm, unsigned int qid, void *mqd) +static int pqm_checkpoint_mqd(struct process_queue_manager *pqm, + unsigned int qid, + void *mqd, + void *ctl_stack) { struct process_queue_node *pqn; @@ -583,17 +596,19 @@ static int pqm_checkpoint_mqd(struct process_queue_manager *pqm, unsigned int qi return -EOPNOTSUPP; } - return pqn->q->device->dqm->ops.checkpoint_mqd(pqn->q->device->dqm, pqn->q, mqd); + return pqn->q->device->dqm->ops.checkpoint_mqd(pqn->q->device->dqm, + pqn->q, mqd, ctl_stack); } static int criu_checkpoint_queue(struct kfd_process_device *pdd, struct queue *q, struct kfd_criu_queue_priv_data *q_data) { - uint8_t *mqd; + uint8_t *mqd, *ctl_stack; int ret; mqd = (void *)(q_data + 1); + ctl_stack = mqd + q_data->mqd_size; q_data->gpu_id = pdd->dev->id; q_data->type = q->properties.type; @@ -620,7 +635,7 @@ static int criu_checkpoint_queue(struct kfd_process_device *pdd, q_data->ctx_save_restore_area_size = q->properties.ctx_save_restore_area_size; - ret = pqm_checkpoint_mqd(&pdd->process->pqm, q->properties.queue_id, mqd); + ret = pqm_checkpoint_mqd(&pdd->process->pqm, q->properties.queue_id, mqd, ctl_stack); if (ret) { pr_err("Failed checkpoint queue_mqd (%d)\n", ret); return ret; @@ -644,6 +659,7 @@ static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, struct kfd_criu_queue_priv_data *q_data; uint64_t q_data_size; uint32_t mqd_size; + uint32_t ctl_stack_size; if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE && q->properties.type != KFD_QUEUE_TYPE_SDMA && @@ -654,11 +670,11 @@ static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, break; } - ret = get_queue_data_sizes(pdd, q, &mqd_size); + ret = get_queue_data_sizes(pdd, q, &mqd_size, &ctl_stack_size); if (ret) break; - q_data_size = sizeof(*q_data) + mqd_size; + q_data_size = sizeof(*q_data) + mqd_size + ctl_stack_size; /* Increase local buffer space if needed */ if (q_private_data_size < q_data_size) { @@ -674,8 +690,9 @@ static int criu_checkpoint_queues_device(struct kfd_process_device *pdd, q_data = (struct kfd_criu_queue_priv_data *)q_private_data; - /* data stored in this order: priv_data, mqd */ + /* data stored in this order: priv_data, mqd, ctl_stack */ q_data->mqd_size = mqd_size; + q_data->ctl_stack_size = ctl_stack_size; ret = criu_checkpoint_queue(pdd, q, q_data); if (ret) @@ -746,8 +763,8 @@ int kfd_criu_restore_queue(struct kfd_process *p, uint64_t *priv_data_offset, uint64_t max_priv_data_size) { + uint8_t *mqd, *ctl_stack, *q_extra_data = NULL; struct kfd_criu_queue_priv_data *q_data; - uint8_t *mqd, *q_extra_data = NULL; struct kfd_process_device *pdd; uint64_t q_extra_data_size; struct queue_properties qp; @@ -769,7 +786,7 @@ int kfd_criu_restore_queue(struct kfd_process *p, } *priv_data_offset += sizeof(*q_data); - q_extra_data_size = q_data->mqd_size; + q_extra_data_size = q_data->ctl_stack_size + q_data->mqd_size; if (*priv_data_offset + q_extra_data_size > max_priv_data_size) { ret = -EINVAL; @@ -805,15 +822,17 @@ int kfd_criu_restore_queue(struct kfd_process *p, ret = -EFAULT; return ret; } - /* data stored in this order: mqd */ + /* data stored in this order: mqd, ctl_stack */ mqd = q_extra_data; + ctl_stack = mqd + q_data->mqd_size; memset(&qp, 0, sizeof(qp)); set_queue_properties_from_criu(&qp, q_data); print_queue_properties(&qp); - ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, mqd, NULL); + ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp, &queue_id, q_data, mqd, ctl_stack, + NULL); if (ret) { pr_err("Failed to create new queue err:%d\n", ret); ret = -EINVAL; @@ -832,7 +851,8 @@ exit: int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm, unsigned int qid, - uint32_t *mqd_size) + uint32_t *mqd_size, + uint32_t *ctl_stack_size) { struct process_queue_node *pqn; @@ -847,7 +867,9 @@ int pqm_get_queue_checkpoint_info(struct process_queue_manager *pqm, return -EOPNOTSUPP; } - pqn->q->device->dqm->ops.get_queue_checkpoint_info(pqn->q->device->dqm, pqn->q, mqd_size); + pqn->q->device->dqm->ops.get_queue_checkpoint_info(pqn->q->device->dqm, + pqn->q, mqd_size, + ctl_stack_size); return 0; } From 40e8a766a761f7fdc8530347527b344fddf6f1a8 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 5 Mar 2021 16:06:41 -0500 Subject: [PATCH 260/339] drm/amdkfd: CRIU checkpoint and restore events Add support to existing CRIU ioctl's to save and restore events during criu checkpoint and restore. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 70 +----- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 272 ++++++++++++++++++++--- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 27 ++- 3 files changed, 280 insertions(+), 89 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 608214ea634d..a4be758647f9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1008,57 +1008,11 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p, * through the event_page_offset field. */ if (args->event_page_offset) { - struct kfd_dev *kfd; - struct kfd_process_device *pdd; - void *mem, *kern_addr; - uint64_t size; - - kfd = kfd_device_by_id(GET_GPU_ID(args->event_page_offset)); - if (!kfd) { - pr_err("Getting device by id failed in %s\n", __func__); - return -EINVAL; - } - mutex_lock(&p->mutex); - - if (p->signal_page) { - pr_err("Event page is already set\n"); - err = -EINVAL; - goto out_unlock; - } - - pdd = kfd_bind_process_to_device(kfd, p); - if (IS_ERR(pdd)) { - err = PTR_ERR(pdd); - goto out_unlock; - } - - mem = kfd_process_device_translate_handle(pdd, - GET_IDR_HANDLE(args->event_page_offset)); - if (!mem) { - pr_err("Can't find BO, offset is 0x%llx\n", - args->event_page_offset); - err = -EINVAL; - goto out_unlock; - } - - err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(kfd->adev, - mem, &kern_addr, &size); - if (err) { - pr_err("Failed to map event page to kernel\n"); - goto out_unlock; - } - - err = kfd_event_page_set(p, kern_addr, size); - if (err) { - pr_err("Failed to set event page\n"); - amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(kfd->adev, mem); - goto out_unlock; - } - - p->signal_handle = args->event_page_offset; - + err = kfd_kmap_event_page(p, args->event_page_offset); mutex_unlock(&p->mutex); + if (err) + return err; } err = kfd_event_create(filp, p, args->event_type, @@ -1067,10 +1021,7 @@ static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p, &args->event_page_offset, &args->event_slot_index); - return err; - -out_unlock: - mutex_unlock(&p->mutex); + pr_debug("Created event (id:0x%08x) (%s)\n", args->event_id, __func__); return err; } @@ -2031,7 +1982,7 @@ static int criu_get_process_object_info(struct kfd_process *p, if (ret) return ret; - num_events = 0; /* TODO: Implement Events */ + num_events = kfd_get_num_events(p); num_svm_ranges = 0; /* TODO: Implement SVM-Ranges */ *num_objects = num_queues + num_events + num_svm_ranges; @@ -2040,7 +1991,7 @@ static int criu_get_process_object_info(struct kfd_process *p, priv_size = sizeof(struct kfd_criu_process_priv_data); priv_size += *num_bos * sizeof(struct kfd_criu_bo_priv_data); priv_size += queues_priv_data_size; - /* TODO: Add Events priv size */ + priv_size += num_events * sizeof(struct kfd_criu_event_priv_data); /* TODO: Add SVM ranges priv size */ *objs_priv_size = priv_size; } @@ -2102,7 +2053,10 @@ static int criu_checkpoint(struct file *filep, if (ret) goto exit_unlock; - /* TODO: Dump Events */ + ret = kfd_criu_checkpoint_events(p, (uint8_t __user *)args->priv_data, + &priv_offset); + if (ret) + goto exit_unlock; /* TODO: Dump SVM-Ranges */ } @@ -2410,8 +2364,8 @@ static int criu_restore_objects(struct file *filep, goto exit; break; case KFD_CRIU_OBJECT_TYPE_EVENT: - /* TODO: Implement Events */ - *priv_offset += sizeof(struct kfd_criu_event_priv_data); + ret = kfd_criu_restore_event(filep, p, (uint8_t __user *)args->priv_data, + priv_offset, max_priv_data_size); if (ret) goto exit; break; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index afe72dd11325..9341ce5d0fc9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -55,7 +55,6 @@ struct kfd_signal_page { bool need_to_free_pages; }; - static uint64_t *page_slots(struct kfd_signal_page *page) { return page->kernel_address; @@ -92,7 +91,8 @@ fail_alloc_signal_store: } static int allocate_event_notification_slot(struct kfd_process *p, - struct kfd_event *ev) + struct kfd_event *ev, + const int *restore_id) { int id; @@ -104,14 +104,19 @@ static int allocate_event_notification_slot(struct kfd_process *p, p->signal_mapped_size = 256*8; } - /* - * Compatibility with old user mode: Only use signal slots - * user mode has mapped, may be less than - * KFD_SIGNAL_EVENT_LIMIT. This also allows future increase - * of the event limit without breaking user mode. - */ - id = idr_alloc(&p->event_idr, ev, 0, p->signal_mapped_size / 8, - GFP_KERNEL); + if (restore_id) { + id = idr_alloc(&p->event_idr, ev, *restore_id, *restore_id + 1, + GFP_KERNEL); + } else { + /* + * Compatibility with old user mode: Only use signal slots + * user mode has mapped, may be less than + * KFD_SIGNAL_EVENT_LIMIT. This also allows future increase + * of the event limit without breaking user mode. + */ + id = idr_alloc(&p->event_idr, ev, 0, p->signal_mapped_size / 8, + GFP_KERNEL); + } if (id < 0) return id; @@ -178,9 +183,8 @@ static struct kfd_event *lookup_signaled_event_by_partial_id( return ev; } -static int create_signal_event(struct file *devkfd, - struct kfd_process *p, - struct kfd_event *ev) +static int create_signal_event(struct file *devkfd, struct kfd_process *p, + struct kfd_event *ev, const int *restore_id) { int ret; @@ -193,7 +197,7 @@ static int create_signal_event(struct file *devkfd, return -ENOSPC; } - ret = allocate_event_notification_slot(p, ev); + ret = allocate_event_notification_slot(p, ev, restore_id); if (ret) { pr_warn("Signal event wasn't created because out of kernel memory\n"); return ret; @@ -209,16 +213,22 @@ static int create_signal_event(struct file *devkfd, return 0; } -static int create_other_event(struct kfd_process *p, struct kfd_event *ev) +static int create_other_event(struct kfd_process *p, struct kfd_event *ev, const int *restore_id) { - /* Cast KFD_LAST_NONSIGNAL_EVENT to uint32_t. This allows an - * intentional integer overflow to -1 without a compiler - * warning. idr_alloc treats a negative value as "maximum - * signed integer". - */ - int id = idr_alloc(&p->event_idr, ev, KFD_FIRST_NONSIGNAL_EVENT_ID, - (uint32_t)KFD_LAST_NONSIGNAL_EVENT_ID + 1, - GFP_KERNEL); + int id; + + if (restore_id) + id = idr_alloc(&p->event_idr, ev, *restore_id, *restore_id + 1, + GFP_KERNEL); + else + /* Cast KFD_LAST_NONSIGNAL_EVENT to uint32_t. This allows an + * intentional integer overflow to -1 without a compiler + * warning. idr_alloc treats a negative value as "maximum + * signed integer". + */ + id = idr_alloc(&p->event_idr, ev, KFD_FIRST_NONSIGNAL_EVENT_ID, + (uint32_t)KFD_LAST_NONSIGNAL_EVENT_ID + 1, + GFP_KERNEL); if (id < 0) return id; @@ -295,8 +305,8 @@ static bool event_can_be_cpu_signaled(const struct kfd_event *ev) return ev->type == KFD_EVENT_TYPE_SIGNAL; } -int kfd_event_page_set(struct kfd_process *p, void *kernel_address, - uint64_t size) +static int kfd_event_page_set(struct kfd_process *p, void *kernel_address, + uint64_t size, uint64_t user_handle) { struct kfd_signal_page *page; @@ -315,10 +325,56 @@ int kfd_event_page_set(struct kfd_process *p, void *kernel_address, p->signal_page = page; p->signal_mapped_size = size; - + p->signal_handle = user_handle; return 0; } +int kfd_kmap_event_page(struct kfd_process *p, uint64_t event_page_offset) +{ + struct kfd_dev *kfd; + struct kfd_process_device *pdd; + void *mem, *kern_addr; + uint64_t size; + int err = 0; + + if (p->signal_page) { + pr_err("Event page is already set\n"); + return -EINVAL; + } + + kfd = kfd_device_by_id(GET_GPU_ID(event_page_offset)); + if (!kfd) { + pr_err("Getting device by id failed in %s\n", __func__); + return -EINVAL; + } + + pdd = kfd_bind_process_to_device(kfd, p); + if (IS_ERR(pdd)) + return PTR_ERR(pdd); + + mem = kfd_process_device_translate_handle(pdd, + GET_IDR_HANDLE(event_page_offset)); + if (!mem) { + pr_err("Can't find BO, offset is 0x%llx\n", event_page_offset); + return -EINVAL; + } + + err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(kfd->adev, + mem, &kern_addr, &size); + if (err) { + pr_err("Failed to map event page to kernel\n"); + return err; + } + + err = kfd_event_page_set(p, kern_addr, size, event_page_offset); + if (err) { + pr_err("Failed to set event page\n"); + amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(kfd->adev, mem); + return err; + } + return err; +} + int kfd_event_create(struct file *devkfd, struct kfd_process *p, uint32_t event_type, bool auto_reset, uint32_t node_id, uint32_t *event_id, uint32_t *event_trigger_data, @@ -343,14 +399,14 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, switch (event_type) { case KFD_EVENT_TYPE_SIGNAL: case KFD_EVENT_TYPE_DEBUG: - ret = create_signal_event(devkfd, p, ev); + ret = create_signal_event(devkfd, p, ev, NULL); if (!ret) { *event_page_offset = KFD_MMAP_TYPE_EVENTS; *event_slot_index = ev->event_id; } break; default: - ret = create_other_event(p, ev); + ret = create_other_event(p, ev, NULL); break; } @@ -366,6 +422,166 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, return ret; } +int kfd_criu_restore_event(struct file *devkfd, + struct kfd_process *p, + uint8_t __user *user_priv_ptr, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size) +{ + struct kfd_criu_event_priv_data *ev_priv; + struct kfd_event *ev = NULL; + int ret = 0; + + ev_priv = kmalloc(sizeof(*ev_priv), GFP_KERNEL); + if (!ev_priv) + return -ENOMEM; + + ev = kzalloc(sizeof(*ev), GFP_KERNEL); + if (!ev) { + ret = -ENOMEM; + goto exit; + } + + if (*priv_data_offset + sizeof(*ev_priv) > max_priv_data_size) { + ret = -EINVAL; + goto exit; + } + + ret = copy_from_user(ev_priv, user_priv_ptr + *priv_data_offset, sizeof(*ev_priv)); + if (ret) { + ret = -EFAULT; + goto exit; + } + *priv_data_offset += sizeof(*ev_priv); + + if (ev_priv->user_handle) { + ret = kfd_kmap_event_page(p, ev_priv->user_handle); + if (ret) + goto exit; + } + + ev->type = ev_priv->type; + ev->auto_reset = ev_priv->auto_reset; + ev->signaled = ev_priv->signaled; + + init_waitqueue_head(&ev->wq); + + mutex_lock(&p->event_mutex); + switch (ev->type) { + case KFD_EVENT_TYPE_SIGNAL: + case KFD_EVENT_TYPE_DEBUG: + ret = create_signal_event(devkfd, p, ev, &ev_priv->event_id); + break; + case KFD_EVENT_TYPE_MEMORY: + memcpy(&ev->memory_exception_data, + &ev_priv->memory_exception_data, + sizeof(struct kfd_hsa_memory_exception_data)); + + ret = create_other_event(p, ev, &ev_priv->event_id); + break; + case KFD_EVENT_TYPE_HW_EXCEPTION: + memcpy(&ev->hw_exception_data, + &ev_priv->hw_exception_data, + sizeof(struct kfd_hsa_hw_exception_data)); + + ret = create_other_event(p, ev, &ev_priv->event_id); + break; + } + +exit: + if (ret) + kfree(ev); + + kfree(ev_priv); + + mutex_unlock(&p->event_mutex); + + return ret; +} + +int kfd_criu_checkpoint_events(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset) +{ + struct kfd_criu_event_priv_data *ev_privs; + int i = 0; + int ret = 0; + struct kfd_event *ev; + uint32_t ev_id; + + uint32_t num_events = kfd_get_num_events(p); + + if (!num_events) + return 0; + + ev_privs = kvzalloc(num_events * sizeof(*ev_privs), GFP_KERNEL); + if (!ev_privs) + return -ENOMEM; + + + idr_for_each_entry(&p->event_idr, ev, ev_id) { + struct kfd_criu_event_priv_data *ev_priv; + + /* + * Currently, all events have same size of private_data, but the current ioctl's + * and CRIU plugin supports private_data of variable sizes + */ + ev_priv = &ev_privs[i]; + + ev_priv->object_type = KFD_CRIU_OBJECT_TYPE_EVENT; + + /* We store the user_handle with the first event */ + if (i == 0 && p->signal_page) + ev_priv->user_handle = p->signal_handle; + + ev_priv->event_id = ev->event_id; + ev_priv->auto_reset = ev->auto_reset; + ev_priv->type = ev->type; + ev_priv->signaled = ev->signaled; + + if (ev_priv->type == KFD_EVENT_TYPE_MEMORY) + memcpy(&ev_priv->memory_exception_data, + &ev->memory_exception_data, + sizeof(struct kfd_hsa_memory_exception_data)); + else if (ev_priv->type == KFD_EVENT_TYPE_HW_EXCEPTION) + memcpy(&ev_priv->hw_exception_data, + &ev->hw_exception_data, + sizeof(struct kfd_hsa_hw_exception_data)); + + pr_debug("Checkpointed event[%d] id = 0x%08x auto_reset = %x type = %x signaled = %x\n", + i, + ev_priv->event_id, + ev_priv->auto_reset, + ev_priv->type, + ev_priv->signaled); + i++; + } + + ret = copy_to_user(user_priv_data + *priv_data_offset, + ev_privs, num_events * sizeof(*ev_privs)); + if (ret) { + pr_err("Failed to copy events priv to user\n"); + ret = -EFAULT; + } + + *priv_data_offset += num_events * sizeof(*ev_privs); + + kvfree(ev_privs); + return ret; +} + +int kfd_get_num_events(struct kfd_process *p) +{ + struct kfd_event *ev; + uint32_t id; + u32 num_events = 0; + + idr_for_each_entry(&p->event_idr, ev, id) + num_events++; + + return num_events; +} + /* Assumes that p is current. */ int kfd_event_destroy(struct kfd_process *p, uint32_t event_id) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 03242975078a..a629e9dc92af 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1099,7 +1099,16 @@ struct kfd_criu_queue_priv_data { struct kfd_criu_event_priv_data { uint32_t object_type; - uint32_t reserved; + uint64_t user_handle; + uint32_t event_id; + uint32_t auto_reset; + uint32_t type; + uint32_t signaled; + + union { + struct kfd_hsa_memory_exception_data memory_exception_data; + struct kfd_hsa_hw_exception_data hw_exception_data; + }; }; int kfd_process_get_queue_info(struct kfd_process *p, @@ -1114,6 +1123,16 @@ int kfd_criu_restore_queue(struct kfd_process *p, uint8_t __user *user_priv_data, uint64_t *priv_data_offset, uint64_t max_priv_data_size); + +int kfd_criu_checkpoint_events(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset); + +int kfd_criu_restore_event(struct file *devkfd, + struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size); /* CRIU - End */ /* Queue Context Management */ @@ -1277,12 +1296,14 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, void kfd_signal_hw_exception_event(u32 pasid); int kfd_set_event(struct kfd_process *p, uint32_t event_id); int kfd_reset_event(struct kfd_process *p, uint32_t event_id); -int kfd_event_page_set(struct kfd_process *p, void *kernel_address, - uint64_t size); +int kfd_kmap_event_page(struct kfd_process *p, uint64_t event_page_offset); + int kfd_event_create(struct file *devkfd, struct kfd_process *p, uint32_t event_type, bool auto_reset, uint32_t node_id, uint32_t *event_id, uint32_t *event_trigger_data, uint64_t *event_page_offset, uint32_t *event_slot_index); + +int kfd_get_num_events(struct kfd_process *p); int kfd_event_destroy(struct kfd_process *p, uint32_t event_id); void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid, From bef153b70c6e3594b849d44a23f806328b9c68d4 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Fri, 9 Apr 2021 12:30:43 -0400 Subject: [PATCH 261/339] drm/amdkfd: CRIU implement gpu_id remapping When doing a restore on a different node, the gpu_id's on the restore node may be different. But the user space application will still refer use the original gpu_id's in the ioctl calls. Adding code to create a gpu id mapping so that kfd can determine actual gpu_id during the user ioctl's. Reviewed-by: Felix Kuehling Signed-off-by: David Yat Sin Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 468 ++++++++++++------ drivers/gpu/drm/amd/amdkfd/kfd_events.c | 45 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 11 + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 32 ++ .../amd/amdkfd/kfd_process_queue_manager.c | 18 +- 5 files changed, 414 insertions(+), 160 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index a4be758647f9..69edeaf3893e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -293,14 +293,17 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, return err; pr_debug("Looking for gpu id 0x%x\n", args->gpu_id); - dev = kfd_device_by_id(args->gpu_id); - if (!dev) { - pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); - return -EINVAL; - } mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); + err = -EINVAL; + goto err_pdd; + } + dev = pdd->dev; + pdd = kfd_bind_process_to_device(dev, p); if (IS_ERR(pdd)) { err = -ESRCH; @@ -345,6 +348,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, err_create_queue: err_bind_process: +err_pdd: mutex_unlock(&p->mutex); return err; } @@ -491,7 +495,6 @@ static int kfd_ioctl_set_memory_policy(struct file *filep, struct kfd_process *p, void *data) { struct kfd_ioctl_set_memory_policy_args *args = data; - struct kfd_dev *dev; int err = 0; struct kfd_process_device *pdd; enum cache_policy default_policy, alternate_policy; @@ -506,13 +509,15 @@ static int kfd_ioctl_set_memory_policy(struct file *filep, return -EINVAL; } - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; - mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); + err = -EINVAL; + goto err_pdd; + } - pdd = kfd_bind_process_to_device(dev, p); + pdd = kfd_bind_process_to_device(pdd->dev, p); if (IS_ERR(pdd)) { err = -ESRCH; goto out; @@ -525,7 +530,7 @@ static int kfd_ioctl_set_memory_policy(struct file *filep, (args->alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) ? cache_policy_coherent : cache_policy_noncoherent; - if (!dev->dqm->ops.set_cache_memory_policy(dev->dqm, + if (!pdd->dev->dqm->ops.set_cache_memory_policy(pdd->dev->dqm, &pdd->qpd, default_policy, alternate_policy, @@ -534,6 +539,7 @@ static int kfd_ioctl_set_memory_policy(struct file *filep, err = -EINVAL; out: +err_pdd: mutex_unlock(&p->mutex); return err; @@ -543,17 +549,18 @@ static int kfd_ioctl_set_trap_handler(struct file *filep, struct kfd_process *p, void *data) { struct kfd_ioctl_set_trap_handler_args *args = data; - struct kfd_dev *dev; int err = 0; struct kfd_process_device *pdd; - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; - mutex_lock(&p->mutex); - pdd = kfd_bind_process_to_device(dev, p); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + err = -EINVAL; + goto err_pdd; + } + + pdd = kfd_bind_process_to_device(pdd->dev, p); if (IS_ERR(pdd)) { err = -ESRCH; goto out; @@ -562,6 +569,7 @@ static int kfd_ioctl_set_trap_handler(struct file *filep, kfd_process_set_trap_handler(&pdd->qpd, args->tba_addr, args->tma_addr); out: +err_pdd: mutex_unlock(&p->mutex); return err; @@ -577,16 +585,20 @@ static int kfd_ioctl_dbg_register(struct file *filep, bool create_ok; long status = 0; - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + status = -EINVAL; + goto err_pdd; + } + dev = pdd->dev; if (dev->adev->asic_type == CHIP_CARRIZO) { pr_debug("kfd_ioctl_dbg_register not supported on CZ\n"); - return -EINVAL; + status = -EINVAL; + goto err_chip_unsupp; } - mutex_lock(&p->mutex); mutex_lock(kfd_get_dbgmgr_mutex()); /* @@ -616,6 +628,8 @@ static int kfd_ioctl_dbg_register(struct file *filep, out: mutex_unlock(kfd_get_dbgmgr_mutex()); +err_pdd: +err_chip_unsupp: mutex_unlock(&p->mutex); return status; @@ -625,13 +639,18 @@ static int kfd_ioctl_dbg_unregister(struct file *filep, struct kfd_process *p, void *data) { struct kfd_ioctl_dbg_unregister_args *args = data; + struct kfd_process_device *pdd; struct kfd_dev *dev; long status; - dev = kfd_device_by_id(args->gpu_id); - if (!dev || !dev->dbgmgr) + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + mutex_unlock(&p->mutex); + if (!pdd || !pdd->dev->dbgmgr) return -EINVAL; + dev = pdd->dev; + if (dev->adev->asic_type == CHIP_CARRIZO) { pr_debug("kfd_ioctl_dbg_unregister not supported on CZ\n"); return -EINVAL; @@ -664,6 +683,7 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep, { struct kfd_ioctl_dbg_address_watch_args *args = data; struct kfd_dev *dev; + struct kfd_process_device *pdd; struct dbg_address_watch_info aw_info; unsigned char *args_buff; long status; @@ -673,15 +693,19 @@ static int kfd_ioctl_dbg_address_watch(struct file *filep, memset((void *) &aw_info, 0, sizeof(struct dbg_address_watch_info)); - dev = kfd_device_by_id(args->gpu_id); - if (!dev) + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + mutex_unlock(&p->mutex); + if (!pdd) { + pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); return -EINVAL; + } + dev = pdd->dev; if (dev->adev->asic_type == CHIP_CARRIZO) { pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n"); return -EINVAL; } - cmd_from_user = (void __user *) args->content_ptr; /* Validate arguments */ @@ -764,6 +788,7 @@ static int kfd_ioctl_dbg_wave_control(struct file *filep, { struct kfd_ioctl_dbg_wave_control_args *args = data; struct kfd_dev *dev; + struct kfd_process_device *pdd; struct dbg_wave_control_info wac_info; unsigned char *args_buff; uint32_t computed_buff_size; @@ -781,9 +806,14 @@ static int kfd_ioctl_dbg_wave_control(struct file *filep, sizeof(wac_info.dbgWave_msg.MemoryVA) + sizeof(wac_info.trapId); - dev = kfd_device_by_id(args->gpu_id); - if (!dev) + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + mutex_unlock(&p->mutex); + if (!pdd) { + pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); return -EINVAL; + } + dev = pdd->dev; if (dev->adev->asic_type == CHIP_CARRIZO) { pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n"); @@ -847,12 +877,14 @@ static int kfd_ioctl_get_clock_counters(struct file *filep, struct kfd_process *p, void *data) { struct kfd_ioctl_get_clock_counters_args *args = data; - struct kfd_dev *dev; + struct kfd_process_device *pdd; - dev = kfd_device_by_id(args->gpu_id); - if (dev) + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + mutex_unlock(&p->mutex); + if (pdd) /* Reading GPU clock counter from KGD */ - args->gpu_clock_counter = amdgpu_amdkfd_get_gpu_clock_counter(dev->adev); + args->gpu_clock_counter = amdgpu_amdkfd_get_gpu_clock_counter(pdd->dev->adev); else /* Node without GPU resource */ args->gpu_clock_counter = 0; @@ -1070,11 +1102,13 @@ static int kfd_ioctl_set_scratch_backing_va(struct file *filep, struct kfd_dev *dev; long err; - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; - mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + err = -EINVAL; + goto err_pdd; + } + dev = pdd->dev; pdd = kfd_bind_process_to_device(dev, p); if (IS_ERR(pdd)) { @@ -1094,6 +1128,7 @@ static int kfd_ioctl_set_scratch_backing_va(struct file *filep, return 0; bind_process_to_device_fail: +err_pdd: mutex_unlock(&p->mutex); return err; } @@ -1102,15 +1137,17 @@ static int kfd_ioctl_get_tile_config(struct file *filep, struct kfd_process *p, void *data) { struct kfd_ioctl_get_tile_config_args *args = data; - struct kfd_dev *dev; + struct kfd_process_device *pdd; struct tile_config config; int err = 0; - dev = kfd_device_by_id(args->gpu_id); - if (!dev) + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + mutex_unlock(&p->mutex); + if (!pdd) return -EINVAL; - amdgpu_amdkfd_get_tile_config(dev->adev, &config); + amdgpu_amdkfd_get_tile_config(pdd->dev->adev, &config); args->gb_addr_config = config.gb_addr_config; args->num_banks = config.num_banks; @@ -1145,40 +1182,37 @@ static int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p, { struct kfd_ioctl_acquire_vm_args *args = data; struct kfd_process_device *pdd; - struct kfd_dev *dev; struct file *drm_file; int ret; - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; - drm_file = fget(args->drm_fd); if (!drm_file) return -EINVAL; mutex_lock(&p->mutex); - - pdd = kfd_get_process_device_data(dev, p); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); if (!pdd) { ret = -EINVAL; - goto err_unlock; + goto err_pdd; } if (pdd->drm_file) { ret = pdd->drm_file == drm_file ? 0 : -EBUSY; - goto err_unlock; + goto err_drm_file; } ret = kfd_process_device_init_vm(pdd, drm_file); if (ret) goto err_unlock; + /* On success, the PDD keeps the drm_file reference */ mutex_unlock(&p->mutex); return 0; err_unlock: +err_pdd: +err_drm_file: mutex_unlock(&p->mutex); fput(drm_file); return ret; @@ -1235,19 +1269,23 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, } mutex_unlock(&p->svms.lock); #endif - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; + mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + err = -EINVAL; + goto err_pdd; + } + + dev = pdd->dev; if ((flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) && (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) && !kfd_dev_is_large_bar(dev)) { pr_err("Alloc host visible vram on small bar is not allowed\n"); - return -EINVAL; + err = -EINVAL; + goto err_large_bar; } - mutex_lock(&p->mutex); - pdd = kfd_bind_process_to_device(dev, p); if (IS_ERR(pdd)) { err = PTR_ERR(pdd); @@ -1308,6 +1346,8 @@ err_free: amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, (struct kgd_mem *)mem, pdd->drm_priv, NULL); err_unlock: +err_pdd: +err_large_bar: mutex_unlock(&p->mutex); return err; } @@ -1318,14 +1358,9 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep, struct kfd_ioctl_free_memory_of_gpu_args *args = data; struct kfd_process_device *pdd; void *mem; - struct kfd_dev *dev; int ret; uint64_t size = 0; - dev = kfd_device_by_id(GET_GPU_ID(args->handle)); - if (!dev) - return -EINVAL; - mutex_lock(&p->mutex); /* * Safeguard to prevent user space from freeing signal BO. @@ -1337,11 +1372,11 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep, goto err_unlock; } - pdd = kfd_get_process_device_data(dev, p); + pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle)); if (!pdd) { pr_err("Process device data doesn't exist\n"); ret = -EINVAL; - goto err_unlock; + goto err_pdd; } mem = kfd_process_device_translate_handle( @@ -1351,7 +1386,7 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep, goto err_unlock; } - ret = amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, + ret = amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, (struct kgd_mem *)mem, pdd->drm_priv, &size); /* If freeing the buffer failed, leave the handle in place for @@ -1364,6 +1399,7 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep, WRITE_ONCE(pdd->vram_usage, pdd->vram_usage - size); err_unlock: +err_pdd: mutex_unlock(&p->mutex); return ret; } @@ -1381,16 +1417,12 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, struct kfd_ioctl_map_memory_to_gpu_args *args = data; struct kfd_process_device *pdd, *peer_pdd; void *mem; - struct kfd_dev *dev, *peer; + struct kfd_dev *dev; long err = 0; int i; uint32_t *devices_arr = NULL; bool table_freed = false; - dev = kfd_device_by_id(GET_GPU_ID(args->handle)); - if (!dev) - return -EINVAL; - if (!args->n_devices) { pr_debug("Device IDs array empty\n"); return -EINVAL; @@ -1414,6 +1446,12 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, } mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle)); + if (!pdd) { + err = -EINVAL; + goto get_process_device_data_failed; + } + dev = pdd->dev; pdd = kfd_bind_process_to_device(dev, p); if (IS_ERR(pdd)) { @@ -1429,21 +1467,22 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, } for (i = args->n_success; i < args->n_devices; i++) { - peer = kfd_device_by_id(devices_arr[i]); - if (!peer) { + peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); + if (!peer_pdd) { pr_debug("Getting device by id failed for 0x%x\n", devices_arr[i]); err = -EINVAL; goto get_mem_obj_from_handle_failed; } - peer_pdd = kfd_bind_process_to_device(peer, p); + peer_pdd = kfd_bind_process_to_device(peer_pdd->dev, p); if (IS_ERR(peer_pdd)) { err = PTR_ERR(peer_pdd); goto get_mem_obj_from_handle_failed; } + err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu( - peer->adev, (struct kgd_mem *)mem, + peer_pdd->dev->adev, (struct kgd_mem *)mem, peer_pdd->drm_priv, &table_freed); if (err) { pr_err("Failed to map to gpu %d/%d\n", @@ -1464,10 +1503,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, /* Flush TLBs after waiting for the page table updates to complete */ if (table_freed || !kfd_flush_tlb_after_unmap(dev)) { for (i = 0; i < args->n_devices; i++) { - peer = kfd_device_by_id(devices_arr[i]); - if (WARN_ON_ONCE(!peer)) - continue; - peer_pdd = kfd_get_process_device_data(peer, p); + peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); if (WARN_ON_ONCE(!peer_pdd)) continue; kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); @@ -1477,6 +1513,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, return err; +get_process_device_data_failed: bind_process_to_device_failed: get_mem_obj_from_handle_failed: map_memory_to_gpu_failed: @@ -1494,14 +1531,9 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, struct kfd_ioctl_unmap_memory_from_gpu_args *args = data; struct kfd_process_device *pdd, *peer_pdd; void *mem; - struct kfd_dev *dev, *peer; long err = 0; uint32_t *devices_arr = NULL, i; - dev = kfd_device_by_id(GET_GPU_ID(args->handle)); - if (!dev) - return -EINVAL; - if (!args->n_devices) { pr_debug("Device IDs array empty\n"); return -EINVAL; @@ -1525,8 +1557,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, } mutex_lock(&p->mutex); - - pdd = kfd_get_process_device_data(dev, p); + pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(args->handle)); if (!pdd) { err = -EINVAL; goto bind_process_to_device_failed; @@ -1540,19 +1571,13 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, } for (i = args->n_success; i < args->n_devices; i++) { - peer = kfd_device_by_id(devices_arr[i]); - if (!peer) { + peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); + if (!peer_pdd) { err = -EINVAL; goto get_mem_obj_from_handle_failed; } - - peer_pdd = kfd_get_process_device_data(peer, p); - if (!peer_pdd) { - err = -ENODEV; - goto get_mem_obj_from_handle_failed; - } err = amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( - peer->adev, (struct kgd_mem *)mem, peer_pdd->drm_priv); + peer_pdd->dev->adev, (struct kgd_mem *)mem, peer_pdd->drm_priv); if (err) { pr_err("Failed to unmap from gpu %d/%d\n", i, args->n_devices); @@ -1562,8 +1587,8 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, } mutex_unlock(&p->mutex); - if (kfd_flush_tlb_after_unmap(dev)) { - err = amdgpu_amdkfd_gpuvm_sync_memory(dev->adev, + if (kfd_flush_tlb_after_unmap(pdd->dev)) { + err = amdgpu_amdkfd_gpuvm_sync_memory(pdd->dev->adev, (struct kgd_mem *) mem, true); if (err) { pr_debug("Sync memory failed, wait interrupted by user signal\n"); @@ -1572,10 +1597,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, /* Flush TLBs after waiting for the page table updates to complete */ for (i = 0; i < args->n_devices; i++) { - peer = kfd_device_by_id(devices_arr[i]); - if (WARN_ON_ONCE(!peer)) - continue; - peer_pdd = kfd_get_process_device_data(peer, p); + peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); if (WARN_ON_ONCE(!peer_pdd)) continue; kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); @@ -1695,29 +1717,29 @@ static int kfd_ioctl_import_dmabuf(struct file *filep, struct kfd_ioctl_import_dmabuf_args *args = data; struct kfd_process_device *pdd; struct dma_buf *dmabuf; - struct kfd_dev *dev; int idr_handle; uint64_t size; void *mem; int r; - dev = kfd_device_by_id(args->gpu_id); - if (!dev) - return -EINVAL; - dmabuf = dma_buf_get(args->dmabuf_fd); if (IS_ERR(dmabuf)) return PTR_ERR(dmabuf); mutex_lock(&p->mutex); + pdd = kfd_process_device_data_by_id(p, args->gpu_id); + if (!pdd) { + r = -EINVAL; + goto err_unlock; + } - pdd = kfd_bind_process_to_device(dev, p); + pdd = kfd_bind_process_to_device(pdd->dev, p); if (IS_ERR(pdd)) { r = PTR_ERR(pdd); goto err_unlock; } - r = amdgpu_amdkfd_gpuvm_import_dmabuf(dev->adev, dmabuf, + r = amdgpu_amdkfd_gpuvm_import_dmabuf(pdd->dev->adev, dmabuf, args->va_addr, pdd->drm_priv, (struct kgd_mem **)&mem, &size, NULL); @@ -1738,7 +1760,7 @@ static int kfd_ioctl_import_dmabuf(struct file *filep, return 0; err_free: - amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->adev, (struct kgd_mem *)mem, + amdgpu_amdkfd_gpuvm_free_memory_of_gpu(pdd->dev->adev, (struct kgd_mem *)mem, pdd->drm_priv, NULL); err_unlock: mutex_unlock(&p->mutex); @@ -1751,13 +1773,16 @@ static int kfd_ioctl_smi_events(struct file *filep, struct kfd_process *p, void *data) { struct kfd_ioctl_smi_events_args *args = data; - struct kfd_dev *dev; + struct kfd_process_device *pdd; - dev = kfd_device_by_id(args->gpuid); - if (!dev) + mutex_lock(&p->mutex); + + pdd = kfd_process_device_data_by_id(p, args->gpuid); + mutex_unlock(&p->mutex); + if (!pdd) return -EINVAL; - return kfd_smi_event_open(dev, &args->anon_fd); + return kfd_smi_event_open(pdd->dev, &args->anon_fd); } static int kfd_ioctl_set_xnack_mode(struct file *filep, @@ -1834,6 +1859,62 @@ static int criu_checkpoint_process(struct kfd_process *p, return ret; } +static int criu_checkpoint_devices(struct kfd_process *p, + uint32_t num_devices, + uint8_t __user *user_addr, + uint8_t __user *user_priv_data, + uint64_t *priv_offset) +{ + struct kfd_criu_device_priv_data *device_priv = NULL; + struct kfd_criu_device_bucket *device_buckets = NULL; + int ret = 0, i; + + device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), GFP_KERNEL); + if (!device_buckets) { + ret = -ENOMEM; + goto exit; + } + + device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL); + if (!device_priv) { + ret = -ENOMEM; + goto exit; + } + + for (i = 0; i < num_devices; i++) { + struct kfd_process_device *pdd = p->pdds[i]; + + device_buckets[i].user_gpu_id = pdd->user_gpu_id; + device_buckets[i].actual_gpu_id = pdd->dev->id; + + /* + * priv_data does not contain useful information for now and is reserved for + * future use, so we do not set its contents. + */ + } + + ret = copy_to_user(user_addr, device_buckets, num_devices * sizeof(*device_buckets)); + if (ret) { + pr_err("Failed to copy device information to user\n"); + ret = -EFAULT; + goto exit; + } + + ret = copy_to_user(user_priv_data + *priv_offset, + device_priv, + num_devices * sizeof(*device_priv)); + if (ret) { + pr_err("Failed to copy device information to user\n"); + ret = -EFAULT; + } + *priv_offset += num_devices * sizeof(*device_priv); + +exit: + kvfree(device_buckets); + kvfree(device_priv); + return ret; +} + uint32_t get_process_num_bos(struct kfd_process *p) { uint32_t num_of_bos = 0; @@ -1902,9 +1983,9 @@ static int criu_checkpoint_bos(struct kfd_process *p, bo_bucket = &bo_buckets[bo_index]; bo_priv = &bo_privs[bo_index]; + bo_bucket->gpu_id = pdd->user_gpu_id; bo_bucket->addr = (uint64_t)kgd_mem->va; bo_bucket->size = amdgpu_bo_size(dumper_bo); - bo_bucket->gpu_id = pdd->dev->id; bo_bucket->alloc_flags = (uint32_t)kgd_mem->alloc_flags; bo_priv->idr_handle = id; @@ -1928,7 +2009,7 @@ static int criu_checkpoint_bos(struct kfd_process *p, for (i = 0; i < p->n_pdds; i++) { if (amdgpu_amdkfd_bo_mapped_to_dev(p->pdds[i]->dev->adev, kgd_mem)) - bo_priv->mapped_gpuids[dev_idx++] = p->pdds[i]->dev->id; + bo_priv->mapped_gpuids[dev_idx++] = p->pdds[i]->user_gpu_id; } pr_debug("bo_size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n" @@ -1967,6 +2048,7 @@ exit: } static int criu_get_process_object_info(struct kfd_process *p, + uint32_t *num_devices, uint32_t *num_bos, uint32_t *num_objects, uint64_t *objs_priv_size) @@ -1976,6 +2058,7 @@ static int criu_get_process_object_info(struct kfd_process *p, uint32_t num_queues, num_events, num_svm_ranges; uint64_t queues_priv_data_size; + *num_devices = p->n_pdds; *num_bos = get_process_num_bos(p); ret = kfd_process_get_queue_info(p, &num_queues, &queues_priv_data_size); @@ -1989,6 +2072,7 @@ static int criu_get_process_object_info(struct kfd_process *p, if (objs_priv_size) { priv_size = sizeof(struct kfd_criu_process_priv_data); + priv_size += *num_devices * sizeof(struct kfd_criu_device_priv_data); priv_size += *num_bos * sizeof(struct kfd_criu_bo_priv_data); priv_size += queues_priv_data_size; priv_size += num_events * sizeof(struct kfd_criu_event_priv_data); @@ -2003,10 +2087,10 @@ static int criu_checkpoint(struct file *filep, struct kfd_ioctl_criu_args *args) { int ret; - uint32_t num_bos, num_objects; + uint32_t num_devices, num_bos, num_objects; uint64_t priv_size, priv_offset = 0; - if (!args->bos || !args->priv_data) + if (!args->devices || !args->bos || !args->priv_data) return -EINVAL; mutex_lock(&p->mutex); @@ -2025,11 +2109,12 @@ static int criu_checkpoint(struct file *filep, goto exit_unlock; } - ret = criu_get_process_object_info(p, &num_bos, &num_objects, &priv_size); + ret = criu_get_process_object_info(p, &num_devices, &num_bos, &num_objects, &priv_size); if (ret) goto exit_unlock; - if (num_bos != args->num_bos || + if (num_devices != args->num_devices || + num_bos != args->num_bos || num_objects != args->num_objects || priv_size != args->priv_data_size) { @@ -2042,6 +2127,11 @@ static int criu_checkpoint(struct file *filep, if (ret) goto exit_unlock; + ret = criu_checkpoint_devices(p, num_devices, (uint8_t __user *)args->devices, + (uint8_t __user *)args->priv_data, &priv_offset); + if (ret) + goto exit_unlock; + ret = criu_checkpoint_bos(p, num_bos, (uint8_t __user *)args->bos, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) @@ -2102,6 +2192,108 @@ exit: return ret; } +static int criu_restore_devices(struct kfd_process *p, + struct kfd_ioctl_criu_args *args, + uint64_t *priv_offset, + uint64_t max_priv_data_size) +{ + struct kfd_criu_device_bucket *device_buckets; + struct kfd_criu_device_priv_data *device_privs; + int ret = 0; + uint32_t i; + + if (args->num_devices != p->n_pdds) + return -EINVAL; + + if (*priv_offset + (args->num_devices * sizeof(*device_privs)) > max_priv_data_size) + return -EINVAL; + + device_buckets = kmalloc_array(args->num_devices, sizeof(*device_buckets), GFP_KERNEL); + if (!device_buckets) + return -ENOMEM; + + ret = copy_from_user(device_buckets, (void __user *)args->devices, + args->num_devices * sizeof(*device_buckets)); + if (ret) { + pr_err("Failed to copy devices buckets from user\n"); + ret = -EFAULT; + goto exit; + } + + for (i = 0; i < args->num_devices; i++) { + struct kfd_dev *dev; + struct kfd_process_device *pdd; + struct file *drm_file; + + /* device private data is not currently used */ + + if (!device_buckets[i].user_gpu_id) { + pr_err("Invalid user gpu_id\n"); + ret = -EINVAL; + goto exit; + } + + dev = kfd_device_by_id(device_buckets[i].actual_gpu_id); + if (!dev) { + pr_err("Failed to find device with gpu_id = %x\n", + device_buckets[i].actual_gpu_id); + ret = -EINVAL; + goto exit; + } + + pdd = kfd_get_process_device_data(dev, p); + if (!pdd) { + pr_err("Failed to get pdd for gpu_id = %x\n", + device_buckets[i].actual_gpu_id); + ret = -EINVAL; + goto exit; + } + pdd->user_gpu_id = device_buckets[i].user_gpu_id; + + drm_file = fget(device_buckets[i].drm_fd); + if (!drm_file) { + pr_err("Invalid render node file descriptor sent from plugin (%d)\n", + device_buckets[i].drm_fd); + ret = -EINVAL; + goto exit; + } + + if (pdd->drm_file) { + ret = -EINVAL; + goto exit; + } + + /* create the vm using render nodes for kfd pdd */ + if (kfd_process_device_init_vm(pdd, drm_file)) { + pr_err("could not init vm for given pdd\n"); + /* On success, the PDD keeps the drm_file reference */ + fput(drm_file); + ret = -EINVAL; + goto exit; + } + /* + * pdd now already has the vm bound to render node so below api won't create a new + * exclusive kfd mapping but use existing one with renderDXXX but is still needed + * for iommu v2 binding and runtime pm. + */ + pdd = kfd_bind_process_to_device(dev, p); + if (IS_ERR(pdd)) { + ret = PTR_ERR(pdd); + goto exit; + } + } + + /* + * We are not copying device private data from user as we are not using the data for now, + * but we still adjust for its private data. + */ + *priv_offset += args->num_devices * sizeof(*device_privs); + +exit: + kfree(device_buckets); + return ret; +} + static int criu_restore_bos(struct kfd_process *p, struct kfd_ioctl_criu_args *args, uint64_t *priv_offset, @@ -2160,19 +2352,6 @@ static int criu_restore_bos(struct kfd_process *p, bo_bucket = &bo_buckets[i]; bo_priv = &bo_privs[i]; - dev = kfd_device_by_id(bo_bucket->gpu_id); - if (!dev) { - ret = -EINVAL; - pr_err("Failed to get pdd\n"); - goto exit; - } - pdd = kfd_get_process_device_data(dev, p); - if (!pdd) { - ret = -EINVAL; - pr_err("Failed to get pdd\n"); - goto exit; - } - pr_debug("kfd restore ioctl - bo_bucket[%d]:\n", i); pr_debug("size = 0x%llx, bo_addr = 0x%llx bo_offset = 0x%llx\n" "gpu_id = 0x%x alloc_flags = 0x%x\n" @@ -2184,6 +2363,14 @@ static int criu_restore_bos(struct kfd_process *p, bo_bucket->alloc_flags, bo_priv->idr_handle); + pdd = kfd_process_device_data_by_id(p, bo_bucket->gpu_id); + if (!pdd) { + pr_err("Failed to get pdd\n"); + ret = -ENODEV; + goto exit; + } + dev = pdd->dev; + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) { pr_debug("restore ioctl: KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL\n"); if (bo_bucket->size != kfd_doorbell_process_slice(dev)) { @@ -2265,12 +2452,12 @@ static int criu_restore_bos(struct kfd_process *p, if (!bo_priv->mapped_gpuids[j]) break; - peer = kfd_device_by_id(bo_priv->mapped_gpuids[j]); - if (!peer) { - pr_debug("Getting device by id failed for 0x%x\n", pdd->dev->id); + peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]); + if (IS_ERR(peer_pdd)) { ret = -EINVAL; goto exit; } + peer = peer_pdd->dev; peer_pdd = kfd_bind_process_to_device(peer, p); if (IS_ERR(peer_pdd)) { @@ -2414,6 +2601,10 @@ static int criu_restore(struct file *filep, if (ret) goto exit_unlock; + ret = criu_restore_devices(p, args, &priv_offset, args->priv_data_size); + if (ret) + goto exit_unlock; + ret = criu_restore_bos(p, args, &priv_offset, args->priv_data_size); if (ret) goto exit_unlock; @@ -2519,13 +2710,14 @@ static int criu_process_info(struct file *filep, args->pid = task_pid_nr_ns(p->lead_thread, task_active_pid_ns(p->lead_thread)); - ret = criu_get_process_object_info(p, &args->num_bos, &args->num_objects, - &args->priv_data_size); + ret = criu_get_process_object_info(p, &args->num_devices, &args->num_bos, + &args->num_objects, &args->priv_data_size); if (ret) goto err_unlock; - dev_dbg(kfd_device, "Num of bos:%u objects:%u priv_data_size:%lld\n", - args->num_bos, args->num_objects, args->priv_data_size); + dev_dbg(kfd_device, "Num of devices:%u bos:%u objects:%u priv_data_size:%lld\n", + args->num_devices, args->num_bos, args->num_objects, + args->priv_data_size); err_unlock: if (ret) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 9341ce5d0fc9..b5eda1e04f34 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -342,11 +342,12 @@ int kfd_kmap_event_page(struct kfd_process *p, uint64_t event_page_offset) return -EINVAL; } - kfd = kfd_device_by_id(GET_GPU_ID(event_page_offset)); - if (!kfd) { + pdd = kfd_process_device_data_by_id(p, GET_GPU_ID(event_page_offset)); + if (!pdd) { pr_err("Getting device by id failed in %s\n", __func__); return -EINVAL; } + kfd = pdd->dev; pdd = kfd_bind_process_to_device(kfd, p); if (IS_ERR(pdd)) @@ -1094,6 +1095,7 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, u32 pasid, { struct kfd_hsa_memory_exception_data memory_exception_data; struct vm_area_struct *vma; + int user_gpu_id; /* * Because we are called from arbitrary context (workqueue) as opposed @@ -1115,12 +1117,17 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, u32 pasid, return; /* Process is exiting */ } + user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id); + if (unlikely(user_gpu_id == -EINVAL)) { + WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", dev->id); + return; + } memset(&memory_exception_data, 0, sizeof(memory_exception_data)); mmap_read_lock(mm); vma = find_vma(mm, address); - memory_exception_data.gpu_id = dev->id; + memory_exception_data.gpu_id = user_gpu_id; memory_exception_data.va = address; /* Set failure reason */ memory_exception_data.failure.NotPresent = 1; @@ -1196,11 +1203,19 @@ void kfd_signal_vm_fault_event(struct kfd_dev *dev, u32 pasid, uint32_t id; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); struct kfd_hsa_memory_exception_data memory_exception_data; + int user_gpu_id; if (!p) return; /* Presumably process exited. */ + + user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id); + if (unlikely(user_gpu_id == -EINVAL)) { + WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", dev->id); + return; + } + memset(&memory_exception_data, 0, sizeof(memory_exception_data)); - memory_exception_data.gpu_id = dev->id; + memory_exception_data.gpu_id = user_gpu_id; memory_exception_data.failure.imprecise = true; /* Set failure reason */ if (info) { @@ -1240,27 +1255,34 @@ void kfd_signal_reset_event(struct kfd_dev *dev) /* Whole gpu reset caused by GPU hang and memory is lost */ memset(&hw_exception_data, 0, sizeof(hw_exception_data)); - hw_exception_data.gpu_id = dev->id; hw_exception_data.memory_lost = 1; hw_exception_data.reset_cause = reset_cause; memset(&memory_exception_data, 0, sizeof(memory_exception_data)); memory_exception_data.ErrorType = KFD_MEM_ERR_SRAM_ECC; - memory_exception_data.gpu_id = dev->id; memory_exception_data.failure.imprecise = true; idx = srcu_read_lock(&kfd_processes_srcu); hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { + int user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id); + + if (unlikely(user_gpu_id == -EINVAL)) { + WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", dev->id); + continue; + } + mutex_lock(&p->event_mutex); id = KFD_FIRST_NONSIGNAL_EVENT_ID; idr_for_each_entry_continue(&p->event_idr, ev, id) { if (ev->type == KFD_EVENT_TYPE_HW_EXCEPTION) { ev->hw_exception_data = hw_exception_data; + ev->hw_exception_data.gpu_id = user_gpu_id; set_event(ev); } if (ev->type == KFD_EVENT_TYPE_MEMORY && reset_cause == KFD_HW_EXCEPTION_ECC) { ev->memory_exception_data = memory_exception_data; + ev->memory_exception_data.gpu_id = user_gpu_id; set_event(ev); } } @@ -1276,18 +1298,25 @@ void kfd_signal_poison_consumed_event(struct kfd_dev *dev, u32 pasid) struct kfd_hsa_hw_exception_data hw_exception_data; struct kfd_event *ev; uint32_t id = KFD_FIRST_NONSIGNAL_EVENT_ID; + int user_gpu_id; if (!p) return; /* Presumably process exited. */ + user_gpu_id = kfd_process_get_user_gpu_id(p, dev->id); + if (unlikely(user_gpu_id == -EINVAL)) { + WARN_ONCE(1, "Could not get user_gpu_id from dev->id:%x\n", dev->id); + return; + } + memset(&hw_exception_data, 0, sizeof(hw_exception_data)); - hw_exception_data.gpu_id = dev->id; + hw_exception_data.gpu_id = user_gpu_id; hw_exception_data.memory_lost = 1; hw_exception_data.reset_cause = KFD_HW_EXCEPTION_ECC; memset(&memory_exception_data, 0, sizeof(memory_exception_data)); memory_exception_data.ErrorType = KFD_MEM_ERR_POISON_CONSUMED; - memory_exception_data.gpu_id = dev->id; + memory_exception_data.gpu_id = user_gpu_id; memory_exception_data.failure.imprecise = true; mutex_lock(&p->event_mutex); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index a629e9dc92af..df68c4274bd9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -774,6 +774,12 @@ struct kfd_process_device { uint64_t faults; uint64_t page_in; uint64_t page_out; + /* + * If this process has been checkpointed before, then the user + * application will use the original gpu_id on the + * checkpointed node to refer to this device. + */ + uint32_t user_gpu_id; }; #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) @@ -933,6 +939,11 @@ int kfd_process_restore_queues(struct kfd_process *p); void kfd_suspend_all_processes(void); int kfd_resume_all_processes(void); +struct kfd_process_device *kfd_process_device_data_by_id(struct kfd_process *process, + uint32_t gpu_id); + +int kfd_process_get_user_gpu_id(struct kfd_process *p, uint32_t actual_gpu_id); + int kfd_process_device_init_vm(struct kfd_process_device *pdd, struct file *drm_file); struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 0649064b8e95..06e6e9180fbc 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1526,6 +1526,7 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, pdd->runtime_inuse = false; pdd->vram_usage = 0; pdd->sdma_past_activity_counter = 0; + pdd->user_gpu_id = dev->id; atomic64_set(&pdd->evict_duration_counter, 0); p->pdds[p->n_pdds++] = pdd; @@ -1981,6 +1982,37 @@ void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type) } } +struct kfd_process_device *kfd_process_device_data_by_id(struct kfd_process *p, uint32_t gpu_id) +{ + int i; + + if (gpu_id) { + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; + + if (pdd->user_gpu_id == gpu_id) + return pdd; + } + } + return NULL; +} + +int kfd_process_get_user_gpu_id(struct kfd_process *p, uint32_t actual_gpu_id) +{ + int i; + + if (!actual_gpu_id) + return 0; + + for (i = 0; i < p->n_pdds; i++) { + struct kfd_process_device *pdd = p->pdds[i]; + + if (pdd->dev->id == actual_gpu_id) + return pdd->user_gpu_id; + } + return -EINVAL; +} + #if defined(CONFIG_DEBUG_FS) int kfd_debugfs_mqds_by_process(struct seq_file *m, void *data) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index bd89dd0ca83e..70ea4849e6a2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -610,7 +610,7 @@ static int criu_checkpoint_queue(struct kfd_process_device *pdd, mqd = (void *)(q_data + 1); ctl_stack = mqd + q_data->mqd_size; - q_data->gpu_id = pdd->dev->id; + q_data->gpu_id = pdd->user_gpu_id; q_data->type = q->properties.type; q_data->format = q->properties.format; q_data->q_id = q->properties.queue_id; @@ -769,7 +769,6 @@ int kfd_criu_restore_queue(struct kfd_process *p, uint64_t q_extra_data_size; struct queue_properties qp; unsigned int queue_id; - struct kfd_dev *dev; int ret = 0; if (*priv_data_offset + sizeof(*q_data) > max_priv_data_size) @@ -807,20 +806,11 @@ int kfd_criu_restore_queue(struct kfd_process *p, *priv_data_offset += q_extra_data_size; - dev = kfd_device_by_id(q_data->gpu_id); - if (!dev) { - pr_err("Could not get kfd_dev from gpu_id = 0x%x\n", - q_data->gpu_id); - - ret = -EINVAL; - goto exit; - } - - pdd = kfd_get_process_device_data(dev, p); + pdd = kfd_process_device_data_by_id(p, q_data->gpu_id); if (!pdd) { pr_err("Failed to get pdd\n"); - ret = -EFAULT; - return ret; + ret = -EINVAL; + goto exit; } /* data stored in this order: mqd, ctl_stack */ mqd = q_extra_data; From be072b06c7397004e6464b4225e13c31ed0b9ca3 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 29 Jun 2021 18:30:36 -0400 Subject: [PATCH 262/339] drm/amdkfd: CRIU export BOs as prime dmabuf objects KFD buffer objects do not associate a GEM handle with them so cannot directly be used with libdrm to initiate a system dma (sDMA) operation to speedup the checkpoint and restore operation so export them as dmabuf objects and use with libdrm helper (amdgpu_bo_import) to further process the sdma command submissions. With sDMA, we see huge improvement in checkpoint and restore operations compared to the generic pci based access via host data path. Suggested-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: David Yat Sin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 71 +++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 69edeaf3893e..ab5107a3fe36 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "kfd_priv.h" #include "kfd_device_queue_manager.h" @@ -42,6 +43,7 @@ #include "kfd_svm.h" #include "amdgpu_amdkfd.h" #include "kfd_smi_events.h" +#include "amdgpu_dma_buf.h" static long kfd_ioctl(struct file *, unsigned int, unsigned long); static int kfd_open(struct inode *, struct file *); @@ -1936,6 +1938,33 @@ uint32_t get_process_num_bos(struct kfd_process *p) return num_of_bos; } +static int criu_get_prime_handle(struct drm_gem_object *gobj, int flags, + u32 *shared_fd) +{ + struct dma_buf *dmabuf; + int ret; + + dmabuf = amdgpu_gem_prime_export(gobj, flags); + if (IS_ERR(dmabuf)) { + ret = PTR_ERR(dmabuf); + pr_err("dmabuf export failed for the BO\n"); + return ret; + } + + ret = dma_buf_fd(dmabuf, flags); + if (ret < 0) { + pr_err("dmabuf create fd failed, ret:%d\n", ret); + goto out_free_dmabuf; + } + + *shared_fd = ret; + return 0; + +out_free_dmabuf: + dma_buf_put(dmabuf); + return ret; +} + static int criu_checkpoint_bos(struct kfd_process *p, uint32_t num_bos, uint8_t __user *user_bos, @@ -1997,6 +2026,14 @@ static int criu_checkpoint_bos(struct kfd_process *p, goto exit; } } + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + ret = criu_get_prime_handle(&dumper_bo->tbo.base, + bo_bucket->alloc_flags & + KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0, + &bo_bucket->dmabuf_fd); + if (ret) + goto exit; + } if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_DOORBELL) bo_bucket->offset = KFD_MMAP_TYPE_DOORBELL | KFD_MMAP_GPU_ID(pdd->dev->id); @@ -2041,6 +2078,10 @@ static int criu_checkpoint_bos(struct kfd_process *p, *priv_offset += num_bos * sizeof(*bo_privs); exit: + while (ret && bo_index--) { + if (bo_buckets[bo_index].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) + close_fd(bo_buckets[bo_index].dmabuf_fd); + } kvfree(bo_buckets); kvfree(bo_privs); @@ -2141,16 +2182,28 @@ static int criu_checkpoint(struct file *filep, ret = kfd_criu_checkpoint_queues(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto exit_unlock; + goto close_bo_fds; ret = kfd_criu_checkpoint_events(p, (uint8_t __user *)args->priv_data, &priv_offset); if (ret) - goto exit_unlock; + goto close_bo_fds; /* TODO: Dump SVM-Ranges */ } +close_bo_fds: + if (ret) { + /* If IOCTL returns err, user assumes all FDs opened in criu_dump_bos are closed */ + uint32_t i; + struct kfd_criu_bo_bucket *bo_buckets = (struct kfd_criu_bo_bucket *) args->bos; + + for (i = 0; i < num_bos; i++) { + if (bo_buckets[i].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) + close_fd(bo_buckets[i].dmabuf_fd); + } + } + exit_unlock: mutex_unlock(&p->mutex); if (ret) @@ -2345,6 +2398,7 @@ static int criu_restore_bos(struct kfd_process *p, struct kfd_criu_bo_priv_data *bo_priv; struct kfd_dev *dev; struct kfd_process_device *pdd; + struct kgd_mem *kgd_mem; void *mem; u64 offset; int idr_handle; @@ -2484,6 +2538,15 @@ static int criu_restore_bos(struct kfd_process *p, } pr_debug("map memory was successful for the BO\n"); + /* create the dmabuf object and export the bo */ + kgd_mem = (struct kgd_mem *)mem; + if (bo_bucket->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) { + ret = criu_get_prime_handle(&kgd_mem->bo->tbo.base, + DRM_RDWR, + &bo_bucket->dmabuf_fd); + if (ret) + goto exit; + } } /* done */ if (flush_tlbs) { @@ -2511,6 +2574,10 @@ static int criu_restore_bos(struct kfd_process *p, ret = -EFAULT; exit: + while (ret && i--) { + if (bo_buckets[i].alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) + close_fd(bo_buckets[i].dmabuf_fd); + } kvfree(bo_buckets); kvfree(bo_privs); return ret; From 4717fe3d8dec42bc951a44f41efc95d635d26325 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Fri, 19 Nov 2021 10:23:05 -0500 Subject: [PATCH 263/339] drm/amdkfd: CRIU checkpoint and restore xnack mode Recoverable page faults are represented by the xnack mode setting inside a kfd process and are used to represent the device page faults. For CR, we don't consider negative values which are typically used for querying the current xnack mode without modifying it. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 15 +++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index ab5107a3fe36..3ec44f71307d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1848,6 +1848,11 @@ static int criu_checkpoint_process(struct kfd_process *p, memset(&process_priv, 0, sizeof(process_priv)); process_priv.version = KFD_CRIU_PRIV_VERSION; + /* For CR, we don't consider negative xnack mode which is used for + * querying without changing it, here 0 simply means disabled and 1 + * means enabled so retry for finding a valid PTE. + */ + process_priv.xnack_mode = p->xnack_enabled ? 1 : 0; ret = copy_to_user(user_priv_data + *priv_offset, &process_priv, sizeof(process_priv)); @@ -2241,6 +2246,16 @@ static int criu_restore_process(struct kfd_process *p, return -EINVAL; } + pr_debug("Setting XNACK mode\n"); + if (process_priv.xnack_mode && !kfd_process_xnack_mode(p, true)) { + pr_err("xnack mode cannot be set\n"); + ret = -EPERM; + goto exit; + } else { + pr_debug("set xnack mode: %d\n", process_priv.xnack_mode); + p->xnack_enabled = process_priv.xnack_mode; + } + exit: return ret; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index df68c4274bd9..903ad4a263f0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1056,6 +1056,7 @@ void kfd_process_set_trap_handler(struct qcm_process_device *qpd, struct kfd_criu_process_priv_data { uint32_t version; + uint32_t xnack_mode; }; struct kfd_criu_device_priv_data { From d1289b41ec4db347794abfed7525e33dd2d9503b Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Wed, 27 Oct 2021 01:08:51 -0400 Subject: [PATCH 264/339] drm/amdkfd: CRIU allow external mm for svm ranges Both svm_range_get_attr and svm_range_set_attr helpers use mm struct from current but for a Checkpoint or Restore operation, the current->mm will fetch the mm for the CRIU master process. So modify these helpers to accept the task mm for a target kfd process to support Checkpoint Restore. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index ffec25e642e2..d34508f5e88b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3203,10 +3203,10 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) } static int -svm_range_set_attr(struct kfd_process *p, uint64_t start, uint64_t size, - uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) +svm_range_set_attr(struct kfd_process *p, struct mm_struct *mm, + uint64_t start, uint64_t size, uint32_t nattr, + struct kfd_ioctl_svm_attribute *attrs) { - struct mm_struct *mm = current->mm; struct list_head update_list; struct list_head insert_list; struct list_head remove_list; @@ -3305,8 +3305,9 @@ out: } static int -svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, - uint32_t nattr, struct kfd_ioctl_svm_attribute *attrs) +svm_range_get_attr(struct kfd_process *p, struct mm_struct *mm, + uint64_t start, uint64_t size, uint32_t nattr, + struct kfd_ioctl_svm_attribute *attrs) { DECLARE_BITMAP(bitmap_access, MAX_GPU_INSTANCE); DECLARE_BITMAP(bitmap_aip, MAX_GPU_INSTANCE); @@ -3316,7 +3317,6 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size, bool get_accessible = false; bool get_flags = false; uint64_t last = start + size - 1UL; - struct mm_struct *mm = current->mm; uint8_t granularity = 0xff; struct interval_tree_node *node; struct svm_range_list *svms; @@ -3485,6 +3485,7 @@ int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, uint64_t size, uint32_t nattrs, struct kfd_ioctl_svm_attribute *attrs) { + struct mm_struct *mm = current->mm; int r; start >>= PAGE_SHIFT; @@ -3492,10 +3493,10 @@ svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, switch (op) { case KFD_IOCTL_SVM_OP_SET_ATTR: - r = svm_range_set_attr(p, start, size, nattrs, attrs); + r = svm_range_set_attr(p, mm, start, size, nattrs, attrs); break; case KFD_IOCTL_SVM_OP_GET_ATTR: - r = svm_range_get_attr(p, start, size, nattrs, attrs); + r = svm_range_get_attr(p, mm, start, size, nattrs, attrs); break; default: r = EINVAL; From d763d8030f440441177d9638ffb0be39cba32a03 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Wed, 1 Dec 2021 10:26:42 -0500 Subject: [PATCH 265/339] drm/amdkfd: use user_gpu_id for svm ranges Currently the SVM ranges use actual_gpu_id but with Checkpoint Restore support its possible that the SVM ranges can be resumed on another node where the actual_gpu_id may not be same as the original (user_gpu_id) gpu id. So modify svm code to use user_gpu_id. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 06e6e9180fbc..8e2780d2f735 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1797,7 +1797,7 @@ int kfd_process_gpuidx_from_gpuid(struct kfd_process *p, uint32_t gpu_id) int i; for (i = 0; i < p->n_pdds; i++) - if (p->pdds[i] && gpu_id == p->pdds[i]->dev->id) + if (p->pdds[i] && gpu_id == p->pdds[i]->user_gpu_id) return i; return -EINVAL; } @@ -1810,7 +1810,7 @@ kfd_process_gpuid_from_adev(struct kfd_process *p, struct amdgpu_device *adev, for (i = 0; i < p->n_pdds; i++) if (p->pdds[i] && p->pdds[i]->dev->adev == adev) { - *gpuid = p->pdds[i]->dev->id; + *gpuid = p->pdds[i]->user_gpu_id; *gpuidx = i; return 0; } From 08a987a8a02b073c620b5f3f363714ccd98c0bc0 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 2 Nov 2021 20:59:17 -0400 Subject: [PATCH 266/339] drm/amdkfd: CRIU Discover svm ranges A KFD process may contain a number of virtual address ranges for shared virtual memory management and each such range can have many SVM attributes spanning across various nodes within the process boundary. This change reports the total number of such SVM ranges and their total private data size by extending the PROCESS_INFO op of the the CRIU IOCTL to discover the svm ranges in the target process and a future patches brings in the required support for checkpoint and restore for SVM ranges. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 12 +++-- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 +- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 59 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 11 +++++ 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 3ec44f71307d..a755ea68a428 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2099,10 +2099,9 @@ static int criu_get_process_object_info(struct kfd_process *p, uint32_t *num_objects, uint64_t *objs_priv_size) { - int ret; - uint64_t priv_size; + uint64_t queues_priv_data_size, svm_priv_data_size, priv_size; uint32_t num_queues, num_events, num_svm_ranges; - uint64_t queues_priv_data_size; + int ret; *num_devices = p->n_pdds; *num_bos = get_process_num_bos(p); @@ -2112,7 +2111,10 @@ static int criu_get_process_object_info(struct kfd_process *p, return ret; num_events = kfd_get_num_events(p); - num_svm_ranges = 0; /* TODO: Implement SVM-Ranges */ + + ret = svm_range_get_info(p, &num_svm_ranges, &svm_priv_data_size); + if (ret) + return ret; *num_objects = num_queues + num_events + num_svm_ranges; @@ -2122,7 +2124,7 @@ static int criu_get_process_object_info(struct kfd_process *p, priv_size += *num_bos * sizeof(struct kfd_criu_bo_priv_data); priv_size += queues_priv_data_size; priv_size += num_events * sizeof(struct kfd_criu_event_priv_data); - /* TODO: Add SVM ranges priv size */ + priv_size += svm_priv_data_size; *objs_priv_size = priv_size; } return 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 903ad4a263f0..715dd0d4fac5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1082,7 +1082,10 @@ enum kfd_criu_object_type { struct kfd_criu_svm_range_priv_data { uint32_t object_type; - uint32_t reserved; + uint64_t start_addr; + uint64_t size; + /* Variable length array of attributes */ + struct kfd_ioctl_svm_attribute attrs[0]; }; struct kfd_criu_queue_priv_data { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index d34508f5e88b..64cd7712c098 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3481,6 +3481,65 @@ fill_values: return 0; } +int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges, + uint64_t *svm_priv_data_size) +{ + uint64_t total_size, accessibility_size, common_attr_size; + int nattr_common = 4, nattr_accessibility = 1; + int num_devices = p->n_pdds; + struct svm_range_list *svms; + struct svm_range *prange; + uint32_t count = 0; + + *svm_priv_data_size = 0; + + svms = &p->svms; + if (!svms) + return -EINVAL; + + mutex_lock(&svms->lock); + list_for_each_entry(prange, &svms->list, list) { + pr_debug("prange: 0x%p start: 0x%lx\t npages: 0x%llx\t end: 0x%llx\n", + prange, prange->start, prange->npages, + prange->start + prange->npages - 1); + count++; + } + mutex_unlock(&svms->lock); + + *num_svm_ranges = count; + /* Only the accessbility attributes need to be queried for all the gpus + * individually, remaining ones are spanned across the entire process + * regardless of the various gpu nodes. Of the remaining attributes, + * KFD_IOCTL_SVM_ATTR_CLR_FLAGS need not be saved. + * + * KFD_IOCTL_SVM_ATTR_PREFERRED_LOC + * KFD_IOCTL_SVM_ATTR_PREFETCH_LOC + * KFD_IOCTL_SVM_ATTR_SET_FLAGS + * KFD_IOCTL_SVM_ATTR_GRANULARITY + * + * ** ACCESSBILITY ATTRIBUTES ** + * (Considered as one, type is altered during query, value is gpuid) + * KFD_IOCTL_SVM_ATTR_ACCESS + * KFD_IOCTL_SVM_ATTR_ACCESS_IN_PLACE + * KFD_IOCTL_SVM_ATTR_NO_ACCESS + */ + if (*num_svm_ranges > 0) { + common_attr_size = sizeof(struct kfd_ioctl_svm_attribute) * + nattr_common; + accessibility_size = sizeof(struct kfd_ioctl_svm_attribute) * + nattr_accessibility * num_devices; + + total_size = sizeof(struct kfd_criu_svm_range_priv_data) + + common_attr_size + accessibility_size; + + *svm_priv_data_size = *num_svm_ranges * total_size; + } + + pr_debug("num_svm_ranges %u total_priv_size %llu\n", *num_svm_ranges, + *svm_priv_data_size); + return 0; +} + int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, uint64_t size, uint32_t nattrs, struct kfd_ioctl_svm_attribute *attrs) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h index 949b477e2f4c..f052b6022e76 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h @@ -183,6 +183,8 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr, void svm_range_free_dma_mappings(struct svm_range *prange); void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm, void *owner); +int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges, + uint64_t *svm_priv_data_size); struct kfd_process_device * svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev); void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm); @@ -220,6 +222,15 @@ static inline int svm_range_schedule_evict_svm_bo( return -EINVAL; } +static inline int svm_range_get_info(struct kfd_process *p, + uint32_t *num_svm_ranges, + uint64_t *svm_priv_data_size) +{ + *num_svm_ranges = 0; + *svm_priv_data_size = 0; + return 0; +} + #define KFD_IS_SVM_API_SUPPORTED(dev) false #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ From 9d5dabfeff3ca63925cfc9c427f2d1fe8929402b Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Wed, 3 Nov 2021 02:40:27 -0400 Subject: [PATCH 267/339] drm/amdkfd: CRIU Save Shared Virtual Memory ranges During checkpoint stage, save the shared virtual memory ranges and attributes for the target process. A process may contain a number of svm ranges and each range might contain a number of attributes. While not all attributes may be applicable for a given prange but during checkpoint we store all possible values for the max possible attribute types. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 +- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 95 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 10 +++ 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index a755ea68a428..721c86ceba22 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2196,7 +2196,9 @@ static int criu_checkpoint(struct file *filep, if (ret) goto close_bo_fds; - /* TODO: Dump SVM-Ranges */ + ret = kfd_criu_checkpoint_svm(p, (uint8_t __user *)args->priv_data, &priv_offset); + if (ret) + goto close_bo_fds; } close_bo_fds: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 64cd7712c098..7cf63995c079 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3540,6 +3540,101 @@ int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges, return 0; } +int kfd_criu_checkpoint_svm(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_data_offset) +{ + struct kfd_criu_svm_range_priv_data *svm_priv = NULL; + struct kfd_ioctl_svm_attribute *query_attr = NULL; + uint64_t svm_priv_data_size, query_attr_size = 0; + int index, nattr_common = 4, ret = 0; + struct svm_range_list *svms; + int num_devices = p->n_pdds; + struct svm_range *prange; + struct mm_struct *mm; + + svms = &p->svms; + if (!svms) + return -EINVAL; + + mm = get_task_mm(p->lead_thread); + if (!mm) { + pr_err("failed to get mm for the target process\n"); + return -ESRCH; + } + + query_attr_size = sizeof(struct kfd_ioctl_svm_attribute) * + (nattr_common + num_devices); + + query_attr = kzalloc(query_attr_size, GFP_KERNEL); + if (!query_attr) { + ret = -ENOMEM; + goto exit; + } + + query_attr[0].type = KFD_IOCTL_SVM_ATTR_PREFERRED_LOC; + query_attr[1].type = KFD_IOCTL_SVM_ATTR_PREFETCH_LOC; + query_attr[2].type = KFD_IOCTL_SVM_ATTR_SET_FLAGS; + query_attr[3].type = KFD_IOCTL_SVM_ATTR_GRANULARITY; + + for (index = 0; index < num_devices; index++) { + struct kfd_process_device *pdd = p->pdds[index]; + + query_attr[index + nattr_common].type = + KFD_IOCTL_SVM_ATTR_ACCESS; + query_attr[index + nattr_common].value = pdd->user_gpu_id; + } + + svm_priv_data_size = sizeof(*svm_priv) + query_attr_size; + + svm_priv = kzalloc(svm_priv_data_size, GFP_KERNEL); + if (!svm_priv) { + ret = -ENOMEM; + goto exit_query; + } + + index = 0; + list_for_each_entry(prange, &svms->list, list) { + + svm_priv->object_type = KFD_CRIU_OBJECT_TYPE_SVM_RANGE; + svm_priv->start_addr = prange->start; + svm_priv->size = prange->npages; + memcpy(&svm_priv->attrs, query_attr, query_attr_size); + pr_debug("CRIU: prange: 0x%p start: 0x%lx\t npages: 0x%llx end: 0x%llx\t size: 0x%llx\n", + prange, prange->start, prange->npages, + prange->start + prange->npages - 1, + prange->npages * PAGE_SIZE); + + ret = svm_range_get_attr(p, mm, svm_priv->start_addr, + svm_priv->size, + (nattr_common + num_devices), + svm_priv->attrs); + if (ret) { + pr_err("CRIU: failed to obtain range attributes\n"); + goto exit_priv; + } + + ret = copy_to_user(user_priv_data + *priv_data_offset, + svm_priv, svm_priv_data_size); + if (ret) { + pr_err("Failed to copy svm priv to user\n"); + goto exit_priv; + } + + *priv_data_offset += svm_priv_data_size; + + } + + +exit_priv: + kfree(svm_priv); +exit_query: + kfree(query_attr); +exit: + mmput(mm); + return ret; +} + int svm_ioctl(struct kfd_process *p, enum kfd_ioctl_svm_op op, uint64_t start, uint64_t size, uint32_t nattrs, struct kfd_ioctl_svm_attribute *attrs) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h index f052b6022e76..f36c2fa8469a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h @@ -185,6 +185,9 @@ void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm, void *owner); int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges, uint64_t *svm_priv_data_size); +int kfd_criu_checkpoint_svm(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_offset); struct kfd_process_device * svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev); void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm); @@ -231,6 +234,13 @@ static inline int svm_range_get_info(struct kfd_process *p, return 0; } +static inline int kfd_criu_checkpoint_svm(struct kfd_process *p, + uint8_t __user *user_priv_data, + uint64_t *priv_offset) +{ + return 0; +} + #define KFD_IS_SVM_API_SUPPORTED(dev) false #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ From c2db32ce77adf82dd2a4193abc709ec51474f84e Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Mon, 8 Nov 2021 11:21:57 -0500 Subject: [PATCH 268/339] drm/amdkfd: CRIU prepare for svm resume During CRIU restore phase, the VMAs for the virtual address ranges are not at their final location yet so in this stage, only cache the data required to successfully resume the svm ranges during an imminent CRIU resume phase. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 58 ++++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 12 +++++ 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 721c86ceba22..c143f242a84d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2643,8 +2643,8 @@ static int criu_restore_objects(struct file *filep, goto exit; break; case KFD_CRIU_OBJECT_TYPE_SVM_RANGE: - /* TODO: Implement SVM range */ - *priv_offset += sizeof(struct kfd_criu_svm_range_priv_data); + ret = kfd_criu_restore_svm(p, (uint8_t __user *)args->priv_data, + priv_offset, max_priv_data_size); if (ret) goto exit; break; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 715dd0d4fac5..74ff4132a163 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -790,6 +790,7 @@ struct svm_range_list { struct list_head list; struct work_struct deferred_list_work; struct list_head deferred_range_list; + struct list_head criu_svm_metadata_list; spinlock_t deferred_list_lock; atomic_t evicted_ranges; atomic_t drain_pagefaults; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 7cf63995c079..41ac049b3316 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -45,6 +45,11 @@ */ #define AMDGPU_SVM_RANGE_RETRY_FAULT_PENDING 2000 +struct criu_svm_metadata { + struct list_head list; + struct kfd_criu_svm_range_priv_data data; +}; + static void svm_range_evict_svm_bo_worker(struct work_struct *work); static bool svm_range_cpu_invalidate_pagetables(struct mmu_interval_notifier *mni, @@ -2875,6 +2880,7 @@ int svm_range_list_init(struct kfd_process *p) INIT_DELAYED_WORK(&svms->restore_work, svm_range_restore_work); INIT_WORK(&svms->deferred_list_work, svm_range_deferred_list_work); INIT_LIST_HEAD(&svms->deferred_range_list); + INIT_LIST_HEAD(&svms->criu_svm_metadata_list); spin_lock_init(&svms->deferred_list_lock); for (i = 0; i < p->n_pdds; i++) @@ -3481,6 +3487,58 @@ fill_values: return 0; } +int kfd_criu_restore_svm(struct kfd_process *p, + uint8_t __user *user_priv_ptr, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size) +{ + uint64_t svm_priv_data_size, svm_object_md_size, svm_attrs_size; + int nattr_common = 4, nattr_accessibility = 1; + struct criu_svm_metadata *criu_svm_md = NULL; + struct svm_range_list *svms = &p->svms; + uint32_t num_devices; + int ret = 0; + + num_devices = p->n_pdds; + /* Handle one SVM range object at a time, also the number of gpus are + * assumed to be same on the restore node, checking must be done while + * evaluating the topology earlier */ + + svm_attrs_size = sizeof(struct kfd_ioctl_svm_attribute) * + (nattr_common + nattr_accessibility * num_devices); + svm_object_md_size = sizeof(struct criu_svm_metadata) + svm_attrs_size; + + svm_priv_data_size = sizeof(struct kfd_criu_svm_range_priv_data) + + svm_attrs_size; + + criu_svm_md = kzalloc(svm_object_md_size, GFP_KERNEL); + if (!criu_svm_md) { + pr_err("failed to allocate memory to store svm metadata\n"); + return -ENOMEM; + } + if (*priv_data_offset + svm_priv_data_size > max_priv_data_size) { + ret = -EINVAL; + goto exit; + } + + ret = copy_from_user(&criu_svm_md->data, user_priv_ptr + *priv_data_offset, + svm_priv_data_size); + if (ret) { + ret = -EFAULT; + goto exit; + } + *priv_data_offset += svm_priv_data_size; + + list_add_tail(&criu_svm_md->list, &svms->criu_svm_metadata_list); + + return 0; + + +exit: + kfree(criu_svm_md); + return ret; +} + int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges, uint64_t *svm_priv_data_size) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h index f36c2fa8469a..3b5948f67de2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h @@ -188,6 +188,10 @@ int svm_range_get_info(struct kfd_process *p, uint32_t *num_svm_ranges, int kfd_criu_checkpoint_svm(struct kfd_process *p, uint8_t __user *user_priv_data, uint64_t *priv_offset); +int kfd_criu_restore_svm(struct kfd_process *p, + uint8_t __user *user_priv_ptr, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size); struct kfd_process_device * svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev); void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm); @@ -241,6 +245,14 @@ static inline int kfd_criu_checkpoint_svm(struct kfd_process *p, return 0; } +static inline int kfd_criu_restore_svm(struct kfd_process *p, + uint8_t __user *user_priv_ptr, + uint64_t *priv_data_offset, + uint64_t max_priv_data_size) +{ + return -EINVAL; +} + #define KFD_IS_SVM_API_SUPPORTED(dev) false #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ From 2a909ae718715b3bac75d945e38dc0a5e4a0f1ba Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Mon, 8 Nov 2021 17:33:42 -0500 Subject: [PATCH 269/339] drm/amdkfd: CRIU resume shared virtual memory ranges In CRIU resume stage, resume all the shared virtual memory ranges from the data stored inside the resuming kfd process during CRIU restore phase. Also setup xnack mode and free up the resources. KFD_IOCTL_SVM_ATTR_CLR_FLAGS is not available for querying via get_attr interface but we must clear the flags during restore as there might be some default flags set when the prange is created. Also handle the invalid PREFETCH atribute values saved during checkpoint by replacing them with another dummy KFD_IOCTL_SVM_ATTR_SET_FLAGS attribute. (rajneesh: Fixed the checkpatch reported problems) Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 +++ drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 103 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_svm.h | 6 ++ 3 files changed, 119 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index c143f242a84d..64e3b4e3a712 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2766,7 +2766,17 @@ static int criu_resume(struct file *filep, } mutex_lock(&target->mutex); + ret = kfd_criu_resume_svm(target); + if (ret) { + pr_err("kfd_criu_resume_svm failed for %i\n", args->pid); + goto exit; + } + ret = amdgpu_amdkfd_criu_resume(target->kgd_process_info); + if (ret) + pr_err("amdgpu_amdkfd_criu_resume failed for %i\n", args->pid); + +exit: mutex_unlock(&target->mutex); kfd_unref_process(target); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 41ac049b3316..41f03d165bad 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3487,6 +3487,109 @@ fill_values: return 0; } +int kfd_criu_resume_svm(struct kfd_process *p) +{ + struct kfd_ioctl_svm_attribute *set_attr_new, *set_attr = NULL; + int nattr_common = 4, nattr_accessibility = 1; + struct criu_svm_metadata *criu_svm_md = NULL; + struct svm_range_list *svms = &p->svms; + struct criu_svm_metadata *next = NULL; + uint32_t set_flags = 0xffffffff; + int i, j, num_attrs, ret = 0; + uint64_t set_attr_size; + struct mm_struct *mm; + + if (list_empty(&svms->criu_svm_metadata_list)) { + pr_debug("No SVM data from CRIU restore stage 2\n"); + return ret; + } + + mm = get_task_mm(p->lead_thread); + if (!mm) { + pr_err("failed to get mm for the target process\n"); + return -ESRCH; + } + + num_attrs = nattr_common + (nattr_accessibility * p->n_pdds); + + i = j = 0; + list_for_each_entry(criu_svm_md, &svms->criu_svm_metadata_list, list) { + pr_debug("criu_svm_md[%d]\n\tstart: 0x%llx size: 0x%llx (npages)\n", + i, criu_svm_md->data.start_addr, criu_svm_md->data.size); + + for (j = 0; j < num_attrs; j++) { + pr_debug("\ncriu_svm_md[%d]->attrs[%d].type : 0x%x \ncriu_svm_md[%d]->attrs[%d].value : 0x%x\n", + i, j, criu_svm_md->data.attrs[j].type, + i, j, criu_svm_md->data.attrs[j].value); + switch (criu_svm_md->data.attrs[j].type) { + /* During Checkpoint operation, the query for + * KFD_IOCTL_SVM_ATTR_PREFETCH_LOC attribute might + * return KFD_IOCTL_SVM_LOCATION_UNDEFINED if they were + * not used by the range which was checkpointed. Care + * must be taken to not restore with an invalid value + * otherwise the gpuidx value will be invalid and + * set_attr would eventually fail so just replace those + * with another dummy attribute such as + * KFD_IOCTL_SVM_ATTR_SET_FLAGS. + */ + case KFD_IOCTL_SVM_ATTR_PREFETCH_LOC: + if (criu_svm_md->data.attrs[j].value == + KFD_IOCTL_SVM_LOCATION_UNDEFINED) { + criu_svm_md->data.attrs[j].type = + KFD_IOCTL_SVM_ATTR_SET_FLAGS; + criu_svm_md->data.attrs[j].value = 0; + } + break; + case KFD_IOCTL_SVM_ATTR_SET_FLAGS: + set_flags = criu_svm_md->data.attrs[j].value; + break; + default: + break; + } + } + + /* CLR_FLAGS is not available via get_attr during checkpoint but + * it needs to be inserted before restoring the ranges so + * allocate extra space for it before calling set_attr + */ + set_attr_size = sizeof(struct kfd_ioctl_svm_attribute) * + (num_attrs + 1); + set_attr_new = krealloc(set_attr, set_attr_size, + GFP_KERNEL); + if (!set_attr_new) { + ret = -ENOMEM; + goto exit; + } + set_attr = set_attr_new; + + memcpy(set_attr, criu_svm_md->data.attrs, num_attrs * + sizeof(struct kfd_ioctl_svm_attribute)); + set_attr[num_attrs].type = KFD_IOCTL_SVM_ATTR_CLR_FLAGS; + set_attr[num_attrs].value = ~set_flags; + + ret = svm_range_set_attr(p, mm, criu_svm_md->data.start_addr, + criu_svm_md->data.size, num_attrs + 1, + set_attr); + if (ret) { + pr_err("CRIU: failed to set range attributes\n"); + goto exit; + } + + i++; + } +exit: + kfree(set_attr); + list_for_each_entry_safe(criu_svm_md, next, &svms->criu_svm_metadata_list, list) { + pr_debug("freeing criu_svm_md[]\n\tstart: 0x%llx\n", + criu_svm_md->data.start_addr); + kfree(criu_svm_md); + } + + mmput(mm); + return ret; + +} + int kfd_criu_restore_svm(struct kfd_process *p, uint8_t __user *user_priv_ptr, uint64_t *priv_data_offset, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h index 3b5948f67de2..66c77f00ac3e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.h @@ -192,6 +192,7 @@ int kfd_criu_restore_svm(struct kfd_process *p, uint8_t __user *user_priv_ptr, uint64_t *priv_data_offset, uint64_t max_priv_data_size); +int kfd_criu_resume_svm(struct kfd_process *p); struct kfd_process_device * svm_range_get_pdd_by_adev(struct svm_range *prange, struct amdgpu_device *adev); void svm_range_list_lock_and_flush_work(struct svm_range_list *svms, struct mm_struct *mm); @@ -253,6 +254,11 @@ static inline int kfd_criu_restore_svm(struct kfd_process *p, return -EINVAL; } +static inline int kfd_criu_resume_svm(struct kfd_process *p) +{ + return 0; +} + #define KFD_IS_SVM_API_SUPPORTED(dev) false #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ From 692996f2bef7aa1737e07554255ba0d9a73fb750 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Tue, 18 Jan 2022 01:47:58 -0500 Subject: [PATCH 270/339] drm/amdkfd: Bump up KFD API version for CRIU - Change KFD minor version to 7 for CRIU Proposed userspace changes: https://github.com/RadeonOpenCompute/criu Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- include/uapi/linux/kfd_ioctl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index 49429a6c42fc..e6a56c146920 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -32,9 +32,10 @@ * - 1.4 - Indicate new SRAM EDC bit in device properties * - 1.5 - Add SVM API * - 1.6 - Query clear flags in SVM get_attr API + * - 1.7 - Checkpoint Restore (CRIU) API */ #define KFD_IOCTL_MAJOR_VERSION 1 -#define KFD_IOCTL_MINOR_VERSION 6 +#define KFD_IOCTL_MINOR_VERSION 7 struct kfd_ioctl_get_version_args { __u32 major_version; /* from KFD */ From 3f1e2e9d9993a3b1e33661fee26566f091e01b2b Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 19:32:58 -0500 Subject: [PATCH 271/339] drm/amdgpu: Nerf "buff" to "buf" Buffer is abbreviated "buf" (buf-fer), not "buff" (buff-er). This is consistent with the rest of the kernel code. Cc: Kent Russell Cc: Alex Deucher Signed-off-by: Luben Tuikov Acked-by: Harish Kasiviswanathan Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index ce5d5ee336a9..792337433a9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -77,11 +77,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) } static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, - unsigned char *buff) + unsigned char *buf) { int ret, size; - ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buff, 1); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1); if (ret < 1) { DRM_WARN("FRU: Failed to get size field"); return ret; @@ -90,9 +90,9 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, /* The size returned by the i2c requires subtraction of 0xC0 since the * size apparently always reports as 0xC0+actual size. */ - size = buff[0] - I2C_PRODUCT_INFO_OFFSET; + size = buf[0] - I2C_PRODUCT_INFO_OFFSET; - ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buff, size); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buf, size); if (ret < 1) { DRM_WARN("FRU: Failed to get data field"); return ret; @@ -103,7 +103,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, int amdgpu_fru_get_product_info(struct amdgpu_device *adev) { - unsigned char buff[AMDGPU_PRODUCT_NAME_LEN+2]; + unsigned char buf[AMDGPU_PRODUCT_NAME_LEN+2]; u32 addrptr; int size, len; int offset = 2; @@ -133,7 +133,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * and the language field, so just start from 0xb, manufacturer size */ addrptr = FRU_EEPROM_MADDR + 0xb; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size); return -EINVAL; @@ -143,7 +143,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * size field being 1 byte. This pattern continues below. */ addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU product name, ret:%d", size); return -EINVAL; @@ -155,12 +155,12 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) AMDGPU_PRODUCT_NAME_LEN); len = AMDGPU_PRODUCT_NAME_LEN - 1; } - /* Start at 2 due to buff using fields 0 and 1 for the address */ - memcpy(adev->product_name, &buff[offset], len); + /* Start at 2 due to buf using fields 0 and 1 for the address */ + memcpy(adev->product_name, &buf[offset], len); adev->product_name[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU product number, ret:%d", size); return -EINVAL; @@ -174,11 +174,11 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->product_number) - 1; } - memcpy(adev->product_number, &buff[offset], len); + memcpy(adev->product_number, &buf[offset], len); adev->product_number[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU product version, ret:%d", size); @@ -186,7 +186,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) } addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buff); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf); if (size < 1) { DRM_ERROR("Failed to read FRU serial number, ret:%d", size); @@ -201,7 +201,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->serial) - 1; } - memcpy(adev->serial, &buff[offset], len); + memcpy(adev->serial, &buf[offset], len); adev->serial[len] = '\0'; return 0; From 3f3a24a0a3a58677d2b4f3c442d7a1be05afb123 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 19:05:20 -0500 Subject: [PATCH 272/339] drm/amdgpu: Don't offset by 2 in FRU EEPROM Read buffers no longer expose the I2C address, and so we don't need to offset by two when we get the read data. Cc: Alex Deucher Cc: Kent Russell Cc: Andrey Grodzovsky Fixes: bd607166af7fe3 ("drm/amdgpu: Enable reading FRU chip via I2C v3") Signed-off-by: Luben Tuikov Acked-by: Harish Kasiviswanathan Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 792337433a9e..61c4e71e3998 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -103,17 +103,13 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, int amdgpu_fru_get_product_info(struct amdgpu_device *adev) { - unsigned char buf[AMDGPU_PRODUCT_NAME_LEN+2]; + unsigned char buf[AMDGPU_PRODUCT_NAME_LEN]; u32 addrptr; int size, len; - int offset = 2; if (!is_fru_eeprom_supported(adev)) return 0; - if (adev->asic_type == CHIP_ALDEBARAN) - offset = 0; - /* If algo exists, it means that the i2c_adapter's initialized */ if (!adev->pm.fru_eeprom_i2c_bus || !adev->pm.fru_eeprom_i2c_bus->algo) { DRM_WARN("Cannot access FRU, EEPROM accessor not initialized"); @@ -155,8 +151,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) AMDGPU_PRODUCT_NAME_LEN); len = AMDGPU_PRODUCT_NAME_LEN - 1; } - /* Start at 2 due to buf using fields 0 and 1 for the address */ - memcpy(adev->product_name, &buf[offset], len); + memcpy(adev->product_name, buf, len); adev->product_name[len] = '\0'; addrptr += size + 1; @@ -174,7 +169,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->product_number) - 1; } - memcpy(adev->product_number, &buf[offset], len); + memcpy(adev->product_number, buf, len); adev->product_number[len] = '\0'; addrptr += size + 1; @@ -201,7 +196,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake"); len = sizeof(adev->serial) - 1; } - memcpy(adev->serial, &buf[offset], len); + memcpy(adev->serial, buf, len); adev->serial[len] = '\0'; return 0; From 00b14ce075732edb2935d738de990e9aa96f1e08 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Thu, 3 Feb 2022 19:48:24 -0500 Subject: [PATCH 273/339] drm/amdgpu: Prevent random memory access in FRU code Prevent random memory access in the FRU EEPROM code by passing the size of the destination buffer to the reading routine, and reading no more than the size of the buffer. Cc: Kent Russell Cc: Alex Deucher Signed-off-by: Luben Tuikov Acked-by: Harish Kasiviswanathan Reviewed-by: Kent Russell Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c index 61c4e71e3998..ecada5eadfe3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c @@ -30,7 +30,6 @@ #include "amdgpu_eeprom.h" #define FRU_EEPROM_MADDR 0x60000 -#define I2C_PRODUCT_INFO_OFFSET 0xC0 static bool is_fru_eeprom_supported(struct amdgpu_device *adev) { @@ -77,9 +76,10 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev) } static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, - unsigned char *buf) + unsigned char *buf, size_t buf_size) { - int ret, size; + int ret; + u8 size; ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1); if (ret < 1) { @@ -90,9 +90,11 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr, /* The size returned by the i2c requires subtraction of 0xC0 since the * size apparently always reports as 0xC0+actual size. */ - size = buf[0] - I2C_PRODUCT_INFO_OFFSET; + size = buf[0] & 0x3F; + size = min_t(size_t, size, buf_size); - ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, buf, size); + ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1, + buf, size); if (ret < 1) { DRM_WARN("FRU: Failed to get data field"); return ret; @@ -129,7 +131,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * and the language field, so just start from 0xb, manufacturer size */ addrptr = FRU_EEPROM_MADDR + 0xb; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size); return -EINVAL; @@ -139,7 +141,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) * size field being 1 byte. This pattern continues below. */ addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU product name, ret:%d", size); return -EINVAL; @@ -155,7 +157,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) adev->product_name[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU product number, ret:%d", size); return -EINVAL; @@ -173,7 +175,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) adev->product_number[len] = '\0'; addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU product version, ret:%d", size); @@ -181,7 +183,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) } addrptr += size + 1; - size = amdgpu_fru_read_eeprom(adev, addrptr, buf); + size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf)); if (size < 1) { DRM_ERROR("Failed to read FRU serial number, ret:%d", size); From 447c7997b62a5115ba4da846dcdee4fc12298a6a Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Thu, 3 Feb 2022 21:18:21 -0500 Subject: [PATCH 274/339] drm/amdgpu: Fix recursive locking warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Noticed the below warning while running a pytorch workload on vega10 GPUs. Change to trylock to avoid conflicts with already held reservation locks. [ +0.000003] WARNING: possible recursive locking detected [ +0.000003] 5.13.0-kfd-rajneesh #1030 Not tainted [ +0.000004] -------------------------------------------- [ +0.000002] python/4822 is trying to acquire lock: [ +0.000004] ffff932cd9a259f8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: amdgpu_bo_release_notify+0xc4/0x160 [amdgpu] [ +0.000203] but task is already holding lock: [ +0.000003] ffff932cbb7181f8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: ttm_eu_reserve_buffers+0x270/0x470 [ttm] [ +0.000017] other info that might help us debug this: [ +0.000002] Possible unsafe locking scenario: [ +0.000003] CPU0 [ +0.000002] ---- [ +0.000002] lock(reservation_ww_class_mutex); [ +0.000004] lock(reservation_ww_class_mutex); [ +0.000003] *** DEADLOCK *** [ +0.000002] May be due to missing lock nesting notation [ +0.000003] 7 locks held by python/4822: [ +0.000003] #0: ffff932c4ac028d0 (&process->mutex){+.+.}-{3:3}, at: kfd_ioctl_map_memory_to_gpu+0x10b/0x320 [amdgpu] [ +0.000232] #1: ffff932c55e830a8 (&info->lock#2){+.+.}-{3:3}, at: amdgpu_amdkfd_gpuvm_map_memory_to_gpu+0x64/0xf60 [amdgpu] [ +0.000241] #2: ffff932cc45b5e68 (&(*mem)->lock){+.+.}-{3:3}, at: amdgpu_amdkfd_gpuvm_map_memory_to_gpu+0xdf/0xf60 [amdgpu] [ +0.000236] #3: ffffb2b35606fd28 (reservation_ww_class_acquire){+.+.}-{0:0}, at: amdgpu_amdkfd_gpuvm_map_memory_to_gpu+0x232/0xf60 [amdgpu] [ +0.000235] #4: ffff932cbb7181f8 (reservation_ww_class_mutex){+.+.}-{3:3}, at: ttm_eu_reserve_buffers+0x270/0x470 [ttm] [ +0.000015] #5: ffffffffc045f700 (*(sspp++)){....}-{0:0}, at: drm_dev_enter+0x5/0xa0 [drm] [ +0.000038] #6: ffff932c52da7078 (&vm->eviction_lock){+.+.}-{3:3}, at: amdgpu_vm_bo_update_mapping+0xd5/0x4f0 [amdgpu] [ +0.000195] stack backtrace: [ +0.000003] CPU: 11 PID: 4822 Comm: python Not tainted 5.13.0-kfd-rajneesh #1030 [ +0.000005] Hardware name: GIGABYTE MZ01-CE0-00/MZ01-CE0-00, BIOS F02 08/29/2018 [ +0.000003] Call Trace: [ +0.000003] dump_stack+0x6d/0x89 [ +0.000010] __lock_acquire+0xb93/0x1a90 [ +0.000009] lock_acquire+0x25d/0x2d0 [ +0.000005] ? amdgpu_bo_release_notify+0xc4/0x160 [amdgpu] [ +0.000184] ? lock_is_held_type+0xa2/0x110 [ +0.000006] ? amdgpu_bo_release_notify+0xc4/0x160 [amdgpu] [ +0.000184] __ww_mutex_lock.constprop.17+0xca/0x1060 [ +0.000007] ? amdgpu_bo_release_notify+0xc4/0x160 [amdgpu] [ +0.000183] ? lock_release+0x13f/0x270 [ +0.000005] ? lock_is_held_type+0xa2/0x110 [ +0.000006] ? amdgpu_bo_release_notify+0xc4/0x160 [amdgpu] [ +0.000183] amdgpu_bo_release_notify+0xc4/0x160 [amdgpu] [ +0.000185] ttm_bo_release+0x4c6/0x580 [ttm] [ +0.000010] amdgpu_bo_unref+0x1a/0x30 [amdgpu] [ +0.000183] amdgpu_vm_free_table+0x76/0xa0 [amdgpu] [ +0.000189] amdgpu_vm_free_pts+0xb8/0xf0 [amdgpu] [ +0.000189] amdgpu_vm_update_ptes+0x411/0x770 [amdgpu] [ +0.000191] amdgpu_vm_bo_update_mapping+0x324/0x4f0 [amdgpu] [ +0.000191] amdgpu_vm_bo_update+0x251/0x610 [amdgpu] [ +0.000191] update_gpuvm_pte+0xcc/0x290 [amdgpu] [ +0.000229] ? amdgpu_vm_bo_map+0xd7/0x130 [amdgpu] [ +0.000190] amdgpu_amdkfd_gpuvm_map_memory_to_gpu+0x912/0xf60 [amdgpu] [ +0.000234] kfd_ioctl_map_memory_to_gpu+0x182/0x320 [amdgpu] [ +0.000218] kfd_ioctl+0x2b9/0x600 [amdgpu] [ +0.000216] ? kfd_ioctl_unmap_memory_from_gpu+0x270/0x270 [amdgpu] [ +0.000216] ? lock_release+0x13f/0x270 [ +0.000006] ? __fget_files+0x107/0x1e0 [ +0.000007] __x64_sys_ioctl+0x8b/0xd0 [ +0.000007] do_syscall_64+0x36/0x70 [ +0.000004] entry_SYSCALL_64_after_hwframe+0x44/0xae [ +0.000007] RIP: 0033:0x7fbff90a7317 [ +0.000004] Code: b3 66 90 48 8b 05 71 4b 2d 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 41 4b 2d 00 f7 d8 64 89 01 48 [ +0.000005] RSP: 002b:00007fbe301fe648 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 [ +0.000006] RAX: ffffffffffffffda RBX: 00007fbcc402d820 RCX: 00007fbff90a7317 [ +0.000003] RDX: 00007fbe301fe690 RSI: 00000000c0184b18 RDI: 0000000000000004 [ +0.000003] RBP: 00007fbe301fe690 R08: 0000000000000000 R09: 00007fbcc402d880 [ +0.000003] R10: 0000000002001000 R11: 0000000000000246 R12: 00000000c0184b18 [ +0.000003] R13: 0000000000000004 R14: 00007fbf689593a0 R15: 00007fbcc402d820 Cc: Christian König Cc: Felix Kuehling Cc: Alex Deucher Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index ec29365d108d..23c9a60693ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1306,7 +1306,8 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) return; - dma_resv_lock(bo->base.resv, NULL); + if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) + return; r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence); if (!WARN_ON(r)) { From 00d6936dbd5486bd5c0a07870d5747eed6f799ec Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Fri, 4 Feb 2022 13:35:51 -0500 Subject: [PATCH 275/339] drm/amdgpu: Set FRU bus for Aldebaran and Vega 20 The FRU and RAS EEPROMs share the same I2C bus on Aldebaran and Vega 20 ASICs. Set the FRU bus "pointer" to this single bus, as access to the FRU is sought through that bus "pointer" and not through the RAS bus "pointer". Cc: Roy Sun Cc: Alex Deucher Fixes: 2f60dd50769efc ("drm/amd: Expose the FRU SMU I2C bus") Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 3 ++- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c index 87acb089cfcc..dd2d66090d23 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c @@ -741,7 +741,7 @@ int smu_v11_0_i2c_control_init(struct amdgpu_device *adev) i2c_set_adapdata(control, smu_i2c); adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; - adev->pm.fru_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; res = i2c_add_adapter(control); if (res) @@ -756,6 +756,7 @@ void smu_v11_0_i2c_control_fini(struct amdgpu_device *adev) i2c_del_adapter(control); adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; } /* diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index ba4c9771ffc5..3d96d4af92d9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1583,6 +1583,7 @@ static int aldebaran_i2c_control_init(struct smu_context *smu) } adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; return 0; Out_err: From d5e8ff5f7b2a41d503914d4896ed3c6b3befe933 Mon Sep 17 00:00:00 2001 From: yipechai Date: Sat, 29 Jan 2022 17:09:08 +0800 Subject: [PATCH 276/339] drm/amdgpu: Fixed the defect of soft lock caused by infinite loop 1. The infinite loop case only occurs on multiple cards support ras functions. 2. The explanation of root cause refer to commit 76641cbbf196 ("drm/amdgpu: Add judgement to avoid infinite loop"). 3. Create new node to manage each unique ras instance to guarantee each device .ras_list is completely independent. 4. Fixes: commit 7a6b8ab3231b51 ("drm/amdgpu: Unify ras block interface for each ras block"). 5. The soft locked logs are as follows: [ 262.165690] CPU: 93 PID: 758 Comm: kworker/93:1 Tainted: G OE 5.13.0-27-generic #29~20.04.1-Ubuntu [ 262.165695] Hardware name: Supermicro AS -4124GS-TNR/H12DSG-O-CPU, BIOS T20200717143848 07/17/2020 [ 262.165698] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [ 262.165980] RIP: 0010:amdgpu_ras_get_ras_block+0x86/0xd0 [amdgpu] [ 262.166239] Code: 68 d8 4c 8d 71 d8 48 39 c3 74 54 49 8b 45 38 48 85 c0 74 32 44 89 fa 44 89 e6 4c 89 ef e8 82 e4 9b dc 85 c0 74 3c 49 8b 46 28 <49> 8d 56 28 4d 89 f5 48 83 e8 28 48 39 d3 74 25 49 89 c6 49 8b 45 [ 262.166243] RSP: 0018:ffffac908fa87d80 EFLAGS: 00000202 [ 262.166247] RAX: ffffffffc1394248 RBX: ffff91e4ab8d6e20 RCX: ffffffffc1394248 [ 262.166249] RDX: ffff91e4aa356e20 RSI: 000000000000000e RDI: ffff91e4ab8c0000 [ 262.166252] RBP: ffffac908fa87da8 R08: 0000000000000007 R09: 0000000000000001 [ 262.166254] R10: ffff91e4930b64ec R11: 0000000000000000 R12: 000000000000000e [ 262.166256] R13: ffff91e4aa356df8 R14: ffffffffc1394320 R15: 0000000000000003 [ 262.166258] FS: 0000000000000000(0000) GS:ffff92238fb40000(0000) knlGS:0000000000000000 [ 262.166261] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 262.166264] CR2: 00000001004865d0 CR3: 000000406d796000 CR4: 0000000000350ee0 [ 262.166267] Call Trace: [ 262.166272] amdgpu_ras_do_recovery+0x130/0x290 [amdgpu] [ 262.166529] ? psi_task_switch+0xd2/0x250 [ 262.166537] ? __switch_to+0x11d/0x460 [ 262.166542] ? __switch_to_asm+0x36/0x70 [ 262.166549] process_one_work+0x220/0x3c0 [ 262.166556] worker_thread+0x4d/0x3f0 [ 262.166560] ? process_one_work+0x3c0/0x3c0 [ 262.166563] kthread+0x12b/0x150 [ 262.166568] ? set_kthread_struct+0x40/0x40 [ 262.166571] ret_from_fork+0x22/0x30 Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 35 ++++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 --- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e440a5268ace..d6608ae3c127 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -75,6 +75,13 @@ const char *ras_mca_block_string[] = { "mca_iohc", }; +struct amdgpu_ras_block_list { + /* ras block link */ + struct list_head node; + + struct amdgpu_ras_block_object *ras_obj; +}; + const char *get_ras_block_str(struct ras_common_if *ras_block) { if (!ras_block) @@ -880,7 +887,8 @@ static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_de enum amdgpu_ras_block block, uint32_t sub_block_index) { int loop_cnt = 0; - struct amdgpu_ras_block_object *obj, *tmp; + struct amdgpu_ras_block_list *node, *tmp; + struct amdgpu_ras_block_object *obj; if (block >= AMDGPU_RAS_BLOCK__LAST) return NULL; @@ -888,7 +896,13 @@ static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_de if (!amdgpu_ras_is_supported(adev, block)) return NULL; - list_for_each_entry_safe(obj, tmp, &adev->ras_list, node) { + list_for_each_entry_safe(node, tmp, &adev->ras_list, node) { + if (!node->ras_obj) { + dev_warn(adev->dev, "Warning: abnormal ras list node.\n"); + continue; + } + + obj = node->ras_obj; if (obj->ras_block_match) { if (obj->ras_block_match(obj, block, sub_block_index) == 0) return obj; @@ -2527,6 +2541,7 @@ int amdgpu_ras_pre_fini(struct amdgpu_device *adev) int amdgpu_ras_fini(struct amdgpu_device *adev) { + struct amdgpu_ras_block_list *ras_node, *tmp; struct amdgpu_ras *con = amdgpu_ras_get_context(adev); if (!adev->ras_enabled || !con) @@ -2545,6 +2560,12 @@ int amdgpu_ras_fini(struct amdgpu_device *adev) amdgpu_ras_set_context(adev, NULL); kfree(con); + /* Clear ras blocks from ras_list and free ras block list node */ + list_for_each_entry_safe(ras_node, tmp, &adev->ras_list, node) { + list_del(&ras_node->node); + kfree(ras_node); + } + return 0; } @@ -2754,14 +2775,20 @@ int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) int amdgpu_ras_register_ras_block(struct amdgpu_device *adev, struct amdgpu_ras_block_object *ras_block_obj) { + struct amdgpu_ras_block_list *ras_node; if (!adev || !ras_block_obj) return -EINVAL; if (!amdgpu_ras_asic_supported(adev)) return 0; - INIT_LIST_HEAD(&ras_block_obj->node); - list_add_tail(&ras_block_obj->node, &adev->ras_list); + ras_node = kzalloc(sizeof(*ras_node), GFP_KERNEL); + if (!ras_node) + return -ENOMEM; + + INIT_LIST_HEAD(&ras_node->node); + ras_node->ras_obj = ras_block_obj; + list_add_tail(&ras_node->node, &adev->ras_list); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index a51a281bd91a..a55743b12d57 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -493,9 +493,6 @@ struct amdgpu_ras_block_object { uint32_t sub_block_index; - /* ras block link */ - struct list_head node; - int (*ras_block_match)(struct amdgpu_ras_block_object *block_obj, enum amdgpu_ras_block block, uint32_t sub_block_index); int (*ras_late_init)(struct amdgpu_device *adev, void *ras_info); From a50b048276c4e1bc6f7e869c99b6bdc91b4e237f Mon Sep 17 00:00:00 2001 From: yipechai Date: Mon, 7 Feb 2022 11:28:28 +0800 Subject: [PATCH 277/339] Revert "drm/amdgpu: Add judgement to avoid infinite loop" The commit d5e8ff5f7b2a ("drm/amdgpu: Fixed the defect of soft lock caused by infinite loop") had fixed this defect. Revert workaround commit a2170b4af62f ("drm/amdgpu: Add judgement to avoid infinite loop"). Signed-off-by: yipechai Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d6608ae3c127..5934326b9db3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -886,7 +886,6 @@ static int amdgpu_ras_block_match_default(struct amdgpu_ras_block_object *block_ static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_device *adev, enum amdgpu_ras_block block, uint32_t sub_block_index) { - int loop_cnt = 0; struct amdgpu_ras_block_list *node, *tmp; struct amdgpu_ras_block_object *obj; @@ -910,9 +909,6 @@ static struct amdgpu_ras_block_object *amdgpu_ras_get_ras_block(struct amdgpu_de if (amdgpu_ras_block_match_default(obj, block) == 0) return obj; } - - if (++loop_cnt >= AMDGPU_RAS_BLOCK__LAST) - break; } return NULL; From 4e781873fa1359c9a85559b6da6548ac5b07ceb5 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Sun, 30 Jan 2022 15:17:32 +0800 Subject: [PATCH 278/339] drm/amdgpu: fix list add issue in vram reserve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parameter order in the list_add_tail is incorrect, it causes the reuse of ras reserved page. Signed-off-by: Tao Zhou Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 7a2b487db57c..6c99ef700cc8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -281,7 +281,7 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr, rsv->mm_node.size = size >> PAGE_SHIFT; spin_lock(&mgr->lock); - list_add_tail(&mgr->reservations_pending, &rsv->node); + list_add_tail(&rsv->node, &mgr->reservations_pending); amdgpu_vram_mgr_do_reserve(&mgr->manager); spin_unlock(&mgr->lock); From 6d53b115be012c282feb8c01a85a14ade99dbaab Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Sat, 29 Jan 2022 09:21:31 +0800 Subject: [PATCH 279/339] drm/amdgpu: add utcl2_harvest to gc 10.3.1 Confirmed with hardware team, there is harvesting for gc 10.3.1. Signed-off-by: Aaron Liu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index b4eddf6e98a6..ff738e9725ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -543,7 +543,9 @@ static void gfxhub_v2_1_utcl2_harvest(struct amdgpu_device *adev) adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines); - if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 3, 3)) { + switch (adev->ip_versions[GC_HWIP][0]) { + case IP_VERSION(10, 3, 1): + case IP_VERSION(10, 3, 3): /* Get SA disabled bitmap from eFuse setting */ efuse_setting = RREG32_SOC15(GC, 0, mmCC_GC_SA_UNIT_DISABLE); efuse_setting &= CC_GC_SA_UNIT_DISABLE__SA_DISABLE_MASK; @@ -566,6 +568,9 @@ static void gfxhub_v2_1_utcl2_harvest(struct amdgpu_device *adev) disabled_sa = tmp; WREG32_SOC15(GC, 0, mmGCUTCL2_HARVEST_BYPASS_GROUPS_YELLOW_CARP, disabled_sa); + break; + default: + break; } } From 29ba7b16b907a1f915aab8b83ef901e209146938 Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Mon, 7 Feb 2022 10:23:36 +0800 Subject: [PATCH 280/339] drm/amdgpu: check the GART table before invalidating TLB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bypass group programming (utcl2_harvest) aims to forbid UTCL2 to send invalidation command to harvested SE/SA. Once invalidation command comes into harvested SE/SA, SE/SA has no response and system hang. This patch is to add checking if the GART table is already allocated before invalidating TLB. The new procedure is as following: 1. Calling amdgpu_gtt_mgr_init() in amdgpu_ttm_init(). After this step GTT BOs can be allocated, but GART mappings are still ignored. 2. Calling amdgpu_gart_table_vram_alloc() from the GMC code. This allocates the GART backing store. 3. Initializing the hardware, and programming the backing store into VMID0 for all VMHUBs. 4. Calling amdgpu_gtt_mgr_recover() to make sure the table is updated with the GTT allocations done before it was allocated. Signed-off-by: Christian König Signed-off-by: Aaron Liu Acked-by: Huang Rui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 91d8207336c1..01cb89ffbd56 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -259,6 +259,9 @@ void amdgpu_gart_invalidate_tlb(struct amdgpu_device *adev) { int i; + if (!adev->gart.ptr) + return; + mb(); amdgpu_device_flush_hdp(adev, NULL); for (i = 0; i < adev->num_vmhubs; i++) From de95753cce66582b0c710dc31592cf15d317118b Mon Sep 17 00:00:00 2001 From: Roman Li Date: Wed, 2 Feb 2022 14:30:09 -0500 Subject: [PATCH 281/339] drm/amd/display: Cap pflip irqs per max otg number [Why] pflip interrupt order are mapped 1 to 1 to otg id. e.g. if irq_src=26 corresponds to otg0 then 27->otg1, 28->otg2... Linux DM registers pflip interrupts per number of crtcs. In fused pipe case crtc numbers can be less than otg id. e.g. if one pipe out of 3(otg#0-2) is fused adev->mode_info.num_crtc=2 so DM only registers irq_src 26,27. This is a bug since if pipe#2 remains unfused DM never gets otg2 pflip interrupt (irq_src=28) That may results in gfx failure due to pflip timeout. [How] Register pflip interrupts per max num of otg instead of num_crtc Signed-off-by: Roman Li Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 ++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 322333b1eb08..11298615abfb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3646,7 +3646,7 @@ static int dcn10_register_irq_handlers(struct amdgpu_device *adev) /* Use GRPH_PFLIP interrupt */ for (i = DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT; - i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + adev->mode_info.num_crtc - 1; + i <= DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT + dc->caps.max_otg_num - 1; i++) { r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DCE, i, &adev->pageflip_irq); if (r) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e1dee42652ba..f616d11250a2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1220,6 +1220,8 @@ struct dc *dc_create(const struct dc_init_data *init_params) dc->caps.max_dp_protocol_version = DP_VERSION_1_4; + dc->caps.max_otg_num = dc->res_pool->res_cap->num_timing_generator; + if (dc->res_pool->dmcu != NULL) dc->versions.dmcu_version = dc->res_pool->dmcu->dmcu_version; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 69d264dd69a7..af0587790776 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -200,6 +200,7 @@ struct dc_caps { bool edp_dsc_support; bool vbios_lttpr_aware; bool vbios_lttpr_enable; + uint32_t max_otg_num; }; struct dc_bug_wa { From bd42571168ed54d309480856fadea3eb99821253 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 12:08:39 +0800 Subject: [PATCH 282/339] drm/amd/pm: correct the way for retrieving enabled ppfeatures on Renoir As other dGPU asics, Renoir should use smu_cmn_get_enabled_mask() for that job. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 2c1eff9fe4f2..ab9c1c156868 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -710,7 +710,8 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, size_t size = 0; int ret = 0, i; - if (!smu->is_apu) { + if (!smu->is_apu || + (smu->adev->asic_type == CHIP_RENOIR)) { ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); From 5af779adc3ab0245b94187a3fad6d10f60013c1b Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 12:04:47 +0800 Subject: [PATCH 283/339] drm/amd/pm: unify the interface for retrieving enabled ppfeatures Instead of having two which do the same thing. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 2 +- .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 6 +- .../drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 6 +- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 95 ++++++++----------- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 4 - 5 files changed, 46 insertions(+), 67 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index 2f57333e6071..cc080a0075ee 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -357,7 +357,7 @@ static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) if (adev->in_suspend) return false; - ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); if (ret) return false; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 721027917f81..b4a3c9b8b54e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -507,7 +507,7 @@ static bool vangogh_is_dpm_running(struct smu_context *smu) if (adev->in_suspend) return false; - ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); if (ret) return false; @@ -1965,7 +1965,7 @@ static int vangogh_system_features_control(struct smu_context *smu, bool en) if (!en) return ret; - ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); if (ret) return ret; @@ -2182,7 +2182,7 @@ static const struct pptable_funcs vangogh_ppt_funcs = { .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable, .is_dpm_running = vangogh_is_dpm_running, .read_sensor = vangogh_read_sensor, - .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_watermarks_table = vangogh_set_watermarks_table, .set_driver_table_location = smu_v11_0_set_driver_table_location, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index bd24a2632214..f425827e2361 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -209,7 +209,7 @@ static int yellow_carp_system_features_control(struct smu_context *smu, bool en) if (!en) return ret; - ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); if (ret) return ret; @@ -258,7 +258,7 @@ static bool yellow_carp_is_dpm_running(struct smu_context *smu) uint32_t feature_mask[2]; uint64_t feature_enabled; - ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); if (ret) return false; @@ -1174,7 +1174,7 @@ static const struct pptable_funcs yellow_carp_ppt_funcs = { .is_dpm_running = yellow_carp_is_dpm_running, .set_watermarks_table = yellow_carp_set_watermarks_table, .get_gpu_metrics = yellow_carp_get_gpu_metrics, - .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_driver_table_location = smu_v13_0_set_driver_table_location, .gfx_off_control = smu_v13_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index ab9c1c156868..dbcb1b7a6b7f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -545,67 +545,59 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, uint32_t *feature_mask, uint32_t num) { - uint32_t feature_mask_high = 0, feature_mask_low = 0; struct smu_feature *feature = &smu->smu_feature; + struct amdgpu_device *adev = smu->adev; + uint32_t *feature_mask_high; + uint32_t *feature_mask_low; int ret = 0; if (!feature_mask || num < 2) return -EINVAL; - if (bitmap_empty(feature->enabled, feature->feature_num)) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh, &feature_mask_high); - if (ret) - return ret; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow, &feature_mask_low); - if (ret) - return ret; - - feature_mask[0] = feature_mask_low; - feature_mask[1] = feature_mask_high; - } else { - bitmap_copy((unsigned long *)feature_mask, feature->enabled, + if (!bitmap_empty(feature->enabled, feature->feature_num)) { + bitmap_copy((unsigned long *)feature_mask, + feature->enabled, feature->feature_num); + return 0; } - return ret; -} - -int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu, - uint32_t *feature_mask, - uint32_t num) -{ - uint32_t feature_mask_en_low = 0; - uint32_t feature_mask_en_high = 0; - struct smu_feature *feature = &smu->smu_feature; - int ret = 0; - - if (!feature_mask || num < 2) - return -EINVAL; - - if (bitmap_empty(feature->enabled, feature->feature_num)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetEnabledSmuFeatures, 0, - &feature_mask_en_low); + feature_mask_low = &feature_mask[0]; + feature_mask_high = &feature_mask[1]; + switch (adev->ip_versions[MP1_HWIP][0]) { + case IP_VERSION(11, 0, 8): + case IP_VERSION(11, 5, 0): + case IP_VERSION(13, 0, 1): + case IP_VERSION(13, 0, 3): + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetEnabledSmuFeatures, + 0, + feature_mask_low); if (ret) return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetEnabledSmuFeatures, 1, - &feature_mask_en_high); - + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetEnabledSmuFeatures, + 1, + feature_mask_high); + break; + case IP_VERSION(12, 0, 0): + case IP_VERSION(12, 0, 1): + /* other dGPU ASICs */ + default: + ret = smu_cmn_send_smc_msg(smu, + SMU_MSG_GetEnabledSmuFeaturesHigh, + feature_mask_high); if (ret) return ret; - feature_mask[0] = feature_mask_en_low; - feature_mask[1] = feature_mask_en_high; - - } else { - bitmap_copy((unsigned long *)feature_mask, feature->enabled, - feature->feature_num); + ret = smu_cmn_send_smc_msg(smu, + SMU_MSG_GetEnabledSmuFeaturesLow, + feature_mask_low); + break; } return ret; - } uint64_t smu_cmn_get_indep_throttler_status( @@ -710,20 +702,11 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, size_t size = 0; int ret = 0, i; - if (!smu->is_apu || - (smu->adev->asic_type == CHIP_RENOIR)) { - ret = smu_cmn_get_enabled_mask(smu, - feature_mask, - 2); - if (ret) - return 0; - } else { - ret = smu_cmn_get_enabled_32_bits_mask(smu, - feature_mask, - 2); - if (ret) - return 0; - } + ret = smu_cmn_get_enabled_mask(smu, + feature_mask, + 2); + if (ret) + return 0; size = sysfs_emit_at(buf, size, "features high: 0x%08x low: 0x%08x\n", feature_mask[1], feature_mask[0]); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index f0b4fb2a0960..4e34c18c6063 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -61,10 +61,6 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); -int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu, - uint32_t *feature_mask, - uint32_t num); - uint64_t smu_cmn_get_indep_throttler_status( const unsigned long dep_status, const uint8_t *throttler_map); From 2d282665d2613fc7be9dde557811a7783ac01735 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 13:01:43 +0800 Subject: [PATCH 284/339] drm/amd/pm: update the data type for retrieving enabled ppfeatures Use uint64_t instead of an array of uint32_t. This can avoid some non-necessary intermediate uint32_t -> uint64_t conversions. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 5 ++-- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 5 +--- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 6 +--- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 5 +--- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 5 +--- .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 4 +-- .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 10 ++----- .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 7 ++--- .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 4 +-- .../drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 9 ++---- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 29 +++++++------------ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 3 +- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 2 +- 14 files changed, 32 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index af368aa1fd0a..86cd8341de65 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2341,7 +2341,7 @@ static int smu_read_sensor(void *handle, *size = 4; break; case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: - ret = smu_feature_get_enabled_mask(smu, (uint32_t *)data, 2); + ret = smu_feature_get_enabled_mask(smu, (uint64_t *)data); *size = 8; break; case AMDGPU_PP_SENSOR_UVD_POWER: diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 79c7cb1a92d7..a3cda241f305 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -989,10 +989,9 @@ struct pptable_funcs { /** * @get_enabled_mask: Get a mask of features that are currently enabled * on the SMU. - * &feature_mask: Array representing enabled feature mask. - * &num: Elements in &feature_mask. + * &feature_mask: Enabled feature mask. */ - int (*get_enabled_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); + int (*get_enabled_mask)(struct smu_context *smu, uint64_t *feature_mask); /** * @feature_is_enabled: Test if a feature is enabled. diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 709c32063ef7..201563072189 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2021,15 +2021,12 @@ static void arcturus_dump_pptable(struct smu_context *smu) static bool arcturus_is_dpm_running(struct smu_context *smu) { int ret = 0; - uint32_t feature_mask[2]; uint64_t feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; - return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index cc080a0075ee..2b38a9154dd4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -350,20 +350,16 @@ static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; int ret = 0; - uint32_t feature_mask[2]; uint64_t feature_enabled; /* we need to re-init after suspend so return false */ if (adev->in_suspend) return false; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32); - /* * cyan_skillfish specific, query default sclk inseted of hard code. */ diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 4a86520d01c3..84cbde3f913d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1639,15 +1639,12 @@ static int navi10_display_config_changed(struct smu_context *smu) static bool navi10_is_dpm_running(struct smu_context *smu) { int ret = 0; - uint32_t feature_mask[2]; uint64_t feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; - return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 22dd372b8d24..b6759f8b5167 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1297,15 +1297,12 @@ static int sienna_cichlid_display_config_changed(struct smu_context *smu) static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) { int ret = 0; - uint32_t feature_mask[2]; uint64_t feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; - return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index b58a4c2823c2..b34d3a416939 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -799,7 +799,7 @@ int smu_v11_0_system_features_control(struct smu_context *smu, bool en) { struct smu_feature *feature = &smu->smu_feature; - uint32_t feature_mask[2]; + uint64_t feature_mask; int ret = 0; ret = smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : @@ -811,7 +811,7 @@ int smu_v11_0_system_features_control(struct smu_context *smu, bitmap_zero(feature->supported, feature->feature_num); if (en) { - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_mask); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index b4a3c9b8b54e..65f30cdafc8f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -500,21 +500,17 @@ static bool vangogh_is_dpm_running(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; int ret = 0; - uint32_t feature_mask[2]; uint64_t feature_enabled; /* we need to re-init after suspend so return false */ if (adev->in_suspend) return false; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); - return !!(feature_enabled & SMC_DPM_FEATURE); } @@ -1952,7 +1948,7 @@ static int vangogh_system_features_control(struct smu_context *smu, bool en) { struct amdgpu_device *adev = smu->adev; struct smu_feature *feature = &smu->smu_feature; - uint32_t feature_mask[2]; + uint64_t feature_mask; int ret = 0; if (adev->pm.fw_version >= 0x43f1700 && !en) @@ -1965,7 +1961,7 @@ static int vangogh_system_features_control(struct smu_context *smu, bool en) if (!en) return ret; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_mask); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index 3d96d4af92d9..890acc4e2cb8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -1450,14 +1450,11 @@ static int aldebaran_usr_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_ static bool aldebaran_is_dpm_running(struct smu_context *smu) { int ret; - uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 1754a3720179..6b77fc4b4698 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -765,7 +765,7 @@ int smu_v13_0_system_features_control(struct smu_context *smu, bool en) { struct smu_feature *feature = &smu->smu_feature; - uint32_t feature_mask[2]; + uint64_t feature_mask; int ret = 0; ret = smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : @@ -777,7 +777,7 @@ int smu_v13_0_system_features_control(struct smu_context *smu, bitmap_zero(feature->supported, feature->feature_num); if (en) { - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_mask); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index f425827e2361..a7aabb8079ed 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -197,7 +197,7 @@ static int yellow_carp_system_features_control(struct smu_context *smu, bool en) { struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; - uint32_t feature_mask[2]; + uint64_t feature_mask; int ret = 0; if (!en && !adev->in_s0ix) @@ -209,7 +209,7 @@ static int yellow_carp_system_features_control(struct smu_context *smu, bool en) if (!en) return ret; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_mask); if (ret) return ret; @@ -255,16 +255,13 @@ static int yellow_carp_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) static bool yellow_carp_is_dpm_running(struct smu_context *smu) { int ret = 0; - uint32_t feature_mask[2]; uint64_t feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); if (ret) return false; - feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; - return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index dbcb1b7a6b7f..0a3cc5f5dff2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -542,8 +542,7 @@ bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, } int smu_cmn_get_enabled_mask(struct smu_context *smu, - uint32_t *feature_mask, - uint32_t num) + uint64_t *feature_mask) { struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; @@ -551,7 +550,7 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, uint32_t *feature_mask_low; int ret = 0; - if (!feature_mask || num < 2) + if (!feature_mask) return -EINVAL; if (!bitmap_empty(feature->enabled, feature->feature_num)) { @@ -561,8 +560,8 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, return 0; } - feature_mask_low = &feature_mask[0]; - feature_mask_high = &feature_mask[1]; + feature_mask_low = &((uint32_t *)feature_mask)[0]; + feature_mask_high = &((uint32_t *)feature_mask)[1]; switch (adev->ip_versions[MP1_HWIP][0]) { case IP_VERSION(11, 0, 8): @@ -695,7 +694,7 @@ static const char *smu_get_feature_name(struct smu_context *smu, size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, char *buf) { - uint32_t feature_mask[2] = { 0 }; + uint64_t feature_mask; int feature_index = 0; uint32_t count = 0; int8_t sort_feature[SMU_FEATURE_COUNT]; @@ -703,13 +702,12 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, int ret = 0, i; ret = smu_cmn_get_enabled_mask(smu, - feature_mask, - 2); + &feature_mask); if (ret) return 0; size = sysfs_emit_at(buf, size, "features high: 0x%08x low: 0x%08x\n", - feature_mask[1], feature_mask[0]); + upper_32_bits(feature_mask), lower_32_bits(feature_mask)); memset(sort_feature, -1, sizeof(sort_feature)); @@ -745,22 +743,17 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask) { int ret = 0; - uint32_t feature_mask[2] = { 0 }; + uint64_t feature_mask; uint64_t feature_2_enabled = 0; uint64_t feature_2_disabled = 0; - uint64_t feature_enables = 0; ret = smu_cmn_get_enabled_mask(smu, - feature_mask, - 2); + &feature_mask); if (ret) return ret; - feature_enables = ((uint64_t)feature_mask[1] << 32 | - (uint64_t)feature_mask[0]); - - feature_2_enabled = ~feature_enables & new_mask; - feature_2_disabled = feature_enables & ~new_mask; + feature_2_enabled = ~feature_mask & new_mask; + feature_2_disabled = feature_mask & ~new_mask; if (feature_2_enabled) { ret = smu_cmn_feature_update_enable_state(smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 4e34c18c6063..bfe3430829c7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -58,8 +58,7 @@ bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type); int smu_cmn_get_enabled_mask(struct smu_context *smu, - uint32_t *feature_mask, - uint32_t num); + uint64_t *feature_mask); uint64_t smu_cmn_get_indep_throttler_status( const unsigned long dep_status, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index a290b5789195..0063346ed163 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -55,7 +55,7 @@ #define smu_send_smc_msg(smu, msg, read_arg) smu_ppt_funcs(send_smc_msg, 0, smu, msg, read_arg) #define smu_init_display_count(smu, count) smu_ppt_funcs(init_display_count, 0, smu, count) #define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) -#define smu_feature_get_enabled_mask(smu, mask, num) smu_ppt_funcs(get_enabled_mask, 0, smu, mask, num) +#define smu_feature_get_enabled_mask(smu, mask) smu_ppt_funcs(get_enabled_mask, 0, smu, mask) #define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) #define smu_disable_all_features_with_exception(smu, no_hw_disablement, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, no_hw_disablement, mask) #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) From 7ade3ca9cdb547eac2cdb661c91a481235e21ae8 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 12:19:17 +0800 Subject: [PATCH 285/339] drm/amd/pm: correct the usage for 'supported' member of smu_feature structure The supported features should be retrieved just after EnableAllDpmFeatures message complete. And the check(whether some dpm feature is supported) is only needed when we decide to enable or disable it. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 11 +++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 8 ++++---- .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 10 +++++----- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 3 --- drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 5 +---- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 3 --- drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 3 --- 7 files changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 86cd8341de65..40e7adf8e9ac 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1057,8 +1057,10 @@ static int smu_get_thermal_temperature_range(struct smu_context *smu) static int smu_smc_hw_setup(struct smu_context *smu) { + struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; uint32_t pcie_gen = 0, pcie_width = 0; + uint64_t features_supported; int ret = 0; if (adev->in_suspend && smu_is_dpm_running(smu)) { @@ -1138,6 +1140,15 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } + ret = smu_feature_get_enabled_mask(smu, &features_supported); + if (ret) { + dev_err(adev->dev, "Failed to retrieve supported dpm features!\n"); + return ret; + } + bitmap_copy(feature->supported, + (unsigned long *)&features_supported, + feature->feature_num); + if (!smu_is_dpm_running(smu)) dev_info(adev->dev, "dpm has been disabled\n"); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 84cbde3f913d..f55ead5f9aba 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1624,8 +1624,8 @@ static int navi10_display_config_changed(struct smu_context *smu) int ret = 0; if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && + smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, smu->display_config->num_display, NULL); @@ -1860,13 +1860,13 @@ static int navi10_notify_smc_display_config(struct smu_context *smu) min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; min_clocks.memory_clock = smu->display_config->min_mem_set_clock; - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { clock_req.clock_type = amd_pp_dcef_clock; clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); if (!ret) { - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetMinDeepSleepDcefclk, min_clocks.dcef_clock_in_sr/100, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index b6759f8b5167..804e1c98238d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1280,8 +1280,8 @@ static int sienna_cichlid_display_config_changed(struct smu_context *smu) int ret = 0; if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && + smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { #if 0 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, smu->display_config->num_display, @@ -1517,13 +1517,13 @@ static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; min_clocks.memory_clock = smu->display_config->min_mem_set_clock; - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { clock_req.clock_type = amd_pp_dcef_clock; clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); if (!ret) { - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetMinDeepSleepDcefclk, min_clocks.dcef_clock_in_sr/100, @@ -3785,7 +3785,7 @@ static int sienna_cichlid_gpo_control(struct smu_context *smu, int ret = 0; - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_GFX_GPO_BIT)) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFX_GPO_BIT)) { ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index b34d3a416939..d36b64371492 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -808,7 +808,6 @@ int smu_v11_0_system_features_control(struct smu_context *smu, return ret; bitmap_zero(feature->enabled, feature->feature_num); - bitmap_zero(feature->supported, feature->feature_num); if (en) { ret = smu_cmn_get_enabled_mask(smu, &feature_mask); @@ -817,8 +816,6 @@ int smu_v11_0_system_features_control(struct smu_context *smu, bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, feature->feature_num); - bitmap_copy(feature->supported, (unsigned long *)&feature_mask, - feature->feature_num); } return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 65f30cdafc8f..478151e72889 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -1956,7 +1956,6 @@ static int vangogh_system_features_control(struct smu_context *smu, bool en) RLC_STATUS_OFF, NULL); bitmap_zero(feature->enabled, feature->feature_num); - bitmap_zero(feature->supported, feature->feature_num); if (!en) return ret; @@ -1967,8 +1966,6 @@ static int vangogh_system_features_control(struct smu_context *smu, bool en) bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, feature->feature_num); - bitmap_copy(feature->supported, (unsigned long *)&feature_mask, - feature->feature_num); return 0; } @@ -1985,7 +1982,7 @@ static int vangogh_post_smu_init(struct smu_context *smu) adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines; /* allow message will be sent after enable message on Vangogh*/ - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_GFXCLK_BIT) && + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL); if (ret) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 6b77fc4b4698..92b5c1108a2e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -774,7 +774,6 @@ int smu_v13_0_system_features_control(struct smu_context *smu, return ret; bitmap_zero(feature->enabled, feature->feature_num); - bitmap_zero(feature->supported, feature->feature_num); if (en) { ret = smu_cmn_get_enabled_mask(smu, &feature_mask); @@ -783,8 +782,6 @@ int smu_v13_0_system_features_control(struct smu_context *smu, bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, feature->feature_num); - bitmap_copy(feature->supported, (unsigned long *)&feature_mask, - feature->feature_num); } return ret; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index a7aabb8079ed..d89e8a03651b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -204,7 +204,6 @@ static int yellow_carp_system_features_control(struct smu_context *smu, bool en) ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); bitmap_zero(feature->enabled, feature->feature_num); - bitmap_zero(feature->supported, feature->feature_num); if (!en) return ret; @@ -215,8 +214,6 @@ static int yellow_carp_system_features_control(struct smu_context *smu, bool en) bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, feature->feature_num); - bitmap_copy(feature->supported, (unsigned long *)&feature_mask, - feature->feature_num); return 0; } From 3c6591e947f5c23c13dec67da3dbff12ccd6e209 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 15:00:35 +0800 Subject: [PATCH 286/339] drm/amd/pm: drop the cache for enabled ppfeatures The following scenarios make the driver cache for enabled ppfeatures outdated and invalid: - Other tools interact with PMFW to change the enabled ppfeatures. - PMFW may enable/disable some features behind driver's back. E.g. for sienna_cichild, on gfxoff entering, PMFW will disable gfx related DPM features. All those are performed without driver's notice. Also considering driver does not actually interact with PMFW such frequently, the benefit brought by such cache is very limited. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 1 - drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 23 +--------- .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 16 +------ .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 23 +--------- .../drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 16 +------ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 46 +++++-------------- 7 files changed, 17 insertions(+), 109 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 40e7adf8e9ac..1d526aef0b65 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -950,7 +950,6 @@ static int smu_sw_init(void *handle) smu->pool_size = adev->pm.smu_prv_buffer_size; smu->smu_feature.feature_num = SMU_FEATURE_MAX; bitmap_zero(smu->smu_feature.supported, SMU_FEATURE_MAX); - bitmap_zero(smu->smu_feature.enabled, SMU_FEATURE_MAX); bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX); mutex_init(&smu->message_lock); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index a3cda241f305..c69c80a3420f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -390,7 +390,6 @@ struct smu_feature uint32_t feature_num; DECLARE_BITMAP(supported, SMU_FEATURE_MAX); DECLARE_BITMAP(allowed, SMU_FEATURE_MAX); - DECLARE_BITMAP(enabled, SMU_FEATURE_MAX); }; struct smu_clocks { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index d36b64371492..d71155a66f97 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -798,27 +798,8 @@ failed: int smu_v11_0_system_features_control(struct smu_context *smu, bool en) { - struct smu_feature *feature = &smu->smu_feature; - uint64_t feature_mask; - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : - SMU_MSG_DisableAllSmuFeatures), NULL); - if (ret) - return ret; - - bitmap_zero(feature->enabled, feature->feature_num); - - if (en) { - ret = smu_cmn_get_enabled_mask(smu, &feature_mask); - if (ret) - return ret; - - bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, - feature->feature_num); - } - - return ret; + return smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : + SMU_MSG_DisableAllSmuFeatures), NULL); } int smu_v11_0_notify_display_change(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 478151e72889..96a5b31f708d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -1947,27 +1947,13 @@ static int vangogh_get_dpm_clock_table(struct smu_context *smu, struct dpm_clock static int vangogh_system_features_control(struct smu_context *smu, bool en) { struct amdgpu_device *adev = smu->adev; - struct smu_feature *feature = &smu->smu_feature; - uint64_t feature_mask; int ret = 0; if (adev->pm.fw_version >= 0x43f1700 && !en) ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify, RLC_STATUS_OFF, NULL); - bitmap_zero(feature->enabled, feature->feature_num); - - if (!en) - return ret; - - ret = smu_cmn_get_enabled_mask(smu, &feature_mask); - if (ret) - return ret; - - bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, - feature->feature_num); - - return 0; + return ret; } static int vangogh_post_smu_init(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 92b5c1108a2e..f0ab1dc3ca59 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -764,27 +764,8 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable) int smu_v13_0_system_features_control(struct smu_context *smu, bool en) { - struct smu_feature *feature = &smu->smu_feature; - uint64_t feature_mask; - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : - SMU_MSG_DisableAllSmuFeatures), NULL); - if (ret) - return ret; - - bitmap_zero(feature->enabled, feature->feature_num); - - if (en) { - ret = smu_cmn_get_enabled_mask(smu, &feature_mask); - if (ret) - return ret; - - bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, - feature->feature_num); - } - - return ret; + return smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : + SMU_MSG_DisableAllSmuFeatures), NULL); } int smu_v13_0_notify_display_change(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index d89e8a03651b..e90387a84cbb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -195,27 +195,13 @@ static int yellow_carp_fini_smc_tables(struct smu_context *smu) static int yellow_carp_system_features_control(struct smu_context *smu, bool en) { - struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; - uint64_t feature_mask; int ret = 0; if (!en && !adev->in_s0ix) ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); - bitmap_zero(feature->enabled, feature->feature_num); - - if (!en) - return ret; - - ret = smu_cmn_get_enabled_mask(smu, &feature_mask); - if (ret) - return ret; - - bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, - feature->feature_num); - - return 0; + return ret; } static int yellow_carp_dpm_set_vcn_enable(struct smu_context *smu, bool enable) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 0a3cc5f5dff2..67d71670bb01 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -496,8 +496,8 @@ int smu_cmn_feature_is_supported(struct smu_context *smu, int smu_cmn_feature_is_enabled(struct smu_context *smu, enum smu_feature_mask mask) { - struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; + uint64_t enabled_features; int feature_id; if (smu->is_apu && adev->family < AMDGPU_FAMILY_VGH) @@ -509,9 +509,12 @@ int smu_cmn_feature_is_enabled(struct smu_context *smu, if (feature_id < 0) return 0; - WARN_ON(feature_id > feature->feature_num); + if (smu_cmn_get_enabled_mask(smu, &enabled_features)) { + dev_err(adev->dev, "Failed to retrieve enabled ppfeatures!\n"); + return 0; + } - return test_bit(feature_id, feature->enabled); + return test_bit(feature_id, (unsigned long *)&enabled_features); } bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, @@ -544,7 +547,6 @@ bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, int smu_cmn_get_enabled_mask(struct smu_context *smu, uint64_t *feature_mask) { - struct smu_feature *feature = &smu->smu_feature; struct amdgpu_device *adev = smu->adev; uint32_t *feature_mask_high; uint32_t *feature_mask_low; @@ -553,13 +555,6 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, if (!feature_mask) return -EINVAL; - if (!bitmap_empty(feature->enabled, feature->feature_num)) { - bitmap_copy((unsigned long *)feature_mask, - feature->enabled, - feature->feature_num); - return 0; - } - feature_mask_low = &((uint32_t *)feature_mask)[0]; feature_mask_high = &((uint32_t *)feature_mask)[1]; @@ -616,7 +611,6 @@ int smu_cmn_feature_update_enable_state(struct smu_context *smu, uint64_t feature_mask, bool enabled) { - struct smu_feature *feature = &smu->smu_feature; int ret = 0; if (enabled) { @@ -630,8 +624,6 @@ int smu_cmn_feature_update_enable_state(struct smu_context *smu, SMU_MSG_EnableSmuFeaturesHigh, upper_32_bits(feature_mask), NULL); - if (ret) - return ret; } else { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DisableSmuFeaturesLow, @@ -643,17 +635,8 @@ int smu_cmn_feature_update_enable_state(struct smu_context *smu, SMU_MSG_DisableSmuFeaturesHigh, upper_32_bits(feature_mask), NULL); - if (ret) - return ret; } - if (enabled) - bitmap_or(feature->enabled, feature->enabled, - (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); - else - bitmap_andnot(feature->enabled, feature->enabled, - (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); - return ret; } @@ -661,7 +644,6 @@ int smu_cmn_feature_set_enabled(struct smu_context *smu, enum smu_feature_mask mask, bool enable) { - struct smu_feature *feature = &smu->smu_feature; int feature_id; feature_id = smu_cmn_to_asic_specific_index(smu, @@ -670,8 +652,6 @@ int smu_cmn_feature_set_enabled(struct smu_context *smu, if (feature_id < 0) return -EINVAL; - WARN_ON(feature_id > feature->feature_num); - return smu_cmn_feature_update_enable_state(smu, 1ULL << feature_id, enable); @@ -793,7 +773,6 @@ int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, bool no_hw_disablement, enum smu_feature_mask mask) { - struct smu_feature *feature = &smu->smu_feature; uint64_t features_to_disable = U64_MAX; int skipped_feature_id; @@ -807,15 +786,12 @@ int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, features_to_disable &= ~(1ULL << skipped_feature_id); } - if (no_hw_disablement) { - bitmap_andnot(feature->enabled, feature->enabled, - (unsigned long *)(&features_to_disable), SMU_FEATURE_MAX); + if (no_hw_disablement) return 0; - } else { - return smu_cmn_feature_update_enable_state(smu, - features_to_disable, - 0); - } + + return smu_cmn_feature_update_enable_state(smu, + features_to_disable, + 0); } int smu_cmn_get_smc_version(struct smu_context *smu, From a89ef0448c9b59c524499663eeb92a43c8bc67fd Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 15:35:00 +0800 Subject: [PATCH 287/339] drm/amd/pm: avoid consecutive retrieving for enabled ppfeatures As the enabled ppfeatures are just retrieved ahead. We can use that directly instead of retrieving again and again. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 67d71670bb01..1a54447a1266 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -680,6 +680,7 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, int8_t sort_feature[SMU_FEATURE_COUNT]; size_t size = 0; int ret = 0, i; + int feature_id; ret = smu_cmn_get_enabled_mask(smu, &feature_mask); @@ -708,11 +709,18 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, if (sort_feature[i] < 0) continue; + /* convert to asic spcific feature ID */ + feature_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + sort_feature[i]); + if (feature_id < 0) + continue; + size += sysfs_emit_at(buf, size, "%02d. %-20s (%2d) : %s\n", count++, smu_get_feature_name(smu, sort_feature[i]), i, - !!smu_cmn_feature_is_enabled(smu, sort_feature[i]) ? + !!test_bit(feature_id, (unsigned long *)&feature_mask) ? "enabled" : "disabled"); } From f69c15e15e74fb0250049c5532d8322c75f423ad Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 8 Dec 2021 15:47:58 +0800 Subject: [PATCH 288/339] drm/amd/pm: revise the implementation of smu_cmn_disable_all_features_with_exception As there is no internal cache for enabled ppfeatures now. Thus the 2nd parameter will be not needed any more. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 9 ++------- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 7 ------- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 1 - drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 2 +- 5 files changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 1d526aef0b65..7925edc9e87b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1360,9 +1360,7 @@ static int smu_disable_dpms(struct smu_context *smu) case IP_VERSION(11, 5, 0): case IP_VERSION(11, 0, 12): case IP_VERSION(11, 0, 13): - return smu_disable_all_features_with_exception(smu, - true, - SMU_FEATURE_COUNT); + return 0; default: break; } @@ -1378,9 +1376,7 @@ static int smu_disable_dpms(struct smu_context *smu) case IP_VERSION(11, 0, 0): case IP_VERSION(11, 0, 5): case IP_VERSION(11, 0, 9): - return smu_disable_all_features_with_exception(smu, - true, - SMU_FEATURE_BACO_BIT); + return 0; default: break; } @@ -1392,7 +1388,6 @@ static int smu_disable_dpms(struct smu_context *smu) */ if (use_baco && smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) { ret = smu_disable_all_features_with_exception(smu, - false, SMU_FEATURE_BACO_BIT); if (ret) dev_err(adev->dev, "Failed to disable smu features except BACO.\n"); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index c69c80a3420f..218de8f8ec30 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -1004,7 +1004,6 @@ struct pptable_funcs { * exception to those in &mask. */ int (*disable_all_features_with_exception)(struct smu_context *smu, - bool no_hw_disablement, enum smu_feature_mask mask); /** diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 1a54447a1266..efb553105df3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -767,9 +767,6 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, * @mask * * @smu: smu_context pointer - * @no_hw_disablement: whether real dpm disablement should be performed - * true: update the cache(about dpm enablement state) only - * false: real dpm disablement plus cache update * @mask: the dpm feature which should not be disabled * SMU_FEATURE_COUNT: no exception, all dpm features * to disable @@ -778,7 +775,6 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, * 0 on success or a negative error code on failure. */ int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, - bool no_hw_disablement, enum smu_feature_mask mask) { uint64_t features_to_disable = U64_MAX; @@ -794,9 +790,6 @@ int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, features_to_disable &= ~(1ULL << skipped_feature_id); } - if (no_hw_disablement) - return 0; - return smu_cmn_feature_update_enable_state(smu, features_to_disable, 0); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index bfe3430829c7..a4c593ed8b03 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -79,7 +79,6 @@ int smu_cmn_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask); int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, - bool no_hw_disablement, enum smu_feature_mask mask); int smu_cmn_get_smc_version(struct smu_context *smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 0063346ed163..530be44e00ec 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -57,7 +57,7 @@ #define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) #define smu_feature_get_enabled_mask(smu, mask) smu_ppt_funcs(get_enabled_mask, 0, smu, mask) #define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) -#define smu_disable_all_features_with_exception(smu, no_hw_disablement, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, no_hw_disablement, mask) +#define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) #define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) #define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) From a423746305d41c1e2767b832742cb572ab173af3 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Tue, 25 Jan 2022 10:56:08 -0500 Subject: [PATCH 289/339] drm/amd/display: Fix for variable may be used uninitialized error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] Build failure due to ‘status’ may be used uninitialized [How] Initialize status to LINK_TRAINING_SUCCESS Reviewed-by: Wenjing Liu Acked-by: Jasdeep Dhillon Signed-off-by: Eric Bernstein Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 18fe8f77821a..d0cb40df60a4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3199,7 +3199,7 @@ static bool dp_verify_link_cap( bool success = false; bool skip_video_pattern; enum clock_source_id dp_cs_id = get_clock_source_id(link); - enum link_training_result status; + enum link_training_result status = LINK_TRAINING_SUCCESS; union hpd_irq_data irq_data; struct link_resource link_res; From 6d33f0e820bfbc4f0b9b2f23d0d30df4bd6c3001 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 25 Jan 2022 12:04:34 -0500 Subject: [PATCH 290/339] drm/amd/display: Fix stream->link_enc unassigned during stream removal [Why] Found when running igt@kms_atomic. Userspace attempts to do a TEST_COMMIT when 0 streams which calls dc_remove_stream_from_ctx. This in turn calls link_enc_unassign which ends up modifying stream->link = NULL directly, causing the global link_enc to be removed preventing further link activity and future link validation from passing. [How] We take care of link_enc unassignment at the start of link_enc_cfg_link_encs_assign so this call is no longer necessary. Fixes global state from being modified while unlocked. Reviewed-by: Jimmy Kizito Acked-by: Jasdeep Dhillon Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index e82aa0559bdf..9df66501a453 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1965,10 +1965,6 @@ enum dc_status dc_remove_stream_from_ctx( dc->res_pool, del_pipe->stream_res.stream_enc, false); - /* Release link encoder from stream in new dc_state. */ - if (dc->res_pool->funcs->link_enc_unassign) - dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); - if (is_dp_128b_132b_signal(del_pipe)) { update_hpo_dp_stream_engine_usage( &new_ctx->res_ctx, dc->res_pool, From 3084488a49d6d58005d6ac1b5457b3f13bad1ed3 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Tue, 25 Jan 2022 09:34:39 -0500 Subject: [PATCH 291/339] drm/amd/display: limit unbounded requesting to 5k Unbounded requesting is unsupported on pipe split modes and this change prevents us running into such a situation with wide modes. Reviewed-by: Charlene Liu Acked-by: Jasdeep Dhillon Signed-off-by: Dmytro Laktyushkin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index f9e312b20598..1166748b85a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1842,7 +1842,8 @@ static int dcn31_populate_dml_pipes_from_context( if (is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) { dc->config.enable_4to1MPC = true; - } else if (!is_dual_plane(pipe->plane_state->format)) { + } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) { + /* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */ context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192; pipes[0].pipe.src.unbounded_req_mode = true; } From 77a35bb579827216d911ece7a6b909e4ac8e1626 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Tue, 25 Jan 2022 14:42:12 -0500 Subject: [PATCH 292/339] drm/amd/display: remove static from optc31_set_drr remove static from optc31_set_drr Reviewed-by: Nevenko Stupar Acked-by: Jasdeep Dhillon Signed-off-by: Eric Bernstein Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c index e8562fa11366..8afe2130d7c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c @@ -161,7 +161,7 @@ static bool optc31_immediate_disable_crtc(struct timing_generator *optc) return true; } -static void optc31_set_drr( +void optc31_set_drr( struct timing_generator *optc, const struct drr_params *params) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h index d8ef2f0d0c95..a37b16040c1d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h @@ -256,4 +256,6 @@ void dcn31_timing_generator_init(struct optc *optc1); +void optc31_set_drr(struct timing_generator *optc, const struct drr_params *params); + #endif /* __DC_OPTC_DCN31_H__ */ From b65007590911ad558999073dbffa413cf4861df3 Mon Sep 17 00:00:00 2001 From: Bing Guo Date: Thu, 20 Jan 2022 18:34:24 -0500 Subject: [PATCH 293/339] drm/amdgpu/display/dc: do blocked MST topology discovery at resume from S3/S4 Why: When resume from sleep or hiberation, blocked MST Topology discovery might need to be used. How: Added "DETECT_REASON_RESUMEFROMS3S4" to enum dc_detect_reason; use it to require blocked MST Topology discovery. Reviewed-by: Wenjing Liu Acked-by: Jasdeep Dhillon Signed-off-by: Bing Guo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- drivers/gpu/drm/amd/display/dc/dc_link.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index cb6c91cd6e83..ec4b300ec067 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -831,7 +831,7 @@ static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason link->type = dc_connection_mst_branch; dm_helpers_dp_update_branch_info(link->ctx, link); if (dm_helpers_dp_mst_start_top_mgr(link->ctx, - link, reason == DETECT_REASON_BOOT)) { + link, (reason == DETECT_REASON_BOOT || reason == DETECT_REASON_RESUMEFROMS3S4))) { link_disconnect_sink(link); } else { link->type = dc_connection_sst_branch; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index e7ead9e25318..9ad3ee4079c3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -312,6 +312,7 @@ void dc_link_blank_dp_stream(struct dc_link *link, bool hw_init); */ enum dc_detect_reason { DETECT_REASON_BOOT, + DETECT_REASON_RESUMEFROMS3S4, DETECT_REASON_HPD, DETECT_REASON_HPDRX, DETECT_REASON_FALLBACK, From ca7f9d0aba9940f4d3e759f44c414c3707a94b21 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 27 Jan 2022 11:55:49 -0500 Subject: [PATCH 294/339] drm/amd/display: fix yellow carp wm clamping Fix clamping to match register field size Reviewed-by: Charlene Liu Acked-by: Jasdeep Dhillon Signed-off-by: Dmytro Laktyushkin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn31/dcn31_hubbub.c | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c index 90c73a1cb986..5e3bcaf12cac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c @@ -138,8 +138,11 @@ static uint32_t convert_and_clamp( ret_val = wm_ns * refclk_mhz; ret_val /= 1000; - if (ret_val > clamp_value) + if (ret_val > clamp_value) { + /* clamping WMs is abnormal, unexpected and may lead to underflow*/ + ASSERT(0); ret_val = clamp_value; + } return ret_val; } @@ -159,7 +162,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) { hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value); @@ -193,7 +196,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) { hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns; prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value); } else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns) @@ -203,7 +206,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) { hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value); @@ -237,7 +240,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) { hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns; prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value); } else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns) @@ -247,7 +250,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) { hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value); @@ -281,7 +284,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) { hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns; prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value); } else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns) @@ -291,7 +294,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) { hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns; prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value); @@ -325,7 +328,7 @@ static bool hubbub31_program_urgent_watermarks( if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) { hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns; prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0x3fff); REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value); } else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns) @@ -351,7 +354,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" @@ -367,7 +370,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->a.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n" @@ -383,7 +386,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.cstate_enter_plus_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_A calculated =%d\n" @@ -399,7 +402,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->a.cstate_pstate.cstate_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.cstate_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_A calculated =%d\n" @@ -416,7 +419,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n" @@ -432,7 +435,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->b.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n" @@ -448,7 +451,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.cstate_enter_plus_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_B calculated =%d\n" @@ -464,7 +467,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->b.cstate_pstate.cstate_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.cstate_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_B calculated =%d\n" @@ -481,7 +484,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n" @@ -497,7 +500,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->c.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n" @@ -513,7 +516,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.cstate_enter_plus_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_C calculated =%d\n" @@ -529,7 +532,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->c.cstate_pstate.cstate_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.cstate_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_C calculated =%d\n" @@ -546,7 +549,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n" @@ -562,7 +565,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->d.cstate_pstate.cstate_exit_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.cstate_exit_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n" @@ -578,7 +581,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.cstate_enter_plus_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_ENTER_WATERMARK_Z8_D calculated =%d\n" @@ -594,7 +597,7 @@ static bool hubbub31_program_stutter_watermarks( watermarks->d.cstate_pstate.cstate_exit_z8_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.cstate_exit_z8_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_Z8_D calculated =%d\n" @@ -625,7 +628,7 @@ static bool hubbub31_program_pstate_watermarks( watermarks->a.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->a.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0, DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" @@ -642,7 +645,7 @@ static bool hubbub31_program_pstate_watermarks( watermarks->b.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->b.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0, DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n" @@ -659,7 +662,7 @@ static bool hubbub31_program_pstate_watermarks( watermarks->c.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->c.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0, DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n" @@ -676,7 +679,7 @@ static bool hubbub31_program_pstate_watermarks( watermarks->d.cstate_pstate.pstate_change_ns; prog_wm_value = convert_and_clamp( watermarks->d.cstate_pstate.pstate_change_ns, - refclk_mhz, 0x1fffff); + refclk_mhz, 0xffff); REG_SET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0, DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" From 98ea24e6c563241814abcb1d22ec207a7ec2fd9b Mon Sep 17 00:00:00 2001 From: Paul Hsieh Date: Wed, 26 Jan 2022 12:49:00 +0800 Subject: [PATCH 295/339] drm/amd/display: change fastboot timing validation [Why] VBIOS light up eDP with 6bpc but driver use 8bpc without disable valid stream then re-enable valid stream. Some panels can't runtime change color depth. [How] Change fastboot timing validation function. Not only check LANE_COUNT, LINK_RATE...etc Reviewed-by: Anthony Koo Acked-by: Jasdeep Dhillon Signed-off-by: Paul Hsieh Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f616d11250a2..83fc03a5c9cd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1462,7 +1462,7 @@ static bool context_changed( return false; } -bool dc_validate_seamless_boot_timing(const struct dc *dc, +bool dc_validate_boot_timing(const struct dc *dc, const struct dc_sink *sink, struct dc_crtc_timing *crtc_timing) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9df66501a453..b36bae4b5bc9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2168,7 +2168,7 @@ static void mark_seamless_boot_stream( if (dc->config.allow_seamless_boot_optimization && !dcb->funcs->is_accelerated_mode(dcb)) { - if (dc_validate_seamless_boot_timing(dc, stream->sink, &stream->timing)) + if (dc_validate_boot_timing(dc, stream->sink, &stream->timing)) stream->apply_seamless_boot_optimization = true; } } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index af0587790776..cba150ceacbf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1126,7 +1126,7 @@ struct dc_validation_set { uint8_t plane_count; }; -bool dc_validate_seamless_boot_timing(const struct dc *dc, +bool dc_validate_boot_timing(const struct dc *dc, const struct dc_sink *sink, struct dc_crtc_timing *crtc_timing); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 8c32b9cb3b49..52b22a944f94 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1761,7 +1761,8 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) edp_link->link_status.link_active) { struct dc_stream_state *edp_stream = edp_streams[0]; - can_apply_edp_fast_boot = !is_edp_ilr_optimization_required(edp_stream->link, &edp_stream->timing); + can_apply_edp_fast_boot = dc_validate_boot_timing(dc, + edp_stream->sink, &edp_stream->timing); edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot; if (can_apply_edp_fast_boot) DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n"); From 559e2655220d56f939a9fbc6212992345025392c Mon Sep 17 00:00:00 2001 From: Zhan Liu Date: Thu, 27 Jan 2022 22:08:53 -0500 Subject: [PATCH 296/339] drm/amd/display: keep eDP Vdd on when eDP stream is already enabled [Why] Even if can_apply_edp_fast_boot is set to 1 at boot, this flag will be cleared to 0 at S3 resume. [How] Keep eDP Vdd on when eDP stream is already enabled. Reviewed-by: Charlene Liu Acked-by: Jasdeep Dhillon Signed-off-by: Zhan Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/dce110/dce110_hw_sequencer.c | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 52b22a944f94..ace04e2ed34e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1770,9 +1770,29 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) break; } } - // We are trying to enable eDP, don't power down VDD - if (can_apply_edp_fast_boot) + + /* + * TO-DO: So far the code logic below only addresses single eDP case. + * For dual eDP case, there are a few things that need to be + * implemented first: + * + * 1. Change the fastboot logic above, so eDP link[0 or 1]'s + * stream[0 or 1] will all be checked. + * + * 2. Change keep_edp_vdd_on to an array, and maintain keep_edp_vdd_on + * for each eDP. + * + * Once above 2 things are completed, we can then change the logic below + * correspondingly, so dual eDP case will be fully covered. + */ + + // We are trying to enable eDP, don't power down VDD if eDP stream is existing + if ((edp_stream_num == 1 && edp_streams[0] != NULL) || can_apply_edp_fast_boot) { keep_edp_vdd_on = true; + DC_LOG_EVENT_LINK_TRAINING("Keep eDP Vdd on\n"); + } else { + DC_LOG_EVENT_LINK_TRAINING("No eDP stream enabled, turn eDP Vdd off\n"); + } } // Check seamless boot support From 39da460fd4c0f8e7290dcc9cbfc9375de9d0eeca Mon Sep 17 00:00:00 2001 From: Ilya Date: Thu, 27 Jan 2022 14:14:32 -0500 Subject: [PATCH 297/339] drm/amd/display: Fix DP LT sequence on EQ fail [Why] The number of lanes wasn't being reset to maximum when reducing link rate due to an EQ failure. This could result in having fewer lanes in the verified link capabilities, a lower maximum link bandwidth, and fewer modes being supported. [How] Reset the number of lanes to max when dropping link rate due to EQ failure during link training. Reviewed-by: Aric Cyr Acked-by: Jasdeep Dhillon Signed-off-by: Ilya Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index d0cb40df60a4..cd9c31b5e55d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3504,6 +3504,7 @@ static bool decide_fallback_link_setting( current_link_setting->link_rate = reduce_link_rate( current_link_setting->link_rate); + current_link_setting->lane_count = initial_link_settings.lane_count; } else { return false; } @@ -3516,6 +3517,7 @@ static bool decide_fallback_link_setting( current_link_setting->link_rate = reduce_link_rate( current_link_setting->link_rate); + current_link_setting->lane_count = initial_link_settings.lane_count; } else { return false; } From e8dd130bfdc627d935d4eda4654059a24864a493 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 29 Jan 2022 22:25:38 -0500 Subject: [PATCH 298/339] drm/amd/display: [FW Promotion] Release 0.0.103.0 Reviewed-by: Aric Cyr Acked-by: Jasdeep Dhillon Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index d6589db40f42..fa1177638706 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xab0ae3c8 +#define DMUB_FW_VERSION_GIT_HASH 0x5189adbf #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 102 +#define DMUB_FW_VERSION_REVISION 103 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From ed3a56f9c638a4ee42031eac748664c834fe245d Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 30 Jan 2022 21:38:52 -0500 Subject: [PATCH 299/339] drm/amd/display: 3.2.172 This version brings along the following fixes: -fix for build failure uninitalized error -Bug fix for DP2 using uncertified cable -limit unbounded request to 5k -fix DP LT sequence on EQ fail -Bug fixes for S3/S4 Acked-by: Jasdeep Dhillon Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index cba150ceacbf..fcb021bf0c96 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.171" +#define DC_VER "3.2.172" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 66d58bf73ba17ac45fca79f2e5e26870cc224ee3 Mon Sep 17 00:00:00 2001 From: Martin Tsai Date: Thu, 27 Jan 2022 12:48:39 +0800 Subject: [PATCH 300/339] drm/amd/display: handle null link encoder [Why] The link encoder mapping could return a null one and causes system crash. [How] Let the mapping can get an available link encoder without endpoint identification check. Reviewed-by: Wenjing Liu Acked-by: Jasdeep Dhillon Signed-off-by: Martin Tsai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 25 +++---------------- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 11 +------- 2 files changed, 5 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index ec4b300ec067..b1718600fa02 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3530,11 +3530,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx) const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res); DC_LOGGER_INIT(link->ctx->logger); - /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ - if (link->ep_type == DISPLAY_ENDPOINT_PHY) - link_encoder = link->link_enc; - else if (link->dc->res_pool->funcs->link_encs_assign) - link_encoder = link_enc_cfg_get_link_enc_used_by_stream(pipe_ctx->stream->ctx->dc, stream); + link_encoder = link_enc_cfg_get_link_enc(link); ASSERT(link_encoder); /* enable_link_dp_mst already check link->enabled_stream_count @@ -3823,11 +3819,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) const struct dc_link_settings empty_link_settings = {0}; DC_LOGGER_INIT(link->ctx->logger); - /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ - if (link->ep_type == DISPLAY_ENDPOINT_PHY) - link_encoder = link->link_enc; - else if (link->dc->res_pool->funcs->link_encs_assign) - link_encoder = link_enc_cfg_get_link_enc_used_by_stream(pipe_ctx->stream->ctx->dc, stream); + link_encoder = link_enc_cfg_get_link_enc(link); ASSERT(link_encoder); /* deallocate_mst_payload is called before disable link. When mode or @@ -3944,13 +3936,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) if (cp_psp == NULL || cp_psp->funcs.update_stream_config == NULL) return; - if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY) - link_enc = pipe_ctx->stream->link->link_enc; - else if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && - pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_stream( - pipe_ctx->stream->ctx->dc, - pipe_ctx->stream); + link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); ASSERT(link_enc); if (link_enc == NULL) return; @@ -4100,10 +4086,7 @@ void core_link_enable_stream( dc_is_virtual_signal(pipe_ctx->stream->signal)) return; - if (dc->res_pool->funcs->link_encs_assign && stream->link->ep_type != DISPLAY_ENDPOINT_PHY) - link_enc = link_enc_cfg_get_link_enc_used_by_stream(dc, stream); - else - link_enc = stream->link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (!dc_is_virtual_signal(pipe_ctx->stream->signal) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index fcf388b509db..b55868a0e0df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1605,16 +1605,7 @@ static void get_pixel_clock_parameters( pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - /* Links supporting dynamically assigned link encoder will be assigned next - * available encoder if one not already assigned. - */ - if (link->is_dig_mapping_flexible && - link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_stream(stream->ctx->dc, stream); - if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(stream->ctx->dc); - } else - link_enc = stream->link->link_enc; + link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); if (link_enc) From d7d7ddc15672940be0dbbe03e016c5bb617256b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 4 Feb 2022 09:42:22 +0100 Subject: [PATCH 301/339] drm/amdgpu: move lockdep assert to the right place. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since newly added BOs don't have any mappings it's ok to add them without holding the VM lock. Only when we add per VM BOs the lock is mandatory. Signed-off-by: Christian König Reported-by: Bhardwaj, Rajneesh Acked-by: Alex Deucher Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e0a2f5211b73..37acd8911168 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -375,6 +375,8 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, if (bo->tbo.base.resv != vm->root.bo->tbo.base.resv) return; + dma_resv_assert_held(vm->root.bo->tbo.base.resv); + vm->bulk_moveable = false; if (bo->tbo.type == ttm_bo_type_kernel && bo->parent) amdgpu_vm_bo_relocated(base); @@ -2244,8 +2246,6 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, { struct amdgpu_bo_va *bo_va; - dma_resv_assert_held(vm->root.bo->tbo.base.resv); - bo_va = kzalloc(sizeof(struct amdgpu_bo_va), GFP_KERNEL); if (bo_va == NULL) { return NULL; From b6fba4ecf3554c515aa5354c54dfdf70d7526ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 7 Feb 2022 09:05:23 +0100 Subject: [PATCH 302/339] drm/amdgpu: reserve the pd while cleaning up PRTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to have lockdep annotation here, so make sure that we reserve the PD while removing PRTs even if it isn't strictly necessary since the VM object is about to be destroyed anyway. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index d1970f37bc88..06fefe0b589c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1188,8 +1188,6 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_VCE) != NULL) amdgpu_vce_free_handles(adev, file_priv); - amdgpu_vm_bo_del(adev, fpriv->prt_va); - if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { /* TODO: how to handle reserve failure */ BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true)); @@ -1200,6 +1198,10 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, pasid = fpriv->vm.pasid; pd = amdgpu_bo_ref(fpriv->vm.root.bo); + if (!WARN_ON(amdgpu_bo_reserve(pd, true))) { + amdgpu_vm_bo_del(adev, fpriv->prt_va); + amdgpu_bo_unreserve(pd); + } amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); amdgpu_vm_fini(adev, &fpriv->vm); From 6cbdf12b87356827d35975dfb3030d116782737c Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 5 Feb 2022 07:00:08 -0800 Subject: [PATCH 303/339] drm/amd/pm: fix error handling clang static analysis reports this error amdgpu_smu.c:2289:9: warning: Called function pointer is null (null dereference) return smu->ppt_funcs->emit_clk_levels( ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There is a logic error in the earlier check of emit_clk_levels. The error value is set to the ret variable but ret is never used. Return directly and remove the unneeded ret variable. Fixes: 5d64f9bbb628 ("amdgpu/pm: Implement new API function "emit" that accepts buffer base and write offset") Reviewed-by: Evan Quan Signed-off-by: Tom Rix Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7925edc9e87b..e846231412bc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2279,7 +2279,6 @@ static int smu_emit_ppclk_levels(void *handle, enum pp_clock_type type, char *bu { struct smu_context *smu = handle; enum smu_clk_type clk_type; - int ret = 0; clk_type = smu_convert_to_smuclk(type); if (clk_type == SMU_CLK_COUNT) @@ -2289,7 +2288,7 @@ static int smu_emit_ppclk_levels(void *handle, enum pp_clock_type type, char *bu return -EOPNOTSUPP; if (!smu->ppt_funcs->emit_clk_levels) - ret = -ENOENT; + return -ENOENT; return smu->ppt_funcs->emit_clk_levels(smu, clk_type, buf, offset); From f54b6bdf4248b1e26ff66932231e1d6a2f16adc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ADra=20Canal?= Date: Wed, 2 Feb 2022 21:39:54 -0300 Subject: [PATCH 304/339] drm/amd/pm: add missing prototypes to amdgpu_dpm_internal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the header with the prototype to silence the following clang warnings: drivers/gpu/drm/amd/amdgpu/../pm/amdgpu_dpm_internal.c:29:6: warning: no previous prototype for function 'amdgpu_dpm_get_active_displays' [-Wmissing-prototypes] void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) ^ drivers/gpu/drm/amd/amdgpu/../pm/amdgpu_dpm_internal.c:29:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) ^ static drivers/gpu/drm/amd/amdgpu/../pm/amdgpu_dpm_internal.c:76:5: warning: no previous prototype for function 'amdgpu_dpm_get_vrefresh' [-Wmissing-prototypes] u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) ^ drivers/gpu/drm/amd/amdgpu/../pm/amdgpu_dpm_internal.c:76:1: note: declare 'static' if the function is not intended to be used outside of this translation unit u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) ^ static 2 warnings generated. Besides that, remove the duplicated prototype of the function amdgpu_dpm_get_vblank_time in order to keep the consistency of the headers. Fixes: 6ddbd37f1074 ("drm/amd/pm: optimize the amdgpu_pm_compute_clocks() implementations") Reviewed-by: Evan Quan Signed-off-by: Maíra Canal Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c | 1 + drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 1 - drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c index ba5f6413412d..42efe838fa85 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm_internal.c @@ -25,6 +25,7 @@ #include "amdgpu_display.h" #include "hwmgr.h" #include "amdgpu_smu.h" +#include "amdgpu_dpm_internal.h" void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 1ed0ef898eb0..43d6b57173a3 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -343,7 +343,6 @@ struct amdgpu_pm { struct amdgpu_ctx *stable_pstate_ctx; }; -u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, void *data, uint32_t *size); diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index 7427c50409d4..caae54487f9c 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -28,6 +28,7 @@ #include "amdgpu_pm.h" #include "amdgpu_dpm.h" #include "amdgpu_atombios.h" +#include "amdgpu_dpm_internal.h" #include "amd_pcie.h" #include "sid.h" #include "r600_dpm.h" From 3786a9bc0455ca58d953319f62daf96b6eb95490 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Feb 2022 14:07:07 -0500 Subject: [PATCH 305/339] drm/amdgpu: drop experimental flag on aldebaran These have been at production level for a while. Drop the flag. Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 78063d01c9db..0a803e7e5994 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1915,10 +1915,10 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x73FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_DIMGREY_CAVEFISH}, /* Aldebaran */ - {0x1002, 0x7408, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, - {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT}, + {0x1002, 0x7408, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN}, + {0x1002, 0x740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN}, + {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN}, + {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN}, /* CYAN_SKILLFISH */ {0x1002, 0x13FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU}, From bcfab8e35ce81e2fd3230c1575024bfde0d28c8b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Feb 2022 10:04:58 -0500 Subject: [PATCH 306/339] drm/amdgpu/display: change pipe policy for DCN 2.0 Fixes hangs on driver load with multiple displays on DCN 2.0 parts. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=215511 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1877 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1886 Fixes: ee2698cf79cc ("drm/amd/display: Changed pipe split policy to allow for multi-display pipe split") Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index b55868a0e0df..dfe2e1c25a26 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1069,7 +1069,7 @@ static const struct dc_debug_options debug_defaults_drv = { .timing_trace = false, .clock_trace = true, .disable_pplib_clock_request = true, - .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, .force_single_disp_pipe_split = false, .disable_dcc = DCC_ENABLE, .vsr_support = true, From 120cc6e67a5e34069693cf1711ea222b8c414685 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 28 Jan 2022 16:26:08 -0500 Subject: [PATCH 307/339] drm/amdgpu: add missing license to dpcs_3_0_0 headers MIT. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h | 7 +++++++ .../gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h index 67faaf68e9d7..0bb47e06eee8 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h @@ -1,3 +1,10 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2020 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + #ifndef _dpcs_3_0_0_OFFSET_HEADER #define _dpcs_3_0_0_OFFSET_HEADER diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h index b4ef50a72868..23fa1121a967 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h @@ -1,3 +1,10 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2020 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + #ifndef _dpcs_3_0_0_SH_MASK_HEADER #define _dpcs_3_0_0_SH_MASK_HEADER From 68550cbc6129159b7a6434796b721e8b66ee12f6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Feb 2022 12:52:21 -0500 Subject: [PATCH 308/339] drm/amdgpu: move dpcs_3_0_0 headers from dcn to dpcs To align with other headers. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c | 4 ++-- drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c | 4 ++-- .../gpu/drm/amd/display/dc/gpio/dcn30/hw_translate_dcn30.c | 4 ++-- drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c | 4 ++-- .../amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_0_offset.h | 0 .../amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_0_sh_mask.h | 0 9 files changed, 14 insertions(+), 14 deletions(-) rename drivers/gpu/drm/amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_0_offset.h (100%) rename drivers/gpu/drm/amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_0_sh_mask.h (100%) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index 0602bde78e6c..589131d415fd 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -42,8 +42,8 @@ #include "nbio/nbio_7_4_offset.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 8ca26383b568..f10f7a0ca02a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -72,8 +72,8 @@ #include "nbio/nbio_7_4_offset.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index 5d9637b07429..4daf8931aa7c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -73,8 +73,8 @@ #include "nbio/nbio_7_2_0_offset.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "reg_helper.h" #include "dce/dmub_abm.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index e512ae6d00d4..88318e8ffca8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -66,8 +66,8 @@ #include "dimgrey_cavefish_ip_offset.h" #include "dcn/dcn_3_0_2_offset.h" #include "dcn/dcn_3_0_2_sh_mask.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "nbio/nbio_7_4_offset.h" #include "amdgpu_socbb.h" diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c index 5f6ae3edb755..3b7df1ac26be 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_factory_dcn30.c @@ -42,8 +42,8 @@ #include "nbio/nbio_7_4_offset.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_translate_dcn30.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_translate_dcn30.c index 0046219a1cc7..6b6b7c7bd12f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_translate_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn30/hw_translate_dcn30.c @@ -40,8 +40,8 @@ #include "nbio/nbio_7_4_offset.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c index 914ce2ce1c2f..0b68c08fac3f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c @@ -37,8 +37,8 @@ #include "nbio/nbio_7_4_offset.h" -#include "dcn/dpcs_3_0_0_offset.h" -#include "dcn/dpcs_3_0_0_sh_mask.h" +#include "dpcs/dpcs_3_0_0_offset.h" +#include "dpcs/dpcs_3_0_0_sh_mask.h" #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_offset.h similarity index 100% rename from drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h rename to drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_offset.h diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_sh_mask.h similarity index 100% rename from drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h rename to drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_sh_mask.h From 4a5dc6c73dbec54648fe01af2f1818dc3ae90d5d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 3 Feb 2022 13:04:46 -0500 Subject: [PATCH 309/339] drm/amdgpu: move dpcs_3_0_3 headers from dcn to dpcs To align with other headers. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c | 4 ++-- .../amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_3_offset.h | 0 .../amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_3_sh_mask.h | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename drivers/gpu/drm/amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_3_offset.h (100%) rename drivers/gpu/drm/amd/include/asic_reg/{dcn => dpcs}/dpcs_3_0_3_sh_mask.h (100%) diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 2de687f64cf6..36649716e991 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -48,8 +48,8 @@ #include "sienna_cichlid_ip_offset.h" #include "dcn/dcn_3_0_3_offset.h" #include "dcn/dcn_3_0_3_sh_mask.h" -#include "dcn/dpcs_3_0_3_offset.h" -#include "dcn/dpcs_3_0_3_sh_mask.h" +#include "dpcs/dpcs_3_0_3_offset.h" +#include "dpcs/dpcs_3_0_3_sh_mask.h" #include "nbio/nbio_2_3_offset.h" #define DC_LOGGER_INIT(logger) diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_offset.h similarity index 100% rename from drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_3_offset.h rename to drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_offset.h diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_sh_mask.h similarity index 100% rename from drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_3_sh_mask.h rename to drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_sh_mask.h From 03e5b167bd2020053f3d10b61a361de8b17c5936 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 7 Feb 2022 14:45:18 +0800 Subject: [PATCH 310/339] drm/amdkfd: rename kfd_process_vm_fault to kfd_dqm_evict_pasid As the function is used in more different cases, use a more general name. Signed-off-by: Tao Zhou Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c index d60576ce10cd..5c8023cba196 100644 --- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c @@ -110,7 +110,7 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev, struct kfd_vm_fault_info info; kfd_smi_event_update_vmfault(dev, pasid); - kfd_process_vm_fault(dev->dqm, pasid); + kfd_dqm_evict_pasid(dev->dqm, pasid); memset(&info, 0, sizeof(info)); amdgpu_amdkfd_gpuvm_get_vm_fault_info(dev->adev, &info); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 63b3c7af681b..219acc818eb4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -2120,7 +2120,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm) kfree(dqm); } -int kfd_process_vm_fault(struct device_queue_manager *dqm, u32 pasid) +int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid) { struct kfd_process_device *pdd; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index e8bc28009c22..7a2b6342a8f2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -308,7 +308,7 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev, info.prot_write = ring_id & 0x20; kfd_smi_event_update_vmfault(dev, pasid); - kfd_process_vm_fault(dev->dqm, pasid); + kfd_dqm_evict_pasid(dev->dqm, pasid); kfd_signal_vm_fault_event(dev, pasid, &info); } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 74ff4132a163..74fb4762c66e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1174,7 +1174,7 @@ void device_queue_manager_uninit(struct device_queue_manager *dqm); struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, enum kfd_queue_type type); void kernel_queue_uninit(struct kernel_queue *kq, bool hanging); -int kfd_process_vm_fault(struct device_queue_manager *dqm, u32 pasid); +int kfd_dqm_evict_pasid(struct device_queue_manager *dqm, u32 pasid); /* Process Queue Manager */ struct process_queue_node { From b1c87b0874a4a2045dc78a8d3d3a77ef61536711 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 7 Feb 2022 14:52:19 +0800 Subject: [PATCH 311/339] drm/amdkfd: use unmap all queues for poison consumption Replace reset queue for specific PASID with unmap all queues, reset queue could break CP scheduler. Signed-off-by: Tao Zhou Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index 7a2b6342a8f2..68ee923a440b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -109,8 +109,7 @@ static void event_interrupt_poison_consumption(struct kfd_dev *dev, switch (source_id) { case SOC15_INTSRC_SQ_INTERRUPT_MSG: - if (dev->dqm->ops.reset_queues) - ret = dev->dqm->ops.reset_queues(dev->dqm, pasid); + kfd_dqm_evict_pasid(dev->dqm, pasid); break; case SOC15_INTSRC_SDMA_ECC: default: From 40f1dc5223ae9b98458124bbeabbabc74c2bccf6 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 8 Feb 2022 12:06:18 +0800 Subject: [PATCH 312/339] drm/amd/pm: drm/amd/pm: disable GetPptLimit message in sriov mode PPT limit cannot be queried from VF Fixes: f3527a6483fbcc ("drm/amd/pm: Enable sysfs required by rocm-smi tool for One VF mode") Signed-off-by: Yang Wang Reviewed-by: Lijo Lazar Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 804e1c98238d..2a7da2bad96a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -140,7 +140,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1), MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), - MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), From de7fbd020d959708282ac0916be3e5498086d9aa Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 8 Feb 2022 14:23:55 +0800 Subject: [PATCH 313/339] drm/amd/pm: fix hwmon node of power1_label create issue it will cause hwmon node of power1_label is not created. v2: the hwmon node of "power1_label" is always needed for all ASICs. and the patch will remove ASIC type check for "power1_label". Fixes: ae07970a0621d6 ("drm/amd/pm: add support for hwmon control of slow and fast PPT limit on vangogh") Signed-off-by: Yang Wang Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index d68e7132da2c..426e00112c91 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3287,8 +3287,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr || attr == &sensor_dev_attr_power2_cap.dev_attr.attr || attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || - attr == &sensor_dev_attr_power2_label.dev_attr.attr || - attr == &sensor_dev_attr_power1_label.dev_attr.attr)) + attr == &sensor_dev_attr_power2_label.dev_attr.attr)) return 0; return effective_mode; From 6c1a7867734bc6f54e8442f47790c90d3afa07a2 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Thu, 9 Dec 2021 18:51:34 -0500 Subject: [PATCH 314/339] drm/amdkfd: Fix TLB flushing in KFD SVM with no HWS With no HWS, TLB flushing will not work in SVM code. Fix this by calling kfd_flush_tlb() which works for both HWS and no HWS case. Signed-off-by: Mukul Joshi Reviewed-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 41f03d165bad..e13ea9797527 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1229,19 +1229,20 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start, if (r) break; } - amdgpu_amdkfd_flush_gpu_tlb_pasid(pdd->dev->adev, - p->pasid, TLB_FLUSH_HEAVYWEIGHT); + kfd_flush_tlb(pdd, TLB_FLUSH_HEAVYWEIGHT); } return r; } static int -svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, - struct svm_range *prange, unsigned long offset, - unsigned long npages, bool readonly, dma_addr_t *dma_addr, - struct amdgpu_device *bo_adev, struct dma_fence **fence) +svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange, + unsigned long offset, unsigned long npages, bool readonly, + dma_addr_t *dma_addr, struct amdgpu_device *bo_adev, + struct dma_fence **fence) { + struct amdgpu_device *adev = pdd->dev->adev; + struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); bool table_freed = false; uint64_t pte_flags; unsigned long last_start; @@ -1305,12 +1306,8 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (fence) *fence = dma_fence_get(vm->last_update); - if (table_freed) { - struct kfd_process *p; - - p = container_of(prange->svms, struct kfd_process, svms); - amdgpu_amdkfd_flush_gpu_tlb_pasid(adev, p->pasid, TLB_FLUSH_LEGACY); - } + if (table_freed) + kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY); out: return r; } @@ -1351,8 +1348,7 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset, continue; } - r = svm_range_map_to_gpu(pdd->dev->adev, drm_priv_to_vm(pdd->drm_priv), - prange, offset, npages, readonly, + r = svm_range_map_to_gpu(pdd, prange, offset, npages, readonly, prange->dma_addr[gpuidx], bo_adev, wait ? &fence : NULL); if (r) From 5bdd3eb253544b1e80f904e1205699d0a126d2d6 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Fri, 4 Feb 2022 11:58:32 -0500 Subject: [PATCH 315/339] drm/amdkfd: Remove unused old debugger implementation Cleanup the kfd code by removing the unused old debugger implementation. The address watch was only ever implemented in the upstream driver for GFXv7 (Kaveri). The user mode tools runtime using this API was never open-sourced. Work on the old debugger prototype that used this API has been discontinued years ago. Only a small piece of resetting wavefronts is kept and is moved to kfd_device_queue_manager.c. Signed-off-by: Mukul Joshi Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- .../drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c | 3 - .../drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 3 - .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 24 - .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c | 25 - .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c | 96 -- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c | 24 - .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 24 - .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h | 10 - drivers/gpu/drm/amd/amdkfd/Makefile | 2 - drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 290 +----- drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c | 845 ------------------ drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h | 230 ----- drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c | 158 ---- drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h | 293 ------ drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 - .../drm/amd/amdkfd/kfd_device_queue_manager.c | 59 ++ .../drm/amd/amdkfd/kfd_device_queue_manager.h | 35 + drivers/gpu/drm/amd/amdkfd/kfd_iommu.c | 12 - drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 - drivers/gpu/drm/amd/amdkfd/kfd_process.c | 19 - .../gpu/drm/amd/include/kgd_kfd_interface.h | 9 - include/uapi/linux/kfd_ioctl.h | 8 +- 22 files changed, 106 insertions(+), 2070 deletions(-) delete mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c delete mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h delete mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c delete mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c index 46cd4ee6bafb..c8935d718207 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_aldebaran.c @@ -37,10 +37,7 @@ const struct kfd2kgd_calls aldebaran_kfd2kgd = { .hqd_sdma_is_occupied = kgd_arcturus_hqd_sdma_is_occupied, .hqd_destroy = kgd_gfx_v9_hqd_destroy, .hqd_sdma_destroy = kgd_arcturus_hqd_sdma_destroy, - .address_watch_disable = kgd_gfx_v9_address_watch_disable, - .address_watch_execute = kgd_gfx_v9_address_watch_execute, .wave_control_execute = kgd_gfx_v9_wave_control_execute, - .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index abe93b3ff765..4191af5a3f13 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -289,10 +289,7 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { .hqd_sdma_is_occupied = kgd_arcturus_hqd_sdma_is_occupied, .hqd_destroy = kgd_gfx_v9_hqd_destroy, .hqd_sdma_destroy = kgd_arcturus_hqd_sdma_destroy, - .address_watch_disable = kgd_gfx_v9_address_watch_disable, - .address_watch_execute = kgd_gfx_v9_address_watch_execute, .wave_control_execute = kgd_gfx_v9_wave_control_execute, - .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index 7b7f4b2764c1..9378fc79e9ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -671,20 +671,6 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev, return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK); } -static int kgd_address_watch_disable(struct amdgpu_device *adev) -{ - return 0; -} - -static int kgd_address_watch_execute(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo) -{ - return 0; -} - static int kgd_wave_control_execute(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd) @@ -709,13 +695,6 @@ static int kgd_wave_control_execute(struct amdgpu_device *adev, return 0; } -static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset) -{ - return 0; -} - static void set_vm_context_page_table_base(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { @@ -767,10 +746,7 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied, .hqd_destroy = kgd_hqd_destroy, .hqd_sdma_destroy = kgd_hqd_sdma_destroy, - .address_watch_disable = kgd_address_watch_disable, - .address_watch_execute = kgd_address_watch_execute, .wave_control_execute = kgd_wave_control_execute, - .address_watch_get_offset = kgd_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = set_vm_context_page_table_base, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c index 1f37d3574001..e9c80ce13f3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c @@ -582,21 +582,6 @@ static int hqd_sdma_destroy_v10_3(struct amdgpu_device *adev, void *mqd, return 0; } - -static int address_watch_disable_v10_3(struct amdgpu_device *adev) -{ - return 0; -} - -static int address_watch_execute_v10_3(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo) -{ - return 0; -} - static int wave_control_execute_v10_3(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd) @@ -621,13 +606,6 @@ static int wave_control_execute_v10_3(struct amdgpu_device *adev, return 0; } -static uint32_t address_watch_get_offset_v10_3(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset) -{ - return 0; -} - static void set_vm_context_page_table_base_v10_3(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { @@ -809,10 +787,7 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = { .hqd_sdma_is_occupied = hqd_sdma_is_occupied_v10_3, .hqd_destroy = hqd_destroy_v10_3, .hqd_sdma_destroy = hqd_sdma_destroy_v10_3, - .address_watch_disable = address_watch_disable_v10_3, - .address_watch_execute = address_watch_execute_v10_3, .wave_control_execute = wave_control_execute_v10_3, - .address_watch_get_offset = address_watch_get_offset_v10_3, .get_atc_vmid_pasid_mapping_info = NULL, .set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3, .program_trap_handler_settings = program_trap_handler_settings_v10_3, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 36528dad7684..65552bb7d2f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -45,43 +45,6 @@ enum { MAX_WATCH_ADDRESSES = 4 }; -enum { - ADDRESS_WATCH_REG_ADDR_HI = 0, - ADDRESS_WATCH_REG_ADDR_LO, - ADDRESS_WATCH_REG_CNTL, - ADDRESS_WATCH_REG_MAX -}; - -/* not defined in the CI/KV reg file */ -enum { - ADDRESS_WATCH_REG_CNTL_ATC_BIT = 0x10000000UL, - ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK = 0x00FFFFFF, - ADDRESS_WATCH_REG_ADDLOW_MASK_EXTENSION = 0x03000000, - /* extend the mask to 26 bits to match the low address field */ - ADDRESS_WATCH_REG_ADDLOW_SHIFT = 6, - ADDRESS_WATCH_REG_ADDHIGH_MASK = 0xFFFF -}; - -static const uint32_t watchRegs[MAX_WATCH_ADDRESSES * ADDRESS_WATCH_REG_MAX] = { - mmTCP_WATCH0_ADDR_H, mmTCP_WATCH0_ADDR_L, mmTCP_WATCH0_CNTL, - mmTCP_WATCH1_ADDR_H, mmTCP_WATCH1_ADDR_L, mmTCP_WATCH1_CNTL, - mmTCP_WATCH2_ADDR_H, mmTCP_WATCH2_ADDR_L, mmTCP_WATCH2_CNTL, - mmTCP_WATCH3_ADDR_H, mmTCP_WATCH3_ADDR_L, mmTCP_WATCH3_CNTL -}; - -union TCP_WATCH_CNTL_BITS { - struct { - uint32_t mask:24; - uint32_t vmid:4; - uint32_t atc:1; - uint32_t mode:2; - uint32_t valid:1; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - static void lock_srbm(struct amdgpu_device *adev, uint32_t mec, uint32_t pipe, uint32_t queue, uint32_t vmid) { @@ -529,55 +492,6 @@ static int kgd_hqd_sdma_destroy(struct amdgpu_device *adev, void *mqd, return 0; } -static int kgd_address_watch_disable(struct amdgpu_device *adev) -{ - union TCP_WATCH_CNTL_BITS cntl; - unsigned int i; - - cntl.u32All = 0; - - cntl.bitfields.valid = 0; - cntl.bitfields.mask = ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK; - cntl.bitfields.atc = 1; - - /* Turning off this address until we set all the registers */ - for (i = 0; i < MAX_WATCH_ADDRESSES; i++) - WREG32(watchRegs[i * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_CNTL], cntl.u32All); - - return 0; -} - -static int kgd_address_watch_execute(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo) -{ - union TCP_WATCH_CNTL_BITS cntl; - - cntl.u32All = cntl_val; - - /* Turning off this watch point until we set all the registers */ - cntl.bitfields.valid = 0; - WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_CNTL], cntl.u32All); - - WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_ADDR_HI], addr_hi); - - WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_ADDR_LO], addr_lo); - - /* Enable the watch point */ - cntl.bitfields.valid = 1; - - WREG32(watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_CNTL], cntl.u32All); - - return 0; -} - static int kgd_wave_control_execute(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd) @@ -602,13 +516,6 @@ static int kgd_wave_control_execute(struct amdgpu_device *adev, return 0; } -static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset) -{ - return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset]; -} - static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev, uint8_t vmid, uint16_t *p_pasid) { @@ -665,10 +572,7 @@ const struct kfd2kgd_calls gfx_v7_kfd2kgd = { .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied, .hqd_destroy = kgd_hqd_destroy, .hqd_sdma_destroy = kgd_hqd_sdma_destroy, - .address_watch_disable = kgd_address_watch_disable, - .address_watch_execute = kgd_address_watch_execute, .wave_control_execute = kgd_wave_control_execute, - .address_watch_get_offset = kgd_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info, .set_scratch_backing_va = set_scratch_backing_va, .set_vm_context_page_table_base = set_vm_context_page_table_base, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 52832cd69a93..9dc5f2a0cc07 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -538,20 +538,6 @@ static bool get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev, return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK); } -static int kgd_address_watch_disable(struct amdgpu_device *adev) -{ - return 0; -} - -static int kgd_address_watch_execute(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo) -{ - return 0; -} - static int kgd_wave_control_execute(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd) @@ -576,13 +562,6 @@ static int kgd_wave_control_execute(struct amdgpu_device *adev, return 0; } -static uint32_t kgd_address_watch_get_offset(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset) -{ - return 0; -} - static void set_scratch_backing_va(struct amdgpu_device *adev, uint64_t va, uint32_t vmid) { @@ -614,10 +593,7 @@ const struct kfd2kgd_calls gfx_v8_kfd2kgd = { .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied, .hqd_destroy = kgd_hqd_destroy, .hqd_sdma_destroy = kgd_hqd_sdma_destroy, - .address_watch_disable = kgd_address_watch_disable, - .address_watch_execute = kgd_address_watch_execute, .wave_control_execute = kgd_wave_control_execute, - .address_watch_get_offset = kgd_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info, .set_scratch_backing_va = set_scratch_backing_va, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 1abf662a0e91..53895a41932e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -622,20 +622,6 @@ bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev, return !!(value & ATC_VMID0_PASID_MAPPING__VALID_MASK); } -int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev) -{ - return 0; -} - -int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo) -{ - return 0; -} - int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd) @@ -660,13 +646,6 @@ int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev, return 0; } -uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset) -{ - return 0; -} - void kgd_gfx_v9_set_vm_context_page_table_base(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { @@ -888,10 +867,7 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied, .hqd_destroy = kgd_gfx_v9_hqd_destroy, .hqd_sdma_destroy = kgd_hqd_sdma_destroy, - .address_watch_disable = kgd_gfx_v9_address_watch_disable, - .address_watch_execute = kgd_gfx_v9_address_watch_execute, .wave_control_execute = kgd_gfx_v9_wave_control_execute, - .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h index 24be49df26fd..c7ed3bc9053c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h @@ -46,19 +46,9 @@ int kgd_gfx_v9_hqd_destroy(struct amdgpu_device *adev, void *mqd, enum kfd_preempt_type reset_type, unsigned int utimeout, uint32_t pipe_id, uint32_t queue_id); -int kgd_gfx_v9_address_watch_disable(struct amdgpu_device *adev); -int kgd_gfx_v9_address_watch_execute(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo); int kgd_gfx_v9_wave_control_execute(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd); -uint32_t kgd_gfx_v9_address_watch_get_offset(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset); - bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct amdgpu_device *adev, uint8_t vmid, uint16_t *p_pasid); diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index c4f3aff11072..19cfbf9577b4 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -51,8 +51,6 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \ $(AMDKFD_PATH)/kfd_events.o \ $(AMDKFD_PATH)/cik_event_interrupt.o \ $(AMDKFD_PATH)/kfd_int_process_v9.o \ - $(AMDKFD_PATH)/kfd_dbgdev.o \ - $(AMDKFD_PATH)/kfd_dbgmgr.o \ $(AMDKFD_PATH)/kfd_smi_events.o \ $(AMDKFD_PATH)/kfd_crat.o diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 64e3b4e3a712..13e46631e289 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -39,7 +39,6 @@ #include #include "kfd_priv.h" #include "kfd_device_queue_manager.h" -#include "kfd_dbgmgr.h" #include "kfd_svm.h" #include "amdgpu_amdkfd.h" #include "kfd_smi_events.h" @@ -580,299 +579,26 @@ err_pdd: static int kfd_ioctl_dbg_register(struct file *filep, struct kfd_process *p, void *data) { - struct kfd_ioctl_dbg_register_args *args = data; - struct kfd_dev *dev; - struct kfd_dbgmgr *dbgmgr_ptr; - struct kfd_process_device *pdd; - bool create_ok; - long status = 0; - - mutex_lock(&p->mutex); - pdd = kfd_process_device_data_by_id(p, args->gpu_id); - if (!pdd) { - status = -EINVAL; - goto err_pdd; - } - dev = pdd->dev; - - if (dev->adev->asic_type == CHIP_CARRIZO) { - pr_debug("kfd_ioctl_dbg_register not supported on CZ\n"); - status = -EINVAL; - goto err_chip_unsupp; - } - - mutex_lock(kfd_get_dbgmgr_mutex()); - - /* - * make sure that we have pdd, if this the first queue created for - * this process - */ - pdd = kfd_bind_process_to_device(dev, p); - if (IS_ERR(pdd)) { - status = PTR_ERR(pdd); - goto out; - } - - if (!dev->dbgmgr) { - /* In case of a legal call, we have no dbgmgr yet */ - create_ok = kfd_dbgmgr_create(&dbgmgr_ptr, dev); - if (create_ok) { - status = kfd_dbgmgr_register(dbgmgr_ptr, p); - if (status != 0) - kfd_dbgmgr_destroy(dbgmgr_ptr); - else - dev->dbgmgr = dbgmgr_ptr; - } - } else { - pr_debug("debugger already registered\n"); - status = -EINVAL; - } - -out: - mutex_unlock(kfd_get_dbgmgr_mutex()); -err_pdd: -err_chip_unsupp: - mutex_unlock(&p->mutex); - - return status; + return -EPERM; } static int kfd_ioctl_dbg_unregister(struct file *filep, struct kfd_process *p, void *data) { - struct kfd_ioctl_dbg_unregister_args *args = data; - struct kfd_process_device *pdd; - struct kfd_dev *dev; - long status; - - mutex_lock(&p->mutex); - pdd = kfd_process_device_data_by_id(p, args->gpu_id); - mutex_unlock(&p->mutex); - if (!pdd || !pdd->dev->dbgmgr) - return -EINVAL; - - dev = pdd->dev; - - if (dev->adev->asic_type == CHIP_CARRIZO) { - pr_debug("kfd_ioctl_dbg_unregister not supported on CZ\n"); - return -EINVAL; - } - - mutex_lock(kfd_get_dbgmgr_mutex()); - - status = kfd_dbgmgr_unregister(dev->dbgmgr, p); - if (!status) { - kfd_dbgmgr_destroy(dev->dbgmgr); - dev->dbgmgr = NULL; - } - - mutex_unlock(kfd_get_dbgmgr_mutex()); - - return status; + return -EPERM; } -/* - * Parse and generate variable size data structure for address watch. - * Total size of the buffer and # watch points is limited in order - * to prevent kernel abuse. (no bearing to the much smaller HW limitation - * which is enforced by dbgdev module) - * please also note that the watch address itself are not "copied from user", - * since it be set into the HW in user mode values. - * - */ static int kfd_ioctl_dbg_address_watch(struct file *filep, struct kfd_process *p, void *data) { - struct kfd_ioctl_dbg_address_watch_args *args = data; - struct kfd_dev *dev; - struct kfd_process_device *pdd; - struct dbg_address_watch_info aw_info; - unsigned char *args_buff; - long status; - void __user *cmd_from_user; - uint64_t watch_mask_value = 0; - unsigned int args_idx = 0; - - memset((void *) &aw_info, 0, sizeof(struct dbg_address_watch_info)); - - mutex_lock(&p->mutex); - pdd = kfd_process_device_data_by_id(p, args->gpu_id); - mutex_unlock(&p->mutex); - if (!pdd) { - pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); - return -EINVAL; - } - dev = pdd->dev; - - if (dev->adev->asic_type == CHIP_CARRIZO) { - pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n"); - return -EINVAL; - } - cmd_from_user = (void __user *) args->content_ptr; - - /* Validate arguments */ - - if ((args->buf_size_in_bytes > MAX_ALLOWED_AW_BUFF_SIZE) || - (args->buf_size_in_bytes <= sizeof(*args) + sizeof(int) * 2) || - (cmd_from_user == NULL)) - return -EINVAL; - - /* this is the actual buffer to work with */ - args_buff = memdup_user(cmd_from_user, - args->buf_size_in_bytes - sizeof(*args)); - if (IS_ERR(args_buff)) - return PTR_ERR(args_buff); - - aw_info.process = p; - - aw_info.num_watch_points = *((uint32_t *)(&args_buff[args_idx])); - args_idx += sizeof(aw_info.num_watch_points); - - aw_info.watch_mode = (enum HSA_DBG_WATCH_MODE *) &args_buff[args_idx]; - args_idx += sizeof(enum HSA_DBG_WATCH_MODE) * aw_info.num_watch_points; - - /* - * set watch address base pointer to point on the array base - * within args_buff - */ - aw_info.watch_address = (uint64_t *) &args_buff[args_idx]; - - /* skip over the addresses buffer */ - args_idx += sizeof(aw_info.watch_address) * aw_info.num_watch_points; - - if (args_idx >= args->buf_size_in_bytes - sizeof(*args)) { - status = -EINVAL; - goto out; - } - - watch_mask_value = (uint64_t) args_buff[args_idx]; - - if (watch_mask_value > 0) { - /* - * There is an array of masks. - * set watch mask base pointer to point on the array base - * within args_buff - */ - aw_info.watch_mask = (uint64_t *) &args_buff[args_idx]; - - /* skip over the masks buffer */ - args_idx += sizeof(aw_info.watch_mask) * - aw_info.num_watch_points; - } else { - /* just the NULL mask, set to NULL and skip over it */ - aw_info.watch_mask = NULL; - args_idx += sizeof(aw_info.watch_mask); - } - - if (args_idx >= args->buf_size_in_bytes - sizeof(args)) { - status = -EINVAL; - goto out; - } - - /* Currently HSA Event is not supported for DBG */ - aw_info.watch_event = NULL; - - mutex_lock(kfd_get_dbgmgr_mutex()); - - status = kfd_dbgmgr_address_watch(dev->dbgmgr, &aw_info); - - mutex_unlock(kfd_get_dbgmgr_mutex()); - -out: - kfree(args_buff); - - return status; + return -EPERM; } /* Parse and generate fixed size data structure for wave control */ static int kfd_ioctl_dbg_wave_control(struct file *filep, struct kfd_process *p, void *data) { - struct kfd_ioctl_dbg_wave_control_args *args = data; - struct kfd_dev *dev; - struct kfd_process_device *pdd; - struct dbg_wave_control_info wac_info; - unsigned char *args_buff; - uint32_t computed_buff_size; - long status; - void __user *cmd_from_user; - unsigned int args_idx = 0; - - memset((void *) &wac_info, 0, sizeof(struct dbg_wave_control_info)); - - /* we use compact form, independent of the packing attribute value */ - computed_buff_size = sizeof(*args) + - sizeof(wac_info.mode) + - sizeof(wac_info.operand) + - sizeof(wac_info.dbgWave_msg.DbgWaveMsg) + - sizeof(wac_info.dbgWave_msg.MemoryVA) + - sizeof(wac_info.trapId); - - mutex_lock(&p->mutex); - pdd = kfd_process_device_data_by_id(p, args->gpu_id); - mutex_unlock(&p->mutex); - if (!pdd) { - pr_debug("Could not find gpu id 0x%x\n", args->gpu_id); - return -EINVAL; - } - dev = pdd->dev; - - if (dev->adev->asic_type == CHIP_CARRIZO) { - pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n"); - return -EINVAL; - } - - /* input size must match the computed "compact" size */ - if (args->buf_size_in_bytes != computed_buff_size) { - pr_debug("size mismatch, computed : actual %u : %u\n", - args->buf_size_in_bytes, computed_buff_size); - return -EINVAL; - } - - cmd_from_user = (void __user *) args->content_ptr; - - if (cmd_from_user == NULL) - return -EINVAL; - - /* copy the entire buffer from user */ - - args_buff = memdup_user(cmd_from_user, - args->buf_size_in_bytes - sizeof(*args)); - if (IS_ERR(args_buff)) - return PTR_ERR(args_buff); - - /* move ptr to the start of the "pay-load" area */ - wac_info.process = p; - - wac_info.operand = *((enum HSA_DBG_WAVEOP *)(&args_buff[args_idx])); - args_idx += sizeof(wac_info.operand); - - wac_info.mode = *((enum HSA_DBG_WAVEMODE *)(&args_buff[args_idx])); - args_idx += sizeof(wac_info.mode); - - wac_info.trapId = *((uint32_t *)(&args_buff[args_idx])); - args_idx += sizeof(wac_info.trapId); - - wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value = - *((uint32_t *)(&args_buff[args_idx])); - wac_info.dbgWave_msg.MemoryVA = NULL; - - mutex_lock(kfd_get_dbgmgr_mutex()); - - pr_debug("Calling dbg manager process %p, operand %u, mode %u, trapId %u, message %u\n", - wac_info.process, wac_info.operand, - wac_info.mode, wac_info.trapId, - wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value); - - status = kfd_dbgmgr_wave_control(dev->dbgmgr, &wac_info); - - pr_debug("Returned status of dbg manager is %ld\n", status); - - mutex_unlock(kfd_get_dbgmgr_mutex()); - - kfree(args_buff); - - return status; + return -EPERM; } static int kfd_ioctl_get_clock_counters(struct file *filep, @@ -2900,16 +2626,16 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { AMDKFD_IOCTL_DEF(AMDKFD_IOC_WAIT_EVENTS, kfd_ioctl_wait_events, 0), - AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_REGISTER, + AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_REGISTER_DEPRECATED, kfd_ioctl_dbg_register, 0), - AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_UNREGISTER, + AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED, kfd_ioctl_dbg_unregister, 0), - AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_ADDRESS_WATCH, + AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED, kfd_ioctl_dbg_address_watch, 0), - AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_WAVE_CONTROL, + AMDKFD_IOCTL_DEF(AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED, kfd_ioctl_dbg_wave_control, 0), AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_SCRATCH_BACKING_VA, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c deleted file mode 100644 index 8eca9ed3ab36..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ /dev/null @@ -1,845 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "kfd_pm4_headers.h" -#include "kfd_pm4_headers_diq.h" -#include "kfd_kernel_queue.h" -#include "kfd_priv.h" -#include "kfd_pm4_opcodes.h" -#include "cik_regs.h" -#include "kfd_dbgmgr.h" -#include "kfd_dbgdev.h" -#include "kfd_device_queue_manager.h" - -static void dbgdev_address_watch_disable_nodiq(struct kfd_dev *dev) -{ - dev->kfd2kgd->address_watch_disable(dev->adev); -} - -static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev, - u32 pasid, uint64_t vmid0_address, - uint32_t *packet_buff, size_t size_in_bytes) -{ - struct pm4__release_mem *rm_packet; - struct pm4__indirect_buffer_pasid *ib_packet; - struct kfd_mem_obj *mem_obj; - size_t pq_packets_size_in_bytes; - union ULARGE_INTEGER *largep; - union ULARGE_INTEGER addr; - struct kernel_queue *kq; - uint64_t *rm_state; - unsigned int *ib_packet_buff; - int status; - - if (WARN_ON(!size_in_bytes)) - return -EINVAL; - - kq = dbgdev->kq; - - pq_packets_size_in_bytes = sizeof(struct pm4__release_mem) + - sizeof(struct pm4__indirect_buffer_pasid); - - /* - * We acquire a buffer from DIQ - * The receive packet buff will be sitting on the Indirect Buffer - * and in the PQ we put the IB packet + sync packet(s). - */ - status = kq_acquire_packet_buffer(kq, - pq_packets_size_in_bytes / sizeof(uint32_t), - &ib_packet_buff); - if (status) { - pr_err("kq_acquire_packet_buffer failed\n"); - return status; - } - - memset(ib_packet_buff, 0, pq_packets_size_in_bytes); - - ib_packet = (struct pm4__indirect_buffer_pasid *) (ib_packet_buff); - - ib_packet->header.count = 3; - ib_packet->header.opcode = IT_INDIRECT_BUFFER_PASID; - ib_packet->header.type = PM4_TYPE_3; - - largep = (union ULARGE_INTEGER *) &vmid0_address; - - ib_packet->bitfields2.ib_base_lo = largep->u.low_part >> 2; - ib_packet->bitfields3.ib_base_hi = largep->u.high_part; - - ib_packet->control = (1 << 23) | (1 << 31) | - ((size_in_bytes / 4) & 0xfffff); - - ib_packet->bitfields5.pasid = pasid; - - /* - * for now we use release mem for GPU-CPU synchronization - * Consider WaitRegMem + WriteData as a better alternative - * we get a GART allocations ( gpu/cpu mapping), - * for the sync variable, and wait until: - * (a) Sync with HW - * (b) Sync var is written by CP to mem. - */ - rm_packet = (struct pm4__release_mem *) (ib_packet_buff + - (sizeof(struct pm4__indirect_buffer_pasid) / - sizeof(unsigned int))); - - status = kfd_gtt_sa_allocate(dbgdev->dev, sizeof(uint64_t), - &mem_obj); - - if (status) { - pr_err("Failed to allocate GART memory\n"); - kq_rollback_packet(kq); - return status; - } - - rm_state = (uint64_t *) mem_obj->cpu_ptr; - - *rm_state = QUEUESTATE__ACTIVE_COMPLETION_PENDING; - - rm_packet->header.opcode = IT_RELEASE_MEM; - rm_packet->header.type = PM4_TYPE_3; - rm_packet->header.count = sizeof(struct pm4__release_mem) / 4 - 2; - - rm_packet->bitfields2.event_type = CACHE_FLUSH_AND_INV_TS_EVENT; - rm_packet->bitfields2.event_index = - event_index___release_mem__end_of_pipe; - - rm_packet->bitfields2.cache_policy = cache_policy___release_mem__lru; - rm_packet->bitfields2.atc = 0; - rm_packet->bitfields2.tc_wb_action_ena = 1; - - addr.quad_part = mem_obj->gpu_addr; - - rm_packet->bitfields4.address_lo_32b = addr.u.low_part >> 2; - rm_packet->address_hi = addr.u.high_part; - - rm_packet->bitfields3.data_sel = - data_sel___release_mem__send_64_bit_data; - - rm_packet->bitfields3.int_sel = - int_sel___release_mem__send_data_after_write_confirm; - - rm_packet->bitfields3.dst_sel = - dst_sel___release_mem__memory_controller; - - rm_packet->data_lo = QUEUESTATE__ACTIVE; - - kq_submit_packet(kq); - - /* Wait till CP writes sync code: */ - status = amdkfd_fence_wait_timeout( - rm_state, - QUEUESTATE__ACTIVE, 1500); - - kfd_gtt_sa_free(dbgdev->dev, mem_obj); - - return status; -} - -static int dbgdev_register_nodiq(struct kfd_dbgdev *dbgdev) -{ - /* - * no action is needed in this case, - * just make sure diq will not be used - */ - - dbgdev->kq = NULL; - - return 0; -} - -static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev) -{ - struct queue_properties properties; - unsigned int qid; - struct kernel_queue *kq = NULL; - int status; - - properties.type = KFD_QUEUE_TYPE_DIQ; - - status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL, - &properties, &qid, NULL, NULL, NULL, NULL); - - if (status) { - pr_err("Failed to create DIQ\n"); - return status; - } - - pr_debug("DIQ Created with queue id: %d\n", qid); - - kq = pqm_get_kernel_queue(dbgdev->pqm, qid); - - if (!kq) { - pr_err("Error getting DIQ\n"); - pqm_destroy_queue(dbgdev->pqm, qid); - return -EFAULT; - } - - dbgdev->kq = kq; - - return status; -} - -static int dbgdev_unregister_nodiq(struct kfd_dbgdev *dbgdev) -{ - /* disable watch address */ - dbgdev_address_watch_disable_nodiq(dbgdev->dev); - return 0; -} - -static int dbgdev_unregister_diq(struct kfd_dbgdev *dbgdev) -{ - /* todo - disable address watch */ - int status; - - status = pqm_destroy_queue(dbgdev->pqm, - dbgdev->kq->queue->properties.queue_id); - dbgdev->kq = NULL; - - return status; -} - -static void dbgdev_address_watch_set_registers( - const struct dbg_address_watch_info *adw_info, - union TCP_WATCH_ADDR_H_BITS *addrHi, - union TCP_WATCH_ADDR_L_BITS *addrLo, - union TCP_WATCH_CNTL_BITS *cntl, - unsigned int index, unsigned int vmid) -{ - union ULARGE_INTEGER addr; - - addr.quad_part = 0; - addrHi->u32All = 0; - addrLo->u32All = 0; - cntl->u32All = 0; - - if (adw_info->watch_mask) - cntl->bitfields.mask = - (uint32_t) (adw_info->watch_mask[index] & - ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK); - else - cntl->bitfields.mask = ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK; - - addr.quad_part = (unsigned long long) adw_info->watch_address[index]; - - addrHi->bitfields.addr = addr.u.high_part & - ADDRESS_WATCH_REG_ADDHIGH_MASK; - addrLo->bitfields.addr = - (addr.u.low_part >> ADDRESS_WATCH_REG_ADDLOW_SHIFT); - - cntl->bitfields.mode = adw_info->watch_mode[index]; - cntl->bitfields.vmid = (uint32_t) vmid; - /* for now assume it is an ATC address */ - cntl->u32All |= ADDRESS_WATCH_REG_CNTL_ATC_BIT; - - pr_debug("\t\t%20s %08x\n", "set reg mask :", cntl->bitfields.mask); - pr_debug("\t\t%20s %08x\n", "set reg add high :", - addrHi->bitfields.addr); - pr_debug("\t\t%20s %08x\n", "set reg add low :", - addrLo->bitfields.addr); -} - -static int dbgdev_address_watch_nodiq(struct kfd_dbgdev *dbgdev, - struct dbg_address_watch_info *adw_info) -{ - union TCP_WATCH_ADDR_H_BITS addrHi; - union TCP_WATCH_ADDR_L_BITS addrLo; - union TCP_WATCH_CNTL_BITS cntl; - struct kfd_process_device *pdd; - unsigned int i; - - /* taking the vmid for that process on the safe way using pdd */ - pdd = kfd_get_process_device_data(dbgdev->dev, - adw_info->process); - if (!pdd) { - pr_err("Failed to get pdd for wave control no DIQ\n"); - return -EFAULT; - } - - addrHi.u32All = 0; - addrLo.u32All = 0; - cntl.u32All = 0; - - if ((adw_info->num_watch_points > MAX_WATCH_ADDRESSES) || - (adw_info->num_watch_points == 0)) { - pr_err("num_watch_points is invalid\n"); - return -EINVAL; - } - - if (!adw_info->watch_mode || !adw_info->watch_address) { - pr_err("adw_info fields are not valid\n"); - return -EINVAL; - } - - for (i = 0; i < adw_info->num_watch_points; i++) { - dbgdev_address_watch_set_registers(adw_info, &addrHi, &addrLo, - &cntl, i, pdd->qpd.vmid); - - pr_debug("\t\t%30s\n", "* * * * * * * * * * * * * * * * * *"); - pr_debug("\t\t%20s %08x\n", "register index :", i); - pr_debug("\t\t%20s %08x\n", "vmid is :", pdd->qpd.vmid); - pr_debug("\t\t%20s %08x\n", "Address Low is :", - addrLo.bitfields.addr); - pr_debug("\t\t%20s %08x\n", "Address high is :", - addrHi.bitfields.addr); - pr_debug("\t\t%20s %08x\n", "Address high is :", - addrHi.bitfields.addr); - pr_debug("\t\t%20s %08x\n", "Control Mask is :", - cntl.bitfields.mask); - pr_debug("\t\t%20s %08x\n", "Control Mode is :", - cntl.bitfields.mode); - pr_debug("\t\t%20s %08x\n", "Control Vmid is :", - cntl.bitfields.vmid); - pr_debug("\t\t%20s %08x\n", "Control atc is :", - cntl.bitfields.atc); - pr_debug("\t\t%30s\n", "* * * * * * * * * * * * * * * * * *"); - - pdd->dev->kfd2kgd->address_watch_execute( - dbgdev->dev->adev, - i, - cntl.u32All, - addrHi.u32All, - addrLo.u32All); - } - - return 0; -} - -static int dbgdev_address_watch_diq(struct kfd_dbgdev *dbgdev, - struct dbg_address_watch_info *adw_info) -{ - struct pm4__set_config_reg *packets_vec; - union TCP_WATCH_ADDR_H_BITS addrHi; - union TCP_WATCH_ADDR_L_BITS addrLo; - union TCP_WATCH_CNTL_BITS cntl; - struct kfd_mem_obj *mem_obj; - unsigned int aw_reg_add_dword; - uint32_t *packet_buff_uint; - unsigned int i; - int status; - size_t ib_size = sizeof(struct pm4__set_config_reg) * 4; - /* we do not control the vmid in DIQ mode, just a place holder */ - unsigned int vmid = 0; - - addrHi.u32All = 0; - addrLo.u32All = 0; - cntl.u32All = 0; - - if ((adw_info->num_watch_points > MAX_WATCH_ADDRESSES) || - (adw_info->num_watch_points == 0)) { - pr_err("num_watch_points is invalid\n"); - return -EINVAL; - } - - if (!adw_info->watch_mode || !adw_info->watch_address) { - pr_err("adw_info fields are not valid\n"); - return -EINVAL; - } - - status = kfd_gtt_sa_allocate(dbgdev->dev, ib_size, &mem_obj); - - if (status) { - pr_err("Failed to allocate GART memory\n"); - return status; - } - - packet_buff_uint = mem_obj->cpu_ptr; - - memset(packet_buff_uint, 0, ib_size); - - packets_vec = (struct pm4__set_config_reg *) (packet_buff_uint); - - packets_vec[0].header.count = 1; - packets_vec[0].header.opcode = IT_SET_CONFIG_REG; - packets_vec[0].header.type = PM4_TYPE_3; - packets_vec[0].bitfields2.vmid_shift = ADDRESS_WATCH_CNTL_OFFSET; - packets_vec[0].bitfields2.insert_vmid = 1; - packets_vec[1].ordinal1 = packets_vec[0].ordinal1; - packets_vec[1].bitfields2.insert_vmid = 0; - packets_vec[2].ordinal1 = packets_vec[0].ordinal1; - packets_vec[2].bitfields2.insert_vmid = 0; - packets_vec[3].ordinal1 = packets_vec[0].ordinal1; - packets_vec[3].bitfields2.vmid_shift = ADDRESS_WATCH_CNTL_OFFSET; - packets_vec[3].bitfields2.insert_vmid = 1; - - for (i = 0; i < adw_info->num_watch_points; i++) { - dbgdev_address_watch_set_registers(adw_info, - &addrHi, - &addrLo, - &cntl, - i, - vmid); - - pr_debug("\t\t%30s\n", "* * * * * * * * * * * * * * * * * *"); - pr_debug("\t\t%20s %08x\n", "register index :", i); - pr_debug("\t\t%20s %08x\n", "vmid is :", vmid); - pr_debug("\t\t%20s %p\n", "Add ptr is :", - adw_info->watch_address); - pr_debug("\t\t%20s %08llx\n", "Add is :", - adw_info->watch_address[i]); - pr_debug("\t\t%20s %08x\n", "Address Low is :", - addrLo.bitfields.addr); - pr_debug("\t\t%20s %08x\n", "Address high is :", - addrHi.bitfields.addr); - pr_debug("\t\t%20s %08x\n", "Control Mask is :", - cntl.bitfields.mask); - pr_debug("\t\t%20s %08x\n", "Control Mode is :", - cntl.bitfields.mode); - pr_debug("\t\t%20s %08x\n", "Control Vmid is :", - cntl.bitfields.vmid); - pr_debug("\t\t%20s %08x\n", "Control atc is :", - cntl.bitfields.atc); - pr_debug("\t\t%30s\n", "* * * * * * * * * * * * * * * * * *"); - - aw_reg_add_dword = - dbgdev->dev->kfd2kgd->address_watch_get_offset( - dbgdev->dev->adev, - i, - ADDRESS_WATCH_REG_CNTL); - - packets_vec[0].bitfields2.reg_offset = - aw_reg_add_dword - AMD_CONFIG_REG_BASE; - - packets_vec[0].reg_data[0] = cntl.u32All; - - aw_reg_add_dword = - dbgdev->dev->kfd2kgd->address_watch_get_offset( - dbgdev->dev->adev, - i, - ADDRESS_WATCH_REG_ADDR_HI); - - packets_vec[1].bitfields2.reg_offset = - aw_reg_add_dword - AMD_CONFIG_REG_BASE; - packets_vec[1].reg_data[0] = addrHi.u32All; - - aw_reg_add_dword = - dbgdev->dev->kfd2kgd->address_watch_get_offset( - dbgdev->dev->adev, - i, - ADDRESS_WATCH_REG_ADDR_LO); - - packets_vec[2].bitfields2.reg_offset = - aw_reg_add_dword - AMD_CONFIG_REG_BASE; - packets_vec[2].reg_data[0] = addrLo.u32All; - - /* enable watch flag if address is not zero*/ - if (adw_info->watch_address[i] > 0) - cntl.bitfields.valid = 1; - else - cntl.bitfields.valid = 0; - - aw_reg_add_dword = - dbgdev->dev->kfd2kgd->address_watch_get_offset( - dbgdev->dev->adev, - i, - ADDRESS_WATCH_REG_CNTL); - - packets_vec[3].bitfields2.reg_offset = - aw_reg_add_dword - AMD_CONFIG_REG_BASE; - packets_vec[3].reg_data[0] = cntl.u32All; - - status = dbgdev_diq_submit_ib( - dbgdev, - adw_info->process->pasid, - mem_obj->gpu_addr, - packet_buff_uint, - ib_size); - - if (status) { - pr_err("Failed to submit IB to DIQ\n"); - break; - } - } - - kfd_gtt_sa_free(dbgdev->dev, mem_obj); - return status; -} - -static int dbgdev_wave_control_set_registers( - struct dbg_wave_control_info *wac_info, - union SQ_CMD_BITS *in_reg_sq_cmd, - union GRBM_GFX_INDEX_BITS *in_reg_gfx_index) -{ - int status = 0; - union SQ_CMD_BITS reg_sq_cmd; - union GRBM_GFX_INDEX_BITS reg_gfx_index; - struct HsaDbgWaveMsgAMDGen2 *pMsg; - - reg_sq_cmd.u32All = 0; - reg_gfx_index.u32All = 0; - pMsg = &wac_info->dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2; - - switch (wac_info->mode) { - /* Send command to single wave */ - case HSA_DBG_WAVEMODE_SINGLE: - /* - * Limit access to the process waves only, - * by setting vmid check - */ - reg_sq_cmd.bits.check_vmid = 1; - reg_sq_cmd.bits.simd_id = pMsg->ui32.SIMD; - reg_sq_cmd.bits.wave_id = pMsg->ui32.WaveId; - reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_SINGLE; - - reg_gfx_index.bits.sh_index = pMsg->ui32.ShaderArray; - reg_gfx_index.bits.se_index = pMsg->ui32.ShaderEngine; - reg_gfx_index.bits.instance_index = pMsg->ui32.HSACU; - - break; - - /* Send command to all waves with matching VMID */ - case HSA_DBG_WAVEMODE_BROADCAST_PROCESS: - - reg_gfx_index.bits.sh_broadcast_writes = 1; - reg_gfx_index.bits.se_broadcast_writes = 1; - reg_gfx_index.bits.instance_broadcast_writes = 1; - - reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_BROADCAST; - - break; - - /* Send command to all CU waves with matching VMID */ - case HSA_DBG_WAVEMODE_BROADCAST_PROCESS_CU: - - reg_sq_cmd.bits.check_vmid = 1; - reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_BROADCAST; - - reg_gfx_index.bits.sh_index = pMsg->ui32.ShaderArray; - reg_gfx_index.bits.se_index = pMsg->ui32.ShaderEngine; - reg_gfx_index.bits.instance_index = pMsg->ui32.HSACU; - - break; - - default: - return -EINVAL; - } - - switch (wac_info->operand) { - case HSA_DBG_WAVEOP_HALT: - reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_HALT; - break; - - case HSA_DBG_WAVEOP_RESUME: - reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_RESUME; - break; - - case HSA_DBG_WAVEOP_KILL: - reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_KILL; - break; - - case HSA_DBG_WAVEOP_DEBUG: - reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_DEBUG; - break; - - case HSA_DBG_WAVEOP_TRAP: - if (wac_info->trapId < MAX_TRAPID) { - reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_TRAP; - reg_sq_cmd.bits.trap_id = wac_info->trapId; - } else { - status = -EINVAL; - } - break; - - default: - status = -EINVAL; - break; - } - - if (status == 0) { - *in_reg_sq_cmd = reg_sq_cmd; - *in_reg_gfx_index = reg_gfx_index; - } - - return status; -} - -static int dbgdev_wave_control_diq(struct kfd_dbgdev *dbgdev, - struct dbg_wave_control_info *wac_info) -{ - - int status; - union SQ_CMD_BITS reg_sq_cmd; - union GRBM_GFX_INDEX_BITS reg_gfx_index; - struct kfd_mem_obj *mem_obj; - uint32_t *packet_buff_uint; - struct pm4__set_config_reg *packets_vec; - size_t ib_size = sizeof(struct pm4__set_config_reg) * 3; - - reg_sq_cmd.u32All = 0; - - status = dbgdev_wave_control_set_registers(wac_info, ®_sq_cmd, - ®_gfx_index); - if (status) { - pr_err("Failed to set wave control registers\n"); - return status; - } - - /* we do not control the VMID in DIQ, so reset it to a known value */ - reg_sq_cmd.bits.vm_id = 0; - - pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); - - pr_debug("\t\t mode is: %u\n", wac_info->mode); - pr_debug("\t\t operand is: %u\n", wac_info->operand); - pr_debug("\t\t trap id is: %u\n", wac_info->trapId); - pr_debug("\t\t msg value is: %u\n", - wac_info->dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value); - pr_debug("\t\t vmid is: N/A\n"); - - pr_debug("\t\t chk_vmid is : %u\n", reg_sq_cmd.bitfields.check_vmid); - pr_debug("\t\t command is : %u\n", reg_sq_cmd.bitfields.cmd); - pr_debug("\t\t queue id is : %u\n", reg_sq_cmd.bitfields.queue_id); - pr_debug("\t\t simd id is : %u\n", reg_sq_cmd.bitfields.simd_id); - pr_debug("\t\t mode is : %u\n", reg_sq_cmd.bitfields.mode); - pr_debug("\t\t vm_id is : %u\n", reg_sq_cmd.bitfields.vm_id); - pr_debug("\t\t wave_id is : %u\n", reg_sq_cmd.bitfields.wave_id); - - pr_debug("\t\t ibw is : %u\n", - reg_gfx_index.bitfields.instance_broadcast_writes); - pr_debug("\t\t ii is : %u\n", - reg_gfx_index.bitfields.instance_index); - pr_debug("\t\t sebw is : %u\n", - reg_gfx_index.bitfields.se_broadcast_writes); - pr_debug("\t\t se_ind is : %u\n", reg_gfx_index.bitfields.se_index); - pr_debug("\t\t sh_ind is : %u\n", reg_gfx_index.bitfields.sh_index); - pr_debug("\t\t sbw is : %u\n", - reg_gfx_index.bitfields.sh_broadcast_writes); - - pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); - - status = kfd_gtt_sa_allocate(dbgdev->dev, ib_size, &mem_obj); - - if (status != 0) { - pr_err("Failed to allocate GART memory\n"); - return status; - } - - packet_buff_uint = mem_obj->cpu_ptr; - - memset(packet_buff_uint, 0, ib_size); - - packets_vec = (struct pm4__set_config_reg *) packet_buff_uint; - packets_vec[0].header.count = 1; - packets_vec[0].header.opcode = IT_SET_UCONFIG_REG; - packets_vec[0].header.type = PM4_TYPE_3; - packets_vec[0].bitfields2.reg_offset = - GRBM_GFX_INDEX / 4 - USERCONFIG_REG_BASE; - - packets_vec[0].bitfields2.insert_vmid = 0; - packets_vec[0].reg_data[0] = reg_gfx_index.u32All; - - packets_vec[1].header.count = 1; - packets_vec[1].header.opcode = IT_SET_CONFIG_REG; - packets_vec[1].header.type = PM4_TYPE_3; - packets_vec[1].bitfields2.reg_offset = SQ_CMD / 4 - AMD_CONFIG_REG_BASE; - - packets_vec[1].bitfields2.vmid_shift = SQ_CMD_VMID_OFFSET; - packets_vec[1].bitfields2.insert_vmid = 1; - packets_vec[1].reg_data[0] = reg_sq_cmd.u32All; - - /* Restore the GRBM_GFX_INDEX register */ - - reg_gfx_index.u32All = 0; - reg_gfx_index.bits.sh_broadcast_writes = 1; - reg_gfx_index.bits.instance_broadcast_writes = 1; - reg_gfx_index.bits.se_broadcast_writes = 1; - - - packets_vec[2].ordinal1 = packets_vec[0].ordinal1; - packets_vec[2].bitfields2.reg_offset = - GRBM_GFX_INDEX / 4 - USERCONFIG_REG_BASE; - - packets_vec[2].bitfields2.insert_vmid = 0; - packets_vec[2].reg_data[0] = reg_gfx_index.u32All; - - status = dbgdev_diq_submit_ib( - dbgdev, - wac_info->process->pasid, - mem_obj->gpu_addr, - packet_buff_uint, - ib_size); - - if (status) - pr_err("Failed to submit IB to DIQ\n"); - - kfd_gtt_sa_free(dbgdev->dev, mem_obj); - - return status; -} - -static int dbgdev_wave_control_nodiq(struct kfd_dbgdev *dbgdev, - struct dbg_wave_control_info *wac_info) -{ - int status; - union SQ_CMD_BITS reg_sq_cmd; - union GRBM_GFX_INDEX_BITS reg_gfx_index; - struct kfd_process_device *pdd; - - reg_sq_cmd.u32All = 0; - - /* taking the VMID for that process on the safe way using PDD */ - pdd = kfd_get_process_device_data(dbgdev->dev, wac_info->process); - - if (!pdd) { - pr_err("Failed to get pdd for wave control no DIQ\n"); - return -EFAULT; - } - status = dbgdev_wave_control_set_registers(wac_info, ®_sq_cmd, - ®_gfx_index); - if (status) { - pr_err("Failed to set wave control registers\n"); - return status; - } - - /* for non DIQ we need to patch the VMID: */ - - reg_sq_cmd.bits.vm_id = pdd->qpd.vmid; - - pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); - - pr_debug("\t\t mode is: %u\n", wac_info->mode); - pr_debug("\t\t operand is: %u\n", wac_info->operand); - pr_debug("\t\t trap id is: %u\n", wac_info->trapId); - pr_debug("\t\t msg value is: %u\n", - wac_info->dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value); - pr_debug("\t\t vmid is: %u\n", pdd->qpd.vmid); - - pr_debug("\t\t chk_vmid is : %u\n", reg_sq_cmd.bitfields.check_vmid); - pr_debug("\t\t command is : %u\n", reg_sq_cmd.bitfields.cmd); - pr_debug("\t\t queue id is : %u\n", reg_sq_cmd.bitfields.queue_id); - pr_debug("\t\t simd id is : %u\n", reg_sq_cmd.bitfields.simd_id); - pr_debug("\t\t mode is : %u\n", reg_sq_cmd.bitfields.mode); - pr_debug("\t\t vm_id is : %u\n", reg_sq_cmd.bitfields.vm_id); - pr_debug("\t\t wave_id is : %u\n", reg_sq_cmd.bitfields.wave_id); - - pr_debug("\t\t ibw is : %u\n", - reg_gfx_index.bitfields.instance_broadcast_writes); - pr_debug("\t\t ii is : %u\n", - reg_gfx_index.bitfields.instance_index); - pr_debug("\t\t sebw is : %u\n", - reg_gfx_index.bitfields.se_broadcast_writes); - pr_debug("\t\t se_ind is : %u\n", reg_gfx_index.bitfields.se_index); - pr_debug("\t\t sh_ind is : %u\n", reg_gfx_index.bitfields.sh_index); - pr_debug("\t\t sbw is : %u\n", - reg_gfx_index.bitfields.sh_broadcast_writes); - - pr_debug("\t\t %30s\n", "* * * * * * * * * * * * * * * * * *"); - - return dbgdev->dev->kfd2kgd->wave_control_execute(dbgdev->dev->adev, - reg_gfx_index.u32All, - reg_sq_cmd.u32All); -} - -int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p) -{ - int status = 0; - unsigned int vmid; - uint16_t queried_pasid; - union SQ_CMD_BITS reg_sq_cmd; - union GRBM_GFX_INDEX_BITS reg_gfx_index; - struct kfd_process_device *pdd; - struct dbg_wave_control_info wac_info; - int first_vmid_to_scan = dev->vm_info.first_vmid_kfd; - int last_vmid_to_scan = dev->vm_info.last_vmid_kfd; - - reg_sq_cmd.u32All = 0; - status = 0; - - wac_info.mode = HSA_DBG_WAVEMODE_BROADCAST_PROCESS; - wac_info.operand = HSA_DBG_WAVEOP_KILL; - - pr_debug("Killing all process wavefronts\n"); - - /* Scan all registers in the range ATC_VMID8_PASID_MAPPING .. - * ATC_VMID15_PASID_MAPPING - * to check which VMID the current process is mapped to. - */ - - for (vmid = first_vmid_to_scan; vmid <= last_vmid_to_scan; vmid++) { - status = dev->kfd2kgd->get_atc_vmid_pasid_mapping_info - (dev->adev, vmid, &queried_pasid); - - if (status && queried_pasid == p->pasid) { - pr_debug("Killing wave fronts of vmid %d and pasid 0x%x\n", - vmid, p->pasid); - break; - } - } - - if (vmid > last_vmid_to_scan) { - pr_err("Didn't find vmid for pasid 0x%x\n", p->pasid); - return -EFAULT; - } - - /* taking the VMID for that process on the safe way using PDD */ - pdd = kfd_get_process_device_data(dev, p); - if (!pdd) - return -EFAULT; - - status = dbgdev_wave_control_set_registers(&wac_info, ®_sq_cmd, - ®_gfx_index); - if (status != 0) - return -EINVAL; - - /* for non DIQ we need to patch the VMID: */ - reg_sq_cmd.bits.vm_id = vmid; - - dev->kfd2kgd->wave_control_execute(dev->adev, - reg_gfx_index.u32All, - reg_sq_cmd.u32All); - - return 0; -} - -void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, - enum DBGDEV_TYPE type) -{ - pdbgdev->dev = pdev; - pdbgdev->kq = NULL; - pdbgdev->type = type; - pdbgdev->pqm = NULL; - - switch (type) { - case DBGDEV_TYPE_NODIQ: - pdbgdev->dbgdev_register = dbgdev_register_nodiq; - pdbgdev->dbgdev_unregister = dbgdev_unregister_nodiq; - pdbgdev->dbgdev_wave_control = dbgdev_wave_control_nodiq; - pdbgdev->dbgdev_address_watch = dbgdev_address_watch_nodiq; - break; - case DBGDEV_TYPE_DIQ: - default: - pdbgdev->dbgdev_register = dbgdev_register_diq; - pdbgdev->dbgdev_unregister = dbgdev_unregister_diq; - pdbgdev->dbgdev_wave_control = dbgdev_wave_control_diq; - pdbgdev->dbgdev_address_watch = dbgdev_address_watch_diq; - break; - } - -} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h deleted file mode 100644 index 0619c777b47e..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef KFD_DBGDEV_H_ -#define KFD_DBGDEV_H_ - -enum { - SQ_CMD_VMID_OFFSET = 28, - ADDRESS_WATCH_CNTL_OFFSET = 24 -}; - -enum { - PRIV_QUEUE_SYNC_TIME_MS = 200 -}; - -/* CONTEXT reg space definition */ -enum { - CONTEXT_REG_BASE = 0xA000, - CONTEXT_REG_END = 0xA400, - CONTEXT_REG_SIZE = CONTEXT_REG_END - CONTEXT_REG_BASE -}; - -/* USER CONFIG reg space definition */ -enum { - USERCONFIG_REG_BASE = 0xC000, - USERCONFIG_REG_END = 0x10000, - USERCONFIG_REG_SIZE = USERCONFIG_REG_END - USERCONFIG_REG_BASE -}; - -/* CONFIG reg space definition */ -enum { - AMD_CONFIG_REG_BASE = 0x2000, /* in dwords */ - AMD_CONFIG_REG_END = 0x2B00, - AMD_CONFIG_REG_SIZE = AMD_CONFIG_REG_END - AMD_CONFIG_REG_BASE -}; - -/* SH reg space definition */ -enum { - SH_REG_BASE = 0x2C00, - SH_REG_END = 0x3000, - SH_REG_SIZE = SH_REG_END - SH_REG_BASE -}; - -/* SQ_CMD definitions */ -#define SQ_CMD 0x8DEC - -enum SQ_IND_CMD_CMD { - SQ_IND_CMD_CMD_NULL = 0x00000000, - SQ_IND_CMD_CMD_HALT = 0x00000001, - SQ_IND_CMD_CMD_RESUME = 0x00000002, - SQ_IND_CMD_CMD_KILL = 0x00000003, - SQ_IND_CMD_CMD_DEBUG = 0x00000004, - SQ_IND_CMD_CMD_TRAP = 0x00000005, -}; - -enum SQ_IND_CMD_MODE { - SQ_IND_CMD_MODE_SINGLE = 0x00000000, - SQ_IND_CMD_MODE_BROADCAST = 0x00000001, - SQ_IND_CMD_MODE_BROADCAST_QUEUE = 0x00000002, - SQ_IND_CMD_MODE_BROADCAST_PIPE = 0x00000003, - SQ_IND_CMD_MODE_BROADCAST_ME = 0x00000004, -}; - -union SQ_IND_INDEX_BITS { - struct { - uint32_t wave_id:4; - uint32_t simd_id:2; - uint32_t thread_id:6; - uint32_t:1; - uint32_t force_read:1; - uint32_t read_timeout:1; - uint32_t unindexed:1; - uint32_t index:16; - - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -union SQ_IND_CMD_BITS { - struct { - uint32_t data:32; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -union SQ_CMD_BITS { - struct { - uint32_t cmd:3; - uint32_t:1; - uint32_t mode:3; - uint32_t check_vmid:1; - uint32_t trap_id:3; - uint32_t:5; - uint32_t wave_id:4; - uint32_t simd_id:2; - uint32_t:2; - uint32_t queue_id:3; - uint32_t:1; - uint32_t vm_id:4; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -union SQ_IND_DATA_BITS { - struct { - uint32_t data:32; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -union GRBM_GFX_INDEX_BITS { - struct { - uint32_t instance_index:8; - uint32_t sh_index:8; - uint32_t se_index:8; - uint32_t:5; - uint32_t sh_broadcast_writes:1; - uint32_t instance_broadcast_writes:1; - uint32_t se_broadcast_writes:1; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -union TCP_WATCH_ADDR_H_BITS { - struct { - uint32_t addr:16; - uint32_t:16; - - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -union TCP_WATCH_ADDR_L_BITS { - struct { - uint32_t:6; - uint32_t addr:26; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -enum { - QUEUESTATE__INVALID = 0, /* so by default we'll get invalid state */ - QUEUESTATE__ACTIVE_COMPLETION_PENDING, - QUEUESTATE__ACTIVE -}; - -union ULARGE_INTEGER { - struct { - uint32_t low_part; - uint32_t high_part; - } u; - unsigned long long quad_part; -}; - - -#define KFD_CIK_VMID_START_OFFSET (8) -#define KFD_CIK_VMID_END_OFFSET (KFD_CIK_VMID_START_OFFSET + (8)) - - -void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, - enum DBGDEV_TYPE type); - -union TCP_WATCH_CNTL_BITS { - struct { - uint32_t mask:24; - uint32_t vmid:4; - uint32_t atc:1; - uint32_t mode:2; - uint32_t valid:1; - } bitfields, bits; - uint32_t u32All; - signed int i32All; - float f32All; -}; - -enum { - ADDRESS_WATCH_REG_CNTL_ATC_BIT = 0x10000000UL, - ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK = 0x00FFFFFF, - ADDRESS_WATCH_REG_ADDLOW_MASK_EXTENSION = 0x03000000, - /* extend the mask to 26 bits in order to match the low address field */ - ADDRESS_WATCH_REG_ADDLOW_SHIFT = 6, - ADDRESS_WATCH_REG_ADDHIGH_MASK = 0xFFFF -}; - -enum { - MAX_TRAPID = 8, /* 3 bits in the bitfield. */ - MAX_WATCH_ADDRESSES = 4 -}; - -enum { - ADDRESS_WATCH_REG_ADDR_HI = 0, - ADDRESS_WATCH_REG_ADDR_LO, - ADDRESS_WATCH_REG_CNTL, - ADDRESS_WATCH_REG_MAX -}; - -#endif /* KFD_DBGDEV_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c deleted file mode 100644 index 9bfa50633654..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include -#include -#include -#include -#include -#include - -#include "kfd_priv.h" -#include "cik_regs.h" -#include "kfd_pm4_headers.h" -#include "kfd_pm4_headers_diq.h" -#include "kfd_dbgmgr.h" -#include "kfd_dbgdev.h" -#include "kfd_device_queue_manager.h" - -static DEFINE_MUTEX(kfd_dbgmgr_mutex); - -struct mutex *kfd_get_dbgmgr_mutex(void) -{ - return &kfd_dbgmgr_mutex; -} - - -static void kfd_dbgmgr_uninitialize(struct kfd_dbgmgr *pmgr) -{ - kfree(pmgr->dbgdev); - - pmgr->dbgdev = NULL; - pmgr->pasid = 0; - pmgr->dev = NULL; -} - -void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr) -{ - if (pmgr) { - kfd_dbgmgr_uninitialize(pmgr); - kfree(pmgr); - } -} - -bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev) -{ - enum DBGDEV_TYPE type = DBGDEV_TYPE_DIQ; - struct kfd_dbgmgr *new_buff; - - if (WARN_ON(!pdev->init_complete)) - return false; - - new_buff = kfd_alloc_struct(new_buff); - if (!new_buff) { - pr_err("Failed to allocate dbgmgr instance\n"); - return false; - } - - new_buff->pasid = 0; - new_buff->dev = pdev; - new_buff->dbgdev = kfd_alloc_struct(new_buff->dbgdev); - if (!new_buff->dbgdev) { - pr_err("Failed to allocate dbgdev instance\n"); - kfree(new_buff); - return false; - } - - /* get actual type of DBGDevice cpsch or not */ - if (pdev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) - type = DBGDEV_TYPE_NODIQ; - - kfd_dbgdev_init(new_buff->dbgdev, pdev, type); - *ppmgr = new_buff; - - return true; -} - -long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p) -{ - if (pmgr->pasid != 0) { - pr_debug("H/W debugger is already active using pasid 0x%x\n", - pmgr->pasid); - return -EBUSY; - } - - /* remember pasid */ - pmgr->pasid = p->pasid; - - /* provide the pqm for diq generation */ - pmgr->dbgdev->pqm = &p->pqm; - - /* activate the actual registering */ - pmgr->dbgdev->dbgdev_register(pmgr->dbgdev); - - return 0; -} - -long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p) -{ - /* Is the requests coming from the already registered process? */ - if (pmgr->pasid != p->pasid) { - pr_debug("H/W debugger is not registered by calling pasid 0x%x\n", - p->pasid); - return -EINVAL; - } - - pmgr->dbgdev->dbgdev_unregister(pmgr->dbgdev); - - pmgr->pasid = 0; - - return 0; -} - -long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr, - struct dbg_wave_control_info *wac_info) -{ - /* Is the requests coming from the already registered process? */ - if (pmgr->pasid != wac_info->process->pasid) { - pr_debug("H/W debugger support was not registered for requester pasid 0x%x\n", - wac_info->process->pasid); - return -EINVAL; - } - - return (long) pmgr->dbgdev->dbgdev_wave_control(pmgr->dbgdev, wac_info); -} - -long kfd_dbgmgr_address_watch(struct kfd_dbgmgr *pmgr, - struct dbg_address_watch_info *adw_info) -{ - /* Is the requests coming from the already registered process? */ - if (pmgr->pasid != adw_info->process->pasid) { - pr_debug("H/W debugger support was not registered for requester pasid 0x%x\n", - adw_info->process->pasid); - return -EINVAL; - } - - return (long) pmgr->dbgdev->dbgdev_address_watch(pmgr->dbgdev, - adw_info); -} - diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h b/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h deleted file mode 100644 index f9c6df1fdc5c..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef KFD_DBGMGR_H_ -#define KFD_DBGMGR_H_ - -#include "kfd_priv.h" - -/* must align with hsakmttypes definition */ -#pragma pack(push, 4) - -enum HSA_DBG_WAVEOP { - HSA_DBG_WAVEOP_HALT = 1, /* Halts a wavefront */ - HSA_DBG_WAVEOP_RESUME = 2, /* Resumes a wavefront */ - HSA_DBG_WAVEOP_KILL = 3, /* Kills a wavefront */ - HSA_DBG_WAVEOP_DEBUG = 4, /* Causes wavefront to enter dbg mode */ - HSA_DBG_WAVEOP_TRAP = 5, /* Causes wavefront to take a trap */ - HSA_DBG_NUM_WAVEOP = 5, - HSA_DBG_MAX_WAVEOP = 0xFFFFFFFF -}; - -enum HSA_DBG_WAVEMODE { - /* send command to a single wave */ - HSA_DBG_WAVEMODE_SINGLE = 0, - /* - * Broadcast to all wavefronts of all processes is not - * supported for HSA user mode - */ - - /* send to waves within current process */ - HSA_DBG_WAVEMODE_BROADCAST_PROCESS = 2, - /* send to waves within current process on CU */ - HSA_DBG_WAVEMODE_BROADCAST_PROCESS_CU = 3, - HSA_DBG_NUM_WAVEMODE = 3, - HSA_DBG_MAX_WAVEMODE = 0xFFFFFFFF -}; - -enum HSA_DBG_WAVEMSG_TYPE { - HSA_DBG_WAVEMSG_AUTO = 0, - HSA_DBG_WAVEMSG_USER = 1, - HSA_DBG_WAVEMSG_ERROR = 2, - HSA_DBG_NUM_WAVEMSG, - HSA_DBG_MAX_WAVEMSG = 0xFFFFFFFF -}; - -enum HSA_DBG_WATCH_MODE { - HSA_DBG_WATCH_READ = 0, /* Read operations only */ - HSA_DBG_WATCH_NONREAD = 1, /* Write or Atomic operations only */ - HSA_DBG_WATCH_ATOMIC = 2, /* Atomic Operations only */ - HSA_DBG_WATCH_ALL = 3, /* Read, Write or Atomic operations */ - HSA_DBG_WATCH_NUM, - HSA_DBG_WATCH_SIZE = 0xFFFFFFFF -}; - -/* This structure is hardware specific and may change in the future */ -struct HsaDbgWaveMsgAMDGen2 { - union { - struct ui32 { - uint32_t UserData:8; /* user data */ - uint32_t ShaderArray:1; /* Shader array */ - uint32_t Priv:1; /* Privileged */ - uint32_t Reserved0:4; /* Reserved, should be 0 */ - uint32_t WaveId:4; /* wave id */ - uint32_t SIMD:2; /* SIMD id */ - uint32_t HSACU:4; /* Compute unit */ - uint32_t ShaderEngine:2;/* Shader engine */ - uint32_t MessageType:2; /* see HSA_DBG_WAVEMSG_TYPE */ - uint32_t Reserved1:4; /* Reserved, should be 0 */ - } ui32; - uint32_t Value; - }; - uint32_t Reserved2; -}; - -union HsaDbgWaveMessageAMD { - struct HsaDbgWaveMsgAMDGen2 WaveMsgInfoGen2; - /* for future HsaDbgWaveMsgAMDGen3; */ -}; - -struct HsaDbgWaveMessage { - void *MemoryVA; /* ptr to associated host-accessible data */ - union HsaDbgWaveMessageAMD DbgWaveMsg; -}; - -/* - * TODO: This definitions to be MOVED to kfd_event, once it is implemented. - * - * HSA sync primitive, Event and HW Exception notification API definitions. - * The API functions allow the runtime to define a so-called sync-primitive, - * a SW object combining a user-mode provided "syncvar" and a scheduler event - * that can be signaled through a defined GPU interrupt. A syncvar is - * a process virtual memory location of a certain size that can be accessed - * by CPU and GPU shader code within the process to set and query the content - * within that memory. The definition of the content is determined by the HSA - * runtime and potentially GPU shader code interfacing with the HSA runtime. - * The syncvar values may be commonly written through an PM4 WRITE_DATA packet - * in the user mode instruction stream. The OS scheduler event is typically - * associated and signaled by an interrupt issued by the GPU, but other HSA - * system interrupt conditions from other HW (e.g. IOMMUv2) may be surfaced - * by the KFD by this mechanism, too. - */ - -/* these are the new definitions for events */ -enum HSA_EVENTTYPE { - HSA_EVENTTYPE_SIGNAL = 0, /* user-mode generated GPU signal */ - HSA_EVENTTYPE_NODECHANGE = 1, /* HSA node change (attach/detach) */ - HSA_EVENTTYPE_DEVICESTATECHANGE = 2, /* HSA device state change - * (start/stop) - */ - HSA_EVENTTYPE_HW_EXCEPTION = 3, /* GPU shader exception event */ - HSA_EVENTTYPE_SYSTEM_EVENT = 4, /* GPU SYSCALL with parameter info */ - HSA_EVENTTYPE_DEBUG_EVENT = 5, /* GPU signal for debugging */ - HSA_EVENTTYPE_PROFILE_EVENT = 6,/* GPU signal for profiling */ - HSA_EVENTTYPE_QUEUE_EVENT = 7, /* GPU signal queue idle state - * (EOP pm4) - */ - /* ... */ - HSA_EVENTTYPE_MAXID, - HSA_EVENTTYPE_TYPE_SIZE = 0xFFFFFFFF -}; - -/* Sub-definitions for various event types: Syncvar */ -struct HsaSyncVar { - union SyncVar { - void *UserData; /* pointer to user mode data */ - uint64_t UserDataPtrValue; /* 64bit compatibility of value */ - } SyncVar; - uint64_t SyncVarSize; -}; - -/* Sub-definitions for various event types: NodeChange */ - -enum HSA_EVENTTYPE_NODECHANGE_FLAGS { - HSA_EVENTTYPE_NODECHANGE_ADD = 0, - HSA_EVENTTYPE_NODECHANGE_REMOVE = 1, - HSA_EVENTTYPE_NODECHANGE_SIZE = 0xFFFFFFFF -}; - -struct HsaNodeChange { - /* HSA node added/removed on the platform */ - enum HSA_EVENTTYPE_NODECHANGE_FLAGS Flags; -}; - -/* Sub-definitions for various event types: DeviceStateChange */ -enum HSA_EVENTTYPE_DEVICESTATECHANGE_FLAGS { - /* device started (and available) */ - HSA_EVENTTYPE_DEVICESTATUSCHANGE_START = 0, - /* device stopped (i.e. unavailable) */ - HSA_EVENTTYPE_DEVICESTATUSCHANGE_STOP = 1, - HSA_EVENTTYPE_DEVICESTATUSCHANGE_SIZE = 0xFFFFFFFF -}; - -enum HSA_DEVICE { - HSA_DEVICE_CPU = 0, - HSA_DEVICE_GPU = 1, - MAX_HSA_DEVICE = 2 -}; - -struct HsaDeviceStateChange { - uint32_t NodeId; /* F-NUMA node that contains the device */ - enum HSA_DEVICE Device; /* device type: GPU or CPU */ - enum HSA_EVENTTYPE_DEVICESTATECHANGE_FLAGS Flags; /* event flags */ -}; - -struct HsaEventData { - enum HSA_EVENTTYPE EventType; /* event type */ - union EventData { - /* - * return data associated with HSA_EVENTTYPE_SIGNAL - * and other events - */ - struct HsaSyncVar SyncVar; - - /* data associated with HSA_EVENTTYPE_NODE_CHANGE */ - struct HsaNodeChange NodeChangeState; - - /* data associated with HSA_EVENTTYPE_DEVICE_STATE_CHANGE */ - struct HsaDeviceStateChange DeviceState; - } EventData; - - /* the following data entries are internal to the KFD & thunk itself */ - - /* internal thunk store for Event data (OsEventHandle) */ - uint64_t HWData1; - /* internal thunk store for Event data (HWAddress) */ - uint64_t HWData2; - /* internal thunk store for Event data (HWData) */ - uint32_t HWData3; -}; - -struct HsaEventDescriptor { - /* event type to allocate */ - enum HSA_EVENTTYPE EventType; - /* H-NUMA node containing GPU device that is event source */ - uint32_t NodeId; - /* pointer to user mode syncvar data, syncvar->UserDataPtrValue - * may be NULL - */ - struct HsaSyncVar SyncVar; -}; - -struct HsaEvent { - uint32_t EventId; - struct HsaEventData EventData; -}; - -#pragma pack(pop) - -enum DBGDEV_TYPE { - DBGDEV_TYPE_ILLEGAL = 0, - DBGDEV_TYPE_NODIQ = 1, - DBGDEV_TYPE_DIQ = 2, - DBGDEV_TYPE_TEST = 3 -}; - -struct dbg_address_watch_info { - struct kfd_process *process; - enum HSA_DBG_WATCH_MODE *watch_mode; - uint64_t *watch_address; - uint64_t *watch_mask; - struct HsaEvent *watch_event; - uint32_t num_watch_points; -}; - -struct dbg_wave_control_info { - struct kfd_process *process; - uint32_t trapId; - enum HSA_DBG_WAVEOP operand; - enum HSA_DBG_WAVEMODE mode; - struct HsaDbgWaveMessage dbgWave_msg; -}; - -struct kfd_dbgdev { - - /* The device that owns this data. */ - struct kfd_dev *dev; - - /* kernel queue for DIQ */ - struct kernel_queue *kq; - - /* a pointer to the pqm of the calling process */ - struct process_queue_manager *pqm; - - /* type of debug device ( DIQ, non DIQ, etc. ) */ - enum DBGDEV_TYPE type; - - /* virtualized function pointers to device dbg */ - int (*dbgdev_register)(struct kfd_dbgdev *dbgdev); - int (*dbgdev_unregister)(struct kfd_dbgdev *dbgdev); - int (*dbgdev_address_watch)(struct kfd_dbgdev *dbgdev, - struct dbg_address_watch_info *adw_info); - int (*dbgdev_wave_control)(struct kfd_dbgdev *dbgdev, - struct dbg_wave_control_info *wac_info); - -}; - -struct kfd_dbgmgr { - u32 pasid; - struct kfd_dev *dev; - struct kfd_dbgdev *dbgdev; -}; - -/* prototypes for debug manager functions */ -struct mutex *kfd_get_dbgmgr_mutex(void); -void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr); -bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev); -long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p); -long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p); -long kfd_dbgmgr_wave_control(struct kfd_dbgmgr *pmgr, - struct dbg_wave_control_info *wac_info); -long kfd_dbgmgr_address_watch(struct kfd_dbgmgr *pmgr, - struct dbg_address_watch_info *adw_info); -#endif /* KFD_DBGMGR_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 5a47f437b455..dbb877fba724 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -575,8 +575,6 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, if (kfd_resume(kfd)) goto kfd_resume_error; - kfd->dbgmgr = NULL; - if (kfd_topology_add_device(kfd)) { dev_err(kfd_device, "Error adding device to topology\n"); goto kfd_topology_add_device_error; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 219acc818eb4..7f6f1a842b0b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -480,6 +480,65 @@ static inline void deallocate_hqd(struct device_queue_manager *dqm, dqm->allocated_queues[q->pipe] |= (1 << q->queue); } +#define SQ_IND_CMD_CMD_KILL 0x00000003 +#define SQ_IND_CMD_MODE_BROADCAST 0x00000001 + +static int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p) +{ + int status = 0; + unsigned int vmid; + uint16_t queried_pasid; + union SQ_CMD_BITS reg_sq_cmd; + union GRBM_GFX_INDEX_BITS reg_gfx_index; + struct kfd_process_device *pdd; + int first_vmid_to_scan = dev->vm_info.first_vmid_kfd; + int last_vmid_to_scan = dev->vm_info.last_vmid_kfd; + + reg_sq_cmd.u32All = 0; + reg_gfx_index.u32All = 0; + + pr_debug("Killing all process wavefronts\n"); + + /* Scan all registers in the range ATC_VMID8_PASID_MAPPING .. + * ATC_VMID15_PASID_MAPPING + * to check which VMID the current process is mapped to. + */ + + for (vmid = first_vmid_to_scan; vmid <= last_vmid_to_scan; vmid++) { + status = dev->kfd2kgd->get_atc_vmid_pasid_mapping_info + (dev->adev, vmid, &queried_pasid); + + if (status && queried_pasid == p->pasid) { + pr_debug("Killing wave fronts of vmid %d and pasid 0x%x\n", + vmid, p->pasid); + break; + } + } + + if (vmid > last_vmid_to_scan) { + pr_err("Didn't find vmid for pasid 0x%x\n", p->pasid); + return -EFAULT; + } + + /* taking the VMID for that process on the safe way using PDD */ + pdd = kfd_get_process_device_data(dev, p); + if (!pdd) + return -EFAULT; + + reg_gfx_index.bits.sh_broadcast_writes = 1; + reg_gfx_index.bits.se_broadcast_writes = 1; + reg_gfx_index.bits.instance_broadcast_writes = 1; + reg_sq_cmd.bits.mode = SQ_IND_CMD_MODE_BROADCAST; + reg_sq_cmd.bits.cmd = SQ_IND_CMD_CMD_KILL; + reg_sq_cmd.bits.vm_id = vmid; + + dev->kfd2kgd->wave_control_execute(dev->adev, + reg_gfx_index.u32All, + reg_sq_cmd.u32All); + + return 0; +} + /* Access to DQM has to be locked before calling destroy_queue_nocpsch_locked * to avoid asynchronized access */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index a7d2e3323977..05a9c17daa3e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -39,6 +39,41 @@ struct device_process_node { struct list_head list; }; +union SQ_CMD_BITS { + struct { + uint32_t cmd:3; + uint32_t:1; + uint32_t mode:3; + uint32_t check_vmid:1; + uint32_t trap_id:3; + uint32_t:5; + uint32_t wave_id:4; + uint32_t simd_id:2; + uint32_t:2; + uint32_t queue_id:3; + uint32_t:1; + uint32_t vm_id:4; + } bitfields, bits; + uint32_t u32All; + signed int i32All; + float f32All; +}; + +union GRBM_GFX_INDEX_BITS { + struct { + uint32_t instance_index:8; + uint32_t sh_index:8; + uint32_t se_index:8; + uint32_t:5; + uint32_t sh_broadcast_writes:1; + uint32_t instance_broadcast_writes:1; + uint32_t se_broadcast_writes:1; + } bitfields, bits; + uint32_t u32All; + signed int i32All; + float f32All; +}; + /** * struct device_queue_manager_ops * diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c index 66ad8d0b8f7f..fe62407dacb2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c @@ -30,7 +30,6 @@ #include #include #include "kfd_priv.h" -#include "kfd_dbgmgr.h" #include "kfd_topology.h" #include "kfd_iommu.h" @@ -163,17 +162,6 @@ static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, u32 pasid) pr_debug("Unbinding process 0x%x from IOMMU\n", pasid); - mutex_lock(kfd_get_dbgmgr_mutex()); - - if (dev->dbgmgr && dev->dbgmgr->pasid == p->pasid) { - if (!kfd_dbgmgr_unregister(dev->dbgmgr, p)) { - kfd_dbgmgr_destroy(dev->dbgmgr); - dev->dbgmgr = NULL; - } - } - - mutex_unlock(kfd_get_dbgmgr_mutex()); - mutex_lock(&p->mutex); pdd = kfd_get_process_device_data(dev, p); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 74fb4762c66e..b6790a637f5c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -300,9 +300,6 @@ struct kfd_dev { */ bool interrupts_active; - /* Debug manager */ - struct kfd_dbgmgr *dbgmgr; - /* Firmware versions */ uint16_t mec_fw_version; uint16_t mec2_fw_version; @@ -1331,8 +1328,6 @@ void kfd_signal_poison_consumed_event(struct kfd_dev *dev, u32 pasid); void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type); -int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p); - bool kfd_is_locked(void); /* Compute profile */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 8e2780d2f735..8c6a48add76e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -40,7 +40,6 @@ struct mm_struct; #include "kfd_priv.h" #include "kfd_device_queue_manager.h" -#include "kfd_dbgmgr.h" #include "kfd_iommu.h" #include "kfd_svm.h" @@ -1158,7 +1157,6 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, struct mm_struct *mm) { struct kfd_process *p; - int i; /* * The kfd_process structure can not be free because the @@ -1178,23 +1176,6 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, mutex_lock(&p->mutex); - /* Iterate over all process device data structures and if the - * pdd is in debug mode, we should first force unregistration, - * then we will be able to destroy the queues - */ - for (i = 0; i < p->n_pdds; i++) { - struct kfd_dev *dev = p->pdds[i]->dev; - - mutex_lock(kfd_get_dbgmgr_mutex()); - if (dev && dev->dbgmgr && dev->dbgmgr->pasid == p->pasid) { - if (!kfd_dbgmgr_unregister(dev->dbgmgr, p)) { - kfd_dbgmgr_destroy(dev->dbgmgr); - dev->dbgmgr = NULL; - } - } - mutex_unlock(kfd_get_dbgmgr_mutex()); - } - kfd_process_dequeue_from_all_devices(p); pqm_uninit(&p->pqm); diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index ac941f62cbed..2f60cf35a444 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -269,18 +269,9 @@ struct kfd2kgd_calls { int (*hqd_sdma_destroy)(struct amdgpu_device *adev, void *mqd, unsigned int timeout); - int (*address_watch_disable)(struct amdgpu_device *adev); - int (*address_watch_execute)(struct amdgpu_device *adev, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo); int (*wave_control_execute)(struct amdgpu_device *adev, uint32_t gfx_index_val, uint32_t sq_cmd); - uint32_t (*address_watch_get_offset)(struct amdgpu_device *adev, - unsigned int watch_point_id, - unsigned int reg_offset); bool (*get_atc_vmid_pasid_mapping_info)(struct amdgpu_device *adev, uint8_t vmid, uint16_t *p_pasid); diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index e6a56c146920..6e4268f5e482 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -756,16 +756,16 @@ struct kfd_ioctl_set_xnack_mode_args { #define AMDKFD_IOC_WAIT_EVENTS \ AMDKFD_IOWR(0x0C, struct kfd_ioctl_wait_events_args) -#define AMDKFD_IOC_DBG_REGISTER \ +#define AMDKFD_IOC_DBG_REGISTER_DEPRECATED \ AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args) -#define AMDKFD_IOC_DBG_UNREGISTER \ +#define AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED \ AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args) -#define AMDKFD_IOC_DBG_ADDRESS_WATCH \ +#define AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED \ AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args) -#define AMDKFD_IOC_DBG_WAVE_CONTROL \ +#define AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED \ AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args) #define AMDKFD_IOC_SET_SCRATCH_BACKING_VA \ From a439b890dbd17457f071e41777aa1d17916258d6 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Fri, 4 Feb 2022 12:15:02 -0500 Subject: [PATCH 316/339] drm/amdkfd: Consolidate MQD manager functions A few MQD manager functions are duplicated for all versions of MQD manager. Remove this duplication by moving the common functions into kfd_mqd_manager.c file. Signed-off-by: Mukul Joshi Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 63 +++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h | 27 ++++++ .../gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c | 76 +++------------ .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c | 85 +++-------------- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 92 +++---------------- .../gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 75 +++------------ 6 files changed, 136 insertions(+), 282 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index e2825ad4d699..9b7544ddced7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -173,3 +173,66 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, } } } + +int kfd_hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd, + uint32_t pipe_id, uint32_t queue_id, + struct queue_properties *p, struct mm_struct *mms) +{ + return mm->dev->kfd2kgd->hiq_mqd_load(mm->dev->adev, mqd, pipe_id, + queue_id, p->doorbell_off); +} + +int kfd_destroy_mqd_cp(struct mqd_manager *mm, void *mqd, + enum kfd_preempt_type type, unsigned int timeout, + uint32_t pipe_id, uint32_t queue_id) +{ + return mm->dev->kfd2kgd->hqd_destroy(mm->dev->adev, mqd, type, timeout, + pipe_id, queue_id); +} + +void kfd_free_mqd_cp(struct mqd_manager *mm, void *mqd, + struct kfd_mem_obj *mqd_mem_obj) +{ + if (mqd_mem_obj->gtt_mem) { + amdgpu_amdkfd_free_gtt_mem(mm->dev->adev, mqd_mem_obj->gtt_mem); + kfree(mqd_mem_obj); + } else { + kfd_gtt_sa_free(mm->dev, mqd_mem_obj); + } +} + +bool kfd_is_occupied_cp(struct mqd_manager *mm, void *mqd, + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id) +{ + return mm->dev->kfd2kgd->hqd_is_occupied(mm->dev->adev, queue_address, + pipe_id, queue_id); +} + +int kfd_load_mqd_sdma(struct mqd_manager *mm, void *mqd, + uint32_t pipe_id, uint32_t queue_id, + struct queue_properties *p, struct mm_struct *mms) +{ + return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->adev, mqd, + (uint32_t __user *)p->write_ptr, + mms); +} + +/* + * preempt type here is ignored because there is only one way + * to preempt sdma queue + */ +int kfd_destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, + enum kfd_preempt_type type, + unsigned int timeout, uint32_t pipe_id, + uint32_t queue_id) +{ + return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->adev, mqd, timeout); +} + +bool kfd_is_occupied_sdma(struct mqd_manager *mm, void *mqd, + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id) +{ + return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h index 23486a23df84..d81ae0699300 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h @@ -136,4 +136,31 @@ void mqd_symmetrically_map_cu_mask(struct mqd_manager *mm, const uint32_t *cu_mask, uint32_t cu_mask_count, uint32_t *se_mask); +int kfd_hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd, + uint32_t pipe_id, uint32_t queue_id, + struct queue_properties *p, struct mm_struct *mms); + +int kfd_destroy_mqd_cp(struct mqd_manager *mm, void *mqd, + enum kfd_preempt_type type, unsigned int timeout, + uint32_t pipe_id, uint32_t queue_id); + +void kfd_free_mqd_cp(struct mqd_manager *mm, void *mqd, + struct kfd_mem_obj *mqd_mem_obj); + +bool kfd_is_occupied_cp(struct mqd_manager *mm, void *mqd, + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id); + +int kfd_load_mqd_sdma(struct mqd_manager *mm, void *mqd, + uint32_t pipe_id, uint32_t queue_id, + struct queue_properties *p, struct mm_struct *mms); + +int kfd_destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, + enum kfd_preempt_type type, unsigned int timeout, + uint32_t pipe_id, uint32_t queue_id); + +bool kfd_is_occupied_sdma(struct mqd_manager *mm, void *mqd, + uint64_t queue_address, uint32_t pipe_id, + uint32_t queue_id); + #endif /* KFD_MQD_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c index 96e3303fa27c..06aae5df6a37 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c @@ -156,13 +156,6 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd, mm->update_mqd(mm, m, q, NULL); } -static void free_mqd(struct mqd_manager *mm, void *mqd, - struct kfd_mem_obj *mqd_mem_obj) -{ - kfd_gtt_sa_free(mm->dev, mqd_mem_obj); -} - - static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id, uint32_t queue_id, struct queue_properties *p, struct mm_struct *mms) @@ -176,15 +169,6 @@ static int load_mqd(struct mqd_manager *mm, void *mqd, uint32_t pipe_id, wptr_shift, wptr_mask, mms); } -static int load_mqd_sdma(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - struct queue_properties *p, struct mm_struct *mms) -{ - return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->adev, mqd, - (uint32_t __user *)p->write_ptr, - mms); -} - static void __update_mqd(struct mqd_manager *mm, void *mqd, struct queue_properties *q, struct mqd_update_info *minfo, unsigned int atc_bit) @@ -271,15 +255,6 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -static int destroy_mqd(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_destroy(mm->dev->adev, mqd, type, timeout, - pipe_id, queue_id); -} - static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) { struct cik_mqd *m; @@ -351,35 +326,6 @@ static void restore_mqd_sdma(struct mqd_manager *mm, void **mqd, qp->is_active = 0; } -/* - * preempt type here is ignored because there is only one way - * to preempt sdma queue - */ -static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->adev, mqd, timeout); -} - -static bool is_occupied(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - - return mm->dev->kfd2kgd->hqd_is_occupied(mm->dev->adev, queue_address, - pipe_id, queue_id); - -} - -static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); -} - /* * HIQ MQD Implementation, concrete implementation for HIQ MQD implementation. * The HIQ queue in Kaveri is using the same MQD structure as all the user mode @@ -460,11 +406,11 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_CP: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->checkpoint_mqd = checkpoint_mqd; mqd->restore_mqd = restore_mqd; mqd->mqd_size = sizeof(struct cik_mqd); @@ -478,8 +424,8 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, mqd->free_mqd = free_mqd_hiq_sdma; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd_hiq; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct cik_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -489,11 +435,11 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_DIQ: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd_hiq; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd_hiq; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct cik_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -503,10 +449,10 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, mqd->allocate_mqd = allocate_sdma_mqd; mqd->init_mqd = init_mqd_sdma; mqd->free_mqd = free_mqd_hiq_sdma; - mqd->load_mqd = load_mqd_sdma; + mqd->load_mqd = kfd_load_mqd_sdma; mqd->update_mqd = update_mqd_sdma; - mqd->destroy_mqd = destroy_mqd_sdma; - mqd->is_occupied = is_occupied_sdma; + mqd->destroy_mqd = kfd_destroy_mqd_sdma; + mqd->is_occupied = kfd_is_occupied_sdma; mqd->checkpoint_mqd = checkpoint_mqd_sdma; mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct cik_sdma_rlc_registers); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c index 0cc8679c24fa..88228009ded4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c @@ -154,14 +154,6 @@ static int load_mqd(struct mqd_manager *mm, void *mqd, return r; } -static int hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - struct queue_properties *p, struct mm_struct *mms) -{ - return mm->dev->kfd2kgd->hiq_mqd_load(mm->dev->adev, mqd, pipe_id, - queue_id, p->doorbell_off); -} - static void update_mqd(struct mqd_manager *mm, void *mqd, struct queue_properties *q, struct mqd_update_info *minfo) @@ -233,31 +225,6 @@ static uint32_t read_doorbell_id(void *mqd) return m->queue_doorbell_id0; } -static int destroy_mqd(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_destroy - (mm->dev->adev, mqd, type, timeout, - pipe_id, queue_id); -} - -static void free_mqd(struct mqd_manager *mm, void *mqd, - struct kfd_mem_obj *mqd_mem_obj) -{ - kfd_gtt_sa_free(mm->dev, mqd_mem_obj); -} - -static bool is_occupied(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_is_occupied( - mm->dev->adev, queue_address, - pipe_id, queue_id); -} - static int get_wave_state(struct mqd_manager *mm, void *mqd, void __user *ctl_stack, u32 *ctl_stack_used_size, @@ -352,15 +319,6 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd, mm->update_mqd(mm, m, q, NULL); } -static int load_mqd_sdma(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - struct queue_properties *p, struct mm_struct *mms) -{ - return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->adev, mqd, - (uint32_t __user *)p->write_ptr, - mms); -} - #define SDMA_RLC_DUMMY_DEFAULT 0xf static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, @@ -390,25 +348,6 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -/* - * * preempt type here is ignored because there is only one way - * * to preempt sdma queue - */ -static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->adev, mqd, timeout); -} - -static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); -} - static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst, @@ -483,11 +422,11 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, pr_debug("%s@%i\n", __func__, __LINE__); mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct v10_compute_mqd); mqd->get_wave_state = get_wave_state; mqd->checkpoint_mqd = checkpoint_mqd; @@ -502,10 +441,10 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, mqd->allocate_mqd = allocate_hiq_mqd; mqd->init_mqd = init_mqd_hiq; mqd->free_mqd = free_mqd_hiq_sdma; - mqd->load_mqd = hiq_load_mqd_kiq; + mqd->load_mqd = kfd_hiq_load_mqd_kiq; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct v10_compute_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -516,11 +455,11 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_DIQ: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd_hiq; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct v10_compute_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -531,10 +470,10 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, mqd->allocate_mqd = allocate_sdma_mqd; mqd->init_mqd = init_mqd_sdma; mqd->free_mqd = free_mqd_hiq_sdma; - mqd->load_mqd = load_mqd_sdma; + mqd->load_mqd = kfd_load_mqd_sdma; mqd->update_mqd = update_mqd_sdma; - mqd->destroy_mqd = destroy_mqd_sdma; - mqd->is_occupied = is_occupied_sdma; + mqd->destroy_mqd = kfd_destroy_mqd_sdma; + mqd->is_occupied = kfd_is_occupied_sdma; mqd->checkpoint_mqd = checkpoint_mqd_sdma; mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct v10_sdma_mqd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index 87da4329dbf2..dff58ee53557 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -204,14 +204,6 @@ static int load_mqd(struct mqd_manager *mm, void *mqd, wptr_shift, 0, mms); } -static int hiq_load_mqd_kiq(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - struct queue_properties *p, struct mm_struct *mms) -{ - return mm->dev->kfd2kgd->hiq_mqd_load(mm->dev->adev, mqd, pipe_id, - queue_id, p->doorbell_off); -} - static void update_mqd(struct mqd_manager *mm, void *mqd, struct queue_properties *q, struct mqd_update_info *minfo) @@ -285,38 +277,6 @@ static uint32_t read_doorbell_id(void *mqd) return m->queue_doorbell_id0; } -static int destroy_mqd(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_destroy - (mm->dev->adev, mqd, type, timeout, - pipe_id, queue_id); -} - -static void free_mqd(struct mqd_manager *mm, void *mqd, - struct kfd_mem_obj *mqd_mem_obj) -{ - struct kfd_dev *kfd = mm->dev; - - if (mqd_mem_obj->gtt_mem) { - amdgpu_amdkfd_free_gtt_mem(kfd->adev, mqd_mem_obj->gtt_mem); - kfree(mqd_mem_obj); - } else { - kfd_gtt_sa_free(mm->dev, mqd_mem_obj); - } -} - -static bool is_occupied(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_is_occupied( - mm->dev->adev, queue_address, - pipe_id, queue_id); -} - static int get_wave_state(struct mqd_manager *mm, void *mqd, void __user *ctl_stack, u32 *ctl_stack_used_size, @@ -422,15 +382,6 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd, mm->update_mqd(mm, m, q, NULL); } -static int load_mqd_sdma(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - struct queue_properties *p, struct mm_struct *mms) -{ - return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->adev, mqd, - (uint32_t __user *)p->write_ptr, - mms); -} - #define SDMA_RLC_DUMMY_DEFAULT 0xf static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, @@ -460,25 +411,6 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -/* - * * preempt type here is ignored because there is only one way - * * to preempt sdma queue - */ -static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->adev, mqd, timeout); -} - -static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); -} - static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst, @@ -551,11 +483,11 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_CP: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->get_wave_state = get_wave_state; mqd->get_checkpoint_info = get_checkpoint_info; mqd->checkpoint_mqd = checkpoint_mqd; @@ -569,10 +501,10 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, mqd->allocate_mqd = allocate_hiq_mqd; mqd->init_mqd = init_mqd_hiq; mqd->free_mqd = free_mqd_hiq_sdma; - mqd->load_mqd = hiq_load_mqd_kiq; + mqd->load_mqd = kfd_hiq_load_mqd_kiq; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct v9_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -582,11 +514,11 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_DIQ: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd_hiq; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct v9_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -596,10 +528,10 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, mqd->allocate_mqd = allocate_sdma_mqd; mqd->init_mqd = init_mqd_sdma; mqd->free_mqd = free_mqd_hiq_sdma; - mqd->load_mqd = load_mqd_sdma; + mqd->load_mqd = kfd_load_mqd_sdma; mqd->update_mqd = update_mqd_sdma; - mqd->destroy_mqd = destroy_mqd_sdma; - mqd->is_occupied = is_occupied_sdma; + mqd->destroy_mqd = kfd_destroy_mqd_sdma; + mqd->is_occupied = kfd_is_occupied_sdma; mqd->checkpoint_mqd = checkpoint_mqd_sdma; mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct v9_sdma_mqd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c index 137b208135a0..86fc5decacf0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c @@ -259,31 +259,6 @@ static void update_mqd_tonga(struct mqd_manager *mm, void *mqd, __update_mqd(mm, mqd, q, minfo, MTYPE_UC, 0); } -static int destroy_mqd(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_destroy - (mm->dev->adev, mqd, type, timeout, - pipe_id, queue_id); -} - -static void free_mqd(struct mqd_manager *mm, void *mqd, - struct kfd_mem_obj *mqd_mem_obj) -{ - kfd_gtt_sa_free(mm->dev, mqd_mem_obj); -} - -static bool is_occupied(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_is_occupied( - mm->dev->adev, queue_address, - pipe_id, queue_id); -} - static int get_wave_state(struct mqd_manager *mm, void *mqd, void __user *ctl_stack, u32 *ctl_stack_used_size, @@ -385,15 +360,6 @@ static void init_mqd_sdma(struct mqd_manager *mm, void **mqd, mm->update_mqd(mm, m, q, NULL); } -static int load_mqd_sdma(struct mqd_manager *mm, void *mqd, - uint32_t pipe_id, uint32_t queue_id, - struct queue_properties *p, struct mm_struct *mms) -{ - return mm->dev->kfd2kgd->hqd_sdma_load(mm->dev->adev, mqd, - (uint32_t __user *)p->write_ptr, - mms); -} - static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, struct queue_properties *q, struct mqd_update_info *minfo) @@ -422,25 +388,6 @@ static void update_mqd_sdma(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -/* - * * preempt type here is ignored because there is only one way - * * to preempt sdma queue - */ -static int destroy_mqd_sdma(struct mqd_manager *mm, void *mqd, - enum kfd_preempt_type type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_destroy(mm->dev->adev, mqd, timeout); -} - -static bool is_occupied_sdma(struct mqd_manager *mm, void *mqd, - uint64_t queue_address, uint32_t pipe_id, - uint32_t queue_id) -{ - return mm->dev->kfd2kgd->hqd_sdma_is_occupied(mm->dev->adev, mqd); -} - static void checkpoint_mqd_sdma(struct mqd_manager *mm, void *mqd, void *mqd_dst, @@ -514,11 +461,11 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_CP: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->get_wave_state = get_wave_state; mqd->get_checkpoint_info = get_checkpoint_info; mqd->checkpoint_mqd = checkpoint_mqd; @@ -534,8 +481,8 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, mqd->free_mqd = free_mqd_hiq_sdma; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd_hiq; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct vi_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -545,11 +492,11 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, case KFD_MQD_TYPE_DIQ: mqd->allocate_mqd = allocate_mqd; mqd->init_mqd = init_mqd_hiq; - mqd->free_mqd = free_mqd; + mqd->free_mqd = kfd_free_mqd_cp; mqd->load_mqd = load_mqd; mqd->update_mqd = update_mqd_hiq; - mqd->destroy_mqd = destroy_mqd; - mqd->is_occupied = is_occupied; + mqd->destroy_mqd = kfd_destroy_mqd_cp; + mqd->is_occupied = kfd_is_occupied_cp; mqd->mqd_size = sizeof(struct vi_mqd); #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; @@ -559,10 +506,10 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, mqd->allocate_mqd = allocate_sdma_mqd; mqd->init_mqd = init_mqd_sdma; mqd->free_mqd = free_mqd_hiq_sdma; - mqd->load_mqd = load_mqd_sdma; + mqd->load_mqd = kfd_load_mqd_sdma; mqd->update_mqd = update_mqd_sdma; - mqd->destroy_mqd = destroy_mqd_sdma; - mqd->is_occupied = is_occupied_sdma; + mqd->destroy_mqd = kfd_destroy_mqd_sdma; + mqd->is_occupied = kfd_is_occupied_sdma; mqd->checkpoint_mqd = checkpoint_mqd_sdma; mqd->restore_mqd = restore_mqd_sdma; mqd->mqd_size = sizeof(struct vi_sdma_mqd); From 1cbbc8d4f788af4c260ef3cae05902ef7b191197 Mon Sep 17 00:00:00 2001 From: zhanglianjie Date: Tue, 8 Feb 2022 16:03:20 +0800 Subject: [PATCH 317/339] drm/radeon/uvd: Fix forgotten unmap buffer objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the buffer object is successfully mapped, call radeon_bo_kunmap before the function returns. Signed-off-by: zhanglianjie Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_uvd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 377f9cdb5b53..0558d928d98d 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -497,6 +497,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, handle = msg[2]; if (handle == 0) { + radeon_bo_kunmap(bo); DRM_ERROR("Invalid UVD handle!\n"); return -EINVAL; } @@ -559,12 +560,10 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, return 0; default: - DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); - return -EINVAL; } - BUG(); + radeon_bo_kunmap(bo); return -EINVAL; } From db7b81545f5abdfd1f13b7f0a3f995994701cf92 Mon Sep 17 00:00:00 2001 From: zhanglianjie Date: Sat, 29 Jan 2022 15:35:23 +0800 Subject: [PATCH 318/339] drm/amd/amdgpu/amdgpu_uvd: Fix forgotten unmap buffer object After the buffer object is successfully mapped, call amdgpu_bo_kunmap before the function returns. Signed-off-by: zhanglianjie Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index 6f8de11a17f1..9cc23b220537 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -834,6 +834,7 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx, handle = msg[2]; if (handle == 0) { + amdgpu_bo_kunmap(bo); DRM_ERROR("Invalid UVD handle!\n"); return -EINVAL; } @@ -892,6 +893,7 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx, DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); } + amdgpu_bo_kunmap(bo); return -EINVAL; } From 3b99e8e37d0ffaa0ef95598b9b83c49c89bc0ea2 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Tue, 8 Feb 2022 15:36:50 +0800 Subject: [PATCH 319/339] drm/amd/pm: correct hwmon power label name only vangogh has 2 types of hwmon power node: "fastPPT" and "slowPPT", the other asic only has 1 type of hwmon power node: "PPT". Signed-off-by: Yang Wang Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 426e00112c91..ad5da252228b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2842,10 +2842,14 @@ static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, struct device_attribute *attr, char *buf) { - int limit_type = to_sensor_dev_attr(attr)->index; + struct amdgpu_device *adev = dev_get_drvdata(dev); - return sysfs_emit(buf, "%s\n", - limit_type == PP_PWR_TYPE_FAST ? "fastPPT" : "slowPPT"); + if (adev->asic_type == CHIP_VANGOGH) + return sysfs_emit(buf, "%s\n", + to_sensor_dev_attr(attr)->index == PP_PWR_TYPE_FAST ? + "fastPPT" : "slowPPT"); + else + return sysfs_emit(buf, "PPT\n"); } static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, From 63b5fa9dbb711e245e59cc14eaae0106eb716447 Mon Sep 17 00:00:00 2001 From: Yang Wang Date: Wed, 9 Feb 2022 22:15:24 +0800 Subject: [PATCH 320/339] drm/amdgpu: fix gmc init fail in sriov mode "adev->gfx.rlc.rlcg_reg_access_supported = true;" the above varible were set too late during driver initialization. it will cause the driver to fail to write/read register during GMC hw init in sriov mode. move gfx_xxx_init_rlcg_reg_access_ctrl() function to gfx early init stage to avoid this issue. Fixes: 5d447e29670148 ("drm/amdgpu: add helper for rlcg indirect reg access") Signed-off-by: Yang Wang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index f54e106e2b86..3d8c5fea572e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4343,7 +4343,6 @@ static int gfx_v10_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.funcs->update_spm_vmid) adev->gfx.rlc.funcs->update_spm_vmid(adev, 0xf); - gfx_v10_0_init_rlcg_reg_access_ctrl(adev); return 0; } @@ -7682,6 +7681,9 @@ static int gfx_v10_0_early_init(void *handle) gfx_v10_0_set_gds_init(adev); gfx_v10_0_set_rlc_funcs(adev); + /* init rlcg reg access ctrl */ + gfx_v10_0_init_rlcg_reg_access_ctrl(adev); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index ca7b886c6ce6..744253be5142 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1934,9 +1934,6 @@ static int gfx_v9_0_rlc_init(struct amdgpu_device *adev) if (adev->gfx.rlc.funcs->update_spm_vmid) adev->gfx.rlc.funcs->update_spm_vmid(adev, 0xf); - /* init rlcg reg access ctrl */ - gfx_v9_0_init_rlcg_reg_access_ctrl(adev); - return 0; } @@ -4755,6 +4752,9 @@ static int gfx_v9_0_early_init(void *handle) gfx_v9_0_set_gds_init(adev); gfx_v9_0_set_rlc_funcs(adev); + /* init rlcg reg access ctrl */ + gfx_v9_0_init_rlcg_reg_access_ctrl(adev); + return 0; } From cc188a73addc8188d73ad11901b697acdc7fd0b0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 9 Feb 2022 11:54:04 +0800 Subject: [PATCH 321/339] drm/amd/pm: fix enabled features retrieving on Renoir and Cyan Skillfish For Cyan Skillfish and Renoir, there is no interface provided by PMFW to retrieve the enabled features. So, we assume all features are enabled. Fixes: 7ade3ca9cdb5 ("drm/amd/pm: correct the usage for 'supported' member of smu_feature structure") Signed-off-by: Evan Quan Tested-by: Nathan Chancellor Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 27 ++++++++++++++----- drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index 2b38a9154dd4..b3a0f3fb3e65 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -562,6 +562,7 @@ static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .fini_smc_tables = smu_v11_0_fini_smc_tables, .read_sensor = cyan_skillfish_read_sensor, .print_clk_levels = cyan_skillfish_print_clk_levels, + .get_enabled_mask = smu_cmn_get_enabled_mask, .is_dpm_running = cyan_skillfish_is_dpm_running, .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index efb553105df3..ea6c2dab5ecc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -500,7 +500,17 @@ int smu_cmn_feature_is_enabled(struct smu_context *smu, uint64_t enabled_features; int feature_id; - if (smu->is_apu && adev->family < AMDGPU_FAMILY_VGH) + if (smu_cmn_get_enabled_mask(smu, &enabled_features)) { + dev_err(adev->dev, "Failed to retrieve enabled ppfeatures!\n"); + return 0; + } + + /* + * For Renoir and Cyan Skillfish, they are assumed to have all features + * enabled. Also considering they have no feature_map available, the + * check here can avoid unwanted feature_map check below. + */ + if (enabled_features == ULLONG_MAX) return 1; feature_id = smu_cmn_to_asic_specific_index(smu, @@ -509,11 +519,6 @@ int smu_cmn_feature_is_enabled(struct smu_context *smu, if (feature_id < 0) return 0; - if (smu_cmn_get_enabled_mask(smu, &enabled_features)) { - dev_err(adev->dev, "Failed to retrieve enabled ppfeatures!\n"); - return 0; - } - return test_bit(feature_id, (unsigned long *)&enabled_features); } @@ -559,7 +564,7 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, feature_mask_high = &((uint32_t *)feature_mask)[1]; switch (adev->ip_versions[MP1_HWIP][0]) { - case IP_VERSION(11, 0, 8): + /* For Vangogh and Yellow Carp */ case IP_VERSION(11, 5, 0): case IP_VERSION(13, 0, 1): case IP_VERSION(13, 0, 3): @@ -575,8 +580,16 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu, 1, feature_mask_high); break; + /* + * For Cyan Skillfish and Renoir, there is no interface provided by PMFW + * to retrieve the enabled features. So, we assume all features are enabled. + * TODO: add other APU ASICs which suffer from the same issue here + */ + case IP_VERSION(11, 0, 8): case IP_VERSION(12, 0, 0): case IP_VERSION(12, 0, 1): + memset(feature_mask, 0xff, sizeof(*feature_mask)); + break; /* other dGPU ASICs */ default: ret = smu_cmn_send_smc_msg(smu, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 530be44e00ec..15bcf72b8e56 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -55,7 +55,7 @@ #define smu_send_smc_msg(smu, msg, read_arg) smu_ppt_funcs(send_smc_msg, 0, smu, msg, read_arg) #define smu_init_display_count(smu, count) smu_ppt_funcs(init_display_count, 0, smu, count) #define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) -#define smu_feature_get_enabled_mask(smu, mask) smu_ppt_funcs(get_enabled_mask, 0, smu, mask) +#define smu_feature_get_enabled_mask(smu, mask) smu_ppt_funcs(get_enabled_mask, -EOPNOTSUPP, smu, mask) #define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) #define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) From e5af61ffaaef0e952e248de895454cd339080035 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 9 Feb 2022 21:09:27 +0300 Subject: [PATCH 322/339] drm/amdkfd: CRIU fix a NULL vs IS_ERR() check The kfd_process_device_data_by_id() does not return error pointers, it returns NULL. Fixes: bef153b70c6e ("drm/amdkfd: CRIU implement gpu_id remapping") Signed-off-by: Dan Carpenter Reviewed-by: David Yat Sin Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 13e46631e289..8d998aac7b42 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2252,7 +2252,7 @@ static int criu_restore_bos(struct kfd_process *p, break; peer_pdd = kfd_process_device_data_by_id(p, bo_priv->mapped_gpuids[j]); - if (IS_ERR(peer_pdd)) { + if (!peer_pdd) { ret = -EINVAL; goto exit; } From 5aa71bd773c390891974b1bcbdb3b12aa17c781d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 9 Feb 2022 21:09:59 +0300 Subject: [PATCH 323/339] drm/amdkfd: CRIU return -EFAULT for copy_to_user() failure If copy_to_user() fails, it returns the number of bytes remaining to be copied but we want to return a negative error code (-EFAULT) to the user. Fixes: 9d5dabfeff3c ("drm/amdkfd: CRIU Save Shared Virtual Memory ranges") Signed-off-by: Dan Carpenter Reviewed-by: David Yat Sin Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index e13ea9797527..783826640da9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3771,10 +3771,10 @@ int kfd_criu_checkpoint_svm(struct kfd_process *p, goto exit_priv; } - ret = copy_to_user(user_priv_data + *priv_data_offset, - svm_priv, svm_priv_data_size); - if (ret) { + if (copy_to_user(user_priv_data + *priv_data_offset, svm_priv, + svm_priv_data_size)) { pr_err("Failed to copy svm priv to user\n"); + ret = -EFAULT; goto exit_priv; } From 574ff46f10102f65c40d24729197033a80458238 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Wed, 9 Feb 2022 06:52:54 -0800 Subject: [PATCH 324/339] drm/amdkfd: fix freeing an unset pointer clang static analysis reports this problem kfd_chardev.c:2092:2: warning: 1st function call argument is an uninitialized value kvfree(bo_privs); ^~~~~~~~~~~~~~~~ When bo_buckets alloc fails, it jumps to an error handler that frees the yet to be allocated bo_privs. Because bo_buckets is the first error, return directly. Fixes: 5ccbb057c0a1 ("drm/amdkfd: CRIU Implement KFD checkpoint ioctl") Signed-off-by: Tom Rix Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 8d998aac7b42..6ad87fb98bcd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1708,10 +1708,8 @@ static int criu_checkpoint_bos(struct kfd_process *p, void *mem; bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), GFP_KERNEL); - if (!bo_buckets) { - ret = -ENOMEM; - goto exit; - } + if (!bo_buckets) + return -ENOMEM; bo_privs = kvzalloc(num_bos * sizeof(*bo_privs), GFP_KERNEL); if (!bo_privs) { From fd22013a098baca78679656d55f8fd0becb99a8d Mon Sep 17 00:00:00 2001 From: Oliver Logush Date: Wed, 9 Feb 2022 14:25:13 -0500 Subject: [PATCH 325/339] drm/amd/display: extend dcn201 support Signed-off-by: Oliver Logush Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b36bae4b5bc9..71b393194c55 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -135,7 +135,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) case FAMILY_NV: dc_version = DCN_VERSION_2_0; - if (asic_id.chip_id == DEVICE_ID_NV_13FE) { + if (asic_id.chip_id == DEVICE_ID_NV_13FE || asic_id.chip_id == DEVICE_ID_NV_143F) { dc_version = DCN_VERSION_2_01; break; } diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index e4a2dfacab4c..e672be6327cb 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -212,6 +212,7 @@ enum { #define ASICREV_IS_GREEN_SARDINE(eChipRev) ((eChipRev >= GREEN_SARDINE_A0) && (eChipRev < 0xFF)) #endif #define DEVICE_ID_NV_13FE 0x13FE // CYAN_SKILLFISH +#define DEVICE_ID_NV_143F 0x143F #define FAMILY_VGH 144 #define DEVICE_ID_VGH_163F 0x163F #define VANGOGH_A0 0x01 From d8a25e48585773afc573e835a52f9cbf409215bc Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 10 Feb 2022 09:04:18 -0800 Subject: [PATCH 326/339] drm/amdkfd: fix loop error handling Clang static analysis reports this problem kfd_chardev.c:2594:16: warning: The expression is an uninitialized value. The computed value will also be garbage while (ret && i--) { ^~~ i is a loop variable and this block unwinds a problem in the loop. When the error happens before the loop, this value is garbage. Move the initialization of i to its decalaration. Fixes: be072b06c739 ("drm/amdkfd: CRIU export BOs as prime dmabuf objects") Signed-off-by: Tom Rix Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 6ad87fb98bcd..d5699aa79578 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -2100,7 +2100,7 @@ static int criu_restore_bos(struct kfd_process *p, const bool criu_resume = true; bool flush_tlbs = false; int ret = 0, j = 0; - uint32_t i; + uint32_t i = 0; if (*priv_offset + (args->num_bos * sizeof(*bo_privs)) > max_priv_data_size) return -EINVAL; @@ -2136,7 +2136,7 @@ static int criu_restore_bos(struct kfd_process *p, *priv_offset += args->num_bos * sizeof(*bo_privs); /* Create and map new BOs */ - for (i = 0; i < args->num_bos; i++) { + for (; i < args->num_bos; i++) { struct kfd_criu_bo_bucket *bo_bucket; struct kfd_criu_bo_priv_data *bo_priv; struct kfd_dev *dev; From f9ed188d5a08cfacb945b21976764f57c0ea9ebd Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Wed, 9 Feb 2022 14:47:44 +0800 Subject: [PATCH 327/339] drm/amdgpu: add support for GC 10.1.4 Add basic support for GC 10.1.4, it uses same IP blocks with GC 10.1.3 Signed-off-by: Lang Yu Reviewed-by: Huang Rui Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/nv.c | 1 + drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 3 ++- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 1 + drivers/gpu/drm/amd/amdkfd/kfd_device.c | 2 ++ 8 files changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index eb4b7059633d..cd7e8522c130 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -674,6 +674,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 2): @@ -709,6 +710,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 2): @@ -910,6 +912,7 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 2): case IP_VERSION(10, 3, 1): @@ -1044,6 +1047,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 2): @@ -1243,6 +1247,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 2): case IP_VERSION(10, 3, 4): @@ -1264,6 +1269,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(9, 2, 2): case IP_VERSION(9, 3, 0): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 3): adev->flags |= AMD_IS_APU; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index f2806959736a..9bc9155cbf06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -137,7 +137,8 @@ static int psp_early_init(void *handle) psp->autoload_supported = true; break; case IP_VERSION(11, 0, 8): - if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) { + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2 || + adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4)) { psp_v11_0_8_set_psp_funcs(psp); psp->autoload_supported = false; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 3d8c5fea572e..8fb4528c741f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3641,6 +3641,7 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) (const u32)ARRAY_SIZE(golden_settings_gc_10_3_5)); break; case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): soc15_program_register_sequence(adev, golden_settings_gc_10_0_cyan_skillfish, (const u32)ARRAY_SIZE(golden_settings_gc_10_0_cyan_skillfish)); @@ -3819,6 +3820,7 @@ static void gfx_v10_0_check_fw_write_wait(struct amdgpu_device *adev) case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): if ((adev->gfx.me_fw_version >= 0x00000046) && (adev->gfx.me_feature_version >= 27) && (adev->gfx.pfp_fw_version >= 0x00000068) && @@ -3959,6 +3961,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) else chip_name = "cyan_skillfish"; break; + case IP_VERSION(10, 1, 4): + chip_name = "cyan_skillfish2"; + break; default: BUG(); } @@ -4565,6 +4570,7 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev) 1 << REG_GET_FIELD(gb_addr_config, GB_ADDR_CONFIG, NUM_PKRS); break; case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): adev->gfx.config.max_hw_contexts = 8; adev->gfx.config.sc_prim_fifo_size_frontend = 0x20; adev->gfx.config.sc_prim_fifo_size_backend = 0x100; @@ -4677,6 +4683,7 @@ static int gfx_v10_0_sw_init(void *handle) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): adev->gfx.me.num_me = 1; adev->gfx.me.num_pipe_per_me = 1; adev->gfx.me.num_queue_per_pipe = 1; @@ -7658,6 +7665,7 @@ static int gfx_v10_0_early_init(void *handle) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): adev->gfx.num_gfx_rings = GFX10_NUM_GFX_RINGS_NV1X; break; case IP_VERSION(10, 3, 0): @@ -9418,6 +9426,7 @@ static void gfx_v10_0_set_rlc_funcs(struct amdgpu_device *adev) case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 2): case IP_VERSION(10, 3, 1): case IP_VERSION(10, 3, 4): diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index bddaf2417344..c64e3a391c99 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -881,6 +881,7 @@ static int gmc_v10_0_sw_init(void *handle) case IP_VERSION(10, 1, 1): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 3, 0): case IP_VERSION(10, 3, 2): case IP_VERSION(10, 3, 1): @@ -1156,7 +1157,8 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3)) + if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 3) || + adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4)) return; adev->mmhub.funcs->get_clockgating(adev, flags); diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index f76834085b34..5e9ab31fee6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -902,6 +902,7 @@ static int nv_common_early_init(void *handle) adev->external_rev_id = adev->rev_id + 0x01; break; case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): adev->cg_flags = 0; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x82; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index 81e033549dda..45e10d5028c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -264,7 +264,8 @@ static int sdma_v5_0_init_microcode(struct amdgpu_device *adev) chip_name = "navi12"; break; case IP_VERSION(5, 0, 1): - if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) + if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2 || + adev->ip_versions[GC_HWIP][0] == IP_VERSION(10, 1, 4)) chip_name = "cyan_skillfish2"; else chip_name = "cyan_skillfish"; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 9624bbe8b501..bb6e49661d13 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -1411,6 +1411,7 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, case IP_VERSION(10, 1, 10): case IP_VERSION(10, 1, 2): case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): pcache_info = navi10_cache_info; num_of_cache_types = ARRAY_SIZE(navi10_cache_info); break; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index dbb877fba724..7f1746289989 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -110,6 +110,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd) case IP_VERSION(10, 3, 1): /* VANGOGH */ case IP_VERSION(10, 3, 3): /* YELLOW_CARP */ case IP_VERSION(10, 1, 3): /* CYAN_SKILLFISH */ + case IP_VERSION(10, 1, 4): case IP_VERSION(10, 1, 10): /* NAVI10 */ case IP_VERSION(10, 1, 2): /* NAVI12 */ case IP_VERSION(10, 1, 1): /* NAVI14 */ @@ -307,6 +308,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) break; /* Cyan Skillfish */ case IP_VERSION(10, 1, 3): + case IP_VERSION(10, 1, 4): gfx_target_version = 100103; if (!vf) f2g = &gfx_v10_kfd2kgd; From 69f915cc97c4bb82b34105a47abf613f7c87215d Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Thu, 10 Feb 2022 15:46:12 +0800 Subject: [PATCH 328/339] drm/amdgpu: loose check for umc poison mode No need to check poison setting for each channel, check for umc0 channel0 is enough. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index 47452b61b615..e613511e07e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -451,21 +451,13 @@ static uint32_t umc_v6_7_query_ras_poison_mode_per_channel( static bool umc_v6_7_query_ras_poison_mode(struct amdgpu_device *adev) { - uint32_t umc_inst = 0; - uint32_t ch_inst = 0; uint32_t umc_reg_offset = 0; - LOOP_UMC_INST_AND_CH(umc_inst, ch_inst) { - umc_reg_offset = get_umc_v6_7_reg_offset(adev, - umc_inst, - ch_inst); - /* Enabling fatal error in one channel will be considered - as fatal error mode */ - if (umc_v6_7_query_ras_poison_mode_per_channel(adev, umc_reg_offset)) - return false; - } - - return true; + /* Enabling fatal error in umc instance0 channel0 will be + * considered as fatal error mode + */ + umc_reg_offset = get_umc_v6_7_reg_offset(adev, 0, 0); + return !umc_v6_7_query_ras_poison_mode_per_channel(adev, umc_reg_offset); } const struct amdgpu_ras_block_hw_ops umc_v6_7_ras_hw_ops = { From b06b48d7ddae440f3393e5c1ddda4d2537b3a7cc Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Tue, 25 Jan 2022 18:34:52 -0500 Subject: [PATCH 329/339] amdgpu/pm: Implement emit_clk_levels for navi10 (v4) Modifications to satisfy checkpatch --strict (v3) Rewrote patchset to order patches as (API, hw impl, usecase) - implement emit_clk_levels for navi10, based on print_clk_levels, but using sysfs_emit without smu_cmn_get_sysfs() workaround Signed-off-by: Darren Powell Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index f55ead5f9aba..f2a00e603467 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1236,6 +1236,215 @@ static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_tabl *max = od_table->max[setting]; } +static int navi10_emit_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + char *buf, + int *offset) +{ + uint16_t *curve_settings; + int ret = 0; + uint32_t cur_value = 0, value = 0; + uint32_t freq_values[3] = {0}; + uint32_t i, levels, mark_index = 0, count = 0; + struct smu_table_context *table_context = &smu->smu_table; + uint32_t gen_speed, lane_width; + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; + PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; + OverDriveTable_t *od_table = + (OverDriveTable_t *)table_context->overdrive_table; + struct smu_11_0_overdrive_table *od_settings = smu->od_settings; + uint32_t min_value, max_value; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_SOCCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_FCLK: + case SMU_VCLK: + case SMU_DCLK: + case SMU_DCEFCLK: + ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value); + if (ret) + return ret; + + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); + if (ret) + return ret; + + if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) { + for (i = 0; i < count; i++) { + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, i, &value); + if (ret) + return ret; + + *offset += sysfs_emit_at(buf, *offset, + "%d: %uMhz %s\n", + i, value, + cur_value == value ? "*" : ""); + } + } else { + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, 0, &freq_values[0]); + if (ret) + return ret; + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + count - 1, + &freq_values[2]); + if (ret) + return ret; + + freq_values[1] = cur_value; + mark_index = cur_value == freq_values[0] ? 0 : + cur_value == freq_values[2] ? 2 : 1; + + levels = 3; + if (mark_index != 1) { + levels = 2; + freq_values[1] = freq_values[2]; + } + + for (i = 0; i < levels; i++) { + *offset += sysfs_emit_at(buf, *offset, + "%d: %uMhz %s\n", + i, freq_values[i], + i == mark_index ? "*" : ""); + } + } + break; + case SMU_PCIE: + gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu); + lane_width = smu_v11_0_get_current_pcie_link_width_level(smu); + for (i = 0; i < NUM_LINK_LEVELS; i++) { + *offset += sysfs_emit_at(buf, *offset, "%d: %s %s %dMhz %s\n", i, + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "", + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "", + pptable->LclkFreq[i], + (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) && + (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ? + "*" : ""); + } + break; + case SMU_OD_SCLK: + if (!smu->od_enabled || !od_table || !od_settings) + return -EOPNOTSUPP; + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) + break; + *offset += sysfs_emit_at(buf, *offset, "OD_SCLK:\n0: %uMhz\n1: %uMhz\n", + od_table->GfxclkFmin, od_table->GfxclkFmax); + break; + case SMU_OD_MCLK: + if (!smu->od_enabled || !od_table || !od_settings) + return -EOPNOTSUPP; + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) + break; + *offset += sysfs_emit_at(buf, *offset, "OD_MCLK:\n1: %uMHz\n", od_table->UclkFmax); + break; + case SMU_OD_VDDC_CURVE: + if (!smu->od_enabled || !od_table || !od_settings) + return -EOPNOTSUPP; + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) + break; + *offset += sysfs_emit_at(buf, *offset, "OD_VDDC_CURVE:\n"); + for (i = 0; i < 3; i++) { + switch (i) { + case 0: + curve_settings = &od_table->GfxclkFreq1; + break; + case 1: + curve_settings = &od_table->GfxclkFreq2; + break; + case 2: + curve_settings = &od_table->GfxclkFreq3; + break; + default: + break; + } + *offset += sysfs_emit_at(buf, *offset, "%d: %uMHz %umV\n", + i, curve_settings[0], + curve_settings[1] / NAVI10_VOLTAGE_SCALE); + } + break; + case SMU_OD_RANGE: + if (!smu->od_enabled || !od_table || !od_settings) + return -EOPNOTSUPP; + *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_RANGE"); + + if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, + &min_value, NULL); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX, + NULL, &max_value); + *offset += sysfs_emit_at(buf, *offset, "SCLK: %7uMhz %10uMhz\n", + min_value, max_value); + } + + if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) { + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, "MCLK: %7uMhz %10uMhz\n", + min_value, max_value); + } + + if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) { + navi10_od_setting_get_range(od_settings, + SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, + "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, + SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, + "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, + SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, + "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, + SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, + "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, + SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, + "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, + SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3, + &min_value, &max_value); + *offset += sysfs_emit_at(buf, *offset, + "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", + min_value, max_value); + } + + break; + default: + break; + } + + return 0; +} + static int navi10_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { @@ -3220,6 +3429,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .i2c_init = navi10_i2c_control_init, .i2c_fini = navi10_i2c_control_fini, .print_clk_levels = navi10_print_clk_levels, + .emit_clk_levels = navi10_emit_clk_levels, .force_clk_levels = navi10_force_clk_levels, .populate_umd_state_clk = navi10_populate_umd_state_clk, .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency, From c8cb19c7b26d78434ec563088d5d377ec2caf616 Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Tue, 25 Jan 2022 18:57:56 -0500 Subject: [PATCH 330/339] amdgpu/pm: Add emit_clock_levels calls (v4) Modifications to satisfy checkpatch --strict (v3) Rewrote patchset to order patches as (API, hw impl, usecase) - modified amdgpu_get_pp_od_clk_voltage to try amdgpu_dpm_emit_clock_levels and fallback to amdgpu_dpm_print_clock_levels if emit is not implemented. - modified amdgpu_get_pp_dpm_clock to try amdgpu_dpm_emit_clock_levels and fallback to amdgpu_dpm_print_clock_levels if emit is not implemented. - Newline is printed to buf if no output produced == Test == LOGFILE=pp_clk.test.log AMDGPU_PCI_ADDR=`lspci -nn | grep "VGA\|Display" | cut -d " " -f 1` AMDGPU_HWMON=`ls -la /sys/class/hwmon | grep $AMDGPU_PCI_ADDR | awk '{print $9}'` HWMON_DIR=/sys/class/hwmon/${AMDGPU_HWMON} lspci -nn | grep "VGA\|Display" > $LOGFILE FILES="pp_od_clk_voltage pp_dpm_sclk pp_dpm_mclk pp_dpm_pcie pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_vclk pp_dpm_dclk " for f in $FILES do echo === $f === >> $LOGFILE cat $HWMON_DIR/device/$f >> $LOGFILE done cat $LOGFILE Signed-off-by: Darren Powell Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 49 +++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index ad5da252228b..b0243068212b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -837,8 +837,17 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - ssize_t size; + int size = 0; int ret; + enum pp_clock_type od_clocks[6] = { + OD_SCLK, + OD_MCLK, + OD_VDDC_CURVE, + OD_RANGE, + OD_VDDGFX_OFFSET, + OD_CCLK, + }; + uint clk_index; if (amdgpu_in_reset(adev)) return -EPERM; @@ -851,16 +860,25 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, return ret; } - size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); - if (size > 0) { - size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf+size); - } else { - size = sysfs_emit(buf, "\n"); + for (clk_index = 0 ; clk_index < 6 ; clk_index++) { + ret = amdgpu_dpm_emit_clock_levels(adev, od_clocks[clk_index], buf, &size); + if (ret) + break; } + if (ret == -ENOENT) { + size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + if (size > 0) { + size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size); + } + } + + if (size == 0) + size = sysfs_emit(buf, "\n"); + pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -985,8 +1003,8 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = drm_to_adev(ddev); - ssize_t size; - int ret; + int size = 0; + int ret = 0; if (amdgpu_in_reset(adev)) return -EPERM; @@ -999,8 +1017,11 @@ static ssize_t amdgpu_get_pp_dpm_clock(struct device *dev, return ret; } - size = amdgpu_dpm_print_clock_levels(adev, type, buf); - if (size <= 0) + ret = amdgpu_dpm_emit_clock_levels(adev, type, buf, &size); + if (ret == -ENOENT) + size = amdgpu_dpm_print_clock_levels(adev, type, buf); + + if (size == 0) size = sysfs_emit(buf, "\n"); pm_runtime_mark_last_busy(ddev->dev); From 60aac460ed97852f620529f43fd58dd05e41644b Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 18 Jan 2022 14:07:51 +0800 Subject: [PATCH 331/339] drm/amd/pm: correct UMD pstate clocks for Dimgrey Cavefish and Beige Goby Correct the UMD pstate profiling clocks for Dimgrey Cavefish and Beige Goby. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 26 +++++++++++++++---- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.h | 8 ++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 2a7da2bad96a..762b63365c36 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1231,21 +1231,37 @@ static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu) &dpm_context->dpm_tables.soc_table; struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; + struct amdgpu_device *adev = smu->adev; pstate_table->gfxclk_pstate.min = gfx_table->min; pstate_table->gfxclk_pstate.peak = gfx_table->max; - if (gfx_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK) - pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK; pstate_table->uclk_pstate.min = mem_table->min; pstate_table->uclk_pstate.peak = mem_table->max; - if (mem_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK) - pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK; pstate_table->socclk_pstate.min = soc_table->min; pstate_table->socclk_pstate.peak = soc_table->max; - if (soc_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK) + + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK; + pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK; pstate_table->socclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK; + break; + case CHIP_DIMGREY_CAVEFISH: + pstate_table->gfxclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_GFXCLK; + pstate_table->uclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_MEMCLK; + pstate_table->socclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_SOCCLK; + break; + case CHIP_BEIGE_GOBY: + pstate_table->gfxclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_GFXCLK; + pstate_table->uclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_MEMCLK; + pstate_table->socclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_SOCCLK; + break; + default: + break; + } return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h index 38cd0ece24f6..42f705c7a36f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h @@ -33,6 +33,14 @@ typedef enum { #define SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK 960 #define SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK 1000 +#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_GFXCLK 1950 +#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_SOCCLK 960 +#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_MEMCLK 676 + +#define BEIGE_GOBY_UMD_PSTATE_PROFILING_GFXCLK 2200 +#define BEIGE_GOBY_UMD_PSTATE_PROFILING_SOCCLK 960 +#define BEIGE_GOBY_UMD_PSTATE_PROFILING_MEMCLK 1000 + extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu); #endif From 816d61d51a31bd16d0fec75526462dc987f09114 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 18 Jan 2022 15:58:51 +0800 Subject: [PATCH 332/339] drm/amd/pm: fulfill the support for DriverSmuConfig table Enable the support for DriverSmuConfig table on Navi1x and Sienna_Cichlid. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 9 +++++++++ .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 13 ++++++++++++- drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index 218de8f8ec30..17594ceb507e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -337,6 +337,7 @@ struct smu_table_context struct smu_bios_boot_up_values boot_values; void *driver_pptable; void *ecc_table; + void *driver_smu_config_table; struct smu_table tables[SMU_TABLE_COUNT]; /* * The driver table is just a staging buffer for diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index f2a00e603467..66f9276c4499 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -510,6 +510,8 @@ static int navi10_tables_init(struct smu_context *smu) SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_DRIVER_SMU_CONFIG, sizeof(DriverSmuConfig_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_NV1X_t), GFP_KERNEL); @@ -526,8 +528,15 @@ static int navi10_tables_init(struct smu_context *smu) if (!smu_table->watermarks_table) goto err2_out; + smu_table->driver_smu_config_table = + kzalloc(tables[SMU_TABLE_DRIVER_SMU_CONFIG].size, GFP_KERNEL); + if (!smu_table->driver_smu_config_table) + goto err3_out; + return 0; +err3_out: + kfree(smu_table->watermarks_table); err2_out: kfree(smu_table->gpu_metrics_table); err1_out: diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 762b63365c36..358031c8c79e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -475,6 +475,8 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_DRIVER_SMU_CONFIG, sizeof(DriverSmuConfigExternal_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); if (!smu_table->metrics_table) @@ -492,10 +494,19 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); if (!smu_table->ecc_table) - return -ENOMEM; + goto err3_out; + + smu_table->driver_smu_config_table = + kzalloc(tables[SMU_TABLE_DRIVER_SMU_CONFIG].size, GFP_KERNEL); + if (!smu_table->driver_smu_config_table) + goto err4_out; return 0; +err4_out: + kfree(smu_table->ecc_table); +err3_out: + kfree(smu_table->watermarks_table); err2_out: kfree(smu_table->gpu_metrics_table); err1_out: diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index d71155a66f97..b87f550af26b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -473,9 +473,11 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu) kfree(smu_table->hardcode_pptable); smu_table->hardcode_pptable = NULL; + kfree(smu_table->driver_smu_config_table); kfree(smu_table->ecc_table); kfree(smu_table->metrics_table); kfree(smu_table->watermarks_table); + smu_table->driver_smu_config_table = NULL; smu_table->ecc_table = NULL; smu_table->metrics_table = NULL; smu_table->watermarks_table = NULL; From 8bbd4d83a68beaf54ae01b2e2aa2024ff1dfc0ba Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Fri, 11 Feb 2022 10:34:04 +0800 Subject: [PATCH 333/339] drm/amdgpu: Reset OOB table error count info The OOB table error count info should be reset after reset eeprom table Signed-off-by: Stanley.Yang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index c09d047272b2..2b844a5aafdb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -263,6 +263,7 @@ static int amdgpu_ras_eeprom_correct_header_tag( */ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) { + struct amdgpu_device *adev = to_amdgpu_device(control); struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; u8 csum; int res; @@ -282,6 +283,8 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) control->ras_num_recs = 0; control->ras_fri = 0; + amdgpu_dpm_send_hbm_bad_pages_num(adev, control->ras_num_recs); + amdgpu_ras_debugfs_set_ret_size(control); mutex_unlock(&control->ras_tbl_mutex); From 461fa7b0ac565ef25c1da0ced31005dd437883a7 Mon Sep 17 00:00:00 2001 From: Ken Xue Date: Fri, 11 Feb 2022 16:18:46 -0500 Subject: [PATCH 334/339] drm/amdgpu: remove ctx->lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KMD reports a warning on holding a lock from drm_syncobj_find_fence, when running amdgpu_test case “syncobj timeline test”. ctx->lock was designed to prevent concurrent "amdgpu_ctx_wait_prev_fence" calls and avoid dead reservation lock from GPU reset. since no reservation lock is held in latest GPU reset any more, ctx->lock can be simply removed and concurrent "amdgpu_ctx_wait_prev_fence" call also can be prevented by PD root bo reservation lock. call stacks: ================= //hold lock amdgpu_cs_ioctl->amdgpu_cs_parser_init->mutex_lock(&parser->ctx->lock); … //report warning amdgpu_cs_dependencies->amdgpu_cs_process_syncobj_timeline_in_dep \ ->amdgpu_syncobj_lookup_and_add_to_sync -> drm_syncobj_find_fence \ -> lockdep_assert_none_held_once … amdgpu_cs_ioctl->amdgpu_cs_parser_fini->mutex_unlock(&parser->ctx->lock); Signed-off-by: Ken Xue Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 +++++++++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h | 1 - 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a34be65c9eaa..af12256e1bd3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -127,8 +127,6 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs goto free_chunk; } - mutex_lock(&p->ctx->lock); - /* skip guilty context job */ if (atomic_read(&p->ctx->guilty) == 1) { ret = -ECANCELED; @@ -585,6 +583,16 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p, } } + /* Move fence waiting after getting reservation lock of + * PD root. Then there is no need on a ctx mutex lock. + */ + r = amdgpu_ctx_wait_prev_fence(p->ctx, p->entity); + if (unlikely(r != 0)) { + if (r != -ERESTARTSYS) + DRM_ERROR("amdgpu_ctx_wait_prev_fence failed.\n"); + goto error_validate; + } + amdgpu_cs_get_threshold_for_moves(p->adev, &p->bytes_moved_threshold, &p->bytes_moved_vis_threshold); p->bytes_moved = 0; @@ -700,7 +708,6 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, dma_fence_put(parser->fence); if (parser->ctx) { - mutex_unlock(&parser->ctx->lock); amdgpu_ctx_put(parser->ctx); } if (parser->bo_list) @@ -944,7 +951,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, if (parser->job->uf_addr && ring->funcs->no_user_fence) return -EINVAL; - return amdgpu_ctx_wait_prev_fence(parser->ctx, parser->entity); + return 0; } static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p, @@ -1363,7 +1370,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) goto out; r = amdgpu_cs_submit(&parser, cs); - out: amdgpu_cs_parser_fini(&parser, r, reserved_buffers); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 2c929fa40379..1c72f6095f08 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -230,7 +230,6 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, kref_init(&ctx->refcount); spin_lock_init(&ctx->ring_lock); - mutex_init(&ctx->lock); ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); ctx->reset_counter_query = ctx->reset_counter; @@ -352,7 +351,6 @@ static void amdgpu_ctx_fini(struct kref *ref) } } amdgpu_ctx_set_stable_pstate(ctx, AMDGPU_CTX_STABLE_PSTATE_NONE); - mutex_destroy(&ctx->lock); kfree(ctx); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h index 142f2f87d44c..d0cbfcea90f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h @@ -49,7 +49,6 @@ struct amdgpu_ctx { bool preamble_presented; int32_t init_priority; int32_t override_priority; - struct mutex lock; atomic_t guilty; unsigned long ras_counter_ce; unsigned long ras_counter_ue; From f3986e86b2d861a2ed2d336bafe53b5c404cb995 Mon Sep 17 00:00:00 2001 From: Rajib Mahapatra Date: Thu, 10 Feb 2022 18:46:40 +0530 Subject: [PATCH 335/339] drm/amdgpu: skipping SDMA hw_init and hw_fini for S0ix. [Why] SDMA ring buffer test failed if suspend is aborted during S0i3 resume. [How] If suspend is aborted for some reason during S0i3 resume cycle, it follows SDMA ring test failing and errors in amdgpu resume. For RN/CZN/Picasso, SMU saves and restores SDMA registers during S0ix cycle. So, skipping SDMA suspend and resume from driver solves the issue. This time, the system is able to resume gracefully even the suspend is aborted. Reviewed-by: Mario Limonciello Reviewed-by: Alex Deucher Signed-off-by: Rajib Mahapatra Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 06a7ceda4c87..02115d63b071 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2058,6 +2058,10 @@ static int sdma_v4_0_suspend(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* SMU saves SDMA state for us */ + if (adev->in_s0ix) + return 0; + return sdma_v4_0_hw_fini(adev); } @@ -2065,6 +2069,10 @@ static int sdma_v4_0_resume(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* SMU restores SDMA state for us */ + if (adev->in_s0ix) + return 0; + return sdma_v4_0_hw_init(adev); } From 1915a433954262ac7466469d1a4684ac54218af4 Mon Sep 17 00:00:00 2001 From: "Stanley.Yang" Date: Fri, 11 Feb 2022 17:35:18 +0800 Subject: [PATCH 336/339] drm/amdgpu: adjust register address calculation the UMC_STATUS register is not linear, adjust offset calculation formula to get correct address Signed-off-by: Stanley.Yang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/umc_v6_7.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c index e613511e07e1..87e4ef18e151 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c @@ -47,6 +47,13 @@ static inline uint32_t get_umc_v6_7_reg_offset(struct amdgpu_device *adev, uint32_t umc_inst, uint32_t ch_inst) { + uint32_t index = umc_inst * adev->umc.channel_inst_num + ch_inst; + + /* adjust umc and channel index offset, + * the register address is not linear on each umc instace */ + umc_inst = index / 4; + ch_inst = index % 4; + return adev->umc.channel_offs * ch_inst + UMC_V6_7_INST_DIST * umc_inst; } From b010a46bd3abb161409afe147a73fe58c115858d Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Thu, 10 Feb 2022 17:09:53 -0500 Subject: [PATCH 337/339] drm/amdkfd: CRIU fix extra whitespace and block comment warnings Fix checkpatch reported warning for a quoted line and block line comments. Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 783826640da9..b71d47afd243 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3514,7 +3514,7 @@ int kfd_criu_resume_svm(struct kfd_process *p) i, criu_svm_md->data.start_addr, criu_svm_md->data.size); for (j = 0; j < num_attrs; j++) { - pr_debug("\ncriu_svm_md[%d]->attrs[%d].type : 0x%x \ncriu_svm_md[%d]->attrs[%d].value : 0x%x\n", + pr_debug("\ncriu_svm_md[%d]->attrs[%d].type : 0x%x\ncriu_svm_md[%d]->attrs[%d].value : 0x%x\n", i, j, criu_svm_md->data.attrs[j].type, i, j, criu_svm_md->data.attrs[j].value); switch (criu_svm_md->data.attrs[j].type) { @@ -3601,7 +3601,8 @@ int kfd_criu_restore_svm(struct kfd_process *p, num_devices = p->n_pdds; /* Handle one SVM range object at a time, also the number of gpus are * assumed to be same on the restore node, checking must be done while - * evaluating the topology earlier */ + * evaluating the topology earlier + */ svm_attrs_size = sizeof(struct kfd_ioctl_svm_attribute) * (nattr_common + nattr_accessibility * num_devices); From 24992ab0b8b0d2521caa9c3dcbed0e2a56cbe3d0 Mon Sep 17 00:00:00 2001 From: Rajneesh Bhardwaj Date: Thu, 10 Feb 2022 17:20:45 -0500 Subject: [PATCH 338/339] drm/amdkfd: Fix prototype warning for get_process_num_bos Fix the warning: no previous prototype for 'get_process_num_bos' [-Wmissing-prototypes] Reported-by: kernel test robot Reviewed-by: Felix Kuehling Signed-off-by: Rajneesh Bhardwaj Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index d5699aa79578..54d997f304b5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1648,7 +1648,7 @@ exit: return ret; } -uint32_t get_process_num_bos(struct kfd_process *p) +static uint32_t get_process_num_bos(struct kfd_process *p) { uint32_t num_of_bos = 0; int i; From 7f161df1a513e2961f4e3c96a8355c8ce93ad175 Mon Sep 17 00:00:00 2001 From: Alex Sierra Date: Wed, 9 Feb 2022 10:54:53 -0600 Subject: [PATCH 339/339] drm/amdkfd: replace err by dbg print at svm vram migration Avoid spam the kernel log on application memory allocation failures. __func__ argument was also removed from dev_fmt macro due to parameter conflicts with dynamic_dev_dbg. Signed-off-by: Alex Sierra Reviewed-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index d986f9ee0e1f..7dcafd337bb2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -36,7 +36,7 @@ #ifdef dev_fmt #undef dev_fmt #endif -#define dev_fmt(fmt) "kfd_migrate: %s: " fmt, __func__ +#define dev_fmt(fmt) "kfd_migrate: " fmt static uint64_t svm_migrate_direct_mapping_addr(struct amdgpu_device *adev, uint64_t addr) @@ -312,7 +312,7 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, r = svm_range_vram_node_new(adev, prange, true); if (r) { - dev_err(adev->dev, "fail %d to alloc vram\n", r); + dev_dbg(adev->dev, "fail %d to alloc vram\n", r); goto out; } @@ -331,7 +331,8 @@ svm_migrate_copy_to_vram(struct amdgpu_device *adev, struct svm_range *prange, DMA_TO_DEVICE); r = dma_mapping_error(dev, src[i]); if (r) { - dev_err(adev->dev, "fail %d dma_map_page\n", r); + dev_err(adev->dev, "%s: fail %d dma_map_page\n", + __func__, r); goto out_free_vram_pages; } } else { @@ -432,8 +433,8 @@ svm_migrate_vma_to_vram(struct amdgpu_device *adev, struct svm_range *prange, r = migrate_vma_setup(&migrate); if (r) { - dev_err(adev->dev, "vma setup fail %d range [0x%lx 0x%lx]\n", r, - prange->start, prange->last); + dev_err(adev->dev, "%s: vma setup fail %d range [0x%lx 0x%lx]\n", + __func__, r, prange->start, prange->last); goto out_free; } @@ -611,7 +612,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange, dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_FROM_DEVICE); r = dma_mapping_error(dev, dst[i]); if (r) { - dev_err(adev->dev, "fail %d dma_map_page\n", r); + dev_err(adev->dev, "%s: fail %d dma_map_page\n", __func__, r); goto out_oom; } @@ -671,8 +672,8 @@ svm_migrate_vma_to_ram(struct amdgpu_device *adev, struct svm_range *prange, r = migrate_vma_setup(&migrate); if (r) { - dev_err(adev->dev, "vma setup fail %d range [0x%lx 0x%lx]\n", r, - prange->start, prange->last); + dev_err(adev->dev, "%s: vma setup fail %d range [0x%lx 0x%lx]\n", + __func__, r, prange->start, prange->last); goto out_free; }