From ea42803a1afa8c5dfa3af9d1a67ce4d745098185 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 28 Jan 2024 19:17:57 -0500 Subject: [PATCH] Fixes for 6.7 Signed-off-by: Sasha Levin --- ...-factor-out-prepare_allocation_zoned.patch | 75 ++ ...timize-hint-byte-for-zoned-allocator.patch | 63 ++ ...-display-add-logging-resource-checks.patch | 76 ++ ...lay-clear-optc-mem-select-on-disable.patch | 62 ++ ...disconnect-phantom-pipe-opp-from-opt.patch | 109 +++ ...do-not-send-commands-to-dmub-if-dmub.patch | 188 ++++ ...fix-conversions-between-bytes-and-kb.patch | 105 +++ ...fix-hang-underflow-when-transitionin.patch | 68 ++ ...init-link-enc-resources-in-dc_state-.patch | 45 + ...refactor-dmcub-enter-exit-idle-inter.patch | 205 +++++ ...update-pixel-clock-params-after-stre.patch | 168 ++++ ...wake-dmcub-before-executing-gpint-co.patch | 216 +++++ ...-wake-dmcub-before-sending-a-command.patch | 826 ++++++++++++++++++ ...e-tunneling-on-high-priority-compute.patch | 122 +++ ...0-set-unord_dispatch-in-compute-mqds.patch | 52 ++ ...1-set-unord_dispatch-in-compute-mqds.patch | 52 ++ ...d-auo-b116xtn02-boe-nt116whm-n21-836.patch | 50 ++ ...m-panel-edp-fix-auo-b116xak01-name-a.patch | 50 ++ ...drm-panel-edp-fix-auo-b116xtn02-name.patch | 39 + ...-properly-encode-registers-as-little.patch | 102 +++ ...d-macros-to-obtain-register-width-an.patch | 79 ++ .../media-v4l-cci-include-linux-bits.h.patch | 36 + ...dd-support-for-little-endian-encoded.patch | 154 ++++ queue-6.7/series | 26 + ...i-add-syscore-callbacks-for-system-w.patch | 101 +++ ...i-disable-an-hfi-instance-when-all-i.patch | 98 +++ ...i-refactor-enabling-code-into-helper.patch | 108 +++ 27 files changed, 3275 insertions(+) create mode 100644 queue-6.7/btrfs-zoned-factor-out-prepare_allocation_zoned.patch create mode 100644 queue-6.7/btrfs-zoned-optimize-hint-byte-for-zoned-allocator.patch create mode 100644 queue-6.7/drm-amd-display-add-logging-resource-checks.patch create mode 100644 queue-6.7/drm-amd-display-clear-optc-mem-select-on-disable.patch create mode 100644 queue-6.7/drm-amd-display-disconnect-phantom-pipe-opp-from-opt.patch create mode 100644 queue-6.7/drm-amd-display-do-not-send-commands-to-dmub-if-dmub.patch create mode 100644 queue-6.7/drm-amd-display-fix-conversions-between-bytes-and-kb.patch create mode 100644 queue-6.7/drm-amd-display-fix-hang-underflow-when-transitionin.patch create mode 100644 queue-6.7/drm-amd-display-init-link-enc-resources-in-dc_state-.patch create mode 100644 queue-6.7/drm-amd-display-refactor-dmcub-enter-exit-idle-inter.patch create mode 100644 queue-6.7/drm-amd-display-update-pixel-clock-params-after-stre.patch create mode 100644 queue-6.7/drm-amd-display-wake-dmcub-before-executing-gpint-co.patch create mode 100644 queue-6.7/drm-amd-display-wake-dmcub-before-sending-a-command.patch create mode 100644 queue-6.7/drm-amdgpu-enable-tunneling-on-high-priority-compute.patch create mode 100644 queue-6.7/drm-amdgpu-gfx10-set-unord_dispatch-in-compute-mqds.patch create mode 100644 queue-6.7/drm-amdgpu-gfx11-set-unord_dispatch-in-compute-mqds.patch create mode 100644 queue-6.7/drm-panel-edp-add-auo-b116xtn02-boe-nt116whm-n21-836.patch create mode 100644 queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xak01-name-a.patch create mode 100644 queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xtn02-name.patch create mode 100644 queue-6.7/media-i2c-imx290-properly-encode-registers-as-little.patch create mode 100644 queue-6.7/media-v4l-cci-add-macros-to-obtain-register-width-an.patch create mode 100644 queue-6.7/media-v4l-cci-include-linux-bits.h.patch create mode 100644 queue-6.7/media-v4l2-cci-add-support-for-little-endian-encoded.patch create mode 100644 queue-6.7/thermal-intel-hfi-add-syscore-callbacks-for-system-w.patch create mode 100644 queue-6.7/thermal-intel-hfi-disable-an-hfi-instance-when-all-i.patch create mode 100644 queue-6.7/thermal-intel-hfi-refactor-enabling-code-into-helper.patch diff --git a/queue-6.7/btrfs-zoned-factor-out-prepare_allocation_zoned.patch b/queue-6.7/btrfs-zoned-factor-out-prepare_allocation_zoned.patch new file mode 100644 index 00000000000..9585f083f87 --- /dev/null +++ b/queue-6.7/btrfs-zoned-factor-out-prepare_allocation_zoned.patch @@ -0,0 +1,75 @@ +From a317a45f938cea69bcf7dcac8eca6a09058d63cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 01:02:28 +0900 +Subject: btrfs: zoned: factor out prepare_allocation_zoned() + +From: Naohiro Aota + +[ Upstream commit b271fee9a41ca1474d30639fd6cc912c9901d0f8 ] + +Factor out prepare_allocation_zoned() for further extension. While at +it, optimize the if-branch a bit. + +Reviewed-by: Johannes Thumshirn +Signed-off-by: Naohiro Aota +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Stable-dep-of: 02444f2ac26e ("btrfs: zoned: optimize hint byte for zoned allocator") +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent-tree.c | 32 +++++++++++++++++++------------- + 1 file changed, 19 insertions(+), 13 deletions(-) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 9c8b00a917bd..9307891b4a85 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4301,6 +4301,24 @@ static int prepare_allocation_clustered(struct btrfs_fs_info *fs_info, + return 0; + } + ++static int prepare_allocation_zoned(struct btrfs_fs_info *fs_info, ++ struct find_free_extent_ctl *ffe_ctl) ++{ ++ if (ffe_ctl->for_treelog) { ++ spin_lock(&fs_info->treelog_bg_lock); ++ if (fs_info->treelog_bg) ++ ffe_ctl->hint_byte = fs_info->treelog_bg; ++ spin_unlock(&fs_info->treelog_bg_lock); ++ } else if (ffe_ctl->for_data_reloc) { ++ spin_lock(&fs_info->relocation_bg_lock); ++ if (fs_info->data_reloc_bg) ++ ffe_ctl->hint_byte = fs_info->data_reloc_bg; ++ spin_unlock(&fs_info->relocation_bg_lock); ++ } ++ ++ return 0; ++} ++ + static int prepare_allocation(struct btrfs_fs_info *fs_info, + struct find_free_extent_ctl *ffe_ctl, + struct btrfs_space_info *space_info, +@@ -4311,19 +4329,7 @@ static int prepare_allocation(struct btrfs_fs_info *fs_info, + return prepare_allocation_clustered(fs_info, ffe_ctl, + space_info, ins); + case BTRFS_EXTENT_ALLOC_ZONED: +- if (ffe_ctl->for_treelog) { +- spin_lock(&fs_info->treelog_bg_lock); +- if (fs_info->treelog_bg) +- ffe_ctl->hint_byte = fs_info->treelog_bg; +- spin_unlock(&fs_info->treelog_bg_lock); +- } +- if (ffe_ctl->for_data_reloc) { +- spin_lock(&fs_info->relocation_bg_lock); +- if (fs_info->data_reloc_bg) +- ffe_ctl->hint_byte = fs_info->data_reloc_bg; +- spin_unlock(&fs_info->relocation_bg_lock); +- } +- return 0; ++ return prepare_allocation_zoned(fs_info, ffe_ctl); + default: + BUG(); + } +-- +2.43.0 + diff --git a/queue-6.7/btrfs-zoned-optimize-hint-byte-for-zoned-allocator.patch b/queue-6.7/btrfs-zoned-optimize-hint-byte-for-zoned-allocator.patch new file mode 100644 index 00000000000..a167097c650 --- /dev/null +++ b/queue-6.7/btrfs-zoned-optimize-hint-byte-for-zoned-allocator.patch @@ -0,0 +1,63 @@ +From 1f1a0d7981c1ff0b900725a9b72082d2469358e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 01:02:29 +0900 +Subject: btrfs: zoned: optimize hint byte for zoned allocator + +From: Naohiro Aota + +[ Upstream commit 02444f2ac26eae6385a65fcd66915084d15dffba ] + +Writing sequentially to a huge file on btrfs on a SMR HDD revealed a +decline of the performance (220 MiB/s to 30 MiB/s after 500 minutes). + +The performance goes down because of increased latency of the extent +allocation, which is induced by a traversing of a lot of full block groups. + +So, this patch optimizes the ffe_ctl->hint_byte by choosing a block group +with sufficient size from the active block group list, which does not +contain full block groups. + +After applying the patch, the performance is maintained well. + +Fixes: 2eda57089ea3 ("btrfs: zoned: implement sequential extent allocation") +CC: stable@vger.kernel.org # 5.15+ +Reviewed-by: Johannes Thumshirn +Signed-off-by: Naohiro Aota +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent-tree.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index 9307891b4a85..31d64812bb60 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -4314,6 +4314,24 @@ static int prepare_allocation_zoned(struct btrfs_fs_info *fs_info, + if (fs_info->data_reloc_bg) + ffe_ctl->hint_byte = fs_info->data_reloc_bg; + spin_unlock(&fs_info->relocation_bg_lock); ++ } else if (ffe_ctl->flags & BTRFS_BLOCK_GROUP_DATA) { ++ struct btrfs_block_group *block_group; ++ ++ spin_lock(&fs_info->zone_active_bgs_lock); ++ list_for_each_entry(block_group, &fs_info->zone_active_bgs, active_bg_list) { ++ /* ++ * No lock is OK here because avail is monotinically ++ * decreasing, and this is just a hint. ++ */ ++ u64 avail = block_group->zone_capacity - block_group->alloc_offset; ++ ++ if (block_group_bits(block_group, ffe_ctl->flags) && ++ avail >= ffe_ctl->num_bytes) { ++ ffe_ctl->hint_byte = block_group->start; ++ break; ++ } ++ } ++ spin_unlock(&fs_info->zone_active_bgs_lock); + } + + return 0; +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-add-logging-resource-checks.patch b/queue-6.7/drm-amd-display-add-logging-resource-checks.patch new file mode 100644 index 00000000000..429bf7b5204 --- /dev/null +++ b/queue-6.7/drm-amd-display-add-logging-resource-checks.patch @@ -0,0 +1,76 @@ +From c5c83cba01f9edd822739b084a53a8744d777b9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Dec 2023 13:19:33 -0500 +Subject: drm/amd/display: Add logging resource checks + +From: Charlene Liu + +[ Upstream commit 8a51cc097dd590a86e8eec5398934ef389ff9a7b ] + +[Why] +When mapping resources, resources could be unavailable. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Sung joon Kim +Acked-by: Alex Hung +Signed-off-by: Charlene Liu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 7 ++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index c535ddb45a36..bc098098345c 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -3626,7 +3626,7 @@ static void commit_planes_for_stream(struct dc *dc, + top_pipe_to_program = resource_get_otg_master_for_stream( + &context->res_ctx, + stream); +- ++ ASSERT(top_pipe_to_program != NULL); + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + +@@ -4457,6 +4457,8 @@ static bool should_commit_minimal_transition_for_windowed_mpo_odm(struct dc *dc, + + cur_pipe = resource_get_otg_master_for_stream(&dc->current_state->res_ctx, stream); + new_pipe = resource_get_otg_master_for_stream(&context->res_ctx, stream); ++ if (!cur_pipe || !new_pipe) ++ return false; + cur_is_odm_in_use = resource_get_odm_slice_count(cur_pipe) > 1; + new_is_odm_in_use = resource_get_odm_slice_count(new_pipe) > 1; + if (cur_is_odm_in_use == new_is_odm_in_use) +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 e4bb1e25ee3b..ae275f1780d5 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -2170,6 +2170,10 @@ void resource_log_pipe_topology_update(struct dc *dc, struct dc_state *state) + for (stream_idx = 0; stream_idx < state->stream_count; stream_idx++) { + otg_master = resource_get_otg_master_for_stream( + &state->res_ctx, state->streams[stream_idx]); ++ if (!otg_master || otg_master->stream_res.tg == NULL) { ++ DC_LOG_DC("topology update: otg_master NULL stream_idx %d!\n", stream_idx); ++ return; ++ } + slice_count = resource_get_opp_heads_for_otg_master(otg_master, + &state->res_ctx, opp_heads); + for (slice_idx = 0; slice_idx < slice_count; slice_idx++) { +@@ -2990,7 +2994,8 @@ bool dc_add_plane_to_context( + + otg_master_pipe = resource_get_otg_master_for_stream( + &context->res_ctx, stream); +- added = resource_append_dpp_pipes_for_plane_composition(context, ++ if (otg_master_pipe) ++ added = resource_append_dpp_pipes_for_plane_composition(context, + dc->current_state, pool, otg_master_pipe, plane_state); + + if (added) { +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-clear-optc-mem-select-on-disable.patch b/queue-6.7/drm-amd-display-clear-optc-mem-select-on-disable.patch new file mode 100644 index 00000000000..ceef7344643 --- /dev/null +++ b/queue-6.7/drm-amd-display-clear-optc-mem-select-on-disable.patch @@ -0,0 +1,62 @@ +From aaad8d7273b03ba4bd2f2450015fed77700a347c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jan 2024 09:42:04 -0500 +Subject: drm/amd/display: Clear OPTC mem select on disable + +From: Ilya Bakoulin + +[ Upstream commit 3ba2a0bfd8cf94eb225e1c60dff16e5c35bde1da ] + +[Why] +Not clearing the memory select bits prior to OPTC disable can cause DSC +corruption issues when attempting to reuse a memory instance for another +OPTC that enables ODM. + +[How] +Clear the memory select bits prior to disabling an OPTC. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Charlene Liu +Acked-by: Alex Hung +Signed-off-by: Ilya Bakoulin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 3 +++ + drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +index 1788eb29474b..823493543325 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +@@ -173,6 +173,9 @@ static bool optc32_disable_crtc(struct timing_generator *optc) + OPTC_SEG3_SRC_SEL, 0xf, + OPTC_NUM_OF_INPUT_SEGMENT, 0); + ++ REG_UPDATE(OPTC_MEMORY_CONFIG, ++ OPTC_MEM_SEL, 0); ++ + /* disable otg request until end of the first line + * in the vertical blank region + */ +diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +index 3d6c1b2c2b4d..5b1547508850 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +@@ -145,6 +145,9 @@ static bool optc35_disable_crtc(struct timing_generator *optc) + OPTC_SEG3_SRC_SEL, 0xf, + OPTC_NUM_OF_INPUT_SEGMENT, 0); + ++ REG_UPDATE(OPTC_MEMORY_CONFIG, ++ OPTC_MEM_SEL, 0); ++ + /* disable otg request until end of the first line + * in the vertical blank region + */ +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-disconnect-phantom-pipe-opp-from-opt.patch b/queue-6.7/drm-amd-display-disconnect-phantom-pipe-opp-from-opt.patch new file mode 100644 index 00000000000..0b235b2e1b2 --- /dev/null +++ b/queue-6.7/drm-amd-display-disconnect-phantom-pipe-opp-from-opt.patch @@ -0,0 +1,109 @@ +From d72780123c58fdaa42a4f60119ccf69668af4d17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Dec 2023 17:17:57 -0500 +Subject: drm/amd/display: Disconnect phantom pipe OPP from OPTC being disabled + +From: George Shen + +[ Upstream commit 7bdbfb4e36e34eb788e44f27666bf0a2b3b90803 ] + +[Why] +If an OPP is used for a different OPTC without first being disconnected +from the previous OPTC, unexpected behaviour can occur. This also +applies to phantom pipes, which is what the current logic missed. + +[How] +Disconnect OPPs from OPTC for phantom pipes before disabling OTG master. + +Also move the disconnection to before the OTG master disable, since the +register is double buffered. + +Reviewed-by: Dillon Varone +Acked-by: Rodrigo Siqueira +Signed-off-by: George Shen +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 3ba2a0bfd8cf ("drm/amd/display: Clear OPTC mem select on disable") +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 19 +++++++++++++------ + .../gpu/drm/amd/display/dc/dcn35/dcn35_optc.c | 12 ++++++------ + 2 files changed, 19 insertions(+), 12 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +index 91ea0d4da06a..1788eb29474b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +@@ -166,12 +166,6 @@ static bool optc32_disable_crtc(struct timing_generator *optc) + { + struct optc *optc1 = DCN10TG_FROM_TG(optc); + +- /* disable otg request until end of the first line +- * in the vertical blank region +- */ +- REG_UPDATE(OTG_CONTROL, +- OTG_MASTER_EN, 0); +- + REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, 0xf, + OPTC_SEG1_SRC_SEL, 0xf, +@@ -179,6 +173,12 @@ static bool optc32_disable_crtc(struct timing_generator *optc) + OPTC_SEG3_SRC_SEL, 0xf, + OPTC_NUM_OF_INPUT_SEGMENT, 0); + ++ /* disable otg request until end of the first line ++ * in the vertical blank region ++ */ ++ REG_UPDATE(OTG_CONTROL, ++ OTG_MASTER_EN, 0); ++ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + +@@ -205,6 +205,13 @@ static void optc32_disable_phantom_otg(struct timing_generator *optc) + { + struct optc *optc1 = DCN10TG_FROM_TG(optc); + ++ REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, ++ OPTC_SEG0_SRC_SEL, 0xf, ++ OPTC_SEG1_SRC_SEL, 0xf, ++ OPTC_SEG2_SRC_SEL, 0xf, ++ OPTC_SEG3_SRC_SEL, 0xf, ++ OPTC_NUM_OF_INPUT_SEGMENT, 0); ++ + REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0); + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +index 08a59cf449ca..3d6c1b2c2b4d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +@@ -138,12 +138,6 @@ static bool optc35_disable_crtc(struct timing_generator *optc) + { + struct optc *optc1 = DCN10TG_FROM_TG(optc); + +- /* disable otg request until end of the first line +- * in the vertical blank region +- */ +- REG_UPDATE(OTG_CONTROL, +- OTG_MASTER_EN, 0); +- + REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, + OPTC_SEG0_SRC_SEL, 0xf, + OPTC_SEG1_SRC_SEL, 0xf, +@@ -151,6 +145,12 @@ static bool optc35_disable_crtc(struct timing_generator *optc) + OPTC_SEG3_SRC_SEL, 0xf, + OPTC_NUM_OF_INPUT_SEGMENT, 0); + ++ /* disable otg request until end of the first line ++ * in the vertical blank region ++ */ ++ REG_UPDATE(OTG_CONTROL, ++ OTG_MASTER_EN, 0); ++ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-do-not-send-commands-to-dmub-if-dmub.patch b/queue-6.7/drm-amd-display-do-not-send-commands-to-dmub-if-dmub.patch new file mode 100644 index 00000000000..535673719e9 --- /dev/null +++ b/queue-6.7/drm-amd-display-do-not-send-commands-to-dmub-if-dmub.patch @@ -0,0 +1,188 @@ +From 8134e950367e2fdc64ba284b01989421d5c41d1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Nov 2023 16:53:12 -0500 +Subject: drm/amd/display: do not send commands to DMUB if DMUB is inactive + from S3 + +From: Samson Tam + +[ Upstream commit 0f657938e4345a77be871d906f3e0de3c58a7a49 ] + +[Why] +On resume from S3, may get apply_idle_optimizations call while DMUB +is inactive which will just time out. + +[How] +Set and track power state in dmub_srv and check power state before +sending commands to DMUB. Add interface in both dmub_srv and +dc_dmub_srv + +Reviewed-by: Nicholas Kazlauskas +Acked-by: Wayne Lin +Signed-off-by: Samson Tam +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 8892780834ae ("drm/amd/display: Wake DMCUB before sending a command") +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 14 +++++++++++++ + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 2 ++ + drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 21 +++++++++++++++++++ + .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 15 +++++++++++++ + 5 files changed, 55 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 a9bd020b165a..4d534ac18356 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -2656,6 +2656,7 @@ static int dm_suspend(void *handle) + hpd_rx_irq_work_suspend(dm); + + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); ++ dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D3); + + return 0; + } +@@ -2851,6 +2852,7 @@ static int dm_resume(void *handle) + if (r) + DRM_ERROR("DMUB interface failed to initialize: status=%d\n", r); + ++ dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); + + dc_resume(dm->dc); +@@ -2901,6 +2903,7 @@ static int dm_resume(void *handle) + } + + /* power on hardware */ ++ dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); + + /* program HPD filter */ +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index 0e07699c1e83..0c963dfd6061 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -1251,3 +1251,17 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) + ASSERT(0); + } + ++void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState) ++{ ++ struct dmub_srv *dmub; ++ ++ if (!dc_dmub_srv) ++ return; ++ ++ dmub = dc_dmub_srv->dmub; ++ ++ if (powerState == DC_ACPI_CM_POWER_STATE_D0) ++ dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D0); ++ else ++ dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3); ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +index d4a60f53faab..c25ce7546f71 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +@@ -102,4 +102,6 @@ void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, con + bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait); + void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle); + void dc_dmub_srv_exit_low_power_state(const struct dc *dc); ++ ++void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState); + #endif /* _DMUB_DC_SRV_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +index df63aa8f01e9..d1a4ed6f5916 100644 +--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +@@ -150,6 +150,13 @@ enum dmub_memory_access_type { + DMUB_MEMORY_ACCESS_DMA + }; + ++/* enum dmub_power_state type - to track DC power state in dmub_srv */ ++enum dmub_srv_power_state_type { ++ DMUB_POWER_STATE_UNDEFINED = 0, ++ DMUB_POWER_STATE_D0 = 1, ++ DMUB_POWER_STATE_D3 = 8 ++}; ++ + /** + * struct dmub_region - dmub hw memory region + * @base: base address for region, must be 256 byte aligned +@@ -485,6 +492,8 @@ struct dmub_srv { + /* Feature capabilities reported by fw */ + struct dmub_feature_caps feature_caps; + struct dmub_visual_confirm_color visual_confirm_color; ++ ++ enum dmub_srv_power_state_type power_state; + }; + + /** +@@ -889,6 +898,18 @@ enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub); + */ + void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_address *addr, uint8_t subvp_index); + ++/** ++ * dmub_srv_set_power_state() - Track DC power state in dmub_srv ++ * @dmub: The dmub service ++ * @power_state: DC power state setting ++ * ++ * Store DC power state in dmub_srv. If dmub_srv is in D3, then don't send messages to DMUB ++ * ++ * Return: ++ * void ++ */ ++void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state); ++ + #if defined(__cplusplus) + } + #endif +diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +index 38360adc53d9..59d4e64845ca 100644 +--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +@@ -713,6 +713,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub, + dmub->hw_funcs.reset_release(dmub); + + dmub->hw_init = true; ++ dmub->power_state = DMUB_POWER_STATE_D0; + + return DMUB_STATUS_OK; + } +@@ -766,6 +767,9 @@ enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub, + if (!dmub->hw_init) + return DMUB_STATUS_INVALID; + ++ if (dmub->power_state != DMUB_POWER_STATE_D0) ++ return DMUB_STATUS_INVALID; ++ + if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity || + dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) { + return DMUB_STATUS_HW_FAILURE; +@@ -784,6 +788,9 @@ enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub) + if (!dmub->hw_init) + return DMUB_STATUS_INVALID; + ++ if (dmub->power_state != DMUB_POWER_STATE_D0) ++ return DMUB_STATUS_INVALID; ++ + /** + * Read back all the queued commands to ensure that they've + * been flushed to framebuffer memory. Otherwise DMCUB might +@@ -1100,3 +1107,11 @@ void dmub_srv_subvp_save_surf_addr(struct dmub_srv *dmub, const struct dc_plane_ + subvp_index); + } + } ++ ++void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_type dmub_srv_power_state) ++{ ++ if (!dmub || !dmub->hw_init) ++ return; ++ ++ dmub->power_state = dmub_srv_power_state; ++} +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-fix-conversions-between-bytes-and-kb.patch b/queue-6.7/drm-amd-display-fix-conversions-between-bytes-and-kb.patch new file mode 100644 index 00000000000..0db050ce246 --- /dev/null +++ b/queue-6.7/drm-amd-display-fix-conversions-between-bytes-and-kb.patch @@ -0,0 +1,105 @@ +From adfaf31b4d2d066f808bda9de05a7bb8fed9d8e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Nov 2023 10:15:28 -0500 +Subject: drm/amd/display: Fix conversions between bytes and KB + +From: Taimur Hassan + +[ Upstream commit 22136ff27c4e01fae81f6588033363a46c72ed8c ] + +[Why] +There are a number of instances where we convert HostVMMinPageSize or +GPUVMMinPageSize from bytes to KB by dividing (rather than multiplying) and +vice versa. +Additionally, in some cases, a parameter is passed through DML in KB but +later checked as if it were in bytes. + +Cc: stable@vger.kernel.org +Reviewed-by: Nicholas Kazlauskas +Acked-by: Hamza Mahfooz +Signed-off-by: Taimur Hassan +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/dml2/display_mode_core.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c +index 4899e9e8c163..62ce95bac8f2 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c ++++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c +@@ -6329,7 +6329,7 @@ static void dml_prefetch_check(struct display_mode_lib_st *mode_lib) + mode_lib->ms.NoOfDPPThisState, + mode_lib->ms.dpte_group_bytes, + s->HostVMInefficiencyFactor, +- mode_lib->ms.soc.hostvm_min_page_size_kbytes, ++ mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, + mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels); + + s->NextMaxVStartup = s->MaxVStartupAllPlanes[j]; +@@ -6542,7 +6542,7 @@ static void dml_prefetch_check(struct display_mode_lib_st *mode_lib) + mode_lib->ms.cache_display_cfg.plane.HostVMEnable, + mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels, + mode_lib->ms.cache_display_cfg.plane.GPUVMEnable, +- mode_lib->ms.soc.hostvm_min_page_size_kbytes, ++ mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, + mode_lib->ms.PDEAndMetaPTEBytesPerFrame[j][k], + mode_lib->ms.MetaRowBytes[j][k], + mode_lib->ms.DPTEBytesPerRow[j][k], +@@ -7687,7 +7687,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib) + CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; + CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; + CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes; +- CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; ++ CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; + CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn; + CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode; + CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = mode_lib->ms.PTEBufferSizeNotExceededPerState; +@@ -7957,7 +7957,7 @@ dml_bool_t dml_core_mode_support(struct display_mode_lib_st *mode_lib) + UseMinimumDCFCLK_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; + UseMinimumDCFCLK_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable; + UseMinimumDCFCLK_params->NumberOfActiveSurfaces = mode_lib->ms.num_active_planes; +- UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; ++ UseMinimumDCFCLK_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; + UseMinimumDCFCLK_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; + UseMinimumDCFCLK_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled; + UseMinimumDCFCLK_params->ImmediateFlipRequirement = s->ImmediateFlipRequiredFinal; +@@ -8699,7 +8699,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc + CalculateVMRowAndSwath_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; + CalculateVMRowAndSwath_params->GPUVMMaxPageTableLevels = mode_lib->ms.cache_display_cfg.plane.GPUVMMaxPageTableLevels; + CalculateVMRowAndSwath_params->GPUVMMinPageSizeKBytes = mode_lib->ms.cache_display_cfg.plane.GPUVMMinPageSizeKBytes; +- CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; ++ CalculateVMRowAndSwath_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; + CalculateVMRowAndSwath_params->PTEBufferModeOverrideEn = mode_lib->ms.cache_display_cfg.plane.PTEBufferModeOverrideEn; + CalculateVMRowAndSwath_params->PTEBufferModeOverrideVal = mode_lib->ms.cache_display_cfg.plane.PTEBufferMode; + CalculateVMRowAndSwath_params->PTEBufferSizeNotExceeded = s->dummy_boolean_array[0]; +@@ -8805,7 +8805,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc + mode_lib->ms.cache_display_cfg.hw.DPPPerSurface, + locals->dpte_group_bytes, + s->HostVMInefficiencyFactor, +- mode_lib->ms.soc.hostvm_min_page_size_kbytes, ++ mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, + mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels); + + locals->TCalc = 24.0 / locals->DCFCLKDeepSleep; +@@ -8995,7 +8995,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc + CalculatePrefetchSchedule_params->GPUVMEnable = mode_lib->ms.cache_display_cfg.plane.GPUVMEnable; + CalculatePrefetchSchedule_params->HostVMEnable = mode_lib->ms.cache_display_cfg.plane.HostVMEnable; + CalculatePrefetchSchedule_params->HostVMMaxNonCachedPageTableLevels = mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels; +- CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes; ++ CalculatePrefetchSchedule_params->HostVMMinPageSize = mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024; + CalculatePrefetchSchedule_params->DynamicMetadataEnable = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataEnable[k]; + CalculatePrefetchSchedule_params->DynamicMetadataVMEnabled = mode_lib->ms.ip.dynamic_metadata_vm_enabled; + CalculatePrefetchSchedule_params->DynamicMetadataLinesBeforeActiveRequired = mode_lib->ms.cache_display_cfg.plane.DynamicMetadataLinesBeforeActiveRequired[k]; +@@ -9240,7 +9240,7 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc + mode_lib->ms.cache_display_cfg.plane.HostVMEnable, + mode_lib->ms.cache_display_cfg.plane.HostVMMaxPageTableLevels, + mode_lib->ms.cache_display_cfg.plane.GPUVMEnable, +- mode_lib->ms.soc.hostvm_min_page_size_kbytes, ++ mode_lib->ms.soc.hostvm_min_page_size_kbytes * 1024, + locals->PDEAndMetaPTEBytesFrame[k], + locals->MetaRowByte[k], + locals->PixelPTEBytesPerRow[k], +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-fix-hang-underflow-when-transitionin.patch b/queue-6.7/drm-amd-display-fix-hang-underflow-when-transitionin.patch new file mode 100644 index 00000000000..b43576c53e8 --- /dev/null +++ b/queue-6.7/drm-amd-display-fix-hang-underflow-when-transitionin.patch @@ -0,0 +1,68 @@ +From cd9cde88c70653798c347b09555d9ef6ac86b9a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Dec 2023 12:19:33 -0500 +Subject: drm/amd/display: Fix hang/underflow when transitioning to ODM4:1 + +From: Ilya Bakoulin + +[ Upstream commit e7b2b108cdeab76a7e7324459e50b0c1214c0386 ] + +[Why] +Under some circumstances, disabling an OPTC and attempting to reclaim +its OPP(s) for a different OPTC could cause a hang/underflow due to OPPs +not being properly disconnected from the disabled OPTC. + +[How] +Ensure that all OPPs are unassigned from an OPTC when it gets disabled. + +Reviewed-by: Alvin Lee +Acked-by: Wayne Lin +Signed-off-by: Ilya Bakoulin +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 3ba2a0bfd8cf ("drm/amd/display: Clear OPTC mem select on disable") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 7 +++++++ + drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c | 7 +++++++ + 2 files changed, 14 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +index a2c4db2cebdd..91ea0d4da06a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +@@ -172,6 +172,13 @@ static bool optc32_disable_crtc(struct timing_generator *optc) + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 0); + ++ REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, ++ OPTC_SEG0_SRC_SEL, 0xf, ++ OPTC_SEG1_SRC_SEL, 0xf, ++ OPTC_SEG2_SRC_SEL, 0xf, ++ OPTC_SEG3_SRC_SEL, 0xf, ++ OPTC_NUM_OF_INPUT_SEGMENT, 0); ++ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +index a4a39f1638cf..08a59cf449ca 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_optc.c +@@ -144,6 +144,13 @@ static bool optc35_disable_crtc(struct timing_generator *optc) + REG_UPDATE(OTG_CONTROL, + OTG_MASTER_EN, 0); + ++ REG_UPDATE_5(OPTC_DATA_SOURCE_SELECT, ++ OPTC_SEG0_SRC_SEL, 0xf, ++ OPTC_SEG1_SRC_SEL, 0xf, ++ OPTC_SEG2_SRC_SEL, 0xf, ++ OPTC_SEG3_SRC_SEL, 0xf, ++ OPTC_NUM_OF_INPUT_SEGMENT, 0); ++ + REG_UPDATE(CONTROL, + VTG0_ENABLE, 0); + +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-init-link-enc-resources-in-dc_state-.patch b/queue-6.7/drm-amd-display-init-link-enc-resources-in-dc_state-.patch new file mode 100644 index 00000000000..7941881345b --- /dev/null +++ b/queue-6.7/drm-amd-display-init-link-enc-resources-in-dc_state-.patch @@ -0,0 +1,45 @@ +From 88a32cde75f9b2fa211cab3ede41a177fef63397 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Dec 2023 21:36:39 -0500 +Subject: drm/amd/display: Init link enc resources in dc_state only if res_pool + presents + +From: Dillon Varone + +[ Upstream commit aa36d8971fccb55ef3241cbfff9d1799e31d8628 ] + +[Why & How] +res_pool is not initialized in all situations such as virtual +environments, and therefore link encoder resources should not be +initialized if res_pool is NULL. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Martin Leung +Acked-by: Alex Hung +Signed-off-by: Dillon Varone +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++- + 1 file 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 c16190a10883..990d775e4cea 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -3774,7 +3774,8 @@ void dc_resource_state_construct( + dst_ctx->clk_mgr = dc->clk_mgr; + + /* Initialise DIG link encoder resource tracking variables. */ +- link_enc_cfg_init(dc, dst_ctx); ++ if (dc->res_pool) ++ link_enc_cfg_init(dc, dst_ctx); + } + + +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-refactor-dmcub-enter-exit-idle-inter.patch b/queue-6.7/drm-amd-display-refactor-dmcub-enter-exit-idle-inter.patch new file mode 100644 index 00000000000..aeeba82ce3c --- /dev/null +++ b/queue-6.7/drm-amd-display-refactor-dmcub-enter-exit-idle-inter.patch @@ -0,0 +1,205 @@ +From 3f7d674fd70342b8208e439bb5838cbae7ce33db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 14:10:05 -0500 +Subject: drm/amd/display: Refactor DMCUB enter/exit idle interface + +From: Nicholas Kazlauskas + +[ Upstream commit 8e57c06bf4b0f51a4d6958e15e1a99c9520d00fa ] + +[Why] +We can hang in place trying to send commands when the DMCUB isn't +powered on. + +[How] +We need to exit out of the idle state prior to sending a command, +but the process that performs the exit also invokes a command itself. + +Fixing this issue involves the following: + +1. Using a software state to track whether or not we need to start + the process to exit idle or notify idle. + +It's possible for the hardware to have exited an idle state without +driver knowledge, but entering one is always restricted to a driver +allow - which makes the SW state vs HW state mismatch issue purely one +of optimization, which should seldomly be hit, if at all. + +2. Refactor any instances of exit/notify idle to use a single wrapper + that maintains this SW state. + +This works simialr to dc_allow_idle_optimizations, but works at the +DMCUB level and makes sure the state is marked prior to any notify/exit +idle so we don't enter an infinite loop. + +3. Make sure we exit out of idle prior to sending any commands or + waiting for DMCUB idle. + +This patch takes care of 1/2. A future patch will take care of wrapping +DMCUB command submission with calls to this new interface. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Hansen Dsouza +Acked-by: Wayne Lin +Signed-off-by: Nicholas Kazlauskas +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: 8892780834ae ("drm/amd/display: Wake DMCUB before sending a command") +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 37 ++++++++++++++++++- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 6 ++- + .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 8 +--- + 4 files changed, 43 insertions(+), 12 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 4d534ac18356..292335b7145c 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -2825,7 +2825,7 @@ static int dm_resume(void *handle) + bool need_hotplug = false; + + if (dm->dc->caps.ips_support) { +- dc_dmub_srv_exit_low_power_state(dm->dc); ++ dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false); + } + + if (amdgpu_in_reset(adev)) { +@@ -8771,7 +8771,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) + if (new_con_state->crtc && + new_con_state->crtc->state->active && + drm_atomic_crtc_needs_modeset(new_con_state->crtc->state)) { +- dc_dmub_srv_exit_low_power_state(dm->dc); ++ dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false); + break; + } + } +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index 0c963dfd6061..9488f739737e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -1143,6 +1143,9 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) + struct dc_context *dc_ctx = dc_dmub_srv->ctx; + enum dmub_status status; + ++ if (!dc_dmub_srv || !dc_dmub_srv->dmub) ++ return true; ++ + if (dc_dmub_srv->ctx->dc->debug.dmcub_emulation) + return true; + +@@ -1158,7 +1161,7 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) + return true; + } + +-void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) ++static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) + { + union dmub_rb_cmd cmd = {0}; + +@@ -1182,7 +1185,7 @@ void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) + dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + +-void dc_dmub_srv_exit_low_power_state(const struct dc *dc) ++static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) + { + const uint32_t max_num_polls = 10000; + uint32_t allow_state = 0; +@@ -1195,6 +1198,9 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) + if (!dc->idle_optimizations_allowed) + return; + ++ if (!dc->ctx->dmub_srv || !dc->ctx->dmub_srv->dmub) ++ return; ++ + if (dc->hwss.get_idle_state && + dc->hwss.set_idle_state && + dc->clk_mgr->funcs->exit_low_power_state) { +@@ -1265,3 +1271,30 @@ void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_c + else + dmub_srv_set_power_state(dmub, DMUB_POWER_STATE_D3); + } ++ ++void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle) ++{ ++ struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; ++ ++ if (!dc_dmub_srv || !dc_dmub_srv->dmub) ++ return; ++ ++ if (dc_dmub_srv->idle_allowed == allow_idle) ++ return; ++ ++ /* ++ * Entering a low power state requires a driver notification. ++ * Powering up the hardware requires notifying PMFW and DMCUB. ++ * Clearing the driver idle allow requires a DMCUB command. ++ * DMCUB commands requires the DMCUB to be powered up and restored. ++ * ++ * Exit out early to prevent an infinite loop of DMCUB commands ++ * triggering exit low power - use software state to track this. ++ */ ++ dc_dmub_srv->idle_allowed = allow_idle; ++ ++ if (!allow_idle) ++ dc_dmub_srv_exit_low_power_state(dc); ++ else ++ dc_dmub_srv_notify_idle(dc, allow_idle); ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +index c25ce7546f71..b63cba6235fc 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +@@ -50,6 +50,8 @@ struct dc_dmub_srv { + + struct dc_context *ctx; + void *dm; ++ ++ bool idle_allowed; + }; + + void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv); +@@ -100,8 +102,8 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc); + void dc_dmub_srv_subvp_save_surf_addr(const struct dc_dmub_srv *dc_dmub_srv, const struct dc_plane_address *addr, uint8_t subvp_index); + + bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait); +-void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle); +-void dc_dmub_srv_exit_low_power_state(const struct dc *dc); ++ ++void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle); + + void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState); + #endif /* _DMUB_DC_SRV_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +index 5a8258287438..cf26d2ad4008 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +@@ -671,11 +671,7 @@ bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) + } + + // TODO: review other cases when idle optimization is allowed +- +- if (!enable) +- dc_dmub_srv_exit_low_power_state(dc); +- else +- dc_dmub_srv_notify_idle(dc, enable); ++ dc_dmub_srv_apply_idle_power_optimizations(dc, enable); + + return true; + } +@@ -685,7 +681,7 @@ void dcn35_z10_restore(const struct dc *dc) + if (dc->debug.disable_z10) + return; + +- dc_dmub_srv_exit_low_power_state(dc); ++ dc_dmub_srv_apply_idle_power_optimizations(dc, false); + + dcn31_z10_restore(dc); + } +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-update-pixel-clock-params-after-stre.patch b/queue-6.7/drm-amd-display-update-pixel-clock-params-after-stre.patch new file mode 100644 index 00000000000..2650b2dcd38 --- /dev/null +++ b/queue-6.7/drm-amd-display-update-pixel-clock-params-after-stre.patch @@ -0,0 +1,168 @@ +From 56127ad7a9086bce14ece3deb9a393ac7fc833e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Nov 2023 14:59:13 -0400 +Subject: drm/amd/display: update pixel clock params after stream slice count + change in context + +From: Wenjing Liu + +[ Upstream commit cfab803884f426b36b58dbe1f86f99742767c208 ] + +[why] +When ODM slice count is changed, otg master pipe's pixel clock params is +no longer valid as the value is dependent on ODM slice count. + +Reviewed-by: Chaitanya Dhere +Acked-by: Hamza Mahfooz +Signed-off-by: Wenjing Liu +Signed-off-by: Alex Deucher +Stable-dep-of: aa36d8971fcc ("drm/amd/display: Init link enc resources in dc_state only if res_pool presents") +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++++++--- + .../drm/amd/display/dc/dcn20/dcn20_resource.c | 16 ++++++++++------ + .../drm/amd/display/dc/dcn20/dcn20_resource.h | 1 + + .../drm/amd/display/dc/dcn32/dcn32_resource.c | 1 + + .../drm/amd/display/dc/dcn321/dcn321_resource.c | 1 + + .../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 6 +----- + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 1 + + 7 files changed, 21 insertions(+), 14 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 ae275f1780d5..c16190a10883 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -2237,7 +2237,7 @@ static struct pipe_ctx *get_last_dpp_pipe_in_mpcc_combine( + } + + static bool update_pipe_params_after_odm_slice_count_change( +- const struct dc_stream_state *stream, ++ struct pipe_ctx *otg_master, + struct dc_state *context, + const struct resource_pool *pool) + { +@@ -2247,9 +2247,12 @@ static bool update_pipe_params_after_odm_slice_count_change( + + for (i = 0; i < pool->pipe_count && result; i++) { + pipe = &context->res_ctx.pipe_ctx[i]; +- if (pipe->stream == stream && pipe->plane_state) ++ if (pipe->stream == otg_master->stream && pipe->plane_state) + result = resource_build_scaling_params(pipe); + } ++ ++ if (pool->funcs->build_pipe_pix_clk_params) ++ pool->funcs->build_pipe_pix_clk_params(otg_master); + return result; + } + +@@ -2932,7 +2935,7 @@ bool resource_update_pipes_for_stream_with_slice_count( + otg_master, new_ctx, pool); + if (result) + result = update_pipe_params_after_odm_slice_count_change( +- otg_master->stream, new_ctx, pool); ++ otg_master, new_ctx, pool); + return result; + } + +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 0a422fbb14bc..e73e59754837 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +@@ -1273,15 +1273,19 @@ static void build_clamping_params(struct dc_stream_state *stream) + stream->clamping.pixel_encoding = stream->timing.pixel_encoding; + } + +-static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) ++void dcn20_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) + { +- + get_pixel_clock_parameters(pipe_ctx, &pipe_ctx->stream_res.pix_clk_params); +- + pipe_ctx->clock_source->funcs->get_pix_clk_dividers( +- pipe_ctx->clock_source, +- &pipe_ctx->stream_res.pix_clk_params, +- &pipe_ctx->pll_settings); ++ pipe_ctx->clock_source, ++ &pipe_ctx->stream_res.pix_clk_params, ++ &pipe_ctx->pll_settings); ++} ++ ++static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) ++{ ++ ++ dcn20_build_pipe_pix_clk_params(pipe_ctx); + + pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +index 37ecaccc5d12..4cee3fa11a7f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +@@ -165,6 +165,7 @@ enum dc_status dcn20_add_stream_to_ctx(struct dc *dc, struct dc_state *new_ctx, + enum dc_status dcn20_add_dsc_to_stream_resource(struct dc *dc, struct dc_state *dc_ctx, struct dc_stream_state *dc_stream); + enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); + enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_state); ++void dcn20_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx); + + #endif /* __DC_RESOURCE_DCN20_H__ */ + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +index 89b072447dba..e940dd0f92b7 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +@@ -2041,6 +2041,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { + .retain_phantom_pipes = dcn32_retain_phantom_pipes, + .save_mall_state = dcn32_save_mall_state, + .restore_mall_state = dcn32_restore_mall_state, ++ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + }; + + static uint32_t read_pipe_fuses(struct dc_context *ctx) +diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +index f7de3eca1225..4156a8cc2bc7 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +@@ -1609,6 +1609,7 @@ static struct resource_funcs dcn321_res_pool_funcs = { + .retain_phantom_pipes = dcn32_retain_phantom_pipes, + .save_mall_state = dcn32_save_mall_state, + .restore_mall_state = dcn32_restore_mall_state, ++ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + }; + + static uint32_t read_pipe_fuses(struct dc_context *ctx) +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +index b46cde525066..92e2ddc9ab7e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +@@ -1237,15 +1237,11 @@ static void update_pipes_with_slice_table(struct dc *dc, struct dc_state *contex + { + int i; + +- for (i = 0; i < table->odm_combine_count; i++) { ++ for (i = 0; i < table->odm_combine_count; i++) + resource_update_pipes_for_stream_with_slice_count(context, + dc->current_state, dc->res_pool, + table->odm_combines[i].stream, + table->odm_combines[i].slice_count); +- /* TODO: move this into the function above */ +- dcn20_build_mapped_resource(dc, context, +- table->odm_combines[i].stream); +- } + + for (i = 0; i < table->mpc_combine_count; i++) + resource_update_pipes_for_plane_with_slice_count(context, +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 bac1420b1de8..10397d4dfb07 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h +@@ -205,6 +205,7 @@ struct resource_funcs { + void (*get_panel_config_defaults)(struct dc_panel_config *panel_config); + void (*save_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config); + void (*restore_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config); ++ void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx); + }; + + struct audio_support{ +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-wake-dmcub-before-executing-gpint-co.patch b/queue-6.7/drm-amd-display-wake-dmcub-before-executing-gpint-co.patch new file mode 100644 index 00000000000..fd8ece25751 --- /dev/null +++ b/queue-6.7/drm-amd-display-wake-dmcub-before-executing-gpint-co.patch @@ -0,0 +1,216 @@ +From 16a05ec8f2b548e5774b97506ef4de2bd9d20f14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 11:22:56 -0500 +Subject: drm/amd/display: Wake DMCUB before executing GPINT commands + +From: Nicholas Kazlauskas + +[ Upstream commit e5ffd1263dd5b44929c676171802e7b6af483f21 ] + +[Why] +DMCUB can be in idle when we attempt to interface with the HW through +the GPINT mailbox resulting in a system hang. + +[How] +Add dc_wake_and_execute_gpint() to wrap the wake, execute, sleep +sequence. + +If the GPINT executes successfully then DMCUB will be put back into +sleep after the optional response is returned. + +It functions similar to the inbox command interface. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Hansen Dsouza +Acked-by: Wayne Lin +Signed-off-by: Nicholas Kazlauskas +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 72 ++++++++++++++----- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 11 +++ + drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 19 ++--- + 3 files changed, 72 insertions(+), 30 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index 50f1e6d5321e..61d1b4eadbee 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -282,17 +282,11 @@ bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv) + bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, + unsigned int stream_mask) + { +- struct dmub_srv *dmub; +- const uint32_t timeout = 30; +- + if (!dc_dmub_srv || !dc_dmub_srv->dmub) + return false; + +- dmub = dc_dmub_srv->dmub; +- +- return dmub_srv_send_gpint_command( +- dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, +- stream_mask, timeout) == DMUB_STATUS_OK; ++ return dc_wake_and_execute_gpint(dc_dmub_srv->ctx, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, ++ stream_mask, NULL, DM_DMUB_WAIT_TYPE_WAIT); + } + + bool dc_dmub_srv_is_restore_required(struct dc_dmub_srv *dc_dmub_srv) +@@ -1107,25 +1101,20 @@ bool dc_dmub_check_min_version(struct dmub_srv *srv) + void dc_dmub_srv_enable_dpia_trace(const struct dc *dc) + { + struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; +- struct dmub_srv *dmub; +- enum dmub_status status; +- static const uint32_t timeout_us = 30; + + if (!dc_dmub_srv || !dc_dmub_srv->dmub) { + DC_LOG_ERROR("%s: invalid parameters.", __func__); + return; + } + +- dmub = dc_dmub_srv->dmub; +- +- status = dmub_srv_send_gpint_command(dmub, DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1, 0x0010, timeout_us); +- if (status != DMUB_STATUS_OK) { ++ if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__SET_TRACE_BUFFER_MASK_WORD1, ++ 0x0010, NULL, DM_DMUB_WAIT_TYPE_WAIT)) { + DC_LOG_ERROR("timeout updating trace buffer mask word\n"); + return; + } + +- status = dmub_srv_send_gpint_command(dmub, DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK, 0x0000, timeout_us); +- if (status != DMUB_STATUS_OK) { ++ if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__UPDATE_TRACE_BUFFER_MASK, ++ 0x0000, NULL, DM_DMUB_WAIT_TYPE_WAIT)) { + DC_LOG_ERROR("timeout updating trace buffer mask word\n"); + return; + } +@@ -1337,3 +1326,52 @@ bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned in + + return result; + } ++ ++static bool dc_dmub_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, ++ uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type) ++{ ++ struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv; ++ const uint32_t wait_us = wait_type == DM_DMUB_WAIT_TYPE_NO_WAIT ? 0 : 30; ++ enum dmub_status status; ++ ++ if (response) ++ *response = 0; ++ ++ if (!dc_dmub_srv || !dc_dmub_srv->dmub) ++ return false; ++ ++ status = dmub_srv_send_gpint_command(dc_dmub_srv->dmub, command_code, param, wait_us); ++ if (status != DMUB_STATUS_OK) { ++ if (status == DMUB_STATUS_TIMEOUT && wait_type == DM_DMUB_WAIT_TYPE_NO_WAIT) ++ return true; ++ ++ return false; ++ } ++ ++ if (response && wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) ++ dmub_srv_get_gpint_response(dc_dmub_srv->dmub, response); ++ ++ return true; ++} ++ ++bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, ++ uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type) ++{ ++ struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv; ++ bool result = false, reallow_idle = false; ++ ++ if (!dc_dmub_srv || !dc_dmub_srv->dmub) ++ return false; ++ ++ if (dc_dmub_srv->idle_allowed) { ++ dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, false); ++ reallow_idle = true; ++ } ++ ++ result = dc_dmub_execute_gpint(ctx, command_code, param, response, wait_type); ++ ++ if (result && reallow_idle) ++ dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true); ++ ++ return result; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +index 784ca3e44414..952bfb368886 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +@@ -145,5 +145,16 @@ bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cm + bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, + union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type); + ++/** ++ * dc_wake_and_execute_gpint() ++ * ++ * @ctx: DC context ++ * @command_code: The command ID to send to DMCUB ++ * @param: The parameter to message DMCUB ++ * @response: Optional response out value - may be NULL. ++ * @wait_type: The wait behavior for the execution ++ */ ++bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, ++ uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type); + + #endif /* _DMUB_DC_SRV_H_ */ +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 3d7cef17f881..3e243e407bb8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +@@ -105,23 +105,18 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state) + */ + static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state, uint8_t panel_inst) + { +- struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; + uint32_t raw_state = 0; + uint32_t retry_count = 0; +- enum dmub_status status; + + do { + // Send gpint command and wait for ack +- status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, panel_inst, 30); +- +- if (status == DMUB_STATUS_OK) { +- // GPINT was executed, get response +- dmub_srv_get_gpint_response(srv, &raw_state); ++ if (dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__GET_PSR_STATE, panel_inst, &raw_state, ++ DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { + *state = convert_psr_state(raw_state); +- } else ++ } else { + // Return invalid state when GPINT times out + *state = PSR_STATE_INVALID; +- ++ } + } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID); + + // Assert if max retry hit +@@ -452,13 +447,11 @@ static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst) + */ + static void dmub_psr_get_residency(struct dmub_psr *dmub, uint32_t *residency, uint8_t panel_inst) + { +- struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; + uint16_t param = (uint16_t)(panel_inst << 8); + + /* Send gpint command and wait for ack */ +- dmub_srv_send_gpint_command(srv, DMUB_GPINT__PSR_RESIDENCY, param, 30); +- +- dmub_srv_get_gpint_response(srv, residency); ++ dc_wake_and_execute_gpint(dmub->ctx, DMUB_GPINT__PSR_RESIDENCY, param, residency, ++ DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); + } + + static const struct dmub_psr_funcs psr_funcs = { +-- +2.43.0 + diff --git a/queue-6.7/drm-amd-display-wake-dmcub-before-sending-a-command.patch b/queue-6.7/drm-amd-display-wake-dmcub-before-sending-a-command.patch new file mode 100644 index 00000000000..3f38fa9a93c --- /dev/null +++ b/queue-6.7/drm-amd-display-wake-dmcub-before-sending-a-command.patch @@ -0,0 +1,826 @@ +From 50b2a6438405c05737873cedb22cffed6722079b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 16:35:04 -0500 +Subject: drm/amd/display: Wake DMCUB before sending a command + +From: Nicholas Kazlauskas + +[ Upstream commit 8892780834ae294bc3697c7d0e056d7743900b39 ] + +[Why] +We can hang in place trying to send commands when the DMCUB isn't +powered on. + +[How] +For functions that execute within a DC context or DC lock we can +wrap the direct calls to dm_execute_dmub_cmd/list with code that +exits idle power optimizations and reallows once we're done with +the command submission on success. + +For DM direct submissions the DM will need to manage the enter/exit +sequencing manually. + +We cannot invoke a DMCUB command directly within the DM execution +helper or we can deadlock. + +Cc: Mario Limonciello +Cc: Alex Deucher +Cc: stable@vger.kernel.org +Reviewed-by: Hansen Dsouza +Acked-by: Wayne Lin +Signed-off-by: Nicholas Kazlauskas +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- + .../drm/amd/display/dc/bios/command_table2.c | 12 ++--- + .../display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 +- + .../dc/clk_mgr/dcn314/dcn314_clk_mgr.c | 2 +- + .../dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 2 +- + .../dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 2 +- + .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 2 +- + drivers/gpu/drm/amd/display/dc/core/dc.c | 12 ++--- + .../drm/amd/display/dc/core/dc_hw_sequencer.c | 2 +- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 53 ++++++++++++++++--- + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 40 ++++++++++++++ + drivers/gpu/drm/amd/display/dc/dc_helper.c | 6 +-- + .../gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c | 14 ++--- + .../drm/amd/display/dc/dce/dmub_hw_lock_mgr.c | 2 +- + .../gpu/drm/amd/display/dc/dce/dmub_outbox.c | 2 +- + drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 14 ++--- + .../gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 2 +- + .../display/dc/dcn31/dcn31_dio_link_encoder.c | 4 +- + .../amd/display/dc/dcn31/dcn31_panel_cntl.c | 4 +- + .../amd/display/dc/hwss/dcn21/dcn21_hwseq.c | 4 +- + .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 8 +-- + .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 4 +- + .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 6 +-- + .../dc/link/protocols/link_dp_capability.c | 2 +- + .../display/dc/link/protocols/link_dp_dpia.c | 3 +- + 25 files changed, 143 insertions(+), 63 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 292335b7145c..9dbbaeb8c6cf 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -10620,7 +10620,7 @@ static bool dm_edid_parser_send_cea(struct amdgpu_display_manager *dm, + input->cea_total_length = total_length; + memcpy(input->payload, data, length); + +- res = dm_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); ++ res = dc_wake_and_execute_dmub_cmd(dm->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); + if (!res) { + DRM_ERROR("EDID CEA parser failed\n"); + return false; +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 ab0adabf9dd4..293a919d605d 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +@@ -123,7 +123,7 @@ static void encoder_control_dmcub( + sizeof(cmd.digx_encoder_control.header); + cmd.digx_encoder_control.encoder_control.dig.stream_param = *dig; + +- dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static enum bp_result encoder_control_digx_v1_5( +@@ -259,7 +259,7 @@ static void transmitter_control_dmcub( + sizeof(cmd.dig1_transmitter_control.header); + cmd.dig1_transmitter_control.transmitter_control.dig = *dig; + +- dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static enum bp_result transmitter_control_v1_6( +@@ -321,7 +321,7 @@ static void transmitter_control_dmcub_v1_7( + sizeof(cmd.dig1_transmitter_control.header); + cmd.dig1_transmitter_control.transmitter_control.dig_v1_7 = *dig; + +- dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static enum bp_result transmitter_control_v1_7( +@@ -429,7 +429,7 @@ static void set_pixel_clock_dmcub( + sizeof(cmd.set_pixel_clock.header); + cmd.set_pixel_clock.pixel_clock.clk = *clk; + +- dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static enum bp_result set_pixel_clock_v7( +@@ -796,7 +796,7 @@ static void enable_disp_power_gating_dmcub( + sizeof(cmd.enable_disp_power_gating.header); + cmd.enable_disp_power_gating.power_gating.pwr = *pwr; + +- dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static enum bp_result enable_disp_power_gating_v2_1( +@@ -1006,7 +1006,7 @@ static void enable_lvtma_control_dmcub( + pwrseq_instance; + cmd.lvtma_control.data.bypass_panel_control_wait = + bypass_panel_control_wait; +- dm_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmcub->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static enum bp_result enable_lvtma_control( +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 3db4ef564b99..ce1386e22576 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 +@@ -253,7 +253,7 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr) +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +index 2618504e260e..59c2a3545db3 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +@@ -281,7 +281,7 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base, + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr) +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +index 8776055bbeaa..644da4637320 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c +@@ -232,7 +232,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +index 09151cc56ce4..12f3e8aa46d8 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +@@ -239,7 +239,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, +diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +index d5fde7d23fbf..45ede6440a79 100644 +--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +@@ -349,7 +349,7 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, + cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; + cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr) +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 5c1185206645..c535ddb45a36 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -519,7 +519,7 @@ dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv, + cmd.secure_display.roi_info.y_end = rect->y + rect->height; + } + +- dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + } + + static inline void +@@ -3386,7 +3386,7 @@ void dc_dmub_update_dirty_rect(struct dc *dc, + + update_dirty_rect->panel_inst = panel_inst; + update_dirty_rect->pipe_idx = j; +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + } + } + } +@@ -5213,7 +5213,7 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc, + ); + } + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -5267,7 +5267,7 @@ bool dc_process_dmub_set_config_async(struct dc *dc, + cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type; + cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data; + +- if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { ++ if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { + /* command is not processed by dmub */ + notify->sc_status = SET_CONFIG_UNKNOWN_ERROR; + return is_cmd_complete; +@@ -5310,7 +5310,7 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc, + cmd.set_mst_alloc_slots.mst_slots_control.instance = dc->links[link_index]->ddc_hw_inst; + cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots; + +- if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) ++ if (!dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) + /* command is not processed by dmub */ + return DC_ERROR_UNEXPECTED; + +@@ -5348,7 +5348,7 @@ void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc, + cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE; + cmd.dpia_hpd_int_enable.enable = hpd_int_enable; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable); + } +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +index fe07160932d6..fc18b9dc946f 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +@@ -724,7 +724,7 @@ void hwss_send_dmcub_cmd(union block_sequence_params *params) + union dmub_rb_cmd *cmd = params->send_dmcub_cmd_params.cmd; + enum dm_dmub_wait_type wait_type = params->send_dmcub_cmd_params.wait_type; + +- dm_execute_dmub_cmd(ctx, cmd, wait_type); ++ dc_wake_and_execute_dmub_cmd(ctx, cmd, wait_type); + } + + void hwss_program_manual_trigger(union block_sequence_params *params) +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +index 9488f739737e..50f1e6d5321e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +@@ -341,7 +341,7 @@ void dc_dmub_srv_drr_update_cmd(struct dc *dc, uint32_t tg_inst, uint32_t vtotal + cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header); + + // Send the command to the DMCUB. +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst) +@@ -355,7 +355,7 @@ void dc_dmub_srv_set_drr_manual_trigger_cmd(struct dc *dc, uint32_t tg_inst) + cmd.drr_update.header.payload_bytes = sizeof(cmd.drr_update) - sizeof(cmd.drr_update.header); + + // Send the command to the DMCUB. +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + static uint8_t dc_dmub_srv_get_pipes_for_stream(struct dc *dc, struct dc_stream_state *stream) +@@ -448,7 +448,7 @@ bool dc_dmub_srv_p_state_delegate(struct dc *dc, bool should_manage_pstate, stru + sizeof(cmd.fw_assisted_mclk_switch) - sizeof(cmd.fw_assisted_mclk_switch.header); + + // Send the command to the DMCUB. +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -469,7 +469,7 @@ void dc_dmub_srv_query_caps_cmd(struct dc_dmub_srv *dc_dmub_srv) + cmd.query_feature_caps.header.payload_bytes = sizeof(struct dmub_cmd_query_feature_caps_data); + + /* If command was processed, copy feature caps to dmub srv */ +- if (dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && ++ if (dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && + cmd.query_feature_caps.header.ret_status == 0) { + memcpy(&dc_dmub_srv->dmub->feature_caps, + &cmd.query_feature_caps.query_feature_caps_data, +@@ -494,7 +494,7 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi + cmd.visual_confirm_color.visual_confirm_color_data.visual_confirm_color.panel_inst = panel_inst; + + // If command was processed, copy feature caps to dmub srv +- if (dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && ++ if (dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && + cmd.visual_confirm_color.header.ret_status == 0) { + memcpy(&dc->ctx->dmub_srv->dmub->visual_confirm_color, + &cmd.visual_confirm_color.visual_confirm_color_data, +@@ -856,7 +856,7 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc, + cmd.fw_assisted_mclk_switch_v2.config_data.watermark_a_cache = wm_val_refclk < 0xFFFF ? wm_val_refclk : 0xFFFF; + } + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmub_diagnostic_data *diag_data) +@@ -1093,7 +1093,7 @@ void dc_send_update_cursor_info_to_dmu( + pipe_idx, pCtx->plane_res.hubp, pCtx->plane_res.dpp); + + /* Combine 2nd cmds update_curosr_info to DMU */ +- dm_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd_list(pCtx->stream->ctx, 2, cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + } + +@@ -1182,6 +1182,7 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) + dc->hwss.set_idle_state(dc, true); + } + ++ /* NOTE: This does not use the "wake" interface since this is part of the wake path. */ + dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + +@@ -1298,3 +1299,41 @@ void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_ + else + dc_dmub_srv_notify_idle(dc, allow_idle); + } ++ ++bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, ++ enum dm_dmub_wait_type wait_type) ++{ ++ return dc_wake_and_execute_dmub_cmd_list(ctx, 1, cmd, wait_type); ++} ++ ++bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, ++ union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type) ++{ ++ struct dc_dmub_srv *dc_dmub_srv = ctx->dmub_srv; ++ bool result = false, reallow_idle = false; ++ ++ if (!dc_dmub_srv || !dc_dmub_srv->dmub) ++ return false; ++ ++ if (count == 0) ++ return true; ++ ++ if (dc_dmub_srv->idle_allowed) { ++ dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, false); ++ reallow_idle = true; ++ } ++ ++ /* ++ * These may have different implementations in DM, so ensure ++ * that we guide it to the expected helper. ++ */ ++ if (count > 1) ++ result = dm_execute_dmub_cmd_list(ctx, count, cmd, wait_type); ++ else ++ result = dm_execute_dmub_cmd(ctx, cmd, wait_type); ++ ++ if (result && reallow_idle) ++ dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true); ++ ++ return result; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +index b63cba6235fc..784ca3e44414 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +@@ -106,4 +106,44 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait); + void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_idle); + + void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState); ++ ++/** ++ * dc_wake_and_execute_dmub_cmd() - Wrapper for DMUB command execution. ++ * ++ * Refer to dc_wake_and_execute_dmub_cmd_list() for usage and limitations, ++ * This function is a convenience wrapper for a single command execution. ++ * ++ * @ctx: DC context ++ * @cmd: The command to send/receive ++ * @wait_type: The wait behavior for the execution ++ * ++ * Return: true on command submission success, false otherwise ++ */ ++bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, ++ enum dm_dmub_wait_type wait_type); ++ ++/** ++ * dc_wake_and_execute_dmub_cmd_list() - Wrapper for DMUB command list execution. ++ * ++ * If the DMCUB hardware was asleep then it wakes the DMUB before ++ * executing the command and attempts to re-enter if the command ++ * submission was successful. ++ * ++ * This should be the preferred command submission interface provided ++ * the DC lock is acquired. ++ * ++ * Entry/exit out of idle power optimizations would need to be ++ * manually performed otherwise through dc_allow_idle_optimizations(). ++ * ++ * @ctx: DC context ++ * @count: Number of commands to send/receive ++ * @cmd: Array of commands to send ++ * @wait_type: The wait behavior for the execution ++ * ++ * Return: true on command submission success, false otherwise ++ */ ++bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned int count, ++ union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type); ++ ++ + #endif /* _DMUB_DC_SRV_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c +index cb6eaddab720..8f9a67825615 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c ++++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c +@@ -50,7 +50,7 @@ static inline void submit_dmub_read_modify_write( + cmd_buf->header.payload_bytes = + sizeof(struct dmub_cmd_read_modify_write_sequence) * offload->reg_seq_count; + +- dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); + + memset(cmd_buf, 0, sizeof(*cmd_buf)); + +@@ -67,7 +67,7 @@ static inline void submit_dmub_burst_write( + cmd_buf->header.payload_bytes = + sizeof(uint32_t) * offload->reg_seq_count; + +- dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); + + memset(cmd_buf, 0, sizeof(*cmd_buf)); + +@@ -80,7 +80,7 @@ static inline void submit_dmub_reg_wait( + { + struct dmub_rb_cmd_reg_wait *cmd_buf = &offload->cmd_data.reg_wait; + +- dm_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(ctx, &offload->cmd_data, DM_DMUB_WAIT_TYPE_NO_WAIT); + + memset(cmd_buf, 0, sizeof(*cmd_buf)); + offload->reg_seq_count = 0; +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c +index 42c802afc468..4cff36351f40 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c +@@ -76,7 +76,7 @@ static void dmub_abm_enable_fractional_pwm(struct dc_context *dc) + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask; + cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + void dmub_abm_init(struct abm *abm, uint32_t backlight) +@@ -155,7 +155,7 @@ bool dmub_abm_set_level(struct abm *abm, uint32_t level, uint8_t panel_mask) + cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask; + cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -186,7 +186,7 @@ void dmub_abm_init_config(struct abm *abm, + + cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + } + +@@ -203,7 +203,7 @@ bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, un + cmd.abm_pause.abm_pause_data.panel_mask = panel_mask; + cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_pause_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -246,7 +246,7 @@ bool dmub_abm_save_restore( + + cmd.abm_save_restore.header.payload_bytes = sizeof(struct dmub_rb_cmd_abm_save_restore); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + // Copy iramtable data into local structure + memcpy((void *)pData, dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, bytes); +@@ -274,7 +274,7 @@ bool dmub_abm_set_pipe(struct abm *abm, + cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; + cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -296,7 +296,7 @@ bool dmub_abm_set_backlight_level(struct abm *abm, + cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst); + cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +index 2aa0e01a6891..ba1fec3016d5 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +@@ -47,7 +47,7 @@ void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv, + if (!lock) + cmd.lock_hw.lock_hw_data.should_release = 1; + +- dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv, +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c +index d8009b2dc56a..98a778996e1a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_outbox.c +@@ -48,5 +48,5 @@ void dmub_enable_outbox_notification(struct dc_dmub_srv *dmub_srv) + sizeof(cmd.outbox1_enable.header); + cmd.outbox1_enable.enable = true; + +- dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } +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 9d4170a356a2..3d7cef17f881 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +@@ -171,7 +171,7 @@ static bool dmub_psr_set_version(struct dmub_psr *dmub, struct dc_stream_state * + 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); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -199,7 +199,7 @@ static void dmub_psr_enable(struct dmub_psr *dmub, bool enable, bool wait, uint8 + + cmd.psr_enable.header.payload_bytes = 0; // Send header only + +- dm_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + /* Below loops 1000 x 500us = 500 ms. + * Exit PSR may need to wait 1-2 frames to power up. Timeout after at +@@ -248,7 +248,7 @@ static void dmub_psr_set_level(struct dmub_psr *dmub, uint16_t psr_level, uint8_ + cmd.psr_set_level.psr_set_level_data.psr_level = psr_level; + cmd.psr_set_level.psr_set_level_data.cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; + cmd.psr_set_level.psr_set_level_data.panel_inst = panel_inst; +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + /* +@@ -267,7 +267,7 @@ static void dmub_psr_set_sink_vtotal_in_psr_active(struct dmub_psr *dmub, + cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_idle = psr_vtotal_idle; + cmd.psr_set_vtotal.psr_set_vtotal_data.psr_vtotal_su = psr_vtotal_su; + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + /* +@@ -286,7 +286,7 @@ static void dmub_psr_set_power_opt(struct dmub_psr *dmub, unsigned int power_opt + cmd.psr_set_power_opt.psr_set_power_opt_data.power_opt = power_opt; + cmd.psr_set_power_opt.psr_set_power_opt_data.panel_inst = panel_inst; + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + /* +@@ -423,7 +423,7 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, + copy_settings_data->relock_delay_frame_cnt = 2; + copy_settings_data->dsc_slice_height = psr_context->dsc_slice_height; + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -444,7 +444,7 @@ static void dmub_psr_force_static(struct dmub_psr *dmub, uint8_t panel_inst) + cmd.psr_force_static.header.sub_type = DMUB_CMD__PSR_FORCE_STATIC; + cmd.psr_enable.header.payload_bytes = 0; + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + /* +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c +index 68cad55c72ab..e13d69a22c1c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c +@@ -691,7 +691,7 @@ static void dmcub_PLAT_54186_wa(struct hubp *hubp, + cmd.PLAT_54186_wa.flip.flip_params.vmid = flip_regs->vmid; + + PERF_TRACE(); // TODO: remove after performance is stable. +- dm_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(hubp->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + PERF_TRACE(); // TODO: remove after performance is stable. + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +index 4596f3bac1b4..26be5fee7411 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +@@ -125,7 +125,7 @@ static bool query_dp_alt_from_dmub(struct link_encoder *enc, + cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data); + cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter); + +- if (!dm_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) ++ if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) + return false; + + return true; +@@ -436,7 +436,7 @@ static bool link_dpia_control(struct dc_context *dc_ctx, + + cmd.dig1_dpia_control.dpia_control = *dpia_control; + +- dm_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc_ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +index d849b1eaa4a5..03248422d6ff 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +@@ -52,7 +52,7 @@ static bool dcn31_query_backlight_info(struct panel_cntl *panel_cntl, union dmub + cmd->panel_cntl.header.payload_bytes = sizeof(cmd->panel_cntl.data); + cmd->panel_cntl.data.pwrseq_inst = dcn31_panel_cntl->base.pwrseq_inst; + +- return dm_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); ++ return dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY); + } + + static uint32_t dcn31_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) +@@ -85,7 +85,7 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl) + panel_cntl->stored_backlight_registers.LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV; + cmd.panel_cntl.data.bl_pwm_ref_div2 = + panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2; +- if (!dm_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) ++ if (!dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) + return 0; + + panel_cntl->stored_backlight_registers.BL_PWM_CNTL = cmd.panel_cntl.data.bl_pwm_cntl; +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c +index 08783ad097d2..8e88dcaf88f5 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c +@@ -154,7 +154,7 @@ static bool dmub_abm_set_pipe(struct abm *abm, uint32_t otg_inst, + cmd.abm_set_pipe.abm_set_pipe_data.ramping_boundary = ramping_boundary; + cmd.abm_set_pipe.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pipe_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +@@ -173,7 +173,7 @@ static void dmub_abm_set_backlight(struct dc_context *dc, uint32_t backlight_pwm + cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_inst); + cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); + +- dm_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + void dcn21_set_abm_immediate_disable(struct pipe_ctx *pipe_ctx) +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +index d71faf2ecd41..772dc0db916f 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +@@ -750,7 +750,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_NO_DF_REQ; + cmd.mall.header.payload_bytes = sizeof(cmd.mall) - sizeof(cmd.mall.header); + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + + return true; + } +@@ -872,7 +872,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.mall.cursor_height = cursor_attr.height; + cmd.mall.cursor_pitch = cursor_attr.pitch; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + /* Use copied cursor, and it's okay to not switch back */ + cursor_attr.address.quad_part = cmd.mall.cursor_copy_dst.quad_part; +@@ -888,7 +888,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.mall.tmr_scale = tmr_scale; + cmd.mall.debug_bits = dc->debug.mall_error_as_fatal; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + + return true; + } +@@ -905,7 +905,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.mall.header.payload_bytes = + sizeof(cmd.mall) - sizeof(cmd.mall.header); + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +index 97798cee876e..52656691ae48 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +@@ -415,7 +415,7 @@ void dcn31_z10_save_init(struct dc *dc) + cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT; + cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + void dcn31_z10_restore(const struct dc *dc) +@@ -433,7 +433,7 @@ void dcn31_z10_restore(const struct dc *dc) + cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT; + cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_RESTORE; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + } + + void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) +diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +index c1a9b746c43f..5bf9e7c1e052 100644 +--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +@@ -277,7 +277,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.cab.header.sub_type = DMUB_CMD__CAB_NO_DCN_REQ; + cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header); + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + + return true; + } +@@ -311,7 +311,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.cab.header.payload_bytes = sizeof(cmd.cab) - sizeof(cmd.cab.header); + cmd.cab.cab_alloc_ways = (uint8_t)ways; + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT); + + return true; + } +@@ -327,7 +327,7 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) + cmd.cab.header.payload_bytes = + sizeof(cmd.cab) - sizeof(cmd.cab.header); + +- dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); ++ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + return true; + } +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +index db87aa7b5c90..2f11eaabbe5f 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +@@ -1392,7 +1392,7 @@ static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id) + cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data); + cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx( + link->dc, link->link_enc->transmitter); +- if (dm_execute_dmub_cmd(link->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && ++ if (dc_wake_and_execute_dmub_cmd(link->dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && + cmd.cable_id.header.ret_status == 1) { + cable_id->raw = cmd.cable_id.data.output_raw; + DC_LOG_DC("usbc_cable_id = %d.\n", cable_id->raw); +diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c +index 0bb749133909..982eda3c46f5 100644 +--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c ++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c +@@ -90,7 +90,8 @@ bool dpia_query_hpd_status(struct dc_link *link) + cmd.query_hpd.data.ch_type = AUX_CHANNEL_DPIA; + + /* Return HPD status reported by DMUB if query successfully executed. */ +- if (dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && cmd.query_hpd.data.status == AUX_RET_SUCCESS) ++ if (dc_wake_and_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && ++ cmd.query_hpd.data.status == AUX_RET_SUCCESS) + is_hpd_high = cmd.query_hpd.data.result; + + DC_LOG_DEBUG("%s: link(%d) dpia(%d) cmd_status(%d) result(%d)\n", +-- +2.43.0 + diff --git a/queue-6.7/drm-amdgpu-enable-tunneling-on-high-priority-compute.patch b/queue-6.7/drm-amdgpu-enable-tunneling-on-high-priority-compute.patch new file mode 100644 index 00000000000..fc3882dd204 --- /dev/null +++ b/queue-6.7/drm-amdgpu-enable-tunneling-on-high-priority-compute.patch @@ -0,0 +1,122 @@ +From a643ef69b7e867d6acfc957b15087a396a093f54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 2 Dec 2023 01:17:40 +0100 +Subject: drm/amdgpu: Enable tunneling on high-priority compute queues +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Friedrich Vock + +[ Upstream commit 91963397c49aa2907aeafa52d929555dcbc9cd07 ] + +This improves latency if the GPU is already busy with other work. +This is useful for VR compositors that submit highly latency-sensitive +compositing work on high-priority compute queues while the GPU is busy +rendering the next frame. + +Userspace merge request: +https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26462 + +v2: bump driver version (Alex) + +Reviewed-by: Marek Olšák +Signed-off-by: Friedrich Vock +Signed-off-by: Alex Deucher +Stable-dep-of: 03ff6d7238b7 ("drm/amdgpu/gfx10: set UNORD_DISPATCH in compute MQDs") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- + drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 10 ++++++---- + drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 ++- + drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 3 ++- + 5 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index 9d92ca157677..50f57d4dfd8f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -757,6 +757,7 @@ struct amdgpu_mqd_prop { + uint64_t eop_gpu_addr; + uint32_t hqd_pipe_priority; + uint32_t hqd_queue_priority; ++ bool allow_tunneling; + bool hqd_active; + }; + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index c0e8e030b96f..a7ad77ed09ca 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -115,9 +115,10 @@ + * 3.54.0 - Add AMDGPU_CTX_QUERY2_FLAGS_RESET_IN_PROGRESS support + * - 3.55.0 - Add AMDGPU_INFO_GPUVM_FAULT query + * - 3.56.0 - Update IB start address and size alignment for decode and encode ++ * - 3.57.0 - Compute tunneling on GFX10+ + */ + #define KMS_DRIVER_MAJOR 3 +-#define KMS_DRIVER_MINOR 56 ++#define KMS_DRIVER_MINOR 57 + #define KMS_DRIVER_PATCHLEVEL 0 + + /* +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +index 6a80d3ec887e..45424ebf9681 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +@@ -642,6 +642,10 @@ static void amdgpu_ring_to_mqd_prop(struct amdgpu_ring *ring, + struct amdgpu_mqd_prop *prop) + { + struct amdgpu_device *adev = ring->adev; ++ bool is_high_prio_compute = ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE && ++ amdgpu_gfx_is_high_priority_compute_queue(adev, ring); ++ bool is_high_prio_gfx = ring->funcs->type == AMDGPU_RING_TYPE_GFX && ++ amdgpu_gfx_is_high_priority_graphics_queue(adev, ring); + + memset(prop, 0, sizeof(*prop)); + +@@ -659,10 +663,8 @@ static void amdgpu_ring_to_mqd_prop(struct amdgpu_ring *ring, + */ + prop->hqd_active = ring->funcs->type == AMDGPU_RING_TYPE_KIQ; + +- if ((ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE && +- amdgpu_gfx_is_high_priority_compute_queue(adev, ring)) || +- (ring->funcs->type == AMDGPU_RING_TYPE_GFX && +- amdgpu_gfx_is_high_priority_graphics_queue(adev, ring))) { ++ prop->allow_tunneling = is_high_prio_compute; ++ if (is_high_prio_compute || is_high_prio_gfx) { + prop->hqd_pipe_priority = AMDGPU_GFX_PIPE_PRIO_HIGH; + prop->hqd_queue_priority = AMDGPU_GFX_QUEUE_PRIORITY_MAXIMUM; + } +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +index 67c198ea8211..d63cab294883 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +@@ -6590,7 +6590,8 @@ static int gfx_v10_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1); + #endif + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); +- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); ++ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, ++ prop->allow_tunneling); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); + mqd->cp_hqd_pq_control = tmp; +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +index cddf3737e8a3..4824a4c04d35 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +@@ -3839,7 +3839,8 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, + (order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); +- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); ++ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, ++ prop->allow_tunneling); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); + mqd->cp_hqd_pq_control = tmp; +-- +2.43.0 + diff --git a/queue-6.7/drm-amdgpu-gfx10-set-unord_dispatch-in-compute-mqds.patch b/queue-6.7/drm-amdgpu-gfx10-set-unord_dispatch-in-compute-mqds.patch new file mode 100644 index 00000000000..686fe635970 --- /dev/null +++ b/queue-6.7/drm-amdgpu-gfx10-set-unord_dispatch-in-compute-mqds.patch @@ -0,0 +1,52 @@ +From 014670a36f0be40246f1111064020ecbbf409ab0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jan 2024 12:23:55 -0500 +Subject: drm/amdgpu/gfx10: set UNORD_DISPATCH in compute MQDs + +From: Alex Deucher + +[ Upstream commit 03ff6d7238b77e5fb2b85dc5fe01d2db9eb893bd ] + +This needs to be set to 1 to avoid a potential deadlock in +the GC 10.x and newer. On GC 9.x and older, this needs +to be set to 0. This can lead to hangs in some mixed +graphics and compute workloads. Updated firmware is also +required for AQL. + +Reviewed-by: Feifei Xu +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 2 +- + drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +index d63cab294883..ecb622b7f970 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +@@ -6589,7 +6589,7 @@ static int gfx_v10_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + #ifdef __BIG_ENDIAN + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ENDIAN_SWAP, 1); + #endif +- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); ++ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, + prop->allow_tunneling); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); +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 8b7fed913526..22cbfa1bdadd 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c +@@ -170,6 +170,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, + m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control |= + ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; ++ m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; + pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); + + m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); +-- +2.43.0 + diff --git a/queue-6.7/drm-amdgpu-gfx11-set-unord_dispatch-in-compute-mqds.patch b/queue-6.7/drm-amdgpu-gfx11-set-unord_dispatch-in-compute-mqds.patch new file mode 100644 index 00000000000..970d7cf8669 --- /dev/null +++ b/queue-6.7/drm-amdgpu-gfx11-set-unord_dispatch-in-compute-mqds.patch @@ -0,0 +1,52 @@ +From c5e4df9a64e2a43992704435b8caec6d6422c929 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jan 2024 12:32:59 -0500 +Subject: drm/amdgpu/gfx11: set UNORD_DISPATCH in compute MQDs + +From: Alex Deucher + +[ Upstream commit 3380fcad2c906872110d31ddf7aa1fdea57f9df6 ] + +This needs to be set to 1 to avoid a potential deadlock in +the GC 10.x and newer. On GC 9.x and older, this needs +to be set to 0. This can lead to hangs in some mixed +graphics and compute workloads. Updated firmware is also +required for AQL. + +Reviewed-by: Feifei Xu +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- + drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +index 4824a4c04d35..806a8cf90487 100644 +--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +@@ -3838,7 +3838,7 @@ static int gfx_v11_0_compute_mqd_init(struct amdgpu_device *adev, void *m, + (order_base_2(prop->queue_size / 4) - 1)); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE, + (order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)); +- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 0); ++ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, + prop->allow_tunneling); + tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c +index 15277f1d5cf0..d722cbd31783 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c +@@ -224,6 +224,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, + m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT; + m->cp_hqd_pq_control |= + ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1; ++ m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK; + pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control); + + m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8); +-- +2.43.0 + diff --git a/queue-6.7/drm-panel-edp-add-auo-b116xtn02-boe-nt116whm-n21-836.patch b/queue-6.7/drm-panel-edp-add-auo-b116xtn02-boe-nt116whm-n21-836.patch new file mode 100644 index 00000000000..b644e3521e2 --- /dev/null +++ b/queue-6.7/drm-panel-edp-add-auo-b116xtn02-boe-nt116whm-n21-836.patch @@ -0,0 +1,50 @@ +From fef3cfe36b19aff9c98113f58e26c5f77b7a1bf2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Oct 2023 11:04:56 +0800 +Subject: drm/panel-edp: Add AUO B116XTN02, BOE NT116WHM-N21,836X2, + NV116WHM-N49 V8.0 + +From: Sheng-Liang Pan + +[ Upstream commit 3db2420422a5912d97966e0176050bb0fc9aa63e ] + +Add panel identification entry for +- AUO B116XTN02 family (product ID:0x235c) +- BOE NT116WHM-N21,836X2 (product ID:0x09c3) +- BOE NV116WHM-N49 V8.0 (product ID:0x0979) + +Signed-off-by: Sheng-Liang Pan +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/20231027110435.1.Ia01fe9ec1c0953e0050a232eaa782fef2c037516@changeid +Stable-dep-of: fc6e76792965 ("drm/panel-edp: drm/panel-edp: Fix AUO B116XAK01 name and timing") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-edp.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c +index 95c8472d878a..5bf28c8443ef 100644 +--- a/drivers/gpu/drm/panel/panel-edp.c ++++ b/drivers/gpu/drm/panel/panel-edp.c +@@ -1840,6 +1840,7 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('A', 'U', 'O', 0x145c, &delay_200_500_e50, "B116XAB01.4"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1ea5, &delay_200_500_e50, "B116XAK01.6"), ++ EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x582d, &delay_200_500_e50, "B133UAN01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), +@@ -1848,8 +1849,10 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x082d, &boe_nv133fhm_n61.delay, "NV133FHM-N62"), ++ EDP_PANEL_ENTRY('B', 'O', 'E', 0x09c3, &delay_200_500_e50, "NT116WHM-N21,836X2"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x094b, &delay_200_500_e50, "NT116WHM-N21"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x095f, &delay_200_500_e50, "NE135FBM-N41 v8.1"), ++ EDP_PANEL_ENTRY('B', 'O', 'E', 0x0979, &delay_200_500_e50, "NV116WHM-N49 V8.0"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x098d, &boe_nv110wtm_n61.delay, "NV110WTM-N61"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x09dd, &delay_200_500_e50, "NT116WHM-N21"), + EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"), +-- +2.43.0 + diff --git a/queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xak01-name-a.patch b/queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xak01-name-a.patch new file mode 100644 index 00000000000..922f9595a54 --- /dev/null +++ b/queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xak01-name-a.patch @@ -0,0 +1,50 @@ +From e0a3e41ba3a1ad22a9241ce78386a20e0509d782 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Nov 2023 12:41:51 -0800 +Subject: drm/panel-edp: drm/panel-edp: Fix AUO B116XAK01 name and timing + +From: Hsin-Yi Wang + +[ Upstream commit fc6e7679296530106ee0954e8ddef1aa58b2e0b5 ] + +Rename AUO 0x405c B116XAK01 to B116XAK01.0 and adjust the timing of +auo_b116xak01: T3=200, T12=500, T7_max = 50 according to decoding edid +and datasheet. + +Fixes: da458286a5e2 ("drm/panel: Add support for AUO B116XAK01 panel") +Cc: stable@vger.kernel.org +Signed-off-by: Hsin-Yi Wang +Reviewed-by: Douglas Anderson +Acked-by: Maxime Ripard +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/20231107204611.3082200-2-hsinyi@chromium.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-edp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c +index 5bf28c8443ef..e93e54a98260 100644 +--- a/drivers/gpu/drm/panel/panel-edp.c ++++ b/drivers/gpu/drm/panel/panel-edp.c +@@ -973,6 +973,8 @@ static const struct panel_desc auo_b116xak01 = { + }, + .delay = { + .hpd_absent = 200, ++ .unprepare = 500, ++ .enable = 50, + }, + }; + +@@ -1841,7 +1843,7 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1ea5, &delay_200_500_e50, "B116XAK01.6"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02"), +- EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), ++ EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x582d, &delay_200_500_e50, "B133UAN01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), +-- +2.43.0 + diff --git a/queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xtn02-name.patch b/queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xtn02-name.patch new file mode 100644 index 00000000000..b7b1ac22b74 --- /dev/null +++ b/queue-6.7/drm-panel-edp-drm-panel-edp-fix-auo-b116xtn02-name.patch @@ -0,0 +1,39 @@ +From 04ef1054362241ee73d186893ad8d7be4edeb23e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Nov 2023 12:41:52 -0800 +Subject: drm/panel-edp: drm/panel-edp: Fix AUO B116XTN02 name + +From: Hsin-Yi Wang + +[ Upstream commit 962845c090c4f85fa4f6872a5b6c89ee61f53cc0 ] + +Rename AUO 0x235c B116XTN02 to B116XTN02.3 according to decoding edid. + +Fixes: 3db2420422a5 ("drm/panel-edp: Add AUO B116XTN02, BOE NT116WHM-N21,836X2, NV116WHM-N49 V8.0") +Cc: stable@vger.kernel.org +Signed-off-by: Hsin-Yi Wang +Reviewed-by: Douglas Anderson +Acked-by: Maxime Ripard +Signed-off-by: Douglas Anderson +Link: https://patchwork.freedesktop.org/patch/msgid/20231107204611.3082200-3-hsinyi@chromium.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-edp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c +index e93e54a98260..7dc6fb7308ce 100644 +--- a/drivers/gpu/drm/panel/panel-edp.c ++++ b/drivers/gpu/drm/panel/panel-edp.c +@@ -1842,7 +1842,7 @@ static const struct edp_panel_entry edp_panels[] = { + EDP_PANEL_ENTRY('A', 'U', 'O', 0x145c, &delay_200_500_e50, "B116XAB01.4"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1e9b, &delay_200_500_e50, "B133UAN02.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x1ea5, &delay_200_500_e50, "B116XAK01.6"), +- EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02"), ++ EDP_PANEL_ENTRY('A', 'U', 'O', 0x235c, &delay_200_500_e50, "B116XTN02.3"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x582d, &delay_200_500_e50, "B133UAN01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), +-- +2.43.0 + diff --git a/queue-6.7/media-i2c-imx290-properly-encode-registers-as-little.patch b/queue-6.7/media-i2c-imx290-properly-encode-registers-as-little.patch new file mode 100644 index 00000000000..3bf913782ac --- /dev/null +++ b/queue-6.7/media-i2c-imx290-properly-encode-registers-as-little.patch @@ -0,0 +1,102 @@ +From 4a67eff61fc9ba951bb2ccc45dadad9efef47cbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Nov 2023 10:50:48 +0100 +Subject: media: i2c: imx290: Properly encode registers as little-endian + +From: Alexander Stein + +[ Upstream commit 60fc87a69523c294eb23a1316af922f6665a6f8c ] + +The conversion to CCI also converted the multi-byte register access to +big-endian. Correct the register definition by using the correct +little-endian ones. + +Fixes: af73323b9770 ("media: imx290: Convert to new CCI register access helpers") +Cc: stable@vger.kernel.org +Signed-off-by: Alexander Stein +Reviewed-by: Hans de Goede +Reviewed-by: Laurent Pinchart +[Sakari Ailus: Fixed the Fixes: tag.] +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/imx290.c | 42 +++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c +index 29098612813c..c6fea5837a19 100644 +--- a/drivers/media/i2c/imx290.c ++++ b/drivers/media/i2c/imx290.c +@@ -41,18 +41,18 @@ + #define IMX290_WINMODE_720P (1 << 4) + #define IMX290_WINMODE_CROP (4 << 4) + #define IMX290_FR_FDG_SEL CCI_REG8(0x3009) +-#define IMX290_BLKLEVEL CCI_REG16(0x300a) ++#define IMX290_BLKLEVEL CCI_REG16_LE(0x300a) + #define IMX290_GAIN CCI_REG8(0x3014) +-#define IMX290_VMAX CCI_REG24(0x3018) ++#define IMX290_VMAX CCI_REG24_LE(0x3018) + #define IMX290_VMAX_MAX 0x3ffff +-#define IMX290_HMAX CCI_REG16(0x301c) ++#define IMX290_HMAX CCI_REG16_LE(0x301c) + #define IMX290_HMAX_MAX 0xffff +-#define IMX290_SHS1 CCI_REG24(0x3020) ++#define IMX290_SHS1 CCI_REG24_LE(0x3020) + #define IMX290_WINWV_OB CCI_REG8(0x303a) +-#define IMX290_WINPV CCI_REG16(0x303c) +-#define IMX290_WINWV CCI_REG16(0x303e) +-#define IMX290_WINPH CCI_REG16(0x3040) +-#define IMX290_WINWH CCI_REG16(0x3042) ++#define IMX290_WINPV CCI_REG16_LE(0x303c) ++#define IMX290_WINWV CCI_REG16_LE(0x303e) ++#define IMX290_WINPH CCI_REG16_LE(0x3040) ++#define IMX290_WINWH CCI_REG16_LE(0x3042) + #define IMX290_OUT_CTRL CCI_REG8(0x3046) + #define IMX290_ODBIT_10BIT (0 << 0) + #define IMX290_ODBIT_12BIT (1 << 0) +@@ -78,28 +78,28 @@ + #define IMX290_ADBIT2 CCI_REG8(0x317c) + #define IMX290_ADBIT2_10BIT 0x12 + #define IMX290_ADBIT2_12BIT 0x00 +-#define IMX290_CHIP_ID CCI_REG16(0x319a) ++#define IMX290_CHIP_ID CCI_REG16_LE(0x319a) + #define IMX290_ADBIT3 CCI_REG8(0x31ec) + #define IMX290_ADBIT3_10BIT 0x37 + #define IMX290_ADBIT3_12BIT 0x0e + #define IMX290_REPETITION CCI_REG8(0x3405) + #define IMX290_PHY_LANE_NUM CCI_REG8(0x3407) + #define IMX290_OPB_SIZE_V CCI_REG8(0x3414) +-#define IMX290_Y_OUT_SIZE CCI_REG16(0x3418) +-#define IMX290_CSI_DT_FMT CCI_REG16(0x3441) ++#define IMX290_Y_OUT_SIZE CCI_REG16_LE(0x3418) ++#define IMX290_CSI_DT_FMT CCI_REG16_LE(0x3441) + #define IMX290_CSI_DT_FMT_RAW10 0x0a0a + #define IMX290_CSI_DT_FMT_RAW12 0x0c0c + #define IMX290_CSI_LANE_MODE CCI_REG8(0x3443) +-#define IMX290_EXTCK_FREQ CCI_REG16(0x3444) +-#define IMX290_TCLKPOST CCI_REG16(0x3446) +-#define IMX290_THSZERO CCI_REG16(0x3448) +-#define IMX290_THSPREPARE CCI_REG16(0x344a) +-#define IMX290_TCLKTRAIL CCI_REG16(0x344c) +-#define IMX290_THSTRAIL CCI_REG16(0x344e) +-#define IMX290_TCLKZERO CCI_REG16(0x3450) +-#define IMX290_TCLKPREPARE CCI_REG16(0x3452) +-#define IMX290_TLPX CCI_REG16(0x3454) +-#define IMX290_X_OUT_SIZE CCI_REG16(0x3472) ++#define IMX290_EXTCK_FREQ CCI_REG16_LE(0x3444) ++#define IMX290_TCLKPOST CCI_REG16_LE(0x3446) ++#define IMX290_THSZERO CCI_REG16_LE(0x3448) ++#define IMX290_THSPREPARE CCI_REG16_LE(0x344a) ++#define IMX290_TCLKTRAIL CCI_REG16_LE(0x344c) ++#define IMX290_THSTRAIL CCI_REG16_LE(0x344e) ++#define IMX290_TCLKZERO CCI_REG16_LE(0x3450) ++#define IMX290_TCLKPREPARE CCI_REG16_LE(0x3452) ++#define IMX290_TLPX CCI_REG16_LE(0x3454) ++#define IMX290_X_OUT_SIZE CCI_REG16_LE(0x3472) + #define IMX290_INCKSEL7 CCI_REG8(0x3480) + + #define IMX290_PGCTRL_REGEN BIT(0) +-- +2.43.0 + diff --git a/queue-6.7/media-v4l-cci-add-macros-to-obtain-register-width-an.patch b/queue-6.7/media-v4l-cci-add-macros-to-obtain-register-width-an.patch new file mode 100644 index 00000000000..929d6833a46 --- /dev/null +++ b/queue-6.7/media-v4l-cci-add-macros-to-obtain-register-width-an.patch @@ -0,0 +1,79 @@ +From dfa1d7061bf7ad69ab4d8bcc1d0b62825122176a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Nov 2023 17:42:40 +0200 +Subject: media: v4l: cci: Add macros to obtain register width and address + +From: Sakari Ailus + +[ Upstream commit cd93cc245dfe334c38da98c14b34f9597e1b4ea6 ] + +Add CCI_REG_WIDTH() macro to obtain register width in bits and similarly, +CCI_REG_WIDTH_BYTES() to obtain it in bytes. + +Also add CCI_REG_ADDR() macro to obtain the address of a register. + +Use both macros in v4l2-cci.c, too. + +Signed-off-by: Sakari Ailus +Reviewed-by: Hans de Goede +Reviewed-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Stable-dep-of: d92e7a013ff3 ("media: v4l2-cci: Add support for little-endian encoded registers") +Signed-off-by: Sasha Levin +--- + drivers/media/v4l2-core/v4l2-cci.c | 8 ++++---- + include/media/v4l2-cci.h | 5 +++++ + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-cci.c b/drivers/media/v4l2-core/v4l2-cci.c +index bc2dbec019b0..3179160abde3 100644 +--- a/drivers/media/v4l2-core/v4l2-cci.c ++++ b/drivers/media/v4l2-core/v4l2-cci.c +@@ -25,8 +25,8 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) + if (err && *err) + return *err; + +- len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); +- reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); ++ len = CCI_REG_WIDTH_BYTES(reg); ++ reg = CCI_REG_ADDR(reg); + + ret = regmap_bulk_read(map, reg, buf, len); + if (ret) { +@@ -75,8 +75,8 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) + if (err && *err) + return *err; + +- len = FIELD_GET(CCI_REG_WIDTH_MASK, reg); +- reg = FIELD_GET(CCI_REG_ADDR_MASK, reg); ++ len = CCI_REG_WIDTH_BYTES(reg); ++ reg = CCI_REG_ADDR(reg); + + switch (len) { + case 1: +diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h +index f2c2962e936b..a2835a663df5 100644 +--- a/include/media/v4l2-cci.h ++++ b/include/media/v4l2-cci.h +@@ -7,6 +7,7 @@ + #ifndef _V4L2_CCI_H + #define _V4L2_CCI_H + ++#include + #include + #include + +@@ -34,6 +35,10 @@ struct cci_reg_sequence { + #define CCI_REG_WIDTH_SHIFT 16 + #define CCI_REG_WIDTH_MASK GENMASK(19, 16) + ++#define CCI_REG_WIDTH_BYTES(x) FIELD_GET(CCI_REG_WIDTH_MASK, x) ++#define CCI_REG_WIDTH(x) (CCI_REG_WIDTH_BYTES(x) << 3) ++#define CCI_REG_ADDR(x) FIELD_GET(CCI_REG_ADDR_MASK, x) ++ + #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) + #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) + #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) +-- +2.43.0 + diff --git a/queue-6.7/media-v4l-cci-include-linux-bits.h.patch b/queue-6.7/media-v4l-cci-include-linux-bits.h.patch new file mode 100644 index 00000000000..5eb2695d221 --- /dev/null +++ b/queue-6.7/media-v4l-cci-include-linux-bits.h.patch @@ -0,0 +1,36 @@ +From e14680ec8098db5252e77579073aabf9fe1ce260 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Nov 2023 10:45:30 +0200 +Subject: media: v4l: cci: Include linux/bits.h + +From: Sakari Ailus + +[ Upstream commit eba5058633b4d11e2a4d65eae9f1fce0b96365d9 ] + +linux/bits.h is needed for GENMASK(). Include it. + +Signed-off-by: Sakari Ailus +Reviewed-by: Hans de Goede +Reviewed-by: Laurent Pinchart +Signed-off-by: Hans Verkuil +Stable-dep-of: d92e7a013ff3 ("media: v4l2-cci: Add support for little-endian encoded registers") +Signed-off-by: Sasha Levin +--- + include/media/v4l2-cci.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h +index 0f6803e4b17e..f2c2962e936b 100644 +--- a/include/media/v4l2-cci.h ++++ b/include/media/v4l2-cci.h +@@ -7,6 +7,7 @@ + #ifndef _V4L2_CCI_H + #define _V4L2_CCI_H + ++#include + #include + + struct i2c_client; +-- +2.43.0 + diff --git a/queue-6.7/media-v4l2-cci-add-support-for-little-endian-encoded.patch b/queue-6.7/media-v4l2-cci-add-support-for-little-endian-encoded.patch new file mode 100644 index 00000000000..cecca4ef0ae --- /dev/null +++ b/queue-6.7/media-v4l2-cci-add-support-for-little-endian-encoded.patch @@ -0,0 +1,154 @@ +From 8a9bd313a0dcd8a144265640d7100a3842d3acba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Nov 2023 10:50:47 +0100 +Subject: media: v4l2-cci: Add support for little-endian encoded registers + +From: Alexander Stein + +[ Upstream commit d92e7a013ff33f4e0b31bbf768d0c85a8acefebf ] + +Some sensors, e.g. Sony IMX290, are using little-endian registers. Add +support for those by encoding the endianness into Bit 20 of the register +address. + +Fixes: af73323b9770 ("media: imx290: Convert to new CCI register access helpers") +Cc: stable@vger.kernel.org +Signed-off-by: Alexander Stein +Reviewed-by: Hans de Goede +Reviewed-by: Laurent Pinchart +[Sakari Ailus: Fixed commit message.] +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/v4l2-core/v4l2-cci.c | 44 ++++++++++++++++++++++++------ + include/media/v4l2-cci.h | 5 ++++ + 2 files changed, 41 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-cci.c b/drivers/media/v4l2-core/v4l2-cci.c +index 3179160abde3..10005c80f43b 100644 +--- a/drivers/media/v4l2-core/v4l2-cci.c ++++ b/drivers/media/v4l2-core/v4l2-cci.c +@@ -18,6 +18,7 @@ + + int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) + { ++ bool little_endian; + unsigned int len; + u8 buf[8]; + int ret; +@@ -25,6 +26,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) + if (err && *err) + return *err; + ++ little_endian = reg & CCI_REG_LE; + len = CCI_REG_WIDTH_BYTES(reg); + reg = CCI_REG_ADDR(reg); + +@@ -40,16 +42,28 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err) + *val = buf[0]; + break; + case 2: +- *val = get_unaligned_be16(buf); ++ if (little_endian) ++ *val = get_unaligned_le16(buf); ++ else ++ *val = get_unaligned_be16(buf); + break; + case 3: +- *val = get_unaligned_be24(buf); ++ if (little_endian) ++ *val = get_unaligned_le24(buf); ++ else ++ *val = get_unaligned_be24(buf); + break; + case 4: +- *val = get_unaligned_be32(buf); ++ if (little_endian) ++ *val = get_unaligned_le32(buf); ++ else ++ *val = get_unaligned_be32(buf); + break; + case 8: +- *val = get_unaligned_be64(buf); ++ if (little_endian) ++ *val = get_unaligned_le64(buf); ++ else ++ *val = get_unaligned_be64(buf); + break; + default: + dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", +@@ -68,6 +82,7 @@ EXPORT_SYMBOL_GPL(cci_read); + + int cci_write(struct regmap *map, u32 reg, u64 val, int *err) + { ++ bool little_endian; + unsigned int len; + u8 buf[8]; + int ret; +@@ -75,6 +90,7 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) + if (err && *err) + return *err; + ++ little_endian = reg & CCI_REG_LE; + len = CCI_REG_WIDTH_BYTES(reg); + reg = CCI_REG_ADDR(reg); + +@@ -83,16 +99,28 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err) + buf[0] = val; + break; + case 2: +- put_unaligned_be16(val, buf); ++ if (little_endian) ++ put_unaligned_le16(val, buf); ++ else ++ put_unaligned_be16(val, buf); + break; + case 3: +- put_unaligned_be24(val, buf); ++ if (little_endian) ++ put_unaligned_le24(val, buf); ++ else ++ put_unaligned_be24(val, buf); + break; + case 4: +- put_unaligned_be32(val, buf); ++ if (little_endian) ++ put_unaligned_le32(val, buf); ++ else ++ put_unaligned_be32(val, buf); + break; + case 8: +- put_unaligned_be64(val, buf); ++ if (little_endian) ++ put_unaligned_le64(val, buf); ++ else ++ put_unaligned_be64(val, buf); + break; + default: + dev_err(regmap_get_device(map), "Error invalid reg-width %u for reg 0x%04x\n", +diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h +index a2835a663df5..8b0b361b464c 100644 +--- a/include/media/v4l2-cci.h ++++ b/include/media/v4l2-cci.h +@@ -38,12 +38,17 @@ struct cci_reg_sequence { + #define CCI_REG_WIDTH_BYTES(x) FIELD_GET(CCI_REG_WIDTH_MASK, x) + #define CCI_REG_WIDTH(x) (CCI_REG_WIDTH_BYTES(x) << 3) + #define CCI_REG_ADDR(x) FIELD_GET(CCI_REG_ADDR_MASK, x) ++#define CCI_REG_LE BIT(20) + + #define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) + #define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) + #define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) + #define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) + #define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG16_LE(x) (CCI_REG_LE | (2U << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG24_LE(x) (CCI_REG_LE | (3U << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG32_LE(x) (CCI_REG_LE | (4U << CCI_REG_WIDTH_SHIFT) | (x)) ++#define CCI_REG64_LE(x) (CCI_REG_LE | (8U << CCI_REG_WIDTH_SHIFT) | (x)) + + /** + * cci_read() - Read a value from a single CCI register +-- +2.43.0 + diff --git a/queue-6.7/series b/queue-6.7/series index 5839844e30d..7cafca00433 100644 --- a/queue-6.7/series +++ b/queue-6.7/series @@ -277,3 +277,29 @@ drm-amdgpu-show-vram-vendor-only-if-available.patch drm-amd-pm-update-the-power-cap-setting.patch drm-amdgpu-pm-fix-the-power-source-flag-error.patch drm-amd-display-fix-uninitialized-variable-usage-in-core_link_-read_dpcd-write_dpcd-functions.patch +thermal-intel-hfi-refactor-enabling-code-into-helper.patch +thermal-intel-hfi-disable-an-hfi-instance-when-all-i.patch +thermal-intel-hfi-add-syscore-callbacks-for-system-w.patch +media-v4l-cci-include-linux-bits.h.patch +media-v4l-cci-add-macros-to-obtain-register-width-an.patch +media-v4l2-cci-add-support-for-little-endian-encoded.patch +media-i2c-imx290-properly-encode-registers-as-little.patch +btrfs-zoned-factor-out-prepare_allocation_zoned.patch +btrfs-zoned-optimize-hint-byte-for-zoned-allocator.patch +drm-amd-display-do-not-send-commands-to-dmub-if-dmub.patch +drm-amd-display-refactor-dmcub-enter-exit-idle-inter.patch +drm-amd-display-wake-dmcub-before-sending-a-command.patch +drm-amd-display-wake-dmcub-before-executing-gpint-co.patch +drm-amd-display-fix-conversions-between-bytes-and-kb.patch +drm-panel-edp-add-auo-b116xtn02-boe-nt116whm-n21-836.patch +drm-panel-edp-drm-panel-edp-fix-auo-b116xak01-name-a.patch +drm-panel-edp-drm-panel-edp-fix-auo-b116xtn02-name.patch +drm-amd-display-fix-hang-underflow-when-transitionin.patch +drm-amd-display-disconnect-phantom-pipe-opp-from-opt.patch +drm-amd-display-clear-optc-mem-select-on-disable.patch +drm-amd-display-add-logging-resource-checks.patch +drm-amd-display-update-pixel-clock-params-after-stre.patch +drm-amd-display-init-link-enc-resources-in-dc_state-.patch +drm-amdgpu-enable-tunneling-on-high-priority-compute.patch +drm-amdgpu-gfx10-set-unord_dispatch-in-compute-mqds.patch +drm-amdgpu-gfx11-set-unord_dispatch-in-compute-mqds.patch diff --git a/queue-6.7/thermal-intel-hfi-add-syscore-callbacks-for-system-w.patch b/queue-6.7/thermal-intel-hfi-add-syscore-callbacks-for-system-w.patch new file mode 100644 index 00000000000..1d4dd9d7a79 --- /dev/null +++ b/queue-6.7/thermal-intel-hfi-add-syscore-callbacks-for-system-w.patch @@ -0,0 +1,101 @@ +From 49cd51dd1a6c35f57633ae76718ba7e45b1dded0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jan 2024 19:07:04 -0800 +Subject: thermal: intel: hfi: Add syscore callbacks for system-wide PM + +From: Ricardo Neri + +[ Upstream commit 97566d09fd02d2ab329774bb89a2cdf2267e86d9 ] + +The kernel allocates a memory buffer and provides its location to the +hardware, which uses it to update the HFI table. This allocation occurs +during boot and remains constant throughout runtime. + +When resuming from hibernation, the restore kernel allocates a second +memory buffer and reprograms the HFI hardware with the new location as +part of a normal boot. The location of the second memory buffer may +differ from the one allocated by the image kernel. + +When the restore kernel transfers control to the image kernel, its HFI +buffer becomes invalid, potentially leading to memory corruption if the +hardware writes to it (the hardware continues to use the buffer from the +restore kernel). + +It is also possible that the hardware "forgets" the address of the memory +buffer when resuming from "deep" suspend. Memory corruption may also occur +in such a scenario. + +To prevent the described memory corruption, disable HFI when preparing to +suspend or hibernate. Enable it when resuming. + +Add syscore callbacks to handle the package of the boot CPU (packages of +non-boot CPUs are handled via CPU offline). Syscore ops always run on the +boot CPU. Additionally, HFI only needs to be disabled during "deep" suspend +and hibernation. Syscore ops only run in these cases. + +Cc: 6.1+ # 6.1+ +Signed-off-by: Ricardo Neri +[ rjw: Comment adjustment, subject and changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/thermal/intel/intel_hfi.c | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c +index bb25c75acd45..1c5a429b2e3e 100644 +--- a/drivers/thermal/intel/intel_hfi.c ++++ b/drivers/thermal/intel/intel_hfi.c +@@ -35,7 +35,9 @@ + #include + #include + #include ++#include + #include ++#include + #include + #include + +@@ -568,6 +570,30 @@ static __init int hfi_parse_features(void) + return 0; + } + ++static void hfi_do_enable(void) ++{ ++ /* This code runs only on the boot CPU. */ ++ struct hfi_cpu_info *info = &per_cpu(hfi_cpu_info, 0); ++ struct hfi_instance *hfi_instance = info->hfi_instance; ++ ++ /* No locking needed. There is no concurrency with CPU online. */ ++ hfi_set_hw_table(hfi_instance); ++ hfi_enable(); ++} ++ ++static int hfi_do_disable(void) ++{ ++ /* No locking needed. There is no concurrency with CPU offline. */ ++ hfi_disable(); ++ ++ return 0; ++} ++ ++static struct syscore_ops hfi_pm_ops = { ++ .resume = hfi_do_enable, ++ .suspend = hfi_do_disable, ++}; ++ + void __init intel_hfi_init(void) + { + struct hfi_instance *hfi_instance; +@@ -599,6 +625,8 @@ void __init intel_hfi_init(void) + if (!hfi_updates_wq) + goto err_nomem; + ++ register_syscore_ops(&hfi_pm_ops); ++ + return; + + err_nomem: +-- +2.43.0 + diff --git a/queue-6.7/thermal-intel-hfi-disable-an-hfi-instance-when-all-i.patch b/queue-6.7/thermal-intel-hfi-disable-an-hfi-instance-when-all-i.patch new file mode 100644 index 00000000000..16a25597738 --- /dev/null +++ b/queue-6.7/thermal-intel-hfi-disable-an-hfi-instance-when-all-i.patch @@ -0,0 +1,98 @@ +From b4b1a43d74d6acd1d9924bf0fb72c6c5a87c2a47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jan 2024 20:14:58 -0800 +Subject: thermal: intel: hfi: Disable an HFI instance when all its CPUs go + offline + +From: Ricardo Neri + +[ Upstream commit 1c53081d773c2cb4461636559b0d55b46559ceec ] + +In preparation to support hibernation, add functionality to disable an HFI +instance during CPU offline. The last CPU of an instance that goes offline +will disable such instance. + +The Intel Software Development Manual states that the operating system must +wait for the hardware to set MSR_IA32_PACKAGE_THERM_STATUS[26] after +disabling an HFI instance to ensure that it will no longer write on the HFI +memory. Some processors, however, do not ever set such bit. Wait a minimum +of 2ms to give time hardware to complete any pending memory writes. + +Signed-off-by: Ricardo Neri +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: 97566d09fd02 ("thermal: intel: hfi: Add syscore callbacks for system-wide PM") +Signed-off-by: Sasha Levin +--- + drivers/thermal/intel/intel_hfi.c | 35 +++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c +index 820613e293cd..bb25c75acd45 100644 +--- a/drivers/thermal/intel/intel_hfi.c ++++ b/drivers/thermal/intel/intel_hfi.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -367,6 +368,32 @@ static void hfi_set_hw_table(struct hfi_instance *hfi_instance) + wrmsrl(MSR_IA32_HW_FEEDBACK_PTR, msr_val); + } + ++/* Caller must hold hfi_instance_lock. */ ++static void hfi_disable(void) ++{ ++ u64 msr_val; ++ int i; ++ ++ rdmsrl(MSR_IA32_HW_FEEDBACK_CONFIG, msr_val); ++ msr_val &= ~HW_FEEDBACK_CONFIG_HFI_ENABLE_BIT; ++ wrmsrl(MSR_IA32_HW_FEEDBACK_CONFIG, msr_val); ++ ++ /* ++ * Wait for hardware to acknowledge the disabling of HFI. Some ++ * processors may not do it. Wait for ~2ms. This is a reasonable ++ * time for hardware to complete any pending actions on the HFI ++ * memory. ++ */ ++ for (i = 0; i < 2000; i++) { ++ rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val); ++ if (msr_val & PACKAGE_THERM_STATUS_HFI_UPDATED) ++ break; ++ ++ udelay(1); ++ cpu_relax(); ++ } ++} ++ + /** + * intel_hfi_online() - Enable HFI on @cpu + * @cpu: CPU in which the HFI will be enabled +@@ -421,6 +448,10 @@ void intel_hfi_online(unsigned int cpu) + /* + * Hardware is programmed with the physical address of the first page + * frame of the table. Hence, the allocated memory must be page-aligned. ++ * ++ * Some processors do not forget the initial address of the HFI table ++ * even after having been reprogrammed. Keep using the same pages. Do ++ * not free them. + */ + hfi_instance->hw_table = alloc_pages_exact(hfi_features.nr_table_pages, + GFP_KERNEL | __GFP_ZERO); +@@ -485,6 +516,10 @@ void intel_hfi_offline(unsigned int cpu) + + mutex_lock(&hfi_instance_lock); + cpumask_clear_cpu(cpu, hfi_instance->cpus); ++ ++ if (!cpumask_weight(hfi_instance->cpus)) ++ hfi_disable(); ++ + mutex_unlock(&hfi_instance_lock); + } + +-- +2.43.0 + diff --git a/queue-6.7/thermal-intel-hfi-refactor-enabling-code-into-helper.patch b/queue-6.7/thermal-intel-hfi-refactor-enabling-code-into-helper.patch new file mode 100644 index 00000000000..6b1f57cec85 --- /dev/null +++ b/queue-6.7/thermal-intel-hfi-refactor-enabling-code-into-helper.patch @@ -0,0 +1,108 @@ +From 3f92b215d8655b6745095ad5f194b5935a5e8096 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jan 2024 20:14:56 -0800 +Subject: thermal: intel: hfi: Refactor enabling code into helper functions + +From: Ricardo Neri + +[ Upstream commit 8a8b6bb93c704776c4b05cb517c3fa8baffb72f5 ] + +In preparation for the addition of a suspend notifier, wrap the logic to +enable HFI and program its memory buffer into helper functions. Both the +CPU hotplug callback and the suspend notifier will use them. + +This refactoring does not introduce functional changes. + +Signed-off-by: Ricardo Neri +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: 97566d09fd02 ("thermal: intel: hfi: Add syscore callbacks for system-wide PM") +Signed-off-by: Sasha Levin +--- + drivers/thermal/intel/intel_hfi.c | 43 ++++++++++++++++--------------- + 1 file changed, 22 insertions(+), 21 deletions(-) + +diff --git a/drivers/thermal/intel/intel_hfi.c b/drivers/thermal/intel/intel_hfi.c +index c69db6c90869..820613e293cd 100644 +--- a/drivers/thermal/intel/intel_hfi.c ++++ b/drivers/thermal/intel/intel_hfi.c +@@ -347,6 +347,26 @@ static void init_hfi_instance(struct hfi_instance *hfi_instance) + hfi_instance->data = hfi_instance->hdr + hfi_features.hdr_size; + } + ++/* Caller must hold hfi_instance_lock. */ ++static void hfi_enable(void) ++{ ++ u64 msr_val; ++ ++ rdmsrl(MSR_IA32_HW_FEEDBACK_CONFIG, msr_val); ++ msr_val |= HW_FEEDBACK_CONFIG_HFI_ENABLE_BIT; ++ wrmsrl(MSR_IA32_HW_FEEDBACK_CONFIG, msr_val); ++} ++ ++static void hfi_set_hw_table(struct hfi_instance *hfi_instance) ++{ ++ phys_addr_t hw_table_pa; ++ u64 msr_val; ++ ++ hw_table_pa = virt_to_phys(hfi_instance->hw_table); ++ msr_val = hw_table_pa | HW_FEEDBACK_PTR_VALID_BIT; ++ wrmsrl(MSR_IA32_HW_FEEDBACK_PTR, msr_val); ++} ++ + /** + * intel_hfi_online() - Enable HFI on @cpu + * @cpu: CPU in which the HFI will be enabled +@@ -364,8 +384,6 @@ void intel_hfi_online(unsigned int cpu) + { + struct hfi_instance *hfi_instance; + struct hfi_cpu_info *info; +- phys_addr_t hw_table_pa; +- u64 msr_val; + u16 die_id; + + /* Nothing to do if hfi_instances are missing. */ +@@ -409,8 +427,6 @@ void intel_hfi_online(unsigned int cpu) + if (!hfi_instance->hw_table) + goto unlock; + +- hw_table_pa = virt_to_phys(hfi_instance->hw_table); +- + /* + * Allocate memory to keep a local copy of the table that + * hardware generates. +@@ -420,16 +436,6 @@ void intel_hfi_online(unsigned int cpu) + if (!hfi_instance->local_table) + goto free_hw_table; + +- /* +- * Program the address of the feedback table of this die/package. On +- * some processors, hardware remembers the old address of the HFI table +- * even after having been reprogrammed and re-enabled. Thus, do not free +- * the pages allocated for the table or reprogram the hardware with a +- * new base address. Namely, program the hardware only once. +- */ +- msr_val = hw_table_pa | HW_FEEDBACK_PTR_VALID_BIT; +- wrmsrl(MSR_IA32_HW_FEEDBACK_PTR, msr_val); +- + init_hfi_instance(hfi_instance); + + INIT_DELAYED_WORK(&hfi_instance->update_work, hfi_update_work_fn); +@@ -438,13 +444,8 @@ void intel_hfi_online(unsigned int cpu) + + cpumask_set_cpu(cpu, hfi_instance->cpus); + +- /* +- * Enable the hardware feedback interface and never disable it. See +- * comment on programming the address of the table. +- */ +- rdmsrl(MSR_IA32_HW_FEEDBACK_CONFIG, msr_val); +- msr_val |= HW_FEEDBACK_CONFIG_HFI_ENABLE_BIT; +- wrmsrl(MSR_IA32_HW_FEEDBACK_CONFIG, msr_val); ++ hfi_set_hw_table(hfi_instance); ++ hfi_enable(); + + unlock: + mutex_unlock(&hfi_instance_lock); +-- +2.43.0 + -- 2.47.3