From: Jared Baldridge jrb@expunge.us
[ Upstream commit 81ad7f9f78e4ff80e95be8282423f511b84f1166 ]
The OneGX1 Pro has a fairly unique combination of generic strings, but we additionally match on the BIOS date just to be safe.
Signed-off-by: Jared Baldridge jrb@expunge.us Reviewed-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Hans de Goede hdegoede@redhat.com Link: https://patchwork.freedesktop.org/patch/msgid/41288ccb-1012-486b-81c1-a24c31... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/drm_panel_orientation_quirks.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 58f5dc2f6dd5..f6bdec7fa925 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -84,6 +84,13 @@ static const struct drm_dmi_panel_orientation_data itworks_tw891 = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, };
+static const struct drm_dmi_panel_orientation_data onegx1_pro = { + .width = 1200, + .height = 1920, + .bios_dates = (const char * const []){ "12/17/2020", NULL }, + .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, +}; + static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = { .width = 720, .height = 1280, @@ -211,6 +218,13 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"), }, .driver_data = (void *)&lcd1200x1920_rightside_up, + }, { /* OneGX1 Pro */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SYSTEM_PRODUCT_NAME"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"), + }, + .driver_data = (void *)&onegx1_pro, }, { /* VIOS LTH17 */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
From: Tong Zhang ztong0001@gmail.com
[ Upstream commit b91907a6241193465ca92e357adf16822242296d ]
if qxl_device_init() fail, drm device will not be registered, in this case, do not run qxl_drm_release()
[ 5.258534] ================================================================== [ 5.258931] BUG: KASAN: user-memory-access in qxl_destroy_monitors_object+0x42/0xa0 [qxl] [ 5.259388] Write of size 8 at addr 00000000000014dc by task modprobe/95 [ 5.259754] [ 5.259842] CPU: 0 PID: 95 Comm: modprobe Not tainted 5.11.0-rc6-00007-g88bb507a74ea #62 [ 5.260309] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd9c812dda54 [ 5.260917] Call Trace: [ 5.261056] dump_stack+0x7d/0xa3 [ 5.261245] kasan_report.cold+0x10c/0x10e [ 5.261475] ? qxl_destroy_monitors_object+0x42/0xa0 [qxl] [ 5.261789] check_memory_region+0x17c/0x1e0 [ 5.262029] qxl_destroy_monitors_object+0x42/0xa0 [qxl] [ 5.262332] qxl_modeset_fini+0x9/0x20 [qxl] [ 5.262595] qxl_drm_release+0x22/0x30 [qxl] [ 5.262841] drm_dev_release+0x32/0x50 [ 5.263047] release_nodes+0x39e/0x410 [ 5.263253] ? devres_release+0x40/0x40 [ 5.263462] really_probe+0x2ea/0x420 [ 5.263664] driver_probe_device+0x6d/0xd0 [ 5.263888] device_driver_attach+0x82/0x90 [ 5.264116] ? device_driver_attach+0x90/0x90 [ 5.264353] __driver_attach+0x60/0x100 [ 5.264563] ? device_driver_attach+0x90/0x90 [ 5.264801] bus_for_each_dev+0xe1/0x140 [ 5.265014] ? subsys_dev_iter_exit+0x10/0x10 [ 5.265251] ? klist_node_init+0x61/0x80 [ 5.265464] bus_add_driver+0x254/0x2a0 [ 5.265673] driver_register+0xd3/0x150 [ 5.265882] ? 0xffffffffc0048000 [ 5.266064] do_one_initcall+0x84/0x250 [ 5.266274] ? trace_event_raw_event_initcall_finish+0x150/0x150 [ 5.266596] ? unpoison_range+0xf/0x30 [ 5.266801] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 5.267082] ? unpoison_range+0xf/0x30 [ 5.267287] ? unpoison_range+0xf/0x30 [ 5.267491] do_init_module+0xf8/0x350 [ 5.267697] load_module+0x3fe6/0x4340 [ 5.267902] ? vm_unmap_ram+0x1d0/0x1d0 [ 5.268115] ? module_frob_arch_sections+0x20/0x20 [ 5.268375] ? __do_sys_finit_module+0x108/0x170 [ 5.268624] __do_sys_finit_module+0x108/0x170 [ 5.268865] ? __ia32_sys_init_module+0x40/0x40 [ 5.269111] ? file_open_root+0x200/0x200 [ 5.269330] ? do_sys_open+0x85/0xe0 [ 5.269527] ? filp_open+0x50/0x50 [ 5.269714] ? exit_to_user_mode_prepare+0xfc/0x130 [ 5.269978] do_syscall_64+0x33/0x40 [ 5.270176] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 5.270450] RIP: 0033:0x7fa3f685bcf7 [ 5.270646] Code: 48 89 57 30 48 8b 04 24 48 89 47 38 e9 1d a0 02 00 48 89 f8 48 89 f7 48 89 d1 [ 5.271634] RSP: 002b:00007ffca83048d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 5.272037] RAX: ffffffffffffffda RBX: 0000000001e94a70 RCX: 00007fa3f685bcf7 [ 5.272416] RDX: 0000000000000000 RSI: 0000000001e939e0 RDI: 0000000000000003 [ 5.272794] RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000001 [ 5.273171] R10: 00007fa3f68bf300 R11: 0000000000000246 R12: 0000000001e939e0 [ 5.273550] R13: 0000000000000000 R14: 0000000001e93bd0 R15: 0000000000000001 [ 5.273928] ==================================================================
Signed-off-by: Tong Zhang ztong0001@gmail.com Link: http://patchwork.freedesktop.org/patch/msgid/20210203040727.868921-1-ztong00... Signed-off-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/qxl/qxl_drv.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 1864467f1063..1b09bbe98055 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -144,6 +144,8 @@ static void qxl_drm_release(struct drm_device *dev) * reordering qxl_modeset_fini() + qxl_device_fini() calls is * non-trivial though. */ + if (!dev->registered) + return; qxl_modeset_fini(qdev); qxl_device_fini(qdev); }
From: Gerd Hoffmann kraxel@redhat.com
[ Upstream commit 4ca77c513537700d3fae69030879f781dde1904c ]
In case we have a shadow surface on shutdown release it so it doesn't leak.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com Acked-by: Thomas Zimmermann tzimmermann@suse.de Link: http://patchwork.freedesktop.org/patch/msgid/20210204145712.1531203-6-kraxel... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/qxl/qxl_display.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 10738e04c09b..56e0c6c625e9 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -1228,6 +1228,10 @@ int qxl_modeset_init(struct qxl_device *qdev)
void qxl_modeset_fini(struct qxl_device *qdev) { + if (qdev->dumb_shadow_bo) { + drm_gem_object_put(&qdev->dumb_shadow_bo->tbo.base); + qdev->dumb_shadow_bo = NULL; + } qxl_destroy_monitors_object(qdev); drm_mode_config_cleanup(&qdev->ddev); }
From: Thomas Zimmermann tzimmermann@suse.de
[ Upstream commit ee4a92d690f30f3793df942939726bec0338e65b ]
Use AST_MAX_HWC_HEIGHT for setting offset_y in the cursor plane's atomic_check. The code used AST_MAX_HWC_WIDTH instead. This worked because both constants has the same value.
Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Acked-by: Gerd Hoffmann kraxel@redhat.com Link: https://patchwork.freedesktop.org/patch/msgid/20210209134632.12157-3-tzimmer... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/ast/ast_mode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 988b270fea5e..758c69aa7232 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -688,7 +688,7 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, unsigned int offset_x, offset_y;
offset_x = AST_MAX_HWC_WIDTH - fb->width; - offset_y = AST_MAX_HWC_WIDTH - fb->height; + offset_y = AST_MAX_HWC_HEIGHT - fb->height;
if (state->fb != old_state->fb) { /* A new cursor image was installed. */
From: Martin Leung martin.leung@amd.com
[ Upstream commit efe213e5a57e0cd92fa4f328dc1963d330549982 ]
[Why] Hardware team remeasured, need to update timings to increase latency slightly and avoid intermittent underflows.
[How] sr exit latency update.
Signed-off-by: Martin Leung martin.leung@amd.com Reviewed-by: Alvin Lee Alvin.Lee2@amd.com Acked-by: Qingqing Zhuo Qingqing.Zhuo@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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 fb7f1dea3c46..71e2d5e02571 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -181,7 +181,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_0_soc = { }, .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ .num_states = 1, - .sr_exit_time_us = 12, + .sr_exit_time_us = 15.5, .sr_enter_plus_exit_time_us = 20, .urgent_latency_us = 4.0, .urgent_latency_pixel_data_only_us = 4.0,
From: Nicholas Kazlauskas nicholas.kazlauskas@amd.com
[ Upstream commit 737b2b536a30a467c405d75f2287e17828838a13 ]
[Why] Color corruption can occur on bootup into a login manager that applies a non-linear gamma LUT because the LUT may not actually be powered on before writing.
It's cleared on the next full pipe reprogramming as we switch to LUTB from LUTA and the pipe accessing the LUT has taken it out of light sleep mode.
[How] The MPCC_OGAM_MEM_PWR_FORCE register does not force the current power mode when set to 0. It only forces when set light sleep, deep sleep or shutdown.
The register to actually force power on and ignore sleep modes is MPCC_OGAM_MEM_PWR_DIS - a value of 0 will enable power requests and a value of 1 will disable them.
When PWR_FORCE!=0 is combined with PWR_DIS=0 then MPCC OGAM memory is forced into the state specified by the force bits.
If PWR_FORCE is 0 then it respects the mode specified by MPCC_OGAM_MEM_LOW_PWR_MODE if the RAM LUT is not in use.
We set that bit to shutdown on low power, but otherwise it inherits from bootup defaults.
So for the fix:
1. Update the sequence to "force" power on when needed
We can use MPCC_OGAM_MEM_PWR_DIS for this to turn on the memory even when the block is in bypass and pending to be enabled for the next frame.
We need this for both low power enabled or disabled.
If we don't set this then we can run into issues when we first program the LUT from bootup.
2. Don't apply FORCE_SEL
Once we enable power requests with DIS=0 we run into the issue of the RAM being forced into light sleep and being unusable for display output. Leave this 0 like we used to for DCN20.
3. Rely on MPCC OGAM init to determine light sleep/deep sleep
MPC low power debug mode isn't enabled on any ASIC currently but we'll respect the setting determined during init if it is.
Lightly tested as working with IGT tests and desktop color adjustment.
4. Change the MPC resource default for DCN30
It was interleaving the dcn20 and dcn30 versions before depending on the sequence.
5. REG_WAIT for it to be on whenever we're powering up the memory
Otherwise we can write register values too early and we'll get corruption.
Signed-off-by: Nicholas Kazlauskas nicholas.kazlauskas@amd.com Reviewed-by: Eric Yang eric.yang2@amd.com Acked-by: Qingqing Zhuo Qingqing.Zhuo@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c index 3e6f76096119..a7598356f37d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -143,16 +143,18 @@ static void mpc3_power_on_ogam_lut( { struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
- if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) { - // Force power on - REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_DIS, power_on == true ? 1:0); - // Wait for confirmation when powering on - if (power_on) - REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10); - } else { - REG_SET(MPCC_MEM_PWR_CTRL[mpcc_id], 0, - MPCC_OGAM_MEM_PWR_FORCE, power_on == true ? 0 : 1); - } + /* + * Powering on: force memory active so the LUT can be updated. + * Powering off: allow entering memory low power mode + * + * Memory low power mode is controlled during MPC OGAM LUT init. + */ + REG_UPDATE(MPCC_MEM_PWR_CTRL[mpcc_id], + MPCC_OGAM_MEM_PWR_DIS, power_on != 0); + + /* Wait for memory to be powered on - we won't be able to write to it otherwise. */ + if (power_on) + REG_WAIT(MPCC_MEM_PWR_CTRL[mpcc_id], MPCC_OGAM_MEM_PWR_STATE, 0, 10, 10); }
static void mpc3_configure_ogam_lut( @@ -1427,7 +1429,7 @@ const struct mpc_funcs dcn30_mpc_funcs = { .acquire_rmu = mpcc3_acquire_rmu, .program_3dlut = mpc3_program_3dlut, .release_rmu = mpcc3_release_rmu, - .power_on_mpc_mem_pwr = mpc20_power_on_ogam_lut, + .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, .get_mpc_out_mux = mpc1_get_mpc_out_mux,
};
From: Huang Rui ray.huang@amd.com
[ Upstream commit ca1203d7d7295c49e5707d7def457bdc524a8edb ]
We should commit the value after restore them back to default as well.
$ echo "r" > pp_od_clk_voltage $ echo "c" > pp_od_clk_voltage
Signed-off-by: Huang Rui ray.huang@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 14 ------- .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 38 ------------------- .../gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 18 --------- 3 files changed, 70 deletions(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index ed05a30d1139..e2a56a7f3d7a 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -1526,20 +1526,6 @@ static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr,
smu10_data->gfx_actual_soft_min_freq = min_freq; smu10_data->gfx_actual_soft_max_freq = max_freq; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - min_freq, - NULL); - if (ret) - return ret; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - max_freq, - NULL); - if (ret) - return ret; } else if (type == PP_OD_COMMIT_DPM_TABLE) { if (size != 0) { pr_err("Input parameter number not correct\n"); 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 101eaa20db9b..a80f551771b9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -1462,7 +1462,6 @@ static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TAB long input[], uint32_t size) { int ret = 0; - int i; struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
if (!(smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)) { @@ -1535,43 +1534,6 @@ static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TAB smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; smu->cpu_actual_soft_min_freq = smu->cpu_default_soft_min_freq; smu->cpu_actual_soft_max_freq = smu->cpu_default_soft_max_freq; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, - smu->gfx_actual_hard_min_freq, NULL); - if (ret) { - dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); - return ret; - } - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, - smu->gfx_actual_soft_max_freq, NULL); - if (ret) { - dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); - return ret; - } - - if (smu->adev->pm.fw_version < 0x43f1b00) { - dev_warn(smu->adev->dev, "CPUSoftMax/CPUSoftMin are not supported, please update SBIOS!\n"); - break; - } - - for (i = 0; i < smu->cpu_core_num; i++) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinCclk, - (i << 20) | smu->cpu_actual_soft_min_freq, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Set hard min cclk failed!"); - return ret; - } - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxCclk, - (i << 20) | smu->cpu_actual_soft_max_freq, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Set soft max cclk failed!"); - return ret; - } - } } break; case PP_OD_COMMIT_DPM_TABLE: 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 5493388fcb10..dbe6d0caddb7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -389,24 +389,6 @@ static int renoir_od_edit_dpm_table(struct smu_context *smu, } smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetHardMinGfxClk, - smu->gfx_actual_hard_min_freq, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); - return ret; - } - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetSoftMaxGfxClk, - smu->gfx_actual_soft_max_freq, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); - return ret; - } break; case PP_OD_COMMIT_DPM_TABLE: if (size != 0) {
From: Tong Zhang ztong0001@gmail.com
[ Upstream commit dc739820ff90acccd013f6bb420222978a982791 ]
a connector is leaked upon module unload, it seems that we should do similar to sample driver as suggested in drm_drv.c.
Adding drm_atomic_helper_shutdown() in ast_pci_remove to prevent leaking.
[ 153.822134] WARNING: CPU: 0 PID: 173 at drivers/gpu/drm/drm_mode_config.c:504 drm_mode_config_cle0 [ 153.822698] Modules linked in: ast(-) drm_vram_helper drm_ttm_helper ttm [last unloaded: ttm] [ 153.823197] CPU: 0 PID: 173 Comm: modprobe Tainted: G W 5.11.0-03615-g55f62bc873474 [ 153.823708] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd9c812dda519-4 [ 153.824333] RIP: 0010:drm_mode_config_cleanup+0x418/0x470 [ 153.824637] Code: 0c 00 00 00 00 48 8b 84 24 a8 00 00 00 65 48 33 04 25 28 00 00 00 75 65 48 81 c0 [ 153.825668] RSP: 0018:ffff888103c9fb70 EFLAGS: 00010212 [ 153.825962] RAX: ffff888102b0d100 RBX: ffff888102b0c298 RCX: ffffffff818d8b2b [ 153.826356] RDX: dffffc0000000000 RSI: 000000007fffffff RDI: ffff888102b0c298 [ 153.826748] RBP: ffff888103c9fba0 R08: 0000000000000001 R09: ffffed1020561857 [ 153.827146] R10: ffff888102b0c2b7 R11: ffffed1020561856 R12: ffff888102b0c000 [ 153.827538] R13: ffff888102b0c2d8 R14: ffff888102b0c2d8 R15: 1ffff11020793f70 [ 153.827935] FS: 00007f24bff456a0(0000) GS:ffff88815b400000(0000) knlGS:0000000000000000 [ 153.828380] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 153.828697] CR2: 0000000001c39018 CR3: 0000000103c90000 CR4: 00000000000006f0 [ 153.829096] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 153.829486] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 153.829883] Call Trace: [ 153.830024] ? drmm_mode_config_init+0x930/0x930 [ 153.830281] ? cpumask_next+0x16/0x20 [ 153.830488] ? mnt_get_count+0x66/0x80 [ 153.830699] ? drm_mode_config_cleanup+0x470/0x470 [ 153.830972] drm_managed_release+0xed/0x1c0 [ 153.831208] drm_dev_release+0x3a/0x50 [ 153.831420] release_nodes+0x39e/0x410 [ 153.831631] ? devres_release+0x40/0x40 [ 153.831852] device_release_driver_internal+0x158/0x270 [ 153.832143] driver_detach+0x76/0xe0 [ 153.832344] bus_remove_driver+0x7e/0x100 [ 153.832568] pci_unregister_driver+0x28/0xf0 [ 153.832821] __x64_sys_delete_module+0x268/0x300 [ 153.833086] ? __ia32_sys_delete_module+0x300/0x300 [ 153.833357] ? call_rcu+0x372/0x4f0 [ 153.833553] ? fpregs_assert_state_consistent+0x4d/0x60 [ 153.833840] ? exit_to_user_mode_prepare+0x2f/0x130 [ 153.834118] do_syscall_64+0x33/0x40 [ 153.834317] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 153.834597] RIP: 0033:0x7f24bfec7cf7 [ 153.834797] Code: 48 89 57 30 48 8b 04 24 48 89 47 38 e9 1d a0 02 00 48 89 f8 48 89 f7 48 89 d6 41 [ 153.835812] RSP: 002b:00007fff72e6cb58 EFLAGS: 00000202 ORIG_RAX: 00000000000000b0 [ 153.836234] RAX: ffffffffffffffda RBX: 00007f24bff45690 RCX: 00007f24bfec7cf7 [ 153.836623] RDX: 00000000ffffffff RSI: 0000000000000080 RDI: 0000000001c2fb10 [ 153.837018] RBP: 0000000001c2fac0 R08: 2f2f2f2f2f2f2f2f R09: 0000000001c2fac0 [ 153.837408] R10: fefefefefefefeff R11: 0000000000000202 R12: 0000000001c2fac0 [ 153.837798] R13: 0000000001c2f9d0 R14: 0000000000000000 R15: 0000000000000001 [ 153.838194] ---[ end trace b92031513bbe596c ]--- [ 153.838441] [drm:drm_mode_config_cleanup] *ERROR* connector VGA-1 leaked!
Signed-off-by: Tong Zhang ztong0001@gmail.com Signed-off-by: Thomas Zimmermann tzimmermann@suse.de Link: https://patchwork.freedesktop.org/patch/msgid/20210222023322.984885-1-ztong0... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/ast/ast_drv.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index ea8164e7a6dc..01837bea18c2 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -30,6 +30,7 @@ #include <linux/module.h> #include <linux/pci.h>
+#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> @@ -138,6 +139,7 @@ static void ast_pci_remove(struct pci_dev *pdev) struct drm_device *dev = pci_get_drvdata(pdev);
drm_dev_unregister(dev); + drm_atomic_helper_shutdown(dev); }
static int ast_drm_freeze(struct drm_device *dev)
From: Eryk Brol eryk.brol@amd.com
[ Upstream commit 349a19b2f1b01e713268c7de9944ad669ccdf369 ]
[why] This check for ASIC revision is no longer useful and causes lightup issues after a topology change in MST DSC scenario. In this case, DSC configs should be recalculated for the new topology. This check prevented that from happening on certain ASICs that do, in fact, support DSC.
[how] Change the ASIC revision to instead check if DSC is supported.
Signed-off-by: Eryk Brol eryk.brol@amd.com Acked-by: Bindu Ramamurthy bindu.r@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 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 d699a5cf6c11..8ad83ccfcc6a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9383,7 +9383,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, }
#if defined(CONFIG_DRM_AMD_DC_DCN) - if (adev->asic_type >= CHIP_NAVI10) { + if (dc_resource_is_dsc_encoding_supported(dc)) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { ret = add_affected_mst_dsc_crtcs(state, crtc);
From: Aric Cyr aric.cyr@amd.com
[ Upstream commit 6ad98e8aeb0106f453bb154933e8355849244990 ]
[Why] There is a window of time where we optimize bandwidth due to no streams enabled will enable PSTATE changing but HUBPs are not disabled yet. This results in underflow counter increasing in some hotplug scenarios.
[How] Set the optimize-bandwidth flag for later processing once all the HUBPs are properly disabled.
Signed-off-by: Aric Cyr aric.cyr@amd.com Acked-by: Bindu Ramamurthy bindu.r@amd.com Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8f8a13c7cf73..c0b827d16268 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2398,7 +2398,8 @@ static void commit_planes_do_stream_update(struct dc *dc, if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
- dc->hwss.optimize_bandwidth(dc, dc->current_state); + dc->optimized_required = true; + } else { if (dc->optimize_seamless_boot_streams == 0) dc->hwss.prepare_bandwidth(dc, dc->current_state);
From: Wyatt Wood wyatt.wood@amd.com
[ Upstream commit 8039bc7130ef4206a58e4dc288621bc97eba08eb ]
[Why] GPINT timeout is causing PSR_STATE_0 to be returned when it shouldn't. We must guarantee that PSR is fully disabled before doing hw programming on driver-side.
[How] Return invalid state if GPINT command times out. Let existing retry logic send the GPINT until successful.
Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Wyatt Wood wyatt.wood@amd.com Reviewed-by: Anthony Koo Anthony.Koo@amd.com Acked-by: Rodrigo Siqueira Rodrigo.Siqueira@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
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 69e34bef274c..febccb35ddad 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -81,13 +81,18 @@ static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state) { struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; uint32_t raw_state; + enum dmub_status status = DMUB_STATUS_INVALID;
// Send gpint command and wait for ack - dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); - - dmub_srv_get_gpint_response(srv, &raw_state); - - *state = convert_psr_state(raw_state); + status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); + + if (status == DMUB_STATUS_OK) { + // GPINT was executed, get response + dmub_srv_get_gpint_response(srv, &raw_state); + *state = convert_psr_state(raw_state); + } else + // Return invalid state when GPINT times out + *state = 0xFF; }
/*
From: Xiaogang Chen xiaogang.chen@amd.com
[ Upstream commit b6f91fc183f758461b9462cc93e673adbbf95c2d ]
amdgpu DM handles INTERRUPT_LOW_IRQ_CONTEXT interrupt(hpd, hpd_rx) by using work queue and uses single work_struct. If new interrupt is recevied before the previous handler finished, new interrupts(same type) will be discarded and driver just sends "amdgpu_dm_irq_schedule_work FAILED" message out. If some important hpd, hpd_rx related interrupts are missed by driver the hot (un)plug devices may cause system hang or instability, such as issues with system resume from S3 sleep with mst device connected.
This patch dynamically allocates new amdgpu_dm_irq_handler_data for new interrupts if previous INTERRUPT_LOW_IRQ_CONTEXT interrupt work has not been handled. So the new interrupt works can be queued to the same workqueue_struct, instead of discard the new interrupts. All allocated amdgpu_dm_irq_handler_data are put into a single linked list and will be reused after.
Signed-off-by: Xiaogang Chen xiaogang.chen@amd.com Reviewed-by: Aurabindo Pillai aurabindo.pillai@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 14 +-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 115 ++++++++++++------ 2 files changed, 80 insertions(+), 49 deletions(-)
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 8bfe901cf237..52cc81705280 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -68,18 +68,6 @@ struct common_irq_params { enum dc_irq_source irq_src; };
-/** - * struct irq_list_head - Linked-list for low context IRQ handlers. - * - * @head: The list_head within &struct handler_data - * @work: A work_struct containing the deferred handler work - */ -struct irq_list_head { - struct list_head head; - /* In case this interrupt needs post-processing, 'work' will be queued*/ - struct work_struct work; -}; - /** * struct dm_compressor_info - Buffer info used by frame buffer compression * @cpu_addr: MMIO cpu addr @@ -293,7 +281,7 @@ struct amdgpu_display_manager { * Note that handlers are called in the same order as they were * registered (FIFO). */ - struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER]; + struct list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER];
/** * @irq_handler_list_high_tab: diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index e0000c180ed1..8ce10d0973c5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -82,6 +82,7 @@ struct amdgpu_dm_irq_handler_data { struct amdgpu_display_manager *dm; /* DAL irq source which registered for this interrupt. */ enum dc_irq_source irq_source; + struct work_struct work; };
#define DM_IRQ_TABLE_LOCK(adev, flags) \ @@ -111,20 +112,10 @@ static void init_handler_common_data(struct amdgpu_dm_irq_handler_data *hcd, */ static void dm_irq_work_func(struct work_struct *work) { - struct irq_list_head *irq_list_head = - container_of(work, struct irq_list_head, work); - struct list_head *handler_list = &irq_list_head->head; - struct amdgpu_dm_irq_handler_data *handler_data; - - list_for_each_entry(handler_data, handler_list, list) { - DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n", - handler_data->irq_source); + struct amdgpu_dm_irq_handler_data *handler_data = + container_of(work, struct amdgpu_dm_irq_handler_data, work);
- DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n", - handler_data->irq_source); - - handler_data->handler(handler_data->handler_arg); - } + handler_data->handler(handler_data->handler_arg);
/* Call a DAL subcomponent which registered for interrupt notification * at INTERRUPT_LOW_IRQ_CONTEXT. @@ -156,7 +147,7 @@ static struct list_head *remove_irq_handler(struct amdgpu_device *adev, break; case INTERRUPT_LOW_IRQ_CONTEXT: default: - hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head; + hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source]; break; }
@@ -290,7 +281,8 @@ void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev, break; case INTERRUPT_LOW_IRQ_CONTEXT: default: - hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head; + hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source]; + INIT_WORK(&handler_data->work, dm_irq_work_func); break; }
@@ -372,7 +364,7 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev, int amdgpu_dm_irq_init(struct amdgpu_device *adev) { int src; - struct irq_list_head *lh; + struct list_head *lh;
DRM_DEBUG_KMS("DM_IRQ\n");
@@ -381,9 +373,7 @@ int amdgpu_dm_irq_init(struct amdgpu_device *adev) for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { /* low context handler list init */ lh = &adev->dm.irq_handler_list_low_tab[src]; - INIT_LIST_HEAD(&lh->head); - INIT_WORK(&lh->work, dm_irq_work_func); - + INIT_LIST_HEAD(lh); /* high context handler init */ INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]); } @@ -400,8 +390,11 @@ int amdgpu_dm_irq_init(struct amdgpu_device *adev) void amdgpu_dm_irq_fini(struct amdgpu_device *adev) { int src; - struct irq_list_head *lh; + struct list_head *lh; + struct list_head *entry, *tmp; + struct amdgpu_dm_irq_handler_data *handler; unsigned long irq_table_flags; + DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n"); for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) { DM_IRQ_TABLE_LOCK(adev, irq_table_flags); @@ -410,7 +403,16 @@ void amdgpu_dm_irq_fini(struct amdgpu_device *adev) * (because no code can schedule a new one). */ lh = &adev->dm.irq_handler_list_low_tab[src]; DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - flush_work(&lh->work); + + if (!list_empty(lh)) { + list_for_each_safe(entry, tmp, lh) { + handler = list_entry( + entry, + struct amdgpu_dm_irq_handler_data, + list); + flush_work(&handler->work); + } + } } }
@@ -420,6 +422,8 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) struct list_head *hnd_list_h; struct list_head *hnd_list_l; unsigned long irq_table_flags; + struct list_head *entry, *tmp; + struct amdgpu_dm_irq_handler_data *handler;
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
@@ -430,14 +434,22 @@ int amdgpu_dm_irq_suspend(struct amdgpu_device *adev) * will be disabled from manage_dm_interrupts on disable CRTC. */ for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6RX; src++) { - hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src]; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) dc_interrupt_set(adev->dm.dc, src, false);
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); - flush_work(&adev->dm.irq_handler_list_low_tab[src].work);
+ if (!list_empty(hnd_list_l)) { + list_for_each_safe (entry, tmp, hnd_list_l) { + handler = list_entry( + entry, + struct amdgpu_dm_irq_handler_data, + list); + flush_work(&handler->work); + } + } DM_IRQ_TABLE_LOCK(adev, irq_table_flags); }
@@ -457,7 +469,7 @@ int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev)
/* re-enable short pulse interrupts HW interrupt */ for (src = DC_IRQ_SOURCE_HPD1RX; src <= DC_IRQ_SOURCE_HPD6RX; src++) { - hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src]; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) dc_interrupt_set(adev->dm.dc, src, true); @@ -483,7 +495,7 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) * will be enabled from manage_dm_interrupts on enable CRTC. */ for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6; src++) { - hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head; + hnd_list_l = &adev->dm.irq_handler_list_low_tab[src]; hnd_list_h = &adev->dm.irq_handler_list_high_tab[src]; if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h)) dc_interrupt_set(adev->dm.dc, src, true); @@ -500,22 +512,53 @@ int amdgpu_dm_irq_resume_late(struct amdgpu_device *adev) static void amdgpu_dm_irq_schedule_work(struct amdgpu_device *adev, enum dc_irq_source irq_source) { - unsigned long irq_table_flags; - struct work_struct *work = NULL; + struct list_head *handler_list = &adev->dm.irq_handler_list_low_tab[irq_source]; + struct amdgpu_dm_irq_handler_data *handler_data; + bool work_queued = false;
- DM_IRQ_TABLE_LOCK(adev, irq_table_flags); + if (list_empty(handler_list)) + return; + + list_for_each_entry (handler_data, handler_list, list) { + if (!queue_work(system_highpri_wq, &handler_data->work)) { + continue; + } else { + work_queued = true; + break; + } + }
- if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head)) - work = &adev->dm.irq_handler_list_low_tab[irq_source].work; + if (!work_queued) { + struct amdgpu_dm_irq_handler_data *handler_data_add; + /*get the amdgpu_dm_irq_handler_data of first item pointed by handler_list*/ + handler_data = container_of(handler_list->next, struct amdgpu_dm_irq_handler_data, list);
- DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags); + /*allocate a new amdgpu_dm_irq_handler_data*/ + handler_data_add = kzalloc(sizeof(*handler_data), GFP_KERNEL); + if (!handler_data_add) { + DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n"); + return; + }
- if (work) { - if (!schedule_work(work)) - DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n", - irq_source); - } + /*copy new amdgpu_dm_irq_handler_data members from handler_data*/ + handler_data_add->handler = handler_data->handler; + handler_data_add->handler_arg = handler_data->handler_arg; + handler_data_add->dm = handler_data->dm; + handler_data_add->irq_source = irq_source;
+ list_add_tail(&handler_data_add->list, handler_list); + + INIT_WORK(&handler_data_add->work, dm_irq_work_func); + + if (queue_work(system_highpri_wq, &handler_data_add->work)) + DRM_DEBUG("Queued work for handling interrupt from " + "display for IRQ source %d\n", + irq_source); + else + DRM_ERROR("Failed to queue work for handling interrupt " + "from display for IRQ source %d\n", + irq_source); + } }
/*
From: Lee Jones lee.jones@linaro.org
[ Upstream commit 3e3527f5b765c6f479ba55e5a570ee9538589a74 ]
Fixes the following W=1 kernel build warning(s):
In file included from drivers/gpu/drm/amd/amdgpu/../display/dc/dce112/dce112_resource.c:59: drivers/gpu/drm/amd/amdgpu/../include/asic_reg/dce/dce_11_2_sh_mask.h:10014:58: warning: initialized field overwritten [-Woverride-init] drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:214:16: note: in expansion of macro ‘AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE__SHIFT’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:127:2: note: in expansion of macro ‘AUX_SF’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce112/dce112_resource.c:177:2: note: in expansion of macro ‘DCE_AUX_MASK_SH_LIST’ drivers/gpu/drm/amd/amdgpu/../include/asic_reg/dce/dce_11_2_sh_mask.h:10014:58: note: (near initialization for ‘aux_shift.AUX_SW_AUTOINCREMENT_DISABLE’) drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:214:16: note: in expansion of macro ‘AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE__SHIFT’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:127:2: note: in expansion of macro ‘AUX_SF’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce112/dce112_resource.c:177:2: note: in expansion of macro ‘DCE_AUX_MASK_SH_LIST’ drivers/gpu/drm/amd/amdgpu/../include/asic_reg/dce/dce_11_2_sh_mask.h:10013:56: warning: initialized field overwritten [-Woverride-init] drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:214:16: note: in expansion of macro ‘AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE_MASK’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:127:2: note: in expansion of macro ‘AUX_SF’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce112/dce112_resource.c:181:2: note: in expansion of macro ‘DCE_AUX_MASK_SH_LIST’ drivers/gpu/drm/amd/amdgpu/../include/asic_reg/dce/dce_11_2_sh_mask.h:10013:56: note: (near initialization for ‘aux_mask.AUX_SW_AUTOINCREMENT_DISABLE’) drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:214:16: note: in expansion of macro ‘AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE_MASK’ drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.h:127:2: note: in expansion of macro ‘AUX_SF’
Cc: Harry Wentland harry.wentland@amd.com Cc: Leo Li sunpeng.li@amd.com Cc: Alex Deucher alexander.deucher@amd.com Cc: "Christian König" christian.koenig@amd.com Cc: David Airlie airlied@linux.ie Cc: Daniel Vetter daniel@ffwll.ch Cc: amd-gfx@lists.freedesktop.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h index 277484cf853e..d4be5954d7aa 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h @@ -99,7 +99,6 @@ struct dce110_aux_registers { AUX_SF(AUX_SW_CONTROL, AUX_SW_GO, mask_sh),\ AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\ AUX_SF(AUX_SW_DATA, AUX_SW_DATA_RW, mask_sh),\ - AUX_SF(AUX_SW_DATA, AUX_SW_AUTOINCREMENT_DISABLE, mask_sh),\ AUX_SF(AUX_SW_DATA, AUX_SW_INDEX, mask_sh),\ AUX_SF(AUX_SW_DATA, AUX_SW_DATA, mask_sh),\ AUX_SF(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, mask_sh),\
From: Arunpravin Arunpravin.PaneerSelvam@amd.com
[ Upstream commit d8cce9306801cfbf709055677f7896905094ff95 ]
Remove unnecessary comments, enable restore mode using '|=' operator, fixes the alignment to improve the code readability.
v2: Move all restoration flag check to bitwise '&' operator
Signed-off-by: Arunpravin Arunpravin.PaneerSelvam@amd.com Reviewed-by: Evan Quan evan.quan@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 34 ++++++++--------------- 1 file changed, 12 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 cd905e41080e..42c4dbe3e362 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -279,35 +279,25 @@ static void smu_set_user_clk_dependencies(struct smu_context *smu, enum smu_clk_ if (smu->adev->in_suspend) return;
- /* - * mclk, fclk and socclk are interdependent - * on each other - */ if (clk == SMU_MCLK) { - /* reset clock dependency */ smu->user_dpm_profile.clk_dependency = 0; - /* set mclk dependent clocks(fclk and socclk) */ smu->user_dpm_profile.clk_dependency = BIT(SMU_FCLK) | BIT(SMU_SOCCLK); } else if (clk == SMU_FCLK) { - /* give priority to mclk, if mclk dependent clocks are set */ + /* MCLK takes precedence over FCLK */ if (smu->user_dpm_profile.clk_dependency == (BIT(SMU_FCLK) | BIT(SMU_SOCCLK))) return;
- /* reset clock dependency */ smu->user_dpm_profile.clk_dependency = 0; - /* set fclk dependent clocks(mclk and socclk) */ smu->user_dpm_profile.clk_dependency = BIT(SMU_MCLK) | BIT(SMU_SOCCLK); } else if (clk == SMU_SOCCLK) { - /* give priority to mclk, if mclk dependent clocks are set */ + /* MCLK takes precedence over SOCCLK */ if (smu->user_dpm_profile.clk_dependency == (BIT(SMU_FCLK) | BIT(SMU_SOCCLK))) return;
- /* reset clock dependency */ smu->user_dpm_profile.clk_dependency = 0; - /* set socclk dependent clocks(mclk and fclk) */ smu->user_dpm_profile.clk_dependency = BIT(SMU_MCLK) | BIT(SMU_FCLK); } else - /* add clk dependencies here, if any */ + /* Add clk dependencies here, if any */ return; }
@@ -331,7 +321,7 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) return;
/* Enable restore flag */ - smu->user_dpm_profile.flags = SMU_DPM_USER_PROFILE_RESTORE; + smu->user_dpm_profile.flags |= SMU_DPM_USER_PROFILE_RESTORE;
/* set the user dpm power limit */ if (smu->user_dpm_profile.power_limit) { @@ -354,8 +344,8 @@ static void smu_restore_dpm_user_profile(struct smu_context *smu) ret = smu_force_clk_levels(smu, clk_type, smu->user_dpm_profile.clk_mask[clk_type]); if (ret) - dev_err(smu->adev->dev, "Failed to set clock type = %d\n", - clk_type); + dev_err(smu->adev->dev, + "Failed to set clock type = %d\n", clk_type); } } } @@ -1777,7 +1767,7 @@ int smu_force_clk_levels(struct smu_context *smu,
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) { + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) { smu->user_dpm_profile.clk_mask[clk_type] = mask; smu_set_user_clk_dependencies(smu, clk_type); } @@ -2034,7 +2024,7 @@ int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed) if (smu->ppt_funcs->set_fan_speed_percent) { percent = speed * 100 / smu->fan_max_rpm; ret = smu->ppt_funcs->set_fan_speed_percent(smu, percent); - if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE) + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) smu->user_dpm_profile.fan_speed_percent = percent; }
@@ -2104,7 +2094,7 @@ int smu_set_power_limit(struct smu_context *smu, uint32_t limit)
if (smu->ppt_funcs->set_power_limit) { ret = smu->ppt_funcs->set_power_limit(smu, limit); - if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE) + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) smu->user_dpm_profile.power_limit = limit; }
@@ -2285,7 +2275,7 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value)
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) + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) smu->user_dpm_profile.fan_mode = value; }
@@ -2293,7 +2283,7 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value)
/* 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.flags & SMU_DPM_USER_PROFILE_RESTORE)) smu->user_dpm_profile.fan_speed_percent = 0;
return ret; @@ -2335,7 +2325,7 @@ int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) if (speed > 100) speed = 100; ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed); - if (!ret && smu->user_dpm_profile.flags != SMU_DPM_USER_PROFILE_RESTORE) + if (!ret && !(smu->user_dpm_profile.flags & SMU_DPM_USER_PROFILE_RESTORE)) smu->user_dpm_profile.fan_speed_percent = speed; }
From: Emily Deng Emily.Deng@amd.com
[ Upstream commit bb0cd09be45ea457f25fdcbcb3d6cf2230f26c46 ]
When unloading driver after killing some applications, it will hit sdma flush tlb job timeout which is called by ttm_bo_delay_delete. So to avoid the job submit after fence driver fini, call ttm_bo_lock_delayed_workqueue before fence driver fini. And also put drm_sched_fini before waiting fence.
Signed-off-by: Emily Deng Emily.Deng@amd.com Reviewed-by: Christian König christian.koenig@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8a5a8ff5d362..5eee251e3335 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3613,6 +3613,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) { dev_info(adev->dev, "amdgpu: finishing device.\n"); flush_delayed_work(&adev->delayed_init_work); + ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); adev->shutdown = true;
kfree(adev->pci_state); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index d56f4023ebb3..7e8e46c39dbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -533,6 +533,8 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
if (!ring || !ring->fence_drv.initialized) continue; + if (!ring->no_scheduler) + drm_sched_fini(&ring->sched); r = amdgpu_fence_wait_empty(ring); if (r) { /* no need to trigger GPU reset as we are unloading */ @@ -541,8 +543,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev) if (ring->fence_drv.irq_src) amdgpu_irq_put(adev, ring->fence_drv.irq_src, ring->fence_drv.irq_type); - if (!ring->no_scheduler) - drm_sched_fini(&ring->sched); + del_timer_sync(&ring->fence_drv.fallback_timer); for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j) dma_fence_put(ring->fence_drv.fences[j]);
From: xndcn xndchn@gmail.com
[ Upstream commit 377f8331d0565e6f71ba081c894029a92d0c7e77 ]
virtio_gpu_object array is not freed or unlocked in some failed cases.
Signed-off-by: xndcn xndchn@gmail.com Link: http://patchwork.freedesktop.org/patch/msgid/20210305151819.14330-1-xndchn@g... Signed-off-by: Gerd Hoffmann kraxel@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 2 +- drivers/gpu/drm/virtio/virtgpu_object.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 23eb6d772e40..669f2ee39515 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -174,7 +174,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, if (!sync_file) { dma_fence_put(&out_fence->f); ret = -ENOMEM; - goto out_memdup; + goto out_unresv; }
exbuf->fence_fd = out_fence_fd; diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index d69a5b6da553..4ff1ec28e630 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -248,6 +248,7 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents, &nents); if (ret != 0) { + virtio_gpu_array_put_free(objs); virtio_gpu_free_object(&shmem_obj->base); return ret; }
From: Obeida Shamoun oshmoun100@googlemail.com
[ Upstream commit cdfd4c689e2a52c313b35ddfc1852ff274f91acb ]
WLED3_SINK_REG_SYNC is, as the name implies, a sink register offset. Therefore, use the sink address as base instead of the ctrl address.
This fixes the sync toggle on wled4, which can be observed by the fact that adjusting brightness now works.
It has no effect on wled3 because sink and ctrl base addresses are the same. This allows adjusting the brightness without having to disable then reenable the module.
Signed-off-by: Obeida Shamoun oshmoun100@googlemail.com Signed-off-by: Konrad Dybcio konrad.dybcio@somainline.org Signed-off-by: Marijn Suijten marijn.suijten@somainline.org Reviewed-by: Daniel Thompson daniel.thompson@linaro.org Acked-by: Kiran Gunda kgunda@codeaurora.org Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/video/backlight/qcom-wled.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 091f07e7c145..fc8b443d10fd 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -336,13 +336,13 @@ static int wled3_sync_toggle(struct wled *wled) unsigned int mask = GENMASK(wled->max_string_count - 1, 0);
rc = regmap_update_bits(wled->regmap, - wled->ctrl_addr + WLED3_SINK_REG_SYNC, + wled->sink_addr + WLED3_SINK_REG_SYNC, mask, mask); if (rc < 0) return rc;
rc = regmap_update_bits(wled->regmap, - wled->ctrl_addr + WLED3_SINK_REG_SYNC, + wled->sink_addr + WLED3_SINK_REG_SYNC, mask, WLED3_SINK_REG_SYNC_CLEAR);
return rc;
From: Kiran Gunda kgunda@codeaurora.org
[ Upstream commit 4d6e9cdff7fbb6bef3e5559596fab3eeffaf95ca ]
Currently, for WLED5, the FSC (Full scale current) setting is not updated properly due to driver toggling the wrong register after an FSC update.
On WLED5 we should only toggle the MOD_SYNC bit after a brightness update. For an FSC update we need to toggle the SYNC bits instead.
Fix it by adopting the common wled3_sync_toggle() for WLED5 and introducing new code to the brightness update path to compensate.
Signed-off-by: Kiran Gunda kgunda@codeaurora.org Reviewed-by: Daniel Thompson daniel.thompson@linaro.org Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/video/backlight/qcom-wled.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index fc8b443d10fd..e9fbe2483844 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -348,7 +348,7 @@ static int wled3_sync_toggle(struct wled *wled) return rc; }
-static int wled5_sync_toggle(struct wled *wled) +static int wled5_mod_sync_toggle(struct wled *wled) { int rc; u8 val; @@ -445,10 +445,23 @@ static int wled_update_status(struct backlight_device *bl) goto unlock_mutex; }
- rc = wled->wled_sync_toggle(wled); - if (rc < 0) { - dev_err(wled->dev, "wled sync failed rc:%d\n", rc); - goto unlock_mutex; + if (wled->version < 5) { + rc = wled->wled_sync_toggle(wled); + if (rc < 0) { + dev_err(wled->dev, "wled sync failed rc:%d\n", rc); + goto unlock_mutex; + } + } else { + /* + * For WLED5 toggling the MOD_SYNC_BIT updates the + * brightness + */ + rc = wled5_mod_sync_toggle(wled); + if (rc < 0) { + dev_err(wled->dev, "wled mod sync failed rc:%d\n", + rc); + goto unlock_mutex; + } } }
@@ -1459,7 +1472,7 @@ static int wled_configure(struct wled *wled) size = ARRAY_SIZE(wled5_opts); *cfg = wled5_config_defaults; wled->wled_set_brightness = wled5_set_brightness; - wled->wled_sync_toggle = wled5_sync_toggle; + wled->wled_sync_toggle = wled3_sync_toggle; wled->wled_cabc_config = wled5_cabc_config; wled->wled_ovp_delay = wled5_ovp_delay; wled->wled_auto_detection_required =
From: Lyude Paul lyude@redhat.com
[ Upstream commit 9962849d0871f5e53d0e3b3d84561f8f2847fbf4 ]
Since encoder mappings for connectors are exposed to userspace, we should be attaching the encoder before exposing the connector to userspace. Just a drive-by fix for an issue I noticed while fixing up usages of drm_dp_aux_init()/drm_dp_aux_register() across the tree.
Signed-off-by: Lyude Paul lyude@redhat.com Reviewed-by: Robert Foss robert.foss@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20210219215326.2227596-9-lyude... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c index 81debd02c169..fbfe0cc89ba4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c @@ -924,12 +924,6 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, drm_connector_helper_add(&anx78xx->connector, &anx78xx_connector_helper_funcs);
- err = drm_connector_register(&anx78xx->connector); - if (err) { - DRM_ERROR("Failed to register connector: %d\n", err); - return err; - } - anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
err = drm_connector_attach_encoder(&anx78xx->connector, @@ -939,6 +933,12 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, return err; }
+ err = drm_connector_register(&anx78xx->connector); + if (err) { + DRM_ERROR("Failed to register connector: %d\n", err); + return err; + } + return 0; }
From: Lyude Paul lyude@redhat.com
[ Upstream commit 212ee8db84600f7b279b8645c62a112bff310995 ]
Just another issue I noticed while correcting usages of drm_dp_aux_init()/drm_dp_aux_register() around the tree. If any of the steps in anx78xx_bridge_attach() fail, we end up leaking resources. So, let's fix that (and fix leaking a DP AUX adapter in the process) by unrolling on errors.
Signed-off-by: Lyude Paul lyude@redhat.com Reviewed-by: Robert Foss robert.foss@linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20210219215326.2227596-10-lyud... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c index fbfe0cc89ba4..bcc778f680a8 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c @@ -918,7 +918,7 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, DRM_MODE_CONNECTOR_DisplayPort); if (err) { DRM_ERROR("Failed to initialize connector: %d\n", err); - return err; + goto aux_unregister; }
drm_connector_helper_add(&anx78xx->connector, @@ -930,16 +930,21 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge, bridge->encoder); if (err) { DRM_ERROR("Failed to link up connector to encoder: %d\n", err); - return err; + goto connector_cleanup; }
err = drm_connector_register(&anx78xx->connector); if (err) { DRM_ERROR("Failed to register connector: %d\n", err); - return err; + goto connector_cleanup; }
return 0; +connector_cleanup: + drm_connector_cleanup(&anx78xx->connector); +aux_unregister: + drm_dp_aux_unregister(&anx78xx->aux); + return err; }
static enum drm_mode_status
From: Philip Yang Philip.Yang@amd.com
[ Upstream commit b672cb1eee59efe6ca5bb2a2ce90060a22860558 ]
If xnack is on, VM retry fault interrupt send to IH ring1, and ring1 will be full quickly. IH cannot receive other interrupts, this causes deadlock if migrating buffer using sdma and waiting for sdma done while handling retry fault.
Remove VMC from IH storm client, enable ring1 write pointer overflow, then IH will drop retry fault interrupts and be able to receive other interrupts while driver is handling retry fault.
IH ring1 write pointer doesn't writeback to memory by IH, and ring1 write pointer recorded by self-irq is not updated, so always read the latest ring1 write pointer from register.
Signed-off-by: Philip Yang Philip.Yang@amd.com Signed-off-by: Felix Kuehling Felix.Kuehling@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 32 +++++++++----------------- drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 32 +++++++++----------------- 2 files changed, 22 insertions(+), 42 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index 88626d83e07b..ca8efa5c6978 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -220,10 +220,8 @@ static int vega10_ih_enable_ring(struct amdgpu_device *adev, tmp = vega10_ih_rb_cntl(ih, tmp); if (ih == &adev->irq.ih) tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RPTR_REARM, !!adev->irq.msi_enabled); - if (ih == &adev->irq.ih1) { - tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 0); + if (ih == &adev->irq.ih1) tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_FULL_DRAIN_ENABLE, 1); - } if (amdgpu_sriov_vf(adev)) { if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) { dev_err(adev->dev, "PSP program IH_RB_CNTL failed!\n"); @@ -265,7 +263,6 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev) u32 ih_chicken; int ret; int i; - u32 tmp;
/* disable irqs */ ret = vega10_ih_toggle_interrupts(adev, false); @@ -291,15 +288,6 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev) } }
- tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL); - tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL, - CLIENT18_IS_STORM_CLIENT, 1); - WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp); - - tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL); - tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1); - WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp); - pci_set_master(adev->pdev);
/* enable interrupts */ @@ -345,11 +333,17 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev, u32 wptr, tmp; struct amdgpu_ih_regs *ih_regs;
- wptr = le32_to_cpu(*ih->wptr_cpu); - ih_regs = &ih->ih_regs; + if (ih == &adev->irq.ih) { + /* Only ring0 supports writeback. On other rings fall back + * to register-based code with overflow checking below. + */ + wptr = le32_to_cpu(*ih->wptr_cpu);
- if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) - goto out; + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + } + + ih_regs = &ih->ih_regs;
/* Double check that the overflow wasn't already cleared. */ wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr); @@ -440,15 +434,11 @@ static int vega10_ih_self_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - uint32_t wptr = cpu_to_le32(entry->src_data[0]); - switch (entry->ring_id) { case 1: - *adev->irq.ih1.wptr_cpu = wptr; schedule_work(&adev->irq.ih1_work); break; case 2: - *adev->irq.ih2.wptr_cpu = wptr; schedule_work(&adev->irq.ih2_work); break; default: break; diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c index 5a3c867d5881..75b06e1964ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c @@ -220,10 +220,8 @@ static int vega20_ih_enable_ring(struct amdgpu_device *adev, tmp = vega20_ih_rb_cntl(ih, tmp); if (ih == &adev->irq.ih) tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RPTR_REARM, !!adev->irq.msi_enabled); - if (ih == &adev->irq.ih1) { - tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_ENABLE, 0); + if (ih == &adev->irq.ih1) tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_FULL_DRAIN_ENABLE, 1); - } if (amdgpu_sriov_vf(adev)) { if (psp_reg_program(&adev->psp, ih_regs->psp_reg_id, tmp)) { dev_err(adev->dev, "PSP program IH_RB_CNTL failed!\n"); @@ -297,7 +295,6 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev) u32 ih_chicken; int ret; int i; - u32 tmp;
/* disable irqs */ ret = vega20_ih_toggle_interrupts(adev, false); @@ -326,15 +323,6 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev) } }
- tmp = RREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL); - tmp = REG_SET_FIELD(tmp, IH_STORM_CLIENT_LIST_CNTL, - CLIENT18_IS_STORM_CLIENT, 1); - WREG32_SOC15(OSSSYS, 0, mmIH_STORM_CLIENT_LIST_CNTL, tmp); - - tmp = RREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL); - tmp = REG_SET_FIELD(tmp, IH_INT_FLOOD_CNTL, FLOOD_CNTL_ENABLE, 1); - WREG32_SOC15(OSSSYS, 0, mmIH_INT_FLOOD_CNTL, tmp); - pci_set_master(adev->pdev);
/* enable interrupts */ @@ -380,11 +368,17 @@ static u32 vega20_ih_get_wptr(struct amdgpu_device *adev, u32 wptr, tmp; struct amdgpu_ih_regs *ih_regs;
- wptr = le32_to_cpu(*ih->wptr_cpu); - ih_regs = &ih->ih_regs; + if (ih == &adev->irq.ih) { + /* Only ring0 supports writeback. On other rings fall back + * to register-based code with overflow checking below. + */ + wptr = le32_to_cpu(*ih->wptr_cpu);
- if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) - goto out; + if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) + goto out; + } + + ih_regs = &ih->ih_regs;
/* Double check that the overflow wasn't already cleared. */ wptr = RREG32_NO_KIQ(ih_regs->ih_rb_wptr); @@ -476,15 +470,11 @@ static int vega20_ih_self_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - uint32_t wptr = cpu_to_le32(entry->src_data[0]); - switch (entry->ring_id) { case 1: - *adev->irq.ih1.wptr_cpu = wptr; schedule_work(&adev->irq.ih1_work); break; case 2: - *adev->irq.ih2.wptr_cpu = wptr; schedule_work(&adev->irq.ih2_work); break; default: break;
From: Alex Sierra alex.sierra@amd.com
[ Upstream commit 9a9c59a8f4f4478d5951eb0bded1d17b936aad6e ]
By default this timestamp is 32 bit counter. It gets overflowed in around 10 minutes.
Signed-off-by: Alex Sierra alex.sierra@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/vega20_ih.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c index 75b06e1964ab..86dcf448e0c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c @@ -104,6 +104,8 @@ static int vega20_ih_toggle_ring_interrupts(struct amdgpu_device *adev,
tmp = RREG32(ih_regs->ih_rb_cntl); tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_ENABLE, (enable ? 1 : 0)); + tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, RB_GPU_TS_ENABLE, 1); + /* enable_intr field is only valid in ring0 */ if (ih == &adev->irq.ih) tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, ENABLE_INTR, (enable ? 1 : 0));
From: Jonathan Kim jonathan.kim@amd.com
[ Upstream commit 4ac5617c4b7d0f0a8f879997f8ceaa14636d7554 ]
The psp supplies the link type in the upper 2 bits of the psp xgmi node information num_hops field. With a new link type, Aldebaran has these bits set to a non-zero value (1 = xGMI3) so the KFD topology will report the incorrect IO link weights without proper masking. The actual number of hops is located in the 3 least significant bits of this field so mask if off accordingly before passing it to the KFD.
Signed-off-by: Jonathan Kim jonathan.kim@amd.com Reviewed-by: Amber Lin amber.lin@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 659b385b27b5..4d3a24fdeb9c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -468,15 +468,22 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev }
+/* + * NOTE psp_xgmi_node_info.num_hops layout is as follows: + * num_hops[7:6] = link type (0 = xGMI2, 1 = xGMI3, 2/3 = reserved) + * num_hops[5:3] = reserved + * num_hops[2:0] = number of hops + */ int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev, struct amdgpu_device *peer_adev) { struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info; + uint8_t num_hops_mask = 0x7; int i;
for (i = 0 ; i < top->num_nodes; ++i) if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id) - return top->nodes[i].num_hops; + return top->nodes[i].num_hops & num_hops_mask; return -EINVAL; }
From: Anson Jacob Anson.Jacob@amd.com
[ Upstream commit 50e2fc36e72d4ad672032ebf646cecb48656efe0 ]
If get_num_sdma_queues or get_num_xgmi_sdma_queues is 0, we end up doing a shift operation where the number of bits shifted equals number of bits in the operand. This behaviour is undefined.
Set num_sdma_queues or num_xgmi_sdma_queues to ULLONG_MAX, if the count is >= number of bits in the operand.
Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1472
Reported-by: Lyude Paul lyude@redhat.com Signed-off-by: Anson Jacob Anson.Jacob@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com Reviewed-by: Felix Kuehling Felix.Kuehling@amd.com Tested-by: Lyude Paul lyude@redhat.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- .../drm/amd/amdkfd/kfd_device_queue_manager.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 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 4598a9a58125..a4266c4bca13 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1128,6 +1128,9 @@ static int set_sched_resources(struct device_queue_manager *dqm)
static int initialize_cpsch(struct device_queue_manager *dqm) { + uint64_t num_sdma_queues; + uint64_t num_xgmi_sdma_queues; + pr_debug("num of pipes: %d\n", get_pipes_per_mec(dqm));
mutex_init(&dqm->lock_hidden); @@ -1136,8 +1139,18 @@ static int initialize_cpsch(struct device_queue_manager *dqm) dqm->active_cp_queue_count = 0; dqm->gws_queue_count = 0; dqm->active_runlist = false; - dqm->sdma_bitmap = ~0ULL >> (64 - get_num_sdma_queues(dqm)); - dqm->xgmi_sdma_bitmap = ~0ULL >> (64 - get_num_xgmi_sdma_queues(dqm)); + + num_sdma_queues = get_num_sdma_queues(dqm); + if (num_sdma_queues >= BITS_PER_TYPE(dqm->sdma_bitmap)) + dqm->sdma_bitmap = ULLONG_MAX; + else + dqm->sdma_bitmap = (BIT_ULL(num_sdma_queues) - 1); + + num_xgmi_sdma_queues = get_num_xgmi_sdma_queues(dqm); + if (num_xgmi_sdma_queues >= BITS_PER_TYPE(dqm->xgmi_sdma_bitmap)) + dqm->xgmi_sdma_bitmap = ULLONG_MAX; + else + dqm->xgmi_sdma_bitmap = (BIT_ULL(num_xgmi_sdma_queues) - 1);
INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception);
From: Joshua Aberback joshua.aberback@amd.com
[ Upstream commit 554ba183b135ef09250b61a202d88512b5bbd03a ]
[Why] The registers for the address of the cursor are aligned to 2KB, so all cursor surfaces also need to be aligned to 2KB. Currently, the provided cursor cache surface is not aligned, so we need a workaround until alignment is enforced by the surface provider.
[How] - round up surface address to nearest multiple of 2048 - current policy is to provide a much bigger cache size than necessary,so this operation is safe
Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Joshua Aberback joshua.aberback@amd.com Reviewed-by: Jun Lei Jun.Lei@amd.com Acked-by: Eryk Brol eryk.brol@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 5 ++--- 1 file changed, 2 insertions(+), 3 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 06dc1e2e8383..07c8d2e2c09c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -848,7 +848,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
cmd.mall.cursor_copy_src.quad_part = cursor_attr.address.quad_part; cmd.mall.cursor_copy_dst.quad_part = - plane->address.grph.cursor_cache_addr.quad_part; + (plane->address.grph.cursor_cache_addr.quad_part + 2047) & ~2047; cmd.mall.cursor_width = cursor_attr.width; cmd.mall.cursor_height = cursor_attr.height; cmd.mall.cursor_pitch = cursor_attr.pitch; @@ -858,8 +858,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
/* Use copied cursor, and it's okay to not switch back */ - cursor_attr.address.quad_part = - plane->address.grph.cursor_cache_addr.quad_part; + cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part; dc_stream_set_cursor_attributes(stream, &cursor_attr); }
From: shaoyunl shaoyun.liu@amd.com
[ Upstream commit c8941550aa66b2a90f4b32c45d59e8571e33336e ]
This recent change introduce SDMA interrupt info printing with irq->process function. These functions do not require a set function to enable/disable the irq
Signed-off-by: shaoyunl shaoyun.liu@amd.com Reviewed-by: Hawking Zhang Hawking.Zhang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index afbbec82a289..9be945d8e72f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -535,7 +535,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev) for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) { struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
- if (!src) + if (!src || !src->funcs || !src->funcs->set) continue; for (k = 0; k < src->num_types; k++) amdgpu_irq_update(adev, src, k);
From: Kenneth Feng kenneth.feng@amd.com
[ Upstream commit 0979d43259e13846d86ba17e451e17fec185d240 ]
Workload number mapped to the correct one. This issue is only on vega10.
Signed-off-by: Kenneth Feng kenneth.feng@amd.com Reviewed-by: Kevin Wang kevin1.wang@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c index 599ec9726601..959143eff651 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -5160,7 +5160,7 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
out: smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, - 1 << power_profile_mode, + (!power_profile_mode) ? 0 : 1 << (power_profile_mode - 1), NULL); hwmgr->power_profile_mode = power_profile_mode;
From: Anson Jacob Anson.Jacob@amd.com
[ Upstream commit 6a30a92997eee49554f72b462dce90abe54a496f ]
[Why] dc_cursor_position do not initialise position.translate_by_source when crtc or plane->state->fb is NULL. UBSAN caught this error in dce110_set_cursor_position, as the value was garbage.
[How] Initialise dc_cursor_position structure elements to 0 in handle_cursor_update before calling get_cursor_position.
Tested-by: Daniel Wheeler daniel.wheeler@amd.com Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1471 Reported-by: Lyude Paul lyude@redhat.com Signed-off-by: Anson Jacob Anson.Jacob@amd.com Reviewed-by: Aurabindo Jayamohanan Pillai Aurabindo.Pillai@amd.com Acked-by: Solomon Chiu solomon.chiu@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +----- 1 file changed, 1 insertion(+), 5 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 8ad83ccfcc6a..167e04ab9d5b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7417,10 +7417,6 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, int x, y; int xorigin = 0, yorigin = 0;
- position->enable = false; - position->x = 0; - position->y = 0; - if (!crtc || !plane->state->fb) return 0;
@@ -7467,7 +7463,7 @@ static void handle_cursor_update(struct drm_plane *plane, struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint64_t address = afb ? afb->address : 0; - struct dc_cursor_position position; + struct dc_cursor_position position = {0}; struct dc_cursor_attributes attributes; int ret;
From: Aric Cyr aric.cyr@amd.com
[ Upstream commit 4710430a779e6077d81218ac768787545bff8c49 ]
[Why] When unplugging a display, the underflow counter can be seen to increase because PSTATE switch is allowed even when some planes are not blanked.
[How] Check that all planes are not active instead of all streams before allowing PSTATE change.
Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Aric Cyr aric.cyr@amd.com Acked-by: Solomon Chiu solomon.chiu@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
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 c7e5a64e06af..81ea5d3a1947 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 @@ -252,6 +252,7 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, bool force_reset = false; bool update_uclk = false; bool p_state_change_support; + int total_plane_count;
if (dc->work_arounds.skip_clock_update || !clk_mgr->smu_present) return; @@ -292,7 +293,8 @@ static void dcn3_update_clocks(struct clk_mgr *clk_mgr_base, clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz;
clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support; - p_state_change_support = new_clocks->p_state_change_support || (display_count == 0); + total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context); + p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0); if (should_update_pstate_support(safe_to_lower, p_state_change_support, clk_mgr_base->clks.p_state_change_support)) { clk_mgr_base->clks.p_state_change_support = p_state_change_support;
From: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com
[ Upstream commit 8ee0fea4baf90e43efe2275de208a7809f9985bc ]
Incorrect variable used, missing initialization during validation.
Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Dmytro Laktyushkin Dmytro.Laktyushkin@amd.com Reviewed-by: Eric Bernstein Eric.Bernstein@amd.com Acked-by: Solomon Chiu solomon.chiu@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c | 1 + drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c | 1 + 2 files changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c index 0f3f510fd83b..9729cf292e84 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c @@ -3437,6 +3437,7 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.DCCEnabledInAnyPlane = true; } } + mode_lib->vba.UrgentLatency = mode_lib->vba.UrgentLatencyPixelDataOnly; for (i = 0; i <= mode_lib->vba.soc.num_states; i++) { locals->FabricAndDRAMBandwidthPerState[i] = dml_min( mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index 210c96cd5b03..51098c2c9854 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -3544,6 +3544,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode mode_lib->vba.DCCEnabledInAnyPlane = true; } } + mode_lib->vba.UrgentLatency = mode_lib->vba.UrgentLatencyPixelDataOnly; for (i = 0; i <= mode_lib->vba.soc.num_states; i++) { locals->FabricAndDRAMBandwidthPerState[i] = dml_min( mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels
From: Qingqing Zhuo qingqing.zhuo@amd.com
[ Upstream commit 51ba691206e35464fd7ec33dd519d141c80b5dff ]
[Why] vblank_workqueue is never released.
[How] Free it upon dm finish.
Tested-by: Daniel Wheeler daniel.wheeler@amd.com Signed-off-by: Qingqing Zhuo qingqing.zhuo@amd.com Reviewed-by: Nicholas Kazlauskas Nicholas.Kazlauskas@amd.com Acked-by: Solomon Chiu solomon.chiu@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++++++++ 1 file changed, 9 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 167e04ab9d5b..9c243f66867a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1191,6 +1191,15 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) if (adev->dm.dc) dc_deinit_callbacks(adev->dm.dc); #endif + +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (adev->dm.vblank_workqueue) { + adev->dm.vblank_workqueue->dm = NULL; + kfree(adev->dm.vblank_workqueue); + adev->dm.vblank_workqueue = NULL; + } +#endif + if (adev->dm.dc->ctx->dmub_srv) { dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); adev->dm.dc->ctx->dmub_srv = NULL;
From: xinhui pan xinhui.pan@amd.com
[ Upstream commit 79fcd446e7e182c52c2c808c76f8de3eb6714349 ]
drm_gem_object_put() should be paired with drm_gem_object_lookup().
All gem objs are saved in fb->base.obj[]. Need put the old first before assign a new obj.
Trigger VRAM leak by running command below $ service gdm restart
Signed-off-by: xinhui pan xinhui.pan@amd.com Acked-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Alex Deucher alexander.deucher@amd.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index f753e04fee99..cbe050436c7b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -910,8 +910,9 @@ int amdgpu_display_framebuffer_init(struct drm_device *dev, }
for (i = 1; i < rfb->base.format->num_planes; ++i) { + drm_gem_object_get(rfb->base.obj[0]); + drm_gem_object_put(rfb->base.obj[i]); rfb->base.obj[i] = rfb->base.obj[0]; - drm_gem_object_get(rfb->base.obj[i]); }
return 0; @@ -960,6 +961,7 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev, return ERR_PTR(ret); }
+ drm_gem_object_put(obj); return &amdgpu_fb->base; }
From: Dmitry Vyukov dvyukov@google.com
[ Upstream commit b4142fc4d52d051d4d8df1fb6c569e5b445d369e ]
vkms_vblank_simulate() uses WARN_ON for timing-dependent condition (timer overrun). This is a mis-use of WARN_ON, WARN_ON must be used to denote kernel bugs. Use pr_warn() instead.
Signed-off-by: Dmitry Vyukov dvyukov@google.com Reported-by: syzbot+4fc21a003c8332eb0bdd@syzkaller.appspotmail.com Cc: Rodrigo Siqueira rodrigosiqueiramelo@gmail.com Cc: Melissa Wen melissa.srw@gmail.com Cc: Haneen Mohammed hamohammed.sa@gmail.com Cc: Daniel Vetter daniel@ffwll.ch Cc: David Airlie airlied@linux.ie Cc: dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org Acked-by: Melissa Wen melissa.srw@gmail.com Signed-off-by: Melissa Wen melissa.srw@gmail.com Link: https://patchwork.freedesktop.org/patch/msgid/20210320132840.1315853-1-dvyuk... Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/vkms/vkms_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 0443b7deeaef..758d8a98d96b 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -18,7 +18,8 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer, output->period_ns); - WARN_ON(ret_overrun != 1); + if (ret_overrun != 1) + pr_warn("%s: vblank timer overrun\n", __func__);
spin_lock(&output->lock); ret = drm_crtc_handle_vblank(crtc);
dri-devel@lists.freedesktop.org