From 1e266f02db8e965c43d825266cfdb3fba02b8a39 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 14 May 2023 21:42:10 -0400 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...add-null-plane_state-check-for-curso.patch | 48 + ...refine-condition-of-cursor-visibilit.patch | 102 ++ ...-additional-hdmi-pixel-clock-frequen.patch | 1164 +++++++++++++++++ ...-hdmi-pixel-clock-frequencies-267.30.patch | 116 ++ .../drm-i915-dg2-support-4k-30-on-hdmi.patch | 82 ++ ...fix-runtime-pm-imbalance-at-gpu-load.patch | 76 ++ .../drm-msm-remove-struct_mutex-usage.patch | 359 +++++ queue-5.15/ksmbd-add-channel-rwlock.patch | 139 ++ ...ix-deadlock-in-ksmbd_find_crypto_ctx.patch | 79 ++ ...smbd-fix-kernel-oops-from-idr_remove.patch | 88 ++ ...fix-multi-session-connection-failure.patch | 241 ++++ ...ssue-while-destroying-session-on-mul.patch | 646 +++++++++ ...not-allow-guest-user-on-multichannel.patch | 66 + ...ssions-list-in-connection-with-xarra.patch | 219 ++++ ...pable-in-fsctl_query_network_interfa.patch | 98 ++ queue-5.15/series | 16 + ...-rtw8821c-fix-rfe_option-field-width.patch | 60 + 17 files changed, 3599 insertions(+) create mode 100644 queue-5.15/drm-amd-display-add-null-plane_state-check-for-curso.patch create mode 100644 queue-5.15/drm-amd-display-refine-condition-of-cursor-visibilit.patch create mode 100644 queue-5.15/drm-i915-dg2-add-additional-hdmi-pixel-clock-frequen.patch create mode 100644 queue-5.15/drm-i915-dg2-add-hdmi-pixel-clock-frequencies-267.30.patch create mode 100644 queue-5.15/drm-i915-dg2-support-4k-30-on-hdmi.patch create mode 100644 queue-5.15/drm-msm-adreno-fix-runtime-pm-imbalance-at-gpu-load.patch create mode 100644 queue-5.15/drm-msm-remove-struct_mutex-usage.patch create mode 100644 queue-5.15/ksmbd-add-channel-rwlock.patch create mode 100644 queue-5.15/ksmbd-fix-deadlock-in-ksmbd_find_crypto_ctx.patch create mode 100644 queue-5.15/ksmbd-fix-kernel-oops-from-idr_remove.patch create mode 100644 queue-5.15/ksmbd-fix-multi-session-connection-failure.patch create mode 100644 queue-5.15/ksmbd-fix-racy-issue-while-destroying-session-on-mul.patch create mode 100644 queue-5.15/ksmbd-not-allow-guest-user-on-multichannel.patch create mode 100644 queue-5.15/ksmbd-replace-sessions-list-in-connection-with-xarra.patch create mode 100644 queue-5.15/ksmbd-set-rss-capable-in-fsctl_query_network_interfa.patch create mode 100644 queue-5.15/wifi-rtw88-rtw8821c-fix-rfe_option-field-width.patch diff --git a/queue-5.15/drm-amd-display-add-null-plane_state-check-for-curso.patch b/queue-5.15/drm-amd-display-add-null-plane_state-check-for-curso.patch new file mode 100644 index 00000000000..8da50458921 --- /dev/null +++ b/queue-5.15/drm-amd-display-add-null-plane_state-check-for-curso.patch @@ -0,0 +1,48 @@ +From aaaeb1f496a41bc5c232bb302489c1fb47ac214f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Mar 2023 09:11:29 -0500 +Subject: drm/amd/display: Add NULL plane_state check for cursor disable logic + +From: Nicholas Kazlauskas + +[ Upstream commit d29fb7baab09b6a1dc484c9c67933253883e770a ] + +[Why] +While scanning the top_pipe connections we can run into a case where +the bottom pipe is still connected to a top_pipe but with a NULL +plane_state. + +[How] +Treat a NULL plane_state the same as the plane being invisible for +pipe cursor disable logic. + +Cc: stable@vger.kernel.org +Cc: Mario Limonciello +Reviewed-by: Charlene Liu +Acked-by: Qingqing Zhuo +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/dcn10/dcn10_hw_sequencer.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index eef6e4c80a37f..73457c32f3e7f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -3225,7 +3225,9 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) + for (test_pipe = pipe_ctx->top_pipe; test_pipe; + test_pipe = test_pipe->top_pipe) { + // Skip invisible layer and pipe-split plane on same layer +- if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer) ++ if (!test_pipe->plane_state || ++ !test_pipe->plane_state->visible || ++ test_pipe->plane_state->layer_index == cur_layer) + continue; + + r2 = test_pipe->plane_res.scl_data.recout; +-- +2.39.2 + diff --git a/queue-5.15/drm-amd-display-refine-condition-of-cursor-visibilit.patch b/queue-5.15/drm-amd-display-refine-condition-of-cursor-visibilit.patch new file mode 100644 index 00000000000..ca0c551d283 --- /dev/null +++ b/queue-5.15/drm-amd-display-refine-condition-of-cursor-visibilit.patch @@ -0,0 +1,102 @@ +From fd496132ad6ffe4d8bd6b7ee1fcea67a7e21110f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Aug 2021 16:44:37 +0800 +Subject: drm/amd/display: Refine condition of cursor visibility for pipe-split + +From: Dale Zhao + +[ Upstream commit 63f8bee439c0e3f94cff90d0f9c7b719be693265 ] + +[Why] +In some scenarios like fullscreen game, major plane is scaled. Then +if a upper layer owns the cursor, cursor is invisiable in the +majority of the screen. + +[How] +Instead assuming upper plane handles cursor, summing up upper +split planes on the same layer. If whole upper plane covers current +half/whole pipe plane, disable cursor. + +Reviewed-by: Krunoslav Kovac +Acked-by: Mikita Lipski +Signed-off-by: Dale Zhao +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Stable-dep-of: d29fb7baab09 ("drm/amd/display: Add NULL plane_state check for cursor disable logic") +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 43 +++++++++++-------- + 1 file changed, 24 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index c655d03ef754d..eef6e4c80a37f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -3211,13 +3211,11 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) + + static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) + { +- struct pipe_ctx *test_pipe; ++ struct pipe_ctx *test_pipe, *split_pipe; + const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data; +- const struct rect *r1 = &scl_data->recout, *r2; +- int r1_r = r1->x + r1->width, r1_b = r1->y + r1->height, r2_r, r2_b; ++ struct rect r1 = scl_data->recout, r2, r2_half; ++ int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b; + int cur_layer = pipe_ctx->plane_state->layer_index; +- bool upper_pipe_exists = false; +- struct fixed31_32 one = dc_fixpt_from_int(1); + + /** + * Disable the cursor if there's another pipe above this with a +@@ -3226,26 +3224,33 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) + */ + for (test_pipe = pipe_ctx->top_pipe; test_pipe; + test_pipe = test_pipe->top_pipe) { +- if (!test_pipe->plane_state->visible) ++ // Skip invisible layer and pipe-split plane on same layer ++ if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer) + continue; + +- r2 = &test_pipe->plane_res.scl_data.recout; +- r2_r = r2->x + r2->width; +- r2_b = r2->y + r2->height; ++ r2 = test_pipe->plane_res.scl_data.recout; ++ r2_r = r2.x + r2.width; ++ r2_b = r2.y + r2.height; ++ split_pipe = test_pipe; + +- if (r1->x >= r2->x && r1->y >= r2->y && r1_r <= r2_r && r1_b <= r2_b) +- return true; ++ /** ++ * There is another half plane on same layer because of ++ * pipe-split, merge together per same height. ++ */ ++ for (split_pipe = pipe_ctx->top_pipe; split_pipe; ++ split_pipe = split_pipe->top_pipe) ++ if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { ++ r2_half = split_pipe->plane_res.scl_data.recout; ++ r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x; ++ r2.width = r2.width + r2_half.width; ++ r2_r = r2.x + r2.width; ++ break; ++ } + +- if (test_pipe->plane_state->layer_index < cur_layer) +- upper_pipe_exists = true; ++ if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b) ++ return true; + } + +- // if plane scaled, assume an upper plane can handle cursor if it exists. +- if (upper_pipe_exists && +- (scl_data->ratios.horz.value != one.value || +- scl_data->ratios.vert.value != one.value)) +- return true; +- + return false; + } + +-- +2.39.2 + diff --git a/queue-5.15/drm-i915-dg2-add-additional-hdmi-pixel-clock-frequen.patch b/queue-5.15/drm-i915-dg2-add-additional-hdmi-pixel-clock-frequen.patch new file mode 100644 index 00000000000..58ca50e7129 --- /dev/null +++ b/queue-5.15/drm-i915-dg2-add-additional-hdmi-pixel-clock-frequen.patch @@ -0,0 +1,1164 @@ +From 37f0743735931f63d8b34afa9047b159605aa62a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 16:48:56 -0700 +Subject: drm/i915/dg2: Add additional HDMI pixel clock frequencies + +From: Taylor, Clinton A + +[ Upstream commit 11c7faa61d136cef92506e4e77d0e6c6e01428bc ] + +Using the BSPEC algorithm add addition HDMI pixel clocks to the existing +table. + +v2: remove 297000 unused entry + +Cc: Matt Roper +Cc: Radhakrishna Sripada +Signed-off-by: Taylor, Clinton A +Reviewed-by: Balasubramani Vivekanandan +[mattrope: Fixed minor whitepsace issue flagged by checkpatch] +Signed-off-by: Matt Roper +Link: https://patchwork.freedesktop.org/patch/msgid/20220801234856.2832317-1-clinton.a.taylor@intel.com +Stable-dep-of: d46746b8b13c ("drm/i915/dg2: Add HDMI pixel clock frequencies 267.30 and 319.89 MHz") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/display/intel_snps_phy.c | 1116 +++++++++++++++++ + 1 file changed, 1116 insertions(+) + +diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c +index 1e6ba0a377265..2030ef0b599f0 100644 +--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c ++++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c +@@ -583,6 +583,1086 @@ static const struct intel_mpllb_state dg2_hdmi_148_5 = { + }; + + /* values in the below table are calculted using the algo */ ++static const struct intel_mpllb_state dg2_hdmi_25200 = { ++ .clock = 25200, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 128) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 41943) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 2621), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_27027 = { ++ .clock = 27027, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 140) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 31876) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 46555), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_28320 = { ++ .clock = 28320, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 148) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 40894) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 30408), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_30240 = { ++ .clock = 30240, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 5) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 160) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 50331) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 42466), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_31500 = { ++ .clock = 31500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 68) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_36000 = { ++ .clock = 36000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 82) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 39320), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_40000 = { ++ .clock = 40000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 96) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_49500 = { ++ .clock = 49500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 1), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 126) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_50000 = { ++ .clock = 50000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 1), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 128) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_57284 = { ++ .clock = 57284, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 150) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 42886) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 49701), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_58000 = { ++ .clock = 58000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 4) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 152) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_65000 = { ++ .clock = 65000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 72) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_71000 = { ++ .clock = 71000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 80) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_74176 = { ++ .clock = 74176, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22334) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 43829), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_75000 = { ++ .clock = 75000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 88) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_78750 = { ++ .clock = 78750, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 94) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_85500 = { ++ .clock = 85500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 104) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_88750 = { ++ .clock = 88750, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 1), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 110) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_106500 = { ++ .clock = 106500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 138) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_108000 = { ++ .clock = 108000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 140) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_115500 = { ++ .clock = 115500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 152) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_119000 = { ++ .clock = 119000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 3) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 158) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_135000 = { ++ .clock = 135000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 76) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 0), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_138500 = { ++ .clock = 138500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 78) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_147160 = { ++ .clock = 147160, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 84) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 56623) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 6815), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_148352 = { ++ .clock = 148352, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22334) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 43829), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_154000 = { ++ .clock = 154000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 13) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 90) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 39320), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_162000 = { ++ .clock = 162000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 96) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 52428) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_209800 = { ++ .clock = 209800, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 134) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 60293) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 7864), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_262750 = { ++ .clock = 262750, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 72) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 36044) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_268500 = { ++ .clock = 268500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 74) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 45875) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_296703 = { ++ .clock = 296703, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22321) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 36804), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_241500 = { ++ .clock = 241500, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 160) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 39321) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 39320), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_497750 = { ++ .clock = 497750, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 15) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 0), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 166) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 36044) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 52427), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_592000 = { ++ .clock = 592000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 13107) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13107), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ ++static const struct intel_mpllb_state dg2_hdmi_593407 = { ++ .clock = 593407, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 0) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 22328) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 7549), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ + static const struct intel_mpllb_state dg2_hdmi_297 = { + .clock = 297000, + .ref_control = +@@ -649,6 +1729,42 @@ static const struct intel_mpllb_state *dg2_hdmi_tables[] = { + &dg2_hdmi_148_5, + &dg2_hdmi_297, + &dg2_hdmi_594, ++ &dg2_hdmi_25200, ++ &dg2_hdmi_27027, ++ &dg2_hdmi_28320, ++ &dg2_hdmi_30240, ++ &dg2_hdmi_31500, ++ &dg2_hdmi_36000, ++ &dg2_hdmi_40000, ++ &dg2_hdmi_49500, ++ &dg2_hdmi_50000, ++ &dg2_hdmi_57284, ++ &dg2_hdmi_58000, ++ &dg2_hdmi_65000, ++ &dg2_hdmi_71000, ++ &dg2_hdmi_74176, ++ &dg2_hdmi_75000, ++ &dg2_hdmi_78750, ++ &dg2_hdmi_85500, ++ &dg2_hdmi_88750, ++ &dg2_hdmi_106500, ++ &dg2_hdmi_108000, ++ &dg2_hdmi_115500, ++ &dg2_hdmi_119000, ++ &dg2_hdmi_135000, ++ &dg2_hdmi_138500, ++ &dg2_hdmi_147160, ++ &dg2_hdmi_148352, ++ &dg2_hdmi_154000, ++ &dg2_hdmi_162000, ++ &dg2_hdmi_209800, ++ &dg2_hdmi_241500, ++ &dg2_hdmi_262750, ++ &dg2_hdmi_268500, ++ &dg2_hdmi_296703, ++ &dg2_hdmi_497750, ++ &dg2_hdmi_592000, ++ &dg2_hdmi_593407, + NULL, + }; + +-- +2.39.2 + diff --git a/queue-5.15/drm-i915-dg2-add-hdmi-pixel-clock-frequencies-267.30.patch b/queue-5.15/drm-i915-dg2-add-hdmi-pixel-clock-frequencies-267.30.patch new file mode 100644 index 00000000000..81da49b7922 --- /dev/null +++ b/queue-5.15/drm-i915-dg2-add-hdmi-pixel-clock-frequencies-267.30.patch @@ -0,0 +1,116 @@ +From dde85629344dc14f02b8de7e9574745e00538403 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Feb 2023 10:06:19 +0530 +Subject: drm/i915/dg2: Add HDMI pixel clock frequencies 267.30 and 319.89 MHz + +From: Ankit Nautiyal + +[ Upstream commit d46746b8b13cbd377ffc733e465d25800459a31b ] + +Add snps phy table values for HDMI pixel clocks 267.30 MHz and +319.89 MHz. Values are based on the Bspec algorithm for +PLL programming for HDMI. + +Cc: stable@vger.kernel.org +Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8008 +Signed-off-by: Ankit Nautiyal +Reviewed-by: Uma Shankar +Signed-off-by: Uma Shankar +Link: https://patchwork.freedesktop.org/patch/msgid/20230223043619.3941382-1-ankit.k.nautiyal@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/display/intel_snps_phy.c | 62 +++++++++++++++++++ + 1 file changed, 62 insertions(+) + +diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c +index 2030ef0b599f0..170690fc735b5 100644 +--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c ++++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c +@@ -1483,6 +1483,36 @@ static const struct intel_mpllb_state dg2_hdmi_262750 = { + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), + }; + ++static const struct intel_mpllb_state dg2_hdmi_267300 = { ++ .clock = 267300, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 7) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 74) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 30146) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 36699), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ + static const struct intel_mpllb_state dg2_hdmi_268500 = { + .clock = 268500, + .ref_control = +@@ -1573,6 +1603,36 @@ static const struct intel_mpllb_state dg2_hdmi_241500 = { + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), + }; + ++static const struct intel_mpllb_state dg2_hdmi_319890 = { ++ .clock = 319890, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 2), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 94) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 64094) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 13631), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ + static const struct intel_mpllb_state dg2_hdmi_497750 = { + .clock = 497750, + .ref_control = +@@ -1760,8 +1820,10 @@ static const struct intel_mpllb_state *dg2_hdmi_tables[] = { + &dg2_hdmi_209800, + &dg2_hdmi_241500, + &dg2_hdmi_262750, ++ &dg2_hdmi_267300, + &dg2_hdmi_268500, + &dg2_hdmi_296703, ++ &dg2_hdmi_319890, + &dg2_hdmi_497750, + &dg2_hdmi_592000, + &dg2_hdmi_593407, +-- +2.39.2 + diff --git a/queue-5.15/drm-i915-dg2-support-4k-30-on-hdmi.patch b/queue-5.15/drm-i915-dg2-support-4k-30-on-hdmi.patch new file mode 100644 index 00000000000..2dc5e4fa845 --- /dev/null +++ b/queue-5.15/drm-i915-dg2-support-4k-30-on-hdmi.patch @@ -0,0 +1,82 @@ +From a2c357aa377de55ac7e5a6eb0b75fb713513b951 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 May 2022 13:34:01 +0530 +Subject: drm/i915/dg2: Support 4k@30 on HDMI + +From: Vandita Kulkarni + +[ Upstream commit edd34368c4c3b45b1386b15f78b2229420f8c6d4 ] + +This patch adds a fix to support 297MHz of dot clock by calculating +the pll values using synopsis algorithm. +This will help to support 4k@30 mode for HDMI monitors on DG2. + +v2: As per the algorithm, set MPLLB VCO range control bits to 3, +in register SNPS_PHY_MPLLB_DIV for 297Mhz. (Matt) + +v3: Fix typo. (Ankit) + +Signed-off-by: Vandita Kulkarni +Signed-off-by: Ankit Nautiyal +Reviewed-by: Matt Roper +Signed-off-by: Matt Roper +Link: https://patchwork.freedesktop.org/patch/msgid/20220525080401.1253511-1-ankit.k.nautiyal@intel.com +Stable-dep-of: d46746b8b13c ("drm/i915/dg2: Add HDMI pixel clock frequencies 267.30 and 319.89 MHz") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/display/intel_snps_phy.c | 32 +++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c +index 536b319ffe5ba..1e6ba0a377265 100644 +--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c ++++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c +@@ -582,6 +582,37 @@ static const struct intel_mpllb_state dg2_hdmi_148_5 = { + REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), + }; + ++/* values in the below table are calculted using the algo */ ++static const struct intel_mpllb_state dg2_hdmi_297 = { ++ .clock = 297000, ++ .ref_control = ++ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, 3), ++ .mpllb_cp = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, 6) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, 14) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, 64) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, 124), ++ .mpllb_div = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, 2) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, 3), ++ .mpllb_div2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, 86) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, 1), ++ .mpllb_fracn1 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, 1) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, 65535), ++ .mpllb_fracn2 = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, 26214) | ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, 26214), ++ .mpllb_sscen = ++ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, 1), ++}; ++ + static const struct intel_mpllb_state dg2_hdmi_594 = { + .clock = 594000, + .ref_control = +@@ -616,6 +647,7 @@ static const struct intel_mpllb_state *dg2_hdmi_tables[] = { + &dg2_hdmi_27_0, + &dg2_hdmi_74_25, + &dg2_hdmi_148_5, ++ &dg2_hdmi_297, + &dg2_hdmi_594, + NULL, + }; +-- +2.39.2 + diff --git a/queue-5.15/drm-msm-adreno-fix-runtime-pm-imbalance-at-gpu-load.patch b/queue-5.15/drm-msm-adreno-fix-runtime-pm-imbalance-at-gpu-load.patch new file mode 100644 index 00000000000..42a1279a49d --- /dev/null +++ b/queue-5.15/drm-msm-adreno-fix-runtime-pm-imbalance-at-gpu-load.patch @@ -0,0 +1,76 @@ +From 854bbaeef7c21e7ac7894cccf342c41245ffebfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Mar 2023 17:48:05 +0100 +Subject: drm/msm/adreno: fix runtime PM imbalance at gpu load + +From: Johan Hovold + +[ Upstream commit 0d997f95b70f98987ae031a89677c13e0e223670 ] + +A recent commit moved enabling of runtime PM to GPU load time (first +open()) but failed to update the error paths so that runtime PM is +disabled if initialisation of the GPU fails. This would trigger a +warning about the unbalanced disable count on the next open() attempt. + +Note that pm_runtime_put_noidle() is sufficient to balance the usage +count when pm_runtime_put_sync() fails (and is chosen over +pm_runtime_resume_and_get() for consistency reasons). + +Fixes: 4b18299b3365 ("drm/msm/adreno: Defer enabling runpm until hw_init()") +Cc: stable@vger.kernel.org # 6.0 +Signed-off-by: Johan Hovold +Patchwork: https://patchwork.freedesktop.org/patch/524971/ +Link: https://lore.kernel.org/r/20230303164807.13124-3-johan+linaro@kernel.org +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/adreno/adreno_device.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c +index afdfa9edbea3d..7c3d80e78fb8b 100644 +--- a/drivers/gpu/drm/msm/adreno/adreno_device.c ++++ b/drivers/gpu/drm/msm/adreno/adreno_device.c +@@ -406,20 +406,21 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev) + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { +- pm_runtime_put_sync(&pdev->dev); ++ pm_runtime_put_noidle(&pdev->dev); + DRM_DEV_ERROR(dev->dev, "Couldn't power up the GPU: %d\n", ret); +- return NULL; ++ goto err_disable_rpm; + } + + mutex_lock(&gpu->lock); + ret = msm_gpu_hw_init(gpu); + mutex_unlock(&gpu->lock); +- pm_runtime_put_autosuspend(&pdev->dev); + if (ret) { + DRM_DEV_ERROR(dev->dev, "gpu hw init failed: %d\n", ret); +- return NULL; ++ goto err_put_rpm; + } + ++ pm_runtime_put_autosuspend(&pdev->dev); ++ + #ifdef CONFIG_DEBUG_FS + if (gpu->funcs->debugfs_init) { + gpu->funcs->debugfs_init(gpu, dev->primary); +@@ -428,6 +429,13 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev) + #endif + + return gpu; ++ ++err_put_rpm: ++ pm_runtime_put_sync(&pdev->dev); ++err_disable_rpm: ++ pm_runtime_disable(&pdev->dev); ++ ++ return NULL; + } + + static void set_gpu_pdev(struct drm_device *dev, +-- +2.39.2 + diff --git a/queue-5.15/drm-msm-remove-struct_mutex-usage.patch b/queue-5.15/drm-msm-remove-struct_mutex-usage.patch new file mode 100644 index 00000000000..8467348d9e1 --- /dev/null +++ b/queue-5.15/drm-msm-remove-struct_mutex-usage.patch @@ -0,0 +1,359 @@ +From 23803255296607d4300e3f257062071bda6cfb9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Nov 2021 10:11:03 -0800 +Subject: drm/msm: Remove struct_mutex usage + +From: Rob Clark + +[ Upstream commit c28e2f2b417ed747bfbc5f900c87f3ec9cc6b25e ] + +The remaining struct_mutex usage is just to serialize various gpu +related things (submit/retire/recover/fault/etc), so replace +struct_mutex with gpu->lock. + +Signed-off-by: Rob Clark +Link: https://lore.kernel.org/r/20211109181117.591148-4-robdclark@gmail.com +Signed-off-by: Rob Clark +Stable-dep-of: 0d997f95b70f ("drm/msm/adreno: fix runtime PM imbalance at gpu load") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/adreno/a5xx_debugfs.c | 4 ++-- + drivers/gpu/drm/msm/adreno/adreno_device.c | 4 ++-- + drivers/gpu/drm/msm/msm_debugfs.c | 12 ++++++------ + drivers/gpu/drm/msm/msm_gpu.c | 14 +++++++------- + drivers/gpu/drm/msm/msm_gpu.h | 20 +++++++++++++++----- + drivers/gpu/drm/msm/msm_perf.c | 9 ++++++--- + drivers/gpu/drm/msm/msm_rd.c | 16 +++++++++------- + drivers/gpu/drm/msm/msm_ringbuffer.c | 4 ++-- + 8 files changed, 49 insertions(+), 34 deletions(-) + +diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c +index c9d11d57aed66..1aa39aa73e745 100644 +--- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c ++++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c +@@ -107,7 +107,7 @@ reset_set(void *data, u64 val) + * try to reset an active GPU. + */ + +- mutex_lock(&dev->struct_mutex); ++ mutex_lock(&gpu->lock); + + release_firmware(adreno_gpu->fw[ADRENO_FW_PM4]); + adreno_gpu->fw[ADRENO_FW_PM4] = NULL; +@@ -133,7 +133,7 @@ reset_set(void *data, u64 val) + gpu->funcs->recover(gpu); + + pm_runtime_put_sync(&gpu->pdev->dev); +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + return 0; + } +diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c +index 3eb9146653444..afdfa9edbea3d 100644 +--- a/drivers/gpu/drm/msm/adreno/adreno_device.c ++++ b/drivers/gpu/drm/msm/adreno/adreno_device.c +@@ -411,9 +411,9 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev) + return NULL; + } + +- mutex_lock(&dev->struct_mutex); ++ mutex_lock(&gpu->lock); + ret = msm_gpu_hw_init(gpu); +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + pm_runtime_put_autosuspend(&pdev->dev); + if (ret) { + DRM_DEV_ERROR(dev->dev, "gpu hw init failed: %d\n", ret); +diff --git a/drivers/gpu/drm/msm/msm_debugfs.c b/drivers/gpu/drm/msm/msm_debugfs.c +index dee13fedee3b5..f970a14b66336 100644 +--- a/drivers/gpu/drm/msm/msm_debugfs.c ++++ b/drivers/gpu/drm/msm/msm_debugfs.c +@@ -29,14 +29,14 @@ static int msm_gpu_show(struct seq_file *m, void *arg) + struct msm_gpu *gpu = priv->gpu; + int ret; + +- ret = mutex_lock_interruptible(&show_priv->dev->struct_mutex); ++ ret = mutex_lock_interruptible(&gpu->lock); + if (ret) + return ret; + + drm_printf(&p, "%s Status:\n", gpu->name); + gpu->funcs->show(gpu, show_priv->state, &p); + +- mutex_unlock(&show_priv->dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + return 0; + } +@@ -48,9 +48,9 @@ static int msm_gpu_release(struct inode *inode, struct file *file) + struct msm_drm_private *priv = show_priv->dev->dev_private; + struct msm_gpu *gpu = priv->gpu; + +- mutex_lock(&show_priv->dev->struct_mutex); ++ mutex_lock(&gpu->lock); + gpu->funcs->gpu_state_put(show_priv->state); +- mutex_unlock(&show_priv->dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + kfree(show_priv); + +@@ -72,7 +72,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file) + if (!show_priv) + return -ENOMEM; + +- ret = mutex_lock_interruptible(&dev->struct_mutex); ++ ret = mutex_lock_interruptible(&gpu->lock); + if (ret) + goto free_priv; + +@@ -81,7 +81,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file) + show_priv->state = gpu->funcs->gpu_state_get(gpu); + pm_runtime_put_sync(&gpu->pdev->dev); + +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + if (IS_ERR(show_priv->state)) { + ret = PTR_ERR(show_priv->state); +diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c +index b01d0a521c908..a2f21b89d077c 100644 +--- a/drivers/gpu/drm/msm/msm_gpu.c ++++ b/drivers/gpu/drm/msm/msm_gpu.c +@@ -150,7 +150,7 @@ int msm_gpu_hw_init(struct msm_gpu *gpu) + { + int ret; + +- WARN_ON(!mutex_is_locked(&gpu->dev->struct_mutex)); ++ WARN_ON(!mutex_is_locked(&gpu->lock)); + + if (!gpu->needs_hw_init) + return 0; +@@ -361,7 +361,7 @@ static void recover_worker(struct kthread_work *work) + char *comm = NULL, *cmd = NULL; + int i; + +- mutex_lock(&dev->struct_mutex); ++ mutex_lock(&gpu->lock); + + DRM_DEV_ERROR(dev->dev, "%s: hangcheck recover!\n", gpu->name); + +@@ -442,7 +442,7 @@ static void recover_worker(struct kthread_work *work) + } + } + +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + msm_gpu_retire(gpu); + } +@@ -450,12 +450,11 @@ static void recover_worker(struct kthread_work *work) + static void fault_worker(struct kthread_work *work) + { + struct msm_gpu *gpu = container_of(work, struct msm_gpu, fault_work); +- struct drm_device *dev = gpu->dev; + struct msm_gem_submit *submit; + struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu); + char *comm = NULL, *cmd = NULL; + +- mutex_lock(&dev->struct_mutex); ++ mutex_lock(&gpu->lock); + + submit = find_submit(cur_ring, cur_ring->memptrs->fence + 1); + if (submit && submit->fault_dumped) +@@ -490,7 +489,7 @@ static void fault_worker(struct kthread_work *work) + memset(&gpu->fault_info, 0, sizeof(gpu->fault_info)); + gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu); + +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + } + + static void hangcheck_timer_reset(struct msm_gpu *gpu) +@@ -734,7 +733,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) + struct msm_ringbuffer *ring = submit->ring; + unsigned long flags; + +- WARN_ON(!mutex_is_locked(&dev->struct_mutex)); ++ WARN_ON(!mutex_is_locked(&gpu->lock)); + + pm_runtime_get_sync(&gpu->pdev->dev); + +@@ -849,6 +848,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, + + INIT_LIST_HEAD(&gpu->active_list); + mutex_init(&gpu->active_lock); ++ mutex_init(&gpu->lock); + kthread_init_work(&gpu->retire_work, retire_worker); + kthread_init_work(&gpu->recover_work, recover_worker); + kthread_init_work(&gpu->fault_work, fault_worker); +diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h +index 2e2424066e701..461ff5a5aa5bb 100644 +--- a/drivers/gpu/drm/msm/msm_gpu.h ++++ b/drivers/gpu/drm/msm/msm_gpu.h +@@ -143,13 +143,23 @@ struct msm_gpu { + */ + struct list_head active_list; + ++ /** ++ * lock: ++ * ++ * General lock for serializing all the gpu things. ++ * ++ * TODO move to per-ring locking where feasible (ie. submit/retire ++ * path, etc) ++ */ ++ struct mutex lock; ++ + /** + * active_submits: + * + * The number of submitted but not yet retired submits, used to + * determine transitions between active and idle. + * +- * Protected by lock ++ * Protected by active_lock + */ + int active_submits; + +@@ -530,28 +540,28 @@ static inline struct msm_gpu_state *msm_gpu_crashstate_get(struct msm_gpu *gpu) + { + struct msm_gpu_state *state = NULL; + +- mutex_lock(&gpu->dev->struct_mutex); ++ mutex_lock(&gpu->lock); + + if (gpu->crashstate) { + kref_get(&gpu->crashstate->ref); + state = gpu->crashstate; + } + +- mutex_unlock(&gpu->dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + return state; + } + + static inline void msm_gpu_crashstate_put(struct msm_gpu *gpu) + { +- mutex_lock(&gpu->dev->struct_mutex); ++ mutex_lock(&gpu->lock); + + if (gpu->crashstate) { + if (gpu->funcs->gpu_state_put(gpu->crashstate)) + gpu->crashstate = NULL; + } + +- mutex_unlock(&gpu->dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + } + + /* +diff --git a/drivers/gpu/drm/msm/msm_perf.c b/drivers/gpu/drm/msm/msm_perf.c +index 3a27153eef084..3d3da79fec2aa 100644 +--- a/drivers/gpu/drm/msm/msm_perf.c ++++ b/drivers/gpu/drm/msm/msm_perf.c +@@ -155,9 +155,12 @@ static int perf_open(struct inode *inode, struct file *file) + struct msm_gpu *gpu = priv->gpu; + int ret = 0; + +- mutex_lock(&dev->struct_mutex); ++ if (!gpu) ++ return -ENODEV; + +- if (perf->open || !gpu) { ++ mutex_lock(&gpu->lock); ++ ++ if (perf->open) { + ret = -EBUSY; + goto out; + } +@@ -171,7 +174,7 @@ static int perf_open(struct inode *inode, struct file *file) + perf->next_jiffies = jiffies + SAMPLE_TIME; + + out: +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + return ret; + } + +diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c +index e3f0dd4a36792..15a44491a42c3 100644 +--- a/drivers/gpu/drm/msm/msm_rd.c ++++ b/drivers/gpu/drm/msm/msm_rd.c +@@ -86,7 +86,7 @@ struct msm_rd_state { + struct msm_gem_submit *submit; + + /* fifo access is synchronized on the producer side by +- * struct_mutex held by submit code (otherwise we could ++ * gpu->lock held by submit code (otherwise we could + * end up w/ cmds logged in different order than they + * were executed). And read_lock synchronizes the reads + */ +@@ -181,9 +181,12 @@ static int rd_open(struct inode *inode, struct file *file) + uint32_t gpu_id; + int ret = 0; + +- mutex_lock(&dev->struct_mutex); ++ if (!gpu) ++ return -ENODEV; + +- if (rd->open || !gpu) { ++ mutex_lock(&gpu->lock); ++ ++ if (rd->open) { + ret = -EBUSY; + goto out; + } +@@ -203,7 +206,7 @@ static int rd_open(struct inode *inode, struct file *file) + rd_write_section(rd, RD_GPU_ID, &gpu_id, sizeof(gpu_id)); + + out: +- mutex_unlock(&dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + return ret; + } + +@@ -343,11 +346,10 @@ static void snapshot_buf(struct msm_rd_state *rd, + msm_gem_unlock(&obj->base); + } + +-/* called under struct_mutex */ ++/* called under gpu->lock */ + void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, + const char *fmt, ...) + { +- struct drm_device *dev = submit->dev; + struct task_struct *task; + char msg[256]; + int i, n; +@@ -358,7 +360,7 @@ void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, + /* writing into fifo is serialized by caller, and + * rd->read_lock is used to serialize the reads + */ +- WARN_ON(!mutex_is_locked(&dev->struct_mutex)); ++ WARN_ON(!mutex_is_locked(&submit->gpu->lock)); + + if (fmt) { + va_list args; +diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c +index bd54c14126497..a2314b75962fd 100644 +--- a/drivers/gpu/drm/msm/msm_ringbuffer.c ++++ b/drivers/gpu/drm/msm/msm_ringbuffer.c +@@ -32,11 +32,11 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job) + pm_runtime_get_sync(&gpu->pdev->dev); + + /* TODO move submit path over to using a per-ring lock.. */ +- mutex_lock(&gpu->dev->struct_mutex); ++ mutex_lock(&gpu->lock); + + msm_gpu_submit(gpu, submit); + +- mutex_unlock(&gpu->dev->struct_mutex); ++ mutex_unlock(&gpu->lock); + + pm_runtime_put(&gpu->pdev->dev); + +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-add-channel-rwlock.patch b/queue-5.15/ksmbd-add-channel-rwlock.patch new file mode 100644 index 00000000000..dd1cd7f83ef --- /dev/null +++ b/queue-5.15/ksmbd-add-channel-rwlock.patch @@ -0,0 +1,139 @@ +From 7584fe5f147216d18ccb3b13f90cdeaad6cd6ecd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 10:15:57 +0900 +Subject: ksmbd: add channel rwlock + +From: Namjae Jeon + +[ Upstream commit 8e06b31e348107c5d78e2c90bb7e69388cb97fb6 ] + +Add missing rwlock for channel list in session. + +Signed-off-by: Namjae Jeon +Reviewed-by: Hyunchul Lee +Signed-off-by: Steve French +Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()") +Signed-off-by: Sasha Levin +--- + fs/ksmbd/mgmt/user_session.c | 3 +++ + fs/ksmbd/mgmt/user_session.h | 1 + + fs/ksmbd/smb2pdu.c | 20 ++++++++++++++++++-- + 3 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c +index 8fe08df668582..0c7b5335c12af 100644 +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -32,11 +32,13 @@ static void free_channel_list(struct ksmbd_session *sess) + { + struct channel *chann, *tmp; + ++ write_lock(&sess->chann_lock); + list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list, + chann_list) { + list_del(&chann->chann_list); + kfree(chann); + } ++ write_unlock(&sess->chann_lock); + } + + static void __session_rpc_close(struct ksmbd_session *sess, +@@ -305,6 +307,7 @@ static struct ksmbd_session *__session_create(int protocol) + INIT_LIST_HEAD(&sess->rpc_handle_list); + sess->sequence_number = 1; + atomic_set(&sess->refcnt, 1); ++ rwlock_init(&sess->chann_lock); + + switch (protocol) { + case CIFDS_SESSION_FLAG_SMB2: +diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h +index 8b08189be3fc2..1ec659f0151bf 100644 +--- a/fs/ksmbd/mgmt/user_session.h ++++ b/fs/ksmbd/mgmt/user_session.h +@@ -48,6 +48,7 @@ struct ksmbd_session { + char sess_key[CIFS_KEY_SIZE]; + + struct hlist_node hlist; ++ rwlock_t chann_lock; + struct list_head ksmbd_chann_list; + struct xarray tree_conns; + struct ida tree_conn_ida; +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index d41995f89befe..e17f7a5dd9974 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1525,7 +1525,9 @@ static int ntlm_authenticate(struct ksmbd_work *work) + + binding_session: + if (conn->dialect >= SMB30_PROT_ID) { ++ read_lock(&sess->chann_lock); + chann = lookup_chann_list(sess, conn); ++ read_unlock(&sess->chann_lock); + if (!chann) { + chann = kmalloc(sizeof(struct channel), GFP_KERNEL); + if (!chann) +@@ -1533,7 +1535,9 @@ static int ntlm_authenticate(struct ksmbd_work *work) + + chann->conn = conn; + INIT_LIST_HEAD(&chann->chann_list); ++ write_lock(&sess->chann_lock); + list_add(&chann->chann_list, &sess->ksmbd_chann_list); ++ write_unlock(&sess->chann_lock); + } + } + +@@ -1608,7 +1612,9 @@ static int krb5_authenticate(struct ksmbd_work *work) + } + + if (conn->dialect >= SMB30_PROT_ID) { ++ read_lock(&sess->chann_lock); + chann = lookup_chann_list(sess, conn); ++ read_unlock(&sess->chann_lock); + if (!chann) { + chann = kmalloc(sizeof(struct channel), GFP_KERNEL); + if (!chann) +@@ -1616,7 +1622,9 @@ static int krb5_authenticate(struct ksmbd_work *work) + + chann->conn = conn; + INIT_LIST_HEAD(&chann->chann_list); ++ write_lock(&sess->chann_lock); + list_add(&chann->chann_list, &sess->ksmbd_chann_list); ++ write_unlock(&sess->chann_lock); + } + } + +@@ -8388,10 +8396,14 @@ int smb3_check_sign_req(struct ksmbd_work *work) + if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { + signing_key = work->sess->smb3signingkey; + } else { ++ read_lock(&work->sess->chann_lock); + chann = lookup_chann_list(work->sess, conn); +- if (!chann) ++ if (!chann) { ++ read_unlock(&work->sess->chann_lock); + return 0; ++ } + signing_key = chann->smb3signingkey; ++ read_unlock(&work->sess->chann_lock); + } + + if (!signing_key) { +@@ -8451,10 +8463,14 @@ void smb3_set_sign_rsp(struct ksmbd_work *work) + le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) { + signing_key = work->sess->smb3signingkey; + } else { ++ read_lock(&work->sess->chann_lock); + chann = lookup_chann_list(work->sess, work->conn); +- if (!chann) ++ if (!chann) { ++ read_unlock(&work->sess->chann_lock); + return; ++ } + signing_key = chann->smb3signingkey; ++ read_unlock(&work->sess->chann_lock); + } + + if (!signing_key) +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-fix-deadlock-in-ksmbd_find_crypto_ctx.patch b/queue-5.15/ksmbd-fix-deadlock-in-ksmbd_find_crypto_ctx.patch new file mode 100644 index 00000000000..d29d30a1312 --- /dev/null +++ b/queue-5.15/ksmbd-fix-deadlock-in-ksmbd_find_crypto_ctx.patch @@ -0,0 +1,79 @@ +From d1aed81d3f634902eb47a032a4579d5a78b29b1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 May 2023 08:44:14 +0900 +Subject: ksmbd: fix deadlock in ksmbd_find_crypto_ctx() + +From: Namjae Jeon + +[ Upstream commit 7b4323373d844954bb76e0e9f39c4e5fc785fa7b ] + +Deadlock is triggered by sending multiple concurrent session setup +requests. It should be reused after releasing when getting ctx for crypto. +Multiple consecutive ctx uses cause deadlock while waiting for releasing +due to the limited number of ctx. + +Cc: stable@vger.kernel.org +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20591 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/auth.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c +index c1408e922fc6b..59d2059467465 100644 +--- a/fs/ksmbd/auth.c ++++ b/fs/ksmbd/auth.c +@@ -220,22 +220,22 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, + { + char ntlmv2_hash[CIFS_ENCPWD_SIZE]; + char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE]; +- struct ksmbd_crypto_ctx *ctx; ++ struct ksmbd_crypto_ctx *ctx = NULL; + char *construct = NULL; + int rc, len; + +- ctx = ksmbd_crypto_ctx_find_hmacmd5(); +- if (!ctx) { +- ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); +- return -ENOMEM; +- } +- + rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name); + if (rc) { + ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc); + goto out; + } + ++ ctx = ksmbd_crypto_ctx_find_hmacmd5(); ++ if (!ctx) { ++ ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); ++ return -ENOMEM; ++ } ++ + rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx), + ntlmv2_hash, + CIFS_HMAC_MD5_HASH_SIZE); +@@ -271,6 +271,8 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, + ksmbd_debug(AUTH, "Could not generate md5 hash\n"); + goto out; + } ++ ksmbd_release_crypto_ctx(ctx); ++ ctx = NULL; + + rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp); + if (rc) { +@@ -281,7 +283,8 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, + if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0) + rc = -EINVAL; + out: +- ksmbd_release_crypto_ctx(ctx); ++ if (ctx) ++ ksmbd_release_crypto_ctx(ctx); + kfree(construct); + return rc; + } +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-fix-kernel-oops-from-idr_remove.patch b/queue-5.15/ksmbd-fix-kernel-oops-from-idr_remove.patch new file mode 100644 index 00000000000..128424ce3ad --- /dev/null +++ b/queue-5.15/ksmbd-fix-kernel-oops-from-idr_remove.patch @@ -0,0 +1,88 @@ +From e422c48bc373790c7a99f05459d85a5335552b26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 10:17:06 +0900 +Subject: ksmbd: fix kernel oops from idr_remove() + +From: Namjae Jeon + +[ Upstream commit 17ea92a9f6d0b9a97aaec5ab748e4591d70a562c ] + +There is a report that kernel oops happen from idr_remove(). + +kernel: BUG: kernel NULL pointer dereference, address: 0000000000000010 +kernel: RIP: 0010:idr_remove+0x1/0x20 +kernel: __ksmbd_close_fd+0xb2/0x2d0 [ksmbd] +kernel: ksmbd_vfs_read+0x91/0x190 [ksmbd] +kernel: ksmbd_fd_put+0x29/0x40 [ksmbd] +kernel: smb2_read+0x210/0x390 [ksmbd] +kernel: __process_request+0xa4/0x180 [ksmbd] +kernel: __handle_ksmbd_work+0xf0/0x290 [ksmbd] +kernel: handle_ksmbd_work+0x2d/0x50 [ksmbd] +kernel: process_one_work+0x21d/0x3f0 +kernel: worker_thread+0x50/0x3d0 +kernel: rescuer_thread+0x390/0x390 +kernel: kthread+0xee/0x120 +kthread_complete_and_exit+0x20/0x20 +kernel: ret_from_fork+0x22/0x30 + +While accessing files, If connection is disconnected, windows send +session setup request included previous session destroy. But while still +processing requests on previous session, this request destroy file +table, which mean file table idr will be freed and set to NULL. +So kernel oops happen from ft->idr in __ksmbd_close_fd(). +This patch don't directly destroy session in destroy_previous_session(). +It just set to KSMBD_SESS_EXITING so that connection will be +terminated after finishing the rest of requests. + +Signed-off-by: Namjae Jeon +Reviewed-by: Hyunchul Lee +Signed-off-by: Steve French +Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()") +Signed-off-by: Sasha Levin +--- + fs/ksmbd/mgmt/user_session.c | 2 ++ + fs/ksmbd/smb2pdu.c | 8 ++++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c +index 0c7b5335c12af..9c4a9c8c02795 100644 +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -241,6 +241,8 @@ struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, + sess = ksmbd_session_lookup(conn, id); + if (!sess && conn->binding) + sess = ksmbd_session_lookup_slowpath(id); ++ if (sess && sess->state != SMB2_SESSION_VALID) ++ sess = NULL; + return sess; + } + +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index e17f7a5dd9974..8bfe2a6c05f92 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -600,6 +600,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn, + { + struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id); + struct ksmbd_user *prev_user; ++ struct channel *chann; + + if (!prev_sess) + return; +@@ -615,8 +616,11 @@ static void destroy_previous_session(struct ksmbd_conn *conn, + } + + put_session(prev_sess); +- xa_erase(&conn->sessions, prev_sess->id); +- ksmbd_session_destroy(prev_sess); ++ prev_sess->state = SMB2_SESSION_EXPIRED; ++ write_lock(&prev_sess->chann_lock); ++ list_for_each_entry(chann, &prev_sess->ksmbd_chann_list, chann_list) ++ chann->conn->status = KSMBD_SESS_EXITING; ++ write_unlock(&prev_sess->chann_lock); + } + + /** +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-fix-multi-session-connection-failure.patch b/queue-5.15/ksmbd-fix-multi-session-connection-failure.patch new file mode 100644 index 00000000000..3f6db3458fc --- /dev/null +++ b/queue-5.15/ksmbd-fix-multi-session-connection-failure.patch @@ -0,0 +1,241 @@ +From a8bbd42d76ead12063d0340271c6043606a71c05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Dec 2021 14:57:27 +0900 +Subject: ksmbd: fix multi session connection failure + +From: Namjae Jeon + +[ Upstream commit ce53d365378cde71bb6596d79c257e600d951d29 ] + +When RSS mode is enable, windows client do simultaneously send several +session requests to server. There is racy issue using +sess->ntlmssp.cryptkey on N connection : 1 session. So authetication +failed using wrong cryptkey on some session. This patch move cryptkey +to ksmbd_conn structure to use each cryptkey on connection. + +Tested-by: Ziwei Xie +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()") +Signed-off-by: Sasha Levin +--- + fs/ksmbd/auth.c | 27 ++++++++++++++------------- + fs/ksmbd/auth.h | 10 +++++----- + fs/ksmbd/connection.h | 7 +------ + fs/ksmbd/mgmt/user_session.h | 1 - + fs/ksmbd/smb2pdu.c | 8 ++++---- + 5 files changed, 24 insertions(+), 29 deletions(-) + +diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c +index b962b16e5aeb7..4867da417c23a 100644 +--- a/fs/ksmbd/auth.c ++++ b/fs/ksmbd/auth.c +@@ -215,7 +215,7 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash, + * Return: 0 on success, error number on error + */ + int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, +- int blen, char *domain_name) ++ int blen, char *domain_name, char *cryptkey) + { + char ntlmv2_hash[CIFS_ENCPWD_SIZE]; + char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE]; +@@ -256,7 +256,7 @@ int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, + goto out; + } + +- memcpy(construct, sess->ntlmssp.cryptkey, CIFS_CRYPTO_KEY_SIZE); ++ memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE); + memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen); + + rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len); +@@ -295,7 +295,8 @@ int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, + * Return: 0 on success, error number on error + */ + int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, +- int blob_len, struct ksmbd_session *sess) ++ int blob_len, struct ksmbd_conn *conn, ++ struct ksmbd_session *sess) + { + char *domain_name; + unsigned int nt_off, dn_off; +@@ -325,7 +326,7 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, + + /* TODO : use domain name that imported from configuration file */ + domain_name = smb_strndup_from_utf16((const char *)authblob + dn_off, +- dn_len, true, sess->conn->local_nls); ++ dn_len, true, conn->local_nls); + if (IS_ERR(domain_name)) + return PTR_ERR(domain_name); + +@@ -334,7 +335,7 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, + domain_name); + ret = ksmbd_auth_ntlmv2(sess, (struct ntlmv2_resp *)((char *)authblob + nt_off), + nt_len - CIFS_ENCPWD_SIZE, +- domain_name); ++ domain_name, conn->ntlmssp.cryptkey); + kfree(domain_name); + return ret; + } +@@ -348,7 +349,7 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, + * + */ + int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, +- int blob_len, struct ksmbd_session *sess) ++ int blob_len, struct ksmbd_conn *conn) + { + if (blob_len < sizeof(struct negotiate_message)) { + ksmbd_debug(AUTH, "negotiate blob len %d too small\n", +@@ -362,7 +363,7 @@ int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, + return -EINVAL; + } + +- sess->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags); ++ conn->ntlmssp.client_flags = le32_to_cpu(negblob->NegotiateFlags); + return 0; + } + +@@ -376,14 +377,14 @@ int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, + */ + unsigned int + ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, +- struct ksmbd_session *sess) ++ struct ksmbd_conn *conn) + { + struct target_info *tinfo; + wchar_t *name; + __u8 *target_name; + unsigned int flags, blob_off, blob_len, type, target_info_len = 0; + int len, uni_len, conv_len; +- int cflags = sess->ntlmssp.client_flags; ++ int cflags = conn->ntlmssp.client_flags; + + memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8); + chgblob->MessageType = NtLmChallenge; +@@ -404,7 +405,7 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, + if (cflags & NTLMSSP_REQUEST_TARGET) + flags |= NTLMSSP_REQUEST_TARGET; + +- if (sess->conn->use_spnego && ++ if (conn->use_spnego && + (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) + flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC; + +@@ -415,7 +416,7 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, + return -ENOMEM; + + conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len, +- sess->conn->local_nls); ++ conn->local_nls); + if (conv_len < 0 || conv_len > len) { + kfree(name); + return -EINVAL; +@@ -431,8 +432,8 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, + chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off); + + /* Initialize random conn challenge */ +- get_random_bytes(sess->ntlmssp.cryptkey, sizeof(__u64)); +- memcpy(chgblob->Challenge, sess->ntlmssp.cryptkey, ++ get_random_bytes(conn->ntlmssp.cryptkey, sizeof(__u64)); ++ memcpy(chgblob->Challenge, conn->ntlmssp.cryptkey, + CIFS_CRYPTO_KEY_SIZE); + + /* Add Target Information to security buffer */ +diff --git a/fs/ksmbd/auth.h b/fs/ksmbd/auth.h +index 9c2d4badd05d1..95629651cf266 100644 +--- a/fs/ksmbd/auth.h ++++ b/fs/ksmbd/auth.h +@@ -38,16 +38,16 @@ struct kvec; + int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov, + unsigned int nvec, int enc); + void ksmbd_copy_gss_neg_header(void *buf); +-int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf); + int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, +- int blen, char *domain_name); ++ int blen, char *domain_name, char *cryptkey); + int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, +- int blob_len, struct ksmbd_session *sess); ++ int blob_len, struct ksmbd_conn *conn, ++ struct ksmbd_session *sess); + int ksmbd_decode_ntlmssp_neg_blob(struct negotiate_message *negblob, +- int blob_len, struct ksmbd_session *sess); ++ int blob_len, struct ksmbd_conn *conn); + unsigned int + ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, +- struct ksmbd_session *sess); ++ struct ksmbd_conn *conn); + int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob, + int in_len, char *out_blob, int *out_len); + int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, +diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h +index 4b15c5e673d92..f3367d7760d7e 100644 +--- a/fs/ksmbd/connection.h ++++ b/fs/ksmbd/connection.h +@@ -72,12 +72,7 @@ struct ksmbd_conn { + int connection_type; + struct ksmbd_stats stats; + char ClientGUID[SMB2_CLIENT_GUID_SIZE]; +- union { +- /* pending trans request table */ +- struct trans_state *recent_trans; +- /* Used by ntlmssp */ +- char *ntlmssp_cryptkey; +- }; ++ struct ntlmssp_auth ntlmssp; + + spinlock_t llist_lock; + struct list_head lock_list; +diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h +index 82289c3cbd2bc..e241f16a38512 100644 +--- a/fs/ksmbd/mgmt/user_session.h ++++ b/fs/ksmbd/mgmt/user_session.h +@@ -45,7 +45,6 @@ struct ksmbd_session { + int state; + __u8 *Preauth_HashValue; + +- struct ntlmssp_auth ntlmssp; + char sess_key[CIFS_KEY_SIZE]; + + struct hlist_node hlist; +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index c8c2b326ee042..bb8126deeaf29 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1316,7 +1316,7 @@ static int ntlm_negotiate(struct ksmbd_work *work, + int sz, rc; + + ksmbd_debug(SMB, "negotiate phase\n"); +- rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->sess); ++ rc = ksmbd_decode_ntlmssp_neg_blob(negblob, negblob_len, work->conn); + if (rc) + return rc; + +@@ -1326,7 +1326,7 @@ static int ntlm_negotiate(struct ksmbd_work *work, + memset(chgblob, 0, sizeof(struct challenge_message)); + + if (!work->conn->use_spnego) { +- sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->sess); ++ sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn); + if (sz < 0) + return -ENOMEM; + +@@ -1342,7 +1342,7 @@ static int ntlm_negotiate(struct ksmbd_work *work, + return -ENOMEM; + + chgblob = (struct challenge_message *)neg_blob; +- sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->sess); ++ sz = ksmbd_build_ntlmssp_challenge_blob(chgblob, work->conn); + if (sz < 0) { + rc = -ENOMEM; + goto out; +@@ -1480,7 +1480,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) + + authblob = user_authblob(conn, req); + sz = le16_to_cpu(req->SecurityBufferLength); +- rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, sess); ++ rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess); + if (rc) { + set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD); + ksmbd_debug(SMB, "authentication failed\n"); +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-fix-racy-issue-while-destroying-session-on-mul.patch b/queue-5.15/ksmbd-fix-racy-issue-while-destroying-session-on-mul.patch new file mode 100644 index 00000000000..99a44519460 --- /dev/null +++ b/queue-5.15/ksmbd-fix-racy-issue-while-destroying-session-on-mul.patch @@ -0,0 +1,646 @@ +From 07bc60603620513e77b5e4d64a1c0786aa9536fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 13:36:52 +0900 +Subject: ksmbd: fix racy issue while destroying session on multichannel + +From: Namjae Jeon + +[ Upstream commit af7c39d971e43cd0af488729bca362427ad99488 ] + +After multi-channel connection with windows, Several channels of +session are connected. Among them, if there is a problem in one channel, +Windows connects again after disconnecting the channel. In this process, +the session is released and a kernel oop can occurs while processing +requests to other channels. When the channel is disconnected, if other +channels still exist in the session after deleting the channel from +the channel list in the session, the session should not be released. +Finally, the session will be released after all channels are disconnected. + +Signed-off-by: Namjae Jeon +Reviewed-by: Hyunchul Lee +Signed-off-by: Steve French +Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()") +Signed-off-by: Sasha Levin +--- + fs/ksmbd/auth.c | 56 ++++++++++++++++-------------- + fs/ksmbd/auth.h | 11 +++--- + fs/ksmbd/connection.h | 7 ---- + fs/ksmbd/mgmt/tree_connect.c | 5 +-- + fs/ksmbd/mgmt/tree_connect.h | 4 ++- + fs/ksmbd/mgmt/user_session.c | 67 ++++++++++++++++++++++++------------ + fs/ksmbd/mgmt/user_session.h | 7 ++-- + fs/ksmbd/oplock.c | 11 +++--- + fs/ksmbd/smb2pdu.c | 21 +++++------ + fs/ksmbd/smb_common.h | 2 +- + fs/ksmbd/vfs.c | 3 +- + fs/ksmbd/vfs_cache.c | 2 +- + 12 files changed, 110 insertions(+), 86 deletions(-) + +diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c +index 4867da417c23a..c1408e922fc6b 100644 +--- a/fs/ksmbd/auth.c ++++ b/fs/ksmbd/auth.c +@@ -120,8 +120,8 @@ static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash, + return rc; + } + +-static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash, +- char *dname) ++static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess, ++ char *ntlmv2_hash, char *dname) + { + int ret, len, conv_len; + wchar_t *domain = NULL; +@@ -157,7 +157,7 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash, + } + + conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len, +- sess->conn->local_nls); ++ conn->local_nls); + if (conv_len < 0 || conv_len > len) { + ret = -EINVAL; + goto out; +@@ -181,7 +181,7 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash, + } + + conv_len = smb_strtoUTF16((__le16 *)domain, dname, len, +- sess->conn->local_nls); ++ conn->local_nls); + if (conv_len < 0 || conv_len > len) { + ret = -EINVAL; + goto out; +@@ -214,8 +214,9 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash, + * + * Return: 0 on success, error number on error + */ +-int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, +- int blen, char *domain_name, char *cryptkey) ++int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, ++ struct ntlmv2_resp *ntlmv2, int blen, char *domain_name, ++ char *cryptkey) + { + char ntlmv2_hash[CIFS_ENCPWD_SIZE]; + char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE]; +@@ -229,7 +230,7 @@ int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, + return -ENOMEM; + } + +- rc = calc_ntlmv2_hash(sess, ntlmv2_hash, domain_name); ++ rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name); + if (rc) { + ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc); + goto out; +@@ -333,7 +334,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, + /* process NTLMv2 authentication */ + ksmbd_debug(AUTH, "decode_ntlmssp_authenticate_blob dname%s\n", + domain_name); +- ret = ksmbd_auth_ntlmv2(sess, (struct ntlmv2_resp *)((char *)authblob + nt_off), ++ ret = ksmbd_auth_ntlmv2(conn, sess, ++ (struct ntlmv2_resp *)((char *)authblob + nt_off), + nt_len - CIFS_ENCPWD_SIZE, + domain_name, conn->ntlmssp.cryptkey); + kfree(domain_name); +@@ -633,8 +635,9 @@ struct derivation { + bool binding; + }; + +-static int generate_key(struct ksmbd_session *sess, struct kvec label, +- struct kvec context, __u8 *key, unsigned int key_size) ++static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess, ++ struct kvec label, struct kvec context, __u8 *key, ++ unsigned int key_size) + { + unsigned char zero = 0x0; + __u8 i[4] = {0, 0, 0, 1}; +@@ -694,8 +697,8 @@ static int generate_key(struct ksmbd_session *sess, struct kvec label, + goto smb3signkey_ret; + } + +- if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || +- sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) ++ if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || ++ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) + rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4); + else + rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4); +@@ -730,17 +733,17 @@ static int generate_smb3signingkey(struct ksmbd_session *sess, + if (!chann) + return 0; + +- if (sess->conn->dialect >= SMB30_PROT_ID && signing->binding) ++ if (conn->dialect >= SMB30_PROT_ID && signing->binding) + key = chann->smb3signingkey; + else + key = sess->smb3signingkey; + +- rc = generate_key(sess, signing->label, signing->context, key, ++ rc = generate_key(conn, sess, signing->label, signing->context, key, + SMB3_SIGN_KEY_SIZE); + if (rc) + return rc; + +- if (!(sess->conn->dialect >= SMB30_PROT_ID && signing->binding)) ++ if (!(conn->dialect >= SMB30_PROT_ID && signing->binding)) + memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE); + + ksmbd_debug(AUTH, "dumping generated AES signing keys\n"); +@@ -794,30 +797,31 @@ struct derivation_twin { + struct derivation decryption; + }; + +-static int generate_smb3encryptionkey(struct ksmbd_session *sess, ++static int generate_smb3encryptionkey(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess, + const struct derivation_twin *ptwin) + { + int rc; + +- rc = generate_key(sess, ptwin->encryption.label, ++ rc = generate_key(conn, sess, ptwin->encryption.label, + ptwin->encryption.context, sess->smb3encryptionkey, + SMB3_ENC_DEC_KEY_SIZE); + if (rc) + return rc; + +- rc = generate_key(sess, ptwin->decryption.label, ++ rc = generate_key(conn, sess, ptwin->decryption.label, + ptwin->decryption.context, + sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE); + if (rc) + return rc; + + ksmbd_debug(AUTH, "dumping generated AES encryption keys\n"); +- ksmbd_debug(AUTH, "Cipher type %d\n", sess->conn->cipher_type); ++ ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type); + ksmbd_debug(AUTH, "Session Id %llu\n", sess->id); + ksmbd_debug(AUTH, "Session Key %*ph\n", + SMB2_NTLMV2_SESSKEY_SIZE, sess->sess_key); +- if (sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || +- sess->conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) { ++ if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || ++ conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM) { + ksmbd_debug(AUTH, "ServerIn Key %*ph\n", + SMB3_GCM256_CRYPTKEY_SIZE, sess->smb3encryptionkey); + ksmbd_debug(AUTH, "ServerOut Key %*ph\n", +@@ -831,7 +835,8 @@ static int generate_smb3encryptionkey(struct ksmbd_session *sess, + return 0; + } + +-int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess) ++int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess) + { + struct derivation_twin twin; + struct derivation *d; +@@ -848,10 +853,11 @@ int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess) + d->context.iov_base = "ServerIn "; + d->context.iov_len = 10; + +- return generate_smb3encryptionkey(sess, &twin); ++ return generate_smb3encryptionkey(conn, sess, &twin); + } + +-int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess) ++int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess) + { + struct derivation_twin twin; + struct derivation *d; +@@ -868,7 +874,7 @@ int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess) + d->context.iov_base = sess->Preauth_HashValue; + d->context.iov_len = 64; + +- return generate_smb3encryptionkey(sess, &twin); ++ return generate_smb3encryptionkey(conn, sess, &twin); + } + + int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf, +diff --git a/fs/ksmbd/auth.h b/fs/ksmbd/auth.h +index 95629651cf266..25b772653de0a 100644 +--- a/fs/ksmbd/auth.h ++++ b/fs/ksmbd/auth.h +@@ -38,8 +38,9 @@ struct kvec; + int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov, + unsigned int nvec, int enc); + void ksmbd_copy_gss_neg_header(void *buf); +-int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, +- int blen, char *domain_name, char *cryptkey); ++int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, ++ struct ntlmv2_resp *ntlmv2, int blen, char *domain_name, ++ char *cryptkey); + int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, + int blob_len, struct ksmbd_conn *conn, + struct ksmbd_session *sess); +@@ -58,8 +59,10 @@ int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess, + struct ksmbd_conn *conn); + int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess, + struct ksmbd_conn *conn); +-int ksmbd_gen_smb30_encryptionkey(struct ksmbd_session *sess); +-int ksmbd_gen_smb311_encryptionkey(struct ksmbd_session *sess); ++int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess); ++int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess); + int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf, + __u8 *pi_hash); + int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len, +diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h +index 7838cc46497d6..89eb41bbd1601 100644 +--- a/fs/ksmbd/connection.h ++++ b/fs/ksmbd/connection.h +@@ -20,13 +20,6 @@ + + #define KSMBD_SOCKET_BACKLOG 16 + +-/* +- * WARNING +- * +- * This is nothing but a HACK. Session status should move to channel +- * or to session. As of now we have 1 tcp_conn : 1 ksmbd_session, but +- * we need to change it to 1 tcp_conn : N ksmbd_sessions. +- */ + enum { + KSMBD_SESS_NEW = 0, + KSMBD_SESS_GOOD, +diff --git a/fs/ksmbd/mgmt/tree_connect.c b/fs/ksmbd/mgmt/tree_connect.c +index 940385c6a9135..dd262daa2c4a5 100644 +--- a/fs/ksmbd/mgmt/tree_connect.c ++++ b/fs/ksmbd/mgmt/tree_connect.c +@@ -16,7 +16,8 @@ + #include "user_session.h" + + struct ksmbd_tree_conn_status +-ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name) ++ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, ++ char *share_name) + { + struct ksmbd_tree_conn_status status = {-ENOENT, NULL}; + struct ksmbd_tree_connect_response *resp = NULL; +@@ -41,7 +42,7 @@ ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name) + goto out_error; + } + +- peer_addr = KSMBD_TCP_PEER_SOCKADDR(sess->conn); ++ peer_addr = KSMBD_TCP_PEER_SOCKADDR(conn); + resp = ksmbd_ipc_tree_connect_request(sess, + sc, + tree_conn, +diff --git a/fs/ksmbd/mgmt/tree_connect.h b/fs/ksmbd/mgmt/tree_connect.h +index 18e2a996e0aab..71e50271dccf0 100644 +--- a/fs/ksmbd/mgmt/tree_connect.h ++++ b/fs/ksmbd/mgmt/tree_connect.h +@@ -12,6 +12,7 @@ + + struct ksmbd_share_config; + struct ksmbd_user; ++struct ksmbd_conn; + + struct ksmbd_tree_connect { + int id; +@@ -40,7 +41,8 @@ static inline int test_tree_conn_flag(struct ksmbd_tree_connect *tree_conn, + struct ksmbd_session; + + struct ksmbd_tree_conn_status +-ksmbd_tree_conn_connect(struct ksmbd_session *sess, char *share_name); ++ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, ++ char *share_name); + + int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, + struct ksmbd_tree_connect *tree_conn); +diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c +index 9c4a9c8c02795..92b1603b5abeb 100644 +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -153,9 +153,6 @@ void ksmbd_session_destroy(struct ksmbd_session *sess) + if (!sess) + return; + +- if (!atomic_dec_and_test(&sess->refcnt)) +- return; +- + down_write(&sessions_table_lock); + hash_del(&sess->hlist); + up_write(&sessions_table_lock); +@@ -186,16 +183,58 @@ static struct ksmbd_session *__session_lookup(unsigned long long id) + int ksmbd_session_register(struct ksmbd_conn *conn, + struct ksmbd_session *sess) + { +- sess->conn = conn; ++ sess->dialect = conn->dialect; ++ memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); + return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL)); + } + ++static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess) ++{ ++ struct channel *chann, *tmp; ++ ++ write_lock(&sess->chann_lock); ++ list_for_each_entry_safe(chann, tmp, &sess->ksmbd_chann_list, ++ chann_list) { ++ if (chann->conn == conn) { ++ list_del(&chann->chann_list); ++ kfree(chann); ++ write_unlock(&sess->chann_lock); ++ return 0; ++ } ++ } ++ write_unlock(&sess->chann_lock); ++ ++ return -ENOENT; ++} ++ + void ksmbd_sessions_deregister(struct ksmbd_conn *conn) + { + struct ksmbd_session *sess; +- unsigned long id; + +- xa_for_each(&conn->sessions, id, sess) { ++ if (conn->binding) { ++ int bkt; ++ ++ down_write(&sessions_table_lock); ++ hash_for_each(sessions_table, bkt, sess, hlist) { ++ if (!ksmbd_chann_del(conn, sess)) { ++ up_write(&sessions_table_lock); ++ goto sess_destroy; ++ } ++ } ++ up_write(&sessions_table_lock); ++ } else { ++ unsigned long id; ++ ++ xa_for_each(&conn->sessions, id, sess) { ++ if (!ksmbd_chann_del(conn, sess)) ++ goto sess_destroy; ++ } ++ } ++ ++ return; ++ ++sess_destroy: ++ if (list_empty(&sess->ksmbd_chann_list)) { + xa_erase(&conn->sessions, sess->id); + ksmbd_session_destroy(sess); + } +@@ -207,27 +246,12 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, + return xa_load(&conn->sessions, id); + } + +-int get_session(struct ksmbd_session *sess) +-{ +- return atomic_inc_not_zero(&sess->refcnt); +-} +- +-void put_session(struct ksmbd_session *sess) +-{ +- if (atomic_dec_and_test(&sess->refcnt)) +- pr_err("get/%s seems to be mismatched.", __func__); +-} +- + struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id) + { + struct ksmbd_session *sess; + + down_read(&sessions_table_lock); + sess = __session_lookup(id); +- if (sess) { +- if (!get_session(sess)) +- sess = NULL; +- } + up_read(&sessions_table_lock); + + return sess; +@@ -308,7 +332,6 @@ static struct ksmbd_session *__session_create(int protocol) + INIT_LIST_HEAD(&sess->ksmbd_chann_list); + INIT_LIST_HEAD(&sess->rpc_handle_list); + sess->sequence_number = 1; +- atomic_set(&sess->refcnt, 1); + rwlock_init(&sess->chann_lock); + + switch (protocol) { +diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h +index 1ec659f0151bf..8934b8ee275ba 100644 +--- a/fs/ksmbd/mgmt/user_session.h ++++ b/fs/ksmbd/mgmt/user_session.h +@@ -33,8 +33,10 @@ struct preauth_session { + struct ksmbd_session { + u64 id; + ++ __u16 dialect; ++ char ClientGUID[SMB2_CLIENT_GUID_SIZE]; ++ + struct ksmbd_user *user; +- struct ksmbd_conn *conn; + unsigned int sequence_number; + unsigned int flags; + +@@ -59,7 +61,6 @@ struct ksmbd_session { + __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; + + struct ksmbd_file_table file_table; +- atomic_t refcnt; + }; + + static inline int test_session_flag(struct ksmbd_session *sess, int bit) +@@ -100,6 +101,4 @@ void ksmbd_release_tree_conn_id(struct ksmbd_session *sess, int id); + int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name); + void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id); + int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id); +-int get_session(struct ksmbd_session *sess); +-void put_session(struct ksmbd_session *sess); + #endif /* __USER_SESSION_MANAGEMENT_H__ */ +diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c +index f9dae6ef21150..3f759f9123ea7 100644 +--- a/fs/ksmbd/oplock.c ++++ b/fs/ksmbd/oplock.c +@@ -30,6 +30,7 @@ static DEFINE_RWLOCK(lease_list_lock); + static struct oplock_info *alloc_opinfo(struct ksmbd_work *work, + u64 id, __u16 Tid) + { ++ struct ksmbd_conn *conn = work->conn; + struct ksmbd_session *sess = work->sess; + struct oplock_info *opinfo; + +@@ -38,7 +39,7 @@ static struct oplock_info *alloc_opinfo(struct ksmbd_work *work, + return NULL; + + opinfo->sess = sess; +- opinfo->conn = sess->conn; ++ opinfo->conn = conn; + opinfo->level = SMB2_OPLOCK_LEVEL_NONE; + opinfo->op_state = OPLOCK_STATE_NONE; + opinfo->pending_break = 0; +@@ -972,7 +973,7 @@ int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, + } + + list_for_each_entry(lb, &lease_table_list, l_entry) { +- if (!memcmp(lb->client_guid, sess->conn->ClientGUID, ++ if (!memcmp(lb->client_guid, sess->ClientGUID, + SMB2_CLIENT_GUID_SIZE)) + goto found; + } +@@ -988,7 +989,7 @@ int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, + rcu_read_unlock(); + if (opinfo->o_fp->f_ci == ci) + goto op_next; +- err = compare_guid_key(opinfo, sess->conn->ClientGUID, ++ err = compare_guid_key(opinfo, sess->ClientGUID, + lctx->lease_key); + if (err) { + err = -EINVAL; +@@ -1122,7 +1123,7 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, + struct oplock_info *m_opinfo; + + /* is lease already granted ? */ +- m_opinfo = same_client_has_lease(ci, sess->conn->ClientGUID, ++ m_opinfo = same_client_has_lease(ci, sess->ClientGUID, + lctx); + if (m_opinfo) { + copy_lease(m_opinfo, opinfo); +@@ -1240,7 +1241,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, + { + struct oplock_info *op, *brk_op; + struct ksmbd_inode *ci; +- struct ksmbd_conn *conn = work->sess->conn; ++ struct ksmbd_conn *conn = work->conn; + + if (!test_share_config_flag(work->tcon->share_conf, + KSMBD_SHARE_FLAG_OPLOCKS)) +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 8bfe2a6c05f92..61d6d4b6b56ac 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -610,12 +610,9 @@ static void destroy_previous_session(struct ksmbd_conn *conn, + if (!prev_user || + strcmp(user->name, prev_user->name) || + user->passkey_sz != prev_user->passkey_sz || +- memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) { +- put_session(prev_sess); ++ memcmp(user->passkey, prev_user->passkey, user->passkey_sz)) + return; +- } + +- put_session(prev_sess); + prev_sess->state = SMB2_SESSION_EXPIRED; + write_lock(&prev_sess->chann_lock); + list_for_each_entry(chann, &prev_sess->ksmbd_chann_list, chann_list) +@@ -1512,7 +1509,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) + + if (smb3_encryption_negotiated(conn) && + !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { +- rc = conn->ops->generate_encryptionkey(sess); ++ rc = conn->ops->generate_encryptionkey(conn, sess); + if (rc) { + ksmbd_debug(SMB, + "SMB3 encryption key generation failed\n"); +@@ -1604,7 +1601,7 @@ static int krb5_authenticate(struct ksmbd_work *work) + sess->sign = true; + + if (smb3_encryption_negotiated(conn)) { +- retval = conn->ops->generate_encryptionkey(sess); ++ retval = conn->ops->generate_encryptionkey(conn, sess); + if (retval) { + ksmbd_debug(SMB, + "SMB3 encryption key generation failed\n"); +@@ -1692,7 +1689,7 @@ int smb2_sess_setup(struct ksmbd_work *work) + goto out_err; + } + +- if (conn->dialect != sess->conn->dialect) { ++ if (conn->dialect != sess->dialect) { + rc = -EINVAL; + goto out_err; + } +@@ -1702,7 +1699,7 @@ int smb2_sess_setup(struct ksmbd_work *work) + goto out_err; + } + +- if (strncmp(conn->ClientGUID, sess->conn->ClientGUID, ++ if (strncmp(conn->ClientGUID, sess->ClientGUID, + SMB2_CLIENT_GUID_SIZE)) { + rc = -ENOENT; + goto out_err; +@@ -1907,7 +1904,7 @@ int smb2_tree_connect(struct ksmbd_work *work) + ksmbd_debug(SMB, "tree connect request for tree %s treename %s\n", + name, treename); + +- status = ksmbd_tree_conn_connect(sess, name); ++ status = ksmbd_tree_conn_connect(conn, sess, name); + if (status.ret == KSMBD_TREE_CONN_STATUS_OK) + rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id); + else +@@ -4895,7 +4892,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, + struct smb2_query_info_rsp *rsp, void *rsp_org) + { + struct ksmbd_session *sess = work->sess; +- struct ksmbd_conn *conn = sess->conn; ++ struct ksmbd_conn *conn = work->conn; + struct ksmbd_share_config *share = work->tcon->share_conf; + int fsinfoclass = 0; + struct kstatfs stfs; +@@ -5831,7 +5828,7 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, + } + next: + return smb2_rename(work, fp, user_ns, rename_info, +- work->sess->conn->local_nls); ++ work->conn->local_nls); + } + + static int set_file_disposition_info(struct ksmbd_file *fp, +@@ -5965,7 +5962,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, + return smb2_create_link(work, work->tcon->share_conf, + (struct smb2_file_link_info *)req->Buffer, + buf_len, fp->filp, +- work->sess->conn->local_nls); ++ work->conn->local_nls); + } + case FILE_DISPOSITION_INFORMATION: + { +diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h +index b9fe3fa149c2e..48cbaa0321400 100644 +--- a/fs/ksmbd/smb_common.h ++++ b/fs/ksmbd/smb_common.h +@@ -454,7 +454,7 @@ struct smb_version_ops { + int (*check_sign_req)(struct ksmbd_work *work); + void (*set_sign_rsp)(struct ksmbd_work *work); + int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn); +- int (*generate_encryptionkey)(struct ksmbd_session *sess); ++ int (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess); + bool (*is_transform_hdr)(void *buf); + int (*decrypt_req)(struct ksmbd_work *work); + int (*encrypt_resp)(struct ksmbd_work *work); +diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c +index 5d40a00fbce50..52cc6a9627ed7 100644 +--- a/fs/ksmbd/vfs.c ++++ b/fs/ksmbd/vfs.c +@@ -483,12 +483,11 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, + char *buf, size_t count, loff_t *pos, bool sync, + ssize_t *written) + { +- struct ksmbd_session *sess = work->sess; + struct file *filp; + loff_t offset = *pos; + int err = 0; + +- if (sess->conn->connection_type) { ++ if (work->conn->connection_type) { + if (!(fp->daccess & FILE_WRITE_DATA_LE)) { + pr_err("no right to write(%pd)\n", + fp->filp->f_path.dentry); +diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c +index 8b873d92d7854..0df8467af39af 100644 +--- a/fs/ksmbd/vfs_cache.c ++++ b/fs/ksmbd/vfs_cache.c +@@ -570,7 +570,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp) + atomic_set(&fp->refcount, 1); + + fp->filp = filp; +- fp->conn = work->sess->conn; ++ fp->conn = work->conn; + fp->tcon = work->tcon; + fp->volatile_id = KSMBD_NO_FID; + fp->persistent_id = KSMBD_NO_FID; +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-not-allow-guest-user-on-multichannel.patch b/queue-5.15/ksmbd-not-allow-guest-user-on-multichannel.patch new file mode 100644 index 00000000000..a28e3635830 --- /dev/null +++ b/queue-5.15/ksmbd-not-allow-guest-user-on-multichannel.patch @@ -0,0 +1,66 @@ +From fad4b1d8a9cb53e6994d1d833c87daf421122327 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 May 2023 08:45:08 +0900 +Subject: ksmbd: not allow guest user on multichannel + +From: Namjae Jeon + +[ Upstream commit 3353ab2df5f68dab7da8d5ebb427a2d265a1f2b2 ] + +This patch return STATUS_NOT_SUPPORTED if binding session is guest. + +Cc: stable@vger.kernel.org +Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-20480 +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/smb2pdu.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 61d6d4b6b56ac..51d495688f45e 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1462,7 +1462,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) + * Reuse session if anonymous try to connect + * on reauthetication. + */ +- if (ksmbd_anonymous_user(user)) { ++ if (conn->binding == false && ksmbd_anonymous_user(user)) { + ksmbd_free_user(user); + return 0; + } +@@ -1476,7 +1476,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) + sess->user = user; + } + +- if (user_guest(sess->user)) { ++ if (conn->binding == false && user_guest(sess->user)) { + rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE; + } else { + struct authenticate_message *authblob; +@@ -1720,6 +1720,11 @@ int smb2_sess_setup(struct ksmbd_work *work) + goto out_err; + } + ++ if (user_guest(sess->user)) { ++ rc = -EOPNOTSUPP; ++ goto out_err; ++ } ++ + conn->binding = true; + } else if ((conn->dialect < SMB30_PROT_ID || + server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) && +@@ -1831,6 +1836,8 @@ int smb2_sess_setup(struct ksmbd_work *work) + rsp->hdr.Status = STATUS_NETWORK_SESSION_EXPIRED; + else if (rc == -ENOMEM) + rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; ++ else if (rc == -EOPNOTSUPP) ++ rsp->hdr.Status = STATUS_NOT_SUPPORTED; + else if (rc) + rsp->hdr.Status = STATUS_LOGON_FAILURE; + +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-replace-sessions-list-in-connection-with-xarra.patch b/queue-5.15/ksmbd-replace-sessions-list-in-connection-with-xarra.patch new file mode 100644 index 00000000000..d4228686df3 --- /dev/null +++ b/queue-5.15/ksmbd-replace-sessions-list-in-connection-with-xarra.patch @@ -0,0 +1,219 @@ +From 1f1cf3e477e086b8bac077b54318929343b36823 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 10:15:10 +0900 +Subject: ksmbd: replace sessions list in connection with xarray + +From: Namjae Jeon + +[ Upstream commit e4d3e6b524c0c928f7fc9e03e047885c4951ae60 ] + +Replace sessions list in connection with xarray. + +Signed-off-by: Namjae Jeon +Reviewed-by: Hyunchul Lee +Signed-off-by: Steve French +Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()") +Signed-off-by: Sasha Levin +--- + fs/ksmbd/connection.c | 3 ++- + fs/ksmbd/connection.h | 2 +- + fs/ksmbd/mgmt/user_session.c | 31 +++++++------------------------ + fs/ksmbd/mgmt/user_session.h | 5 ++--- + fs/ksmbd/smb2pdu.c | 13 +++++++++---- + 5 files changed, 21 insertions(+), 33 deletions(-) + +diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c +index 21cda82f156de..b4c79359ef8b7 100644 +--- a/fs/ksmbd/connection.c ++++ b/fs/ksmbd/connection.c +@@ -36,6 +36,7 @@ void ksmbd_conn_free(struct ksmbd_conn *conn) + list_del(&conn->conns_list); + write_unlock(&conn_list_lock); + ++ xa_destroy(&conn->sessions); + kvfree(conn->request_buf); + kfree(conn->preauth_info); + kfree(conn); +@@ -66,12 +67,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) + + init_waitqueue_head(&conn->req_running_q); + INIT_LIST_HEAD(&conn->conns_list); +- INIT_LIST_HEAD(&conn->sessions); + INIT_LIST_HEAD(&conn->requests); + INIT_LIST_HEAD(&conn->async_requests); + spin_lock_init(&conn->request_lock); + spin_lock_init(&conn->credits_lock); + ida_init(&conn->async_ida); ++ xa_init(&conn->sessions); + + spin_lock_init(&conn->llist_lock); + INIT_LIST_HEAD(&conn->lock_list); +diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h +index f3367d7760d7e..7838cc46497d6 100644 +--- a/fs/ksmbd/connection.h ++++ b/fs/ksmbd/connection.h +@@ -55,7 +55,7 @@ struct ksmbd_conn { + struct nls_table *local_nls; + struct list_head conns_list; + /* smb session 1 per user */ +- struct list_head sessions; ++ struct xarray sessions; + unsigned long last_active; + /* How many request are running currently */ + atomic_t req_running; +diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c +index 0fa467f2c8973..8fe08df668582 100644 +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -154,8 +154,6 @@ void ksmbd_session_destroy(struct ksmbd_session *sess) + if (!atomic_dec_and_test(&sess->refcnt)) + return; + +- list_del(&sess->sessions_entry); +- + down_write(&sessions_table_lock); + hash_del(&sess->hlist); + up_write(&sessions_table_lock); +@@ -183,42 +181,28 @@ static struct ksmbd_session *__session_lookup(unsigned long long id) + return NULL; + } + +-void ksmbd_session_register(struct ksmbd_conn *conn, +- struct ksmbd_session *sess) ++int ksmbd_session_register(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess) + { + sess->conn = conn; +- list_add(&sess->sessions_entry, &conn->sessions); ++ return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL)); + } + + void ksmbd_sessions_deregister(struct ksmbd_conn *conn) + { + struct ksmbd_session *sess; ++ unsigned long id; + +- while (!list_empty(&conn->sessions)) { +- sess = list_entry(conn->sessions.next, +- struct ksmbd_session, +- sessions_entry); +- ++ xa_for_each(&conn->sessions, id, sess) { ++ xa_erase(&conn->sessions, sess->id); + ksmbd_session_destroy(sess); + } + } + +-static bool ksmbd_session_id_match(struct ksmbd_session *sess, +- unsigned long long id) +-{ +- return sess->id == id; +-} +- + struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, + unsigned long long id) + { +- struct ksmbd_session *sess = NULL; +- +- list_for_each_entry(sess, &conn->sessions, sessions_entry) { +- if (ksmbd_session_id_match(sess, id)) +- return sess; +- } +- return NULL; ++ return xa_load(&conn->sessions, id); + } + + int get_session(struct ksmbd_session *sess) +@@ -316,7 +300,6 @@ static struct ksmbd_session *__session_create(int protocol) + goto error; + + set_session_flag(sess, protocol); +- INIT_LIST_HEAD(&sess->sessions_entry); + xa_init(&sess->tree_conns); + INIT_LIST_HEAD(&sess->ksmbd_chann_list); + INIT_LIST_HEAD(&sess->rpc_handle_list); +diff --git a/fs/ksmbd/mgmt/user_session.h b/fs/ksmbd/mgmt/user_session.h +index e241f16a38512..8b08189be3fc2 100644 +--- a/fs/ksmbd/mgmt/user_session.h ++++ b/fs/ksmbd/mgmt/user_session.h +@@ -57,7 +57,6 @@ struct ksmbd_session { + __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE]; + __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; + +- struct list_head sessions_entry; + struct ksmbd_file_table file_table; + atomic_t refcnt; + }; +@@ -84,8 +83,8 @@ void ksmbd_session_destroy(struct ksmbd_session *sess); + struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id); + struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, + unsigned long long id); +-void ksmbd_session_register(struct ksmbd_conn *conn, +- struct ksmbd_session *sess); ++int ksmbd_session_register(struct ksmbd_conn *conn, ++ struct ksmbd_session *sess); + void ksmbd_sessions_deregister(struct ksmbd_conn *conn); + struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn, + unsigned long long id); +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index bb8126deeaf29..d41995f89befe 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -595,7 +595,8 @@ int smb2_check_user_session(struct ksmbd_work *work) + return -EINVAL; + } + +-static void destroy_previous_session(struct ksmbd_user *user, u64 id) ++static void destroy_previous_session(struct ksmbd_conn *conn, ++ struct ksmbd_user *user, u64 id) + { + struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id); + struct ksmbd_user *prev_user; +@@ -614,6 +615,7 @@ static void destroy_previous_session(struct ksmbd_user *user, u64 id) + } + + put_session(prev_sess); ++ xa_erase(&conn->sessions, prev_sess->id); + ksmbd_session_destroy(prev_sess); + } + +@@ -1452,7 +1454,7 @@ static int ntlm_authenticate(struct ksmbd_work *work) + /* Check for previous session */ + prev_id = le64_to_cpu(req->PreviousSessionId); + if (prev_id && prev_id != sess->id) +- destroy_previous_session(user, prev_id); ++ destroy_previous_session(conn, user, prev_id); + + if (sess->state == SMB2_SESSION_VALID) { + /* +@@ -1575,7 +1577,7 @@ static int krb5_authenticate(struct ksmbd_work *work) + /* Check previous session */ + prev_sess_id = le64_to_cpu(req->PreviousSessionId); + if (prev_sess_id && prev_sess_id != sess->id) +- destroy_previous_session(sess->user, prev_sess_id); ++ destroy_previous_session(conn, sess->user, prev_sess_id); + + if (sess->state == SMB2_SESSION_VALID) + ksmbd_free_user(sess->user); +@@ -1664,7 +1666,9 @@ int smb2_sess_setup(struct ksmbd_work *work) + goto out_err; + } + rsp->hdr.SessionId = cpu_to_le64(sess->id); +- ksmbd_session_register(conn, sess); ++ rc = ksmbd_session_register(conn, sess); ++ if (rc) ++ goto out_err; + } else if (conn->dialect >= SMB30_PROT_ID && + (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) && + req->Flags & SMB2_SESSION_REQ_FLAG_BINDING) { +@@ -1845,6 +1849,7 @@ int smb2_sess_setup(struct ksmbd_work *work) + if (sess->user && sess->user->flags & KSMBD_USER_FLAG_DELAY_SESSION) + try_delay = true; + ++ xa_erase(&conn->sessions, sess->id); + ksmbd_session_destroy(sess); + work->sess = NULL; + if (try_delay) +-- +2.39.2 + diff --git a/queue-5.15/ksmbd-set-rss-capable-in-fsctl_query_network_interfa.patch b/queue-5.15/ksmbd-set-rss-capable-in-fsctl_query_network_interfa.patch new file mode 100644 index 00000000000..3822bebdaf5 --- /dev/null +++ b/queue-5.15/ksmbd-set-rss-capable-in-fsctl_query_network_interfa.patch @@ -0,0 +1,98 @@ +From 2e51f3e34f664076b1f2292e990f84b18a40bfc3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Dec 2021 10:26:43 +0900 +Subject: ksmbd: set RSS capable in FSCTL_QUERY_NETWORK_INTERFACE_INFO + +From: Namjae Jeon + +[ Upstream commit a58b45a4dbfd0bf2ebb157789da4d8e6368afb1b ] + +Set RSS capable in FSCTL_QUERY_NETWORK_INTERFACE_INFO if netdev has +multi tx queues. And add ksmbd_compare_user() to avoid racy condition +issue in ksmbd_free_user(). because windows client is simultaneously used +to send session setup requests for multichannel connection. + +Tested-by: Ziwei Xie +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()") +Signed-off-by: Sasha Levin +--- + fs/ksmbd/mgmt/user_config.c | 10 ++++++++++ + fs/ksmbd/mgmt/user_config.h | 1 + + fs/ksmbd/smb2pdu.c | 15 ++++++++++----- + 3 files changed, 21 insertions(+), 5 deletions(-) + +diff --git a/fs/ksmbd/mgmt/user_config.c b/fs/ksmbd/mgmt/user_config.c +index 1019d3677d553..279d00feff216 100644 +--- a/fs/ksmbd/mgmt/user_config.c ++++ b/fs/ksmbd/mgmt/user_config.c +@@ -67,3 +67,13 @@ int ksmbd_anonymous_user(struct ksmbd_user *user) + return 1; + return 0; + } ++ ++bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2) ++{ ++ if (strcmp(u1->name, u2->name)) ++ return false; ++ if (memcmp(u1->passkey, u2->passkey, u1->passkey_sz)) ++ return false; ++ ++ return true; ++} +diff --git a/fs/ksmbd/mgmt/user_config.h b/fs/ksmbd/mgmt/user_config.h +index aff80b0295790..6a44109617f14 100644 +--- a/fs/ksmbd/mgmt/user_config.h ++++ b/fs/ksmbd/mgmt/user_config.h +@@ -64,4 +64,5 @@ struct ksmbd_user *ksmbd_login_user(const char *account); + struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp); + void ksmbd_free_user(struct ksmbd_user *user); + int ksmbd_anonymous_user(struct ksmbd_user *user); ++bool ksmbd_compare_user(struct ksmbd_user *u1, struct ksmbd_user *u2); + #endif /* __USER_CONFIG_MANAGEMENT_H__ */ +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 22d9fcb5f7ca4..c8c2b326ee042 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1463,10 +1463,16 @@ static int ntlm_authenticate(struct ksmbd_work *work) + ksmbd_free_user(user); + return 0; + } +- ksmbd_free_user(sess->user); ++ ++ if (!ksmbd_compare_user(sess->user, user)) { ++ ksmbd_free_user(user); ++ return -EPERM; ++ } ++ ksmbd_free_user(user); ++ } else { ++ sess->user = user; + } + +- sess->user = user; + if (user_guest(sess->user)) { + rsp->SessionFlags = SMB2_SESSION_FLAG_IS_GUEST_LE; + } else { +@@ -2071,9 +2077,6 @@ int smb2_session_logoff(struct ksmbd_work *work) + + ksmbd_debug(SMB, "request\n"); + +- /* Got a valid session, set connection state */ +- WARN_ON(sess->conn != conn); +- + /* setting CifsExiting here may race with start_tcp_sess */ + ksmbd_conn_set_need_reconnect(work); + ksmbd_close_session_fds(work); +@@ -7302,6 +7305,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn, + nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex); + + nii_rsp->Capability = 0; ++ if (netdev->real_num_tx_queues > 1) ++ nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE); + if (ksmbd_rdma_capable_netdev(netdev)) + nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE); + +-- +2.39.2 + diff --git a/queue-5.15/series b/queue-5.15/series index 5d1584e50ca..79750c36473 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -100,3 +100,19 @@ asoc-soc-compress-inherit-atomicity-from-dai-link-for-compress-fe.patch asoc-soc-pcm-move-debugfs-removal-out-of-spinlock.patch asoc-dpcm-don-t-pick-up-be-without-substream.patch asoc-soc-pcm.c-call-__soc_pcm_close-in-soc_pcm_close.patch +drm-i915-dg2-support-4k-30-on-hdmi.patch +drm-i915-dg2-add-additional-hdmi-pixel-clock-frequen.patch +drm-i915-dg2-add-hdmi-pixel-clock-frequencies-267.30.patch +drm-msm-remove-struct_mutex-usage.patch +drm-msm-adreno-fix-runtime-pm-imbalance-at-gpu-load.patch +drm-amd-display-refine-condition-of-cursor-visibilit.patch +drm-amd-display-add-null-plane_state-check-for-curso.patch +wifi-rtw88-rtw8821c-fix-rfe_option-field-width.patch +ksmbd-set-rss-capable-in-fsctl_query_network_interfa.patch +ksmbd-fix-multi-session-connection-failure.patch +ksmbd-replace-sessions-list-in-connection-with-xarra.patch +ksmbd-add-channel-rwlock.patch +ksmbd-fix-kernel-oops-from-idr_remove.patch +ksmbd-fix-racy-issue-while-destroying-session-on-mul.patch +ksmbd-fix-deadlock-in-ksmbd_find_crypto_ctx.patch +ksmbd-not-allow-guest-user-on-multichannel.patch diff --git a/queue-5.15/wifi-rtw88-rtw8821c-fix-rfe_option-field-width.patch b/queue-5.15/wifi-rtw88-rtw8821c-fix-rfe_option-field-width.patch new file mode 100644 index 00000000000..2f37ed2d9f1 --- /dev/null +++ b/queue-5.15/wifi-rtw88-rtw8821c-fix-rfe_option-field-width.patch @@ -0,0 +1,60 @@ +From 8228ea44695e99e6db63c07c111d7d45c8bfc77a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Apr 2023 16:03:56 +0200 +Subject: wifi: rtw88: rtw8821c: Fix rfe_option field width + +From: Sascha Hauer + +[ Upstream commit 14705f969d98187a1cc2682e0c9bd2e230b8098f ] + +On my RTW8821CU chipset rfe_option reads as 0x22. Looking at the +vendor driver suggests that the field width of rfe_option is 5 bit, +so rfe_option should be masked with 0x1f. + +Without this the rfe_option comparisons with 2 further down the +driver evaluate as false when they should really evaluate as true. +The effect is that 2G channels do not work. + +rfe_option is also used as an array index into rtw8821c_rfe_defs[]. +rtw8821c_rfe_defs[34] (0x22) was added as part of adding USB support, +likely because rfe_option reads as 0x22. As this now becomes 0x2, +rtw8821c_rfe_defs[34] is no longer used and can be removed. + +Note that this might not be the whole truth. In the vendor driver +there are indeed places where the unmasked rfe_option value is used. +However, the driver has several places where rfe_option is tested +with the pattern if (rfe_option == 2 || rfe_option == 0x22) or +if (rfe_option == 4 || rfe_option == 0x24), so that rfe_option BIT(5) +has no influence on the code path taken. We therefore mask BIT(5) +out from rfe_option entirely until this assumption is proved wrong +by some chip variant we do not know yet. + +Signed-off-by: Sascha Hauer +Tested-by: Alexandru gagniuc +Tested-by: Larry Finger +Tested-by: ValdikSS +Cc: stable@vger.kernel.org +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230417140358.2240429-3-s.hauer@pengutronix.de +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/rtw8821c.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +index 897da3ed2f029..280602a34fe67 100644 +--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c ++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c +@@ -40,7 +40,7 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) + + map = (struct rtw8821c_efuse *)log_map; + +- efuse->rfe_option = map->rfe_option; ++ efuse->rfe_option = map->rfe_option & 0x1f; + efuse->rf_board_option = map->rf_board_option; + efuse->crystal_cap = map->xtal_k; + efuse->pa_type_2g = map->pa_type; +-- +2.39.2 + -- 2.47.3