--- /dev/null
+From 5803aff837622f3bed7e77a0487af65cc88bdd38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Aug 2024 17:11:28 +0530
+Subject: drm/i915/hdcp: Use correct cp_irq_count
+
+From: Suraj Kandpal <suraj.kandpal@intel.com>
+
+[ Upstream commit 5d41eeb6725e3e24853629e5d7635e4bc45d736e ]
+
+We are checking cp_irq_count from the wrong hdcp structure which
+ends up giving timed out errors. We only increment the cp_irq_count
+of the primary connector's hdcp structure but here in case of
+multidisplay setup we end up checking the secondary connector's hdcp
+structure, which will not have its cp_irq_count incremented. This leads
+to a timed out at CP_IRQ error even though a CP_IRQ was raised. Extract
+it from the correct intel_hdcp structure.
+
+--v2
+-Explain why it was the wrong hdcp structure [Jani]
+
+Fixes: 8c9e4f68b861 ("drm/i915/hdcp: Use per-device debugs")
+Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
+Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240809114127.3940699-2-suraj.kandpal@intel.com
+(cherry picked from commit dd925902634def895690426bf10e0a8b3e56f56d)
+Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+index 92b03073acdd5..555428606e127 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+@@ -39,7 +39,9 @@ static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder)
+ static void intel_dp_hdcp_wait_for_cp_irq(struct intel_connector *connector,
+ int timeout)
+ {
+- struct intel_hdcp *hdcp = &connector->hdcp;
++ struct intel_digital_port *dig_port = intel_attached_dig_port(connector);
++ struct intel_dp *dp = &dig_port->dp;
++ struct intel_hdcp *hdcp = &dp->attached_connector->hdcp;
+ long ret;
+
+ #define C (hdcp->cp_irq_count_cached != atomic_read(&hdcp->cp_irq_count))
+--
+2.43.0
+
--- /dev/null
+From 53637a4dd22de8561bf8848eddb9b1d93dea139f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 13:20:08 -0700
+Subject: drm/msm/dp: fix the max supported bpp logic
+
+From: Abhinav Kumar <quic_abhinavk@quicinc.com>
+
+[ Upstream commit d19d5b8d8f6dab942ce5ddbcf34bf7275e778250 ]
+
+Fix the dp_panel_get_supported_bpp() API to return the minimum
+supported bpp correctly for relevant cases and use this API
+to correct the behavior of DP driver which hard-codes the max supported
+bpp to 30.
+
+This is incorrect because the number of lanes and max data rate
+supported by the lanes need to be taken into account.
+
+Replace the hardcoded limit with the appropriate math which accounts
+for the accurate number of lanes and max data rate.
+
+changes in v2:
+ - Fix the dp_panel_get_supported_bpp() and use it
+ - Drop the max_t usage as dp_panel_get_supported_bpp() already
+ returns the min_bpp correctly now
+
+changes in v3:
+ - replace min_t with just min as all params are u32
+
+Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support")
+Reported-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/43
+Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> # SM8350-HDK
+Reviewed-by: Stephen Boyd <swboyd@chromium.org>
+Patchwork: https://patchwork.freedesktop.org/patch/607073/
+Link: https://lore.kernel.org/r/20240805202009.1120981-1-quic_abhinavk@quicinc.com
+Signed-off-by: Stephen Boyd <swboyd@chromium.org>
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/dp/dp_panel.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
+index 07db8f37cd06a..017fb8cc8ab67 100644
+--- a/drivers/gpu/drm/msm/dp/dp_panel.c
++++ b/drivers/gpu/drm/msm/dp/dp_panel.c
+@@ -90,22 +90,22 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
+ static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
+ u32 mode_edid_bpp, u32 mode_pclk_khz)
+ {
+- struct dp_link_info *link_info;
++ const struct dp_link_info *link_info;
+ const u32 max_supported_bpp = 30, min_supported_bpp = 18;
+- u32 bpp = 0, data_rate_khz = 0;
++ u32 bpp, data_rate_khz;
+
+- bpp = min_t(u32, mode_edid_bpp, max_supported_bpp);
++ bpp = min(mode_edid_bpp, max_supported_bpp);
+
+ link_info = &dp_panel->link_info;
+ data_rate_khz = link_info->num_lanes * link_info->rate * 8;
+
+- while (bpp > min_supported_bpp) {
++ do {
+ if (mode_pclk_khz * bpp <= data_rate_khz)
+- break;
++ return bpp;
+ bpp -= 6;
+- }
++ } while (bpp > min_supported_bpp);
+
+- return bpp;
++ return min_supported_bpp;
+ }
+
+ static int dp_panel_update_modes(struct drm_connector *connector,
+@@ -442,8 +442,9 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel)
+ drm_mode->clock);
+ drm_dbg_dp(panel->drm_dev, "bpp = %d\n", dp_panel->dp_mode.bpp);
+
+- dp_panel->dp_mode.bpp = max_t(u32, 18,
+- min_t(u32, dp_panel->dp_mode.bpp, 30));
++ dp_panel->dp_mode.bpp = dp_panel_get_mode_bpp(dp_panel, dp_panel->dp_mode.bpp,
++ dp_panel->dp_mode.drm_mode.clock);
++
+ drm_dbg_dp(panel->drm_dev, "updated bpp = %d\n",
+ dp_panel->dp_mode.bpp);
+
+--
+2.43.0
+
--- /dev/null
+From bf835cd6a85eed3b96d38dae9568a9e87456cc0d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jul 2024 15:04:50 -0700
+Subject: drm/msm/dp: reset the link phy params before link training
+
+From: Abhinav Kumar <quic_abhinavk@quicinc.com>
+
+[ Upstream commit 319aca883bfa1b85ee08411541b51b9a934ac858 ]
+
+Before re-starting link training reset the link phy params namely
+the pre-emphasis and voltage swing levels otherwise the next
+link training begins at the previously cached levels which can result
+in link training failures.
+
+Fixes: 8ede2ecc3e5e ("drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets")
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> # SM8350-HDK
+Reviewed-by: Stephen Boyd <swboyd@chromium.org>
+Patchwork: https://patchwork.freedesktop.org/patch/605946/
+Link: https://lore.kernel.org/r/20240725220450.131245-1-quic_abhinavk@quicinc.com
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
+index 7bc8a9f0657a9..f342fc5ae41ec 100644
+--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
++++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
+@@ -1286,6 +1286,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
+ link_info.rate = ctrl->link->link_params.rate;
+ link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING;
+
++ dp_link_reset_phy_params_vx_px(ctrl->link);
++
+ dp_aux_link_configure(ctrl->aux, &link_info);
+
+ if (drm_dp_max_downspread(dpcd))
+--
+2.43.0
+
--- /dev/null
+From 00c9c40af914b0d4c9e91e19f934440e9f3415d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jun 2024 00:13:41 +0300
+Subject: drm/msm/dpu: cleanup FB if dpu_format_populate_layout fails
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit bfa1a6283be390947d3649c482e5167186a37016 ]
+
+If the dpu_format_populate_layout() fails, then FB is prepared, but not
+cleaned up. This ends up leaking the pin_count on the GEM object and
+causes a splat during DRM file closure:
+
+msm_obj->pin_count
+WARNING: CPU: 2 PID: 569 at drivers/gpu/drm/msm/msm_gem.c:121 update_lru_locked+0xc4/0xcc
+[...]
+Call trace:
+ update_lru_locked+0xc4/0xcc
+ put_pages+0xac/0x100
+ msm_gem_free_object+0x138/0x180
+ drm_gem_object_free+0x1c/0x30
+ drm_gem_object_handle_put_unlocked+0x108/0x10c
+ drm_gem_object_release_handle+0x58/0x70
+ idr_for_each+0x68/0xec
+ drm_gem_release+0x28/0x40
+ drm_file_free+0x174/0x234
+ drm_release+0xb0/0x160
+ __fput+0xc0/0x2c8
+ __fput_sync+0x50/0x5c
+ __arm64_sys_close+0x38/0x7c
+ invoke_syscall+0x48/0x118
+ el0_svc_common.constprop.0+0x40/0xe0
+ do_el0_svc+0x1c/0x28
+ el0_svc+0x4c/0x120
+ el0t_64_sync_handler+0x100/0x12c
+ el0t_64_sync+0x190/0x194
+irq event stamp: 129818
+hardirqs last enabled at (129817): [<ffffa5f6d953fcc0>] console_unlock+0x118/0x124
+hardirqs last disabled at (129818): [<ffffa5f6da7dcf04>] el1_dbg+0x24/0x8c
+softirqs last enabled at (129808): [<ffffa5f6d94afc18>] handle_softirqs+0x4c8/0x4e8
+softirqs last disabled at (129785): [<ffffa5f6d94105e4>] __do_softirq+0x14/0x20
+
+Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/600714/
+Link: https://lore.kernel.org/r/20240625-dpu-mode-config-width-v5-1-501d984d634f@linaro.org
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+index 1c3a2657450c6..eabc4813c649c 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+@@ -680,6 +680,9 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
+ new_state->fb, &layout);
+ if (ret) {
+ DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
++ if (pstate->aspace)
++ msm_framebuffer_cleanup(new_state->fb, pstate->aspace,
++ pstate->needs_dirtyfb);
+ return ret;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 3f8f69f13996f8f4c79bd300703ce0b0f780e8b2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Aug 2024 22:47:34 +0300
+Subject: drm/msm/dpu: don't play tricks with debug macros
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit df24373435f5899a2a98b7d377479c8d4376613b ]
+
+DPU debugging macros need to be converted to a proper drm_debug_*
+macros, however this is a going an intrusive patch, not suitable for a
+fix. Wire DPU_DEBUG and DPU_DEBUG_DRIVER to always use DRM_DEBUG_DRIVER
+to make sure that DPU debugging messages always end up in the drm debug
+messages and are controlled via the usual drm.debug mask.
+
+I don't think that it is a good idea for a generic DPU_DEBUG macro to be
+tied to DRM_UT_KMS. It is used to report a debug message from driver, so by
+default it should go to the DRM_UT_DRIVER channel. While refactoring
+debug macros later on we might end up with particular messages going to
+ATOMIC or KMS, but DRIVER should be the default.
+
+Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/606932/
+Link: https://lore.kernel.org/r/20240802-dpu-fix-wb-v2-2-7eac9eb8e895@linaro.org
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 14 ++------------
+ 1 file changed, 2 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+index e2adc937ea63b..935ff6fd172c4 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+@@ -31,24 +31,14 @@
+ * @fmt: Pointer to format string
+ */
+ #define DPU_DEBUG(fmt, ...) \
+- do { \
+- if (drm_debug_enabled(DRM_UT_KMS)) \
+- DRM_DEBUG(fmt, ##__VA_ARGS__); \
+- else \
+- pr_debug(fmt, ##__VA_ARGS__); \
+- } while (0)
++ DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
+
+ /**
+ * DPU_DEBUG_DRIVER - macro for hardware driver logging
+ * @fmt: Pointer to format string
+ */
+ #define DPU_DEBUG_DRIVER(fmt, ...) \
+- do { \
+- if (drm_debug_enabled(DRM_UT_DRIVER)) \
+- DRM_ERROR(fmt, ##__VA_ARGS__); \
+- else \
+- pr_debug(fmt, ##__VA_ARGS__); \
+- } while (0)
++ DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
+
+ #define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)
+ #define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
+--
+2.43.0
+
--- /dev/null
+From 9d305ea45a0c08c4848cff74dbf7cc0946edfa57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 00:45:55 +0300
+Subject: drm/msm/dpu: limit QCM2290 to RGB formats only
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 2db13c4a631505029ada9404e09a2b06a268c1c4 ]
+
+The QCM2290 doesn't have CSC blocks, so it can not support YUV formats
+even on ViG blocks. Fix the formats declared by _VIG_SBLK_NOSCALE().
+
+Fixes: 5334087ee743 ("drm/msm: add support for QCM2290 MDSS")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/601048/
+Link: https://lore.kernel.org/r/20240627-dpu-virtual-wide-v5-1-5efb90cbb8be@linaro.org
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+index 9b72977feafa4..e61b5681f3bbd 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+@@ -308,8 +308,8 @@ static const u32 wb2_formats_rgb_yuv[] = {
+ { \
+ .maxdwnscale = SSPP_UNITY_SCALE, \
+ .maxupscale = SSPP_UNITY_SCALE, \
+- .format_list = plane_formats_yuv, \
+- .num_formats = ARRAY_SIZE(plane_formats_yuv), \
++ .format_list = plane_formats, \
++ .num_formats = ARRAY_SIZE(plane_formats), \
+ .virt_format_list = plane_formats, \
+ .virt_num_formats = ARRAY_SIZE(plane_formats), \
+ }
+--
+2.43.0
+
--- /dev/null
+From 7f38661e3cdf7929bd731a2edaeffb5fb166fd40 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jul 2024 12:17:22 -0700
+Subject: drm/msm/dpu: move dpu_encoder's connector assignment to
+ atomic_enable()
+
+From: Abhinav Kumar <quic_abhinavk@quicinc.com>
+
+[ Upstream commit aedf02e46eb549dac8db4821a6b9f0c6bf6e3990 ]
+
+For cases where the crtc's connectors_changed was set without enable/active
+getting toggled , there is an atomic_enable() call followed by an
+atomic_disable() but without an atomic_mode_set().
+
+This results in a NULL ptr access for the dpu_encoder_get_drm_fmt() call in
+the atomic_enable() as the dpu_encoder's connector was cleared in the
+atomic_disable() but not re-assigned as there was no atomic_mode_set() call.
+
+Fix the NULL ptr access by moving the assignment for atomic_enable() and also
+use drm_atomic_get_new_connector_for_encoder() to get the connector from
+the atomic_state.
+
+Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
+Reported-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/59
+Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Tested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> # SM8350-HDK
+Patchwork: https://patchwork.freedesktop.org/patch/606729/
+Link: https://lore.kernel.org/r/20240731191723.3050932-1-quic_abhinavk@quicinc.com
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+index 697ad4a640516..a6c5e3bc9bf15 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+@@ -1179,8 +1179,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
+
+ cstate->num_mixers = num_lm;
+
+- dpu_enc->connector = conn_state->connector;
+-
+ for (i = 0; i < dpu_enc->num_phys_encs; i++) {
+ struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+
+@@ -1277,6 +1275,8 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc,
+
+ dpu_enc->commit_done_timedout = false;
+
++ dpu_enc->connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
++
+ cur_mode = &dpu_enc->base.crtc->state->adjusted_mode;
+
+ dpu_enc->wide_bus_en = dpu_encoder_is_widebus_enabled(drm_enc);
+--
+2.43.0
+
--- /dev/null
+From 3deb908f4b2a9305715a938c33b08736addd33f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 00:45:56 +0300
+Subject: drm/msm/dpu: relax YUV requirements
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit cb18195914e353ece0e789e365a5a16872169805 ]
+
+YUV formats require only CSC to be enabled. Even decimated formats
+should not require scaler. Relax the requirement and don't check for the
+scaler block while checking if YUV format can be enabled.
+
+Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/601049/
+Link: https://lore.kernel.org/r/20240627-dpu-virtual-wide-v5-2-5efb90cbb8be@linaro.org
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+index eabc4813c649c..cbdb9628d962d 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+@@ -746,10 +746,9 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
+ min_src_size = MSM_FORMAT_IS_YUV(fmt) ? 2 : 1;
+
+ if (MSM_FORMAT_IS_YUV(fmt) &&
+- (!pipe->sspp->cap->sblk->scaler_blk.len ||
+- !pipe->sspp->cap->sblk->csc_blk.len)) {
++ !pipe->sspp->cap->sblk->csc_blk.len) {
+ DPU_DEBUG_PLANE(pdpu,
+- "plane doesn't have scaler/csc for yuv\n");
++ "plane doesn't have csc for yuv\n");
+ return -EINVAL;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 049534483fc24d831403e6593097ccaab8b6500c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jun 2024 00:45:57 +0300
+Subject: drm/msm/dpu: take plane rotation into account for wide planes
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit d3a785e4f983f523380e023d8a05fb6d04402957 ]
+
+Take into account the plane rotation and flipping when calculating src
+positions for the wide plane parts.
+
+This is not an issue yet, because rotation is only supported for the
+UBWC planes and wide UBWC planes are rejected anyway because in parallel
+multirect case only the half of the usual width is supported for tiled
+formats. However it's better to fix this now rather than stumbling upon
+it later.
+
+Fixes: 80e8ae3b38ab ("drm/msm/dpu: add support for wide planes")
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Patchwork: https://patchwork.freedesktop.org/patch/601059/
+Link: https://lore.kernel.org/r/20240627-dpu-virtual-wide-v5-3-5efb90cbb8be@linaro.org
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+index cbdb9628d962d..c31d283d1c6c1 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+@@ -865,6 +865,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
+
+ max_linewidth = pdpu->catalog->caps->max_linewidth;
+
++ drm_rect_rotate(&pipe_cfg->src_rect,
++ new_plane_state->fb->width, new_plane_state->fb->height,
++ new_plane_state->rotation);
++
+ if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) ||
+ _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_clk_rate) {
+ /*
+@@ -914,6 +918,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
+ r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
+ }
+
++ drm_rect_rotate_inv(&pipe_cfg->src_rect,
++ new_plane_state->fb->width, new_plane_state->fb->height,
++ new_plane_state->rotation);
++ if (r_pipe->sspp)
++ drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
++ new_plane_state->fb->width, new_plane_state->fb->height,
++ new_plane_state->rotation);
++
+ ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt, &crtc_state->adjusted_mode);
+ if (ret)
+ return ret;
+--
+2.43.0
+
--- /dev/null
+From 4a746fa3f64f612ab37f0c314535592f7c04e4cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Aug 2024 16:52:27 -0700
+Subject: drm/msm: fix the highest_bank_bit for sc7180
+
+From: Abhinav Kumar <quic_abhinavk@quicinc.com>
+
+[ Upstream commit 3e30296b374af33cb4c12ff93df0b1e5b2d0f80b ]
+
+sc7180 programs the ubwc settings as 0x1e as that would mean a
+highest bank bit of 14 which matches what the GPU sets as well.
+
+However, the highest_bank_bit field of the msm_mdss_data which is
+being used to program the SSPP's fetch configuration is programmed
+to a highest bank bit of 16 as 0x3 translates to 16 and not 14.
+
+Fix the highest bank bit field used for the SSPP to match the mdss
+and gpu settings.
+
+Fixes: 6f410b246209 ("drm/msm/mdss: populate missing data")
+Reviewed-by: Rob Clark <robdclark@gmail.com>
+Tested-by: Stephen Boyd <swboyd@chromium.org> # Trogdor.Lazor
+Patchwork: https://patchwork.freedesktop.org/patch/607625/
+Link: https://lore.kernel.org/r/20240808235227.2701479-1-quic_abhinavk@quicinc.com
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/msm_mdss.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
+index fab6ad4e5107c..ec75274178028 100644
+--- a/drivers/gpu/drm/msm/msm_mdss.c
++++ b/drivers/gpu/drm/msm/msm_mdss.c
+@@ -577,7 +577,7 @@ static const struct msm_mdss_data sc7180_data = {
+ .ubwc_enc_version = UBWC_2_0,
+ .ubwc_dec_version = UBWC_2_0,
+ .ubwc_static = 0x1e,
+- .highest_bank_bit = 0x3,
++ .highest_bank_bit = 0x1,
+ .reg_bus_bw = 76800,
+ };
+
+--
+2.43.0
+
--- /dev/null
+From 515bfd7752e9c7e6944d2e6c4b5261ec1cd1f3d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 15:59:08 +0200
+Subject: drm/xe: Decouple job seqno and lrc seqno
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 08f7200899ca72dec550af092ae424b7db099abd ]
+
+Tightly coupling these seqno presents problems if alternative fences for
+jobs are used. Decouple these for correctness.
+
+v2:
+- Slightly reword commit message (Thomas)
+- Make sure the lrc fence ops are used in comparison (Thomas)
+- Assume seqno is unsigned rather than signed in format string (Thomas)
+
+Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240527135912.152156-2-thomas.hellstrom@linux.intel.com
+Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_exec_queue.c | 2 +-
+ drivers/gpu/drm/xe/xe_guc_submit.c | 5 +++--
+ drivers/gpu/drm/xe/xe_ring_ops.c | 12 ++++++------
+ drivers/gpu/drm/xe/xe_sched_job.c | 16 ++++++++--------
+ drivers/gpu/drm/xe/xe_sched_job.h | 5 +++++
+ drivers/gpu/drm/xe/xe_sched_job_types.h | 2 ++
+ drivers/gpu/drm/xe/xe_trace.h | 7 +++++--
+ 7 files changed, 30 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
+index 33b03605a1d15..79d099e054916 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue.c
++++ b/drivers/gpu/drm/xe/xe_exec_queue.c
+@@ -98,7 +98,7 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
+
+ if (xe_exec_queue_is_parallel(q)) {
+ q->parallel.composite_fence_ctx = dma_fence_context_alloc(1);
+- q->parallel.composite_fence_seqno = XE_FENCE_INITIAL_SEQNO;
++ q->parallel.composite_fence_seqno = 0;
+ }
+
+ return q;
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index 8c75791cbc4fb..e48285c81bf57 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -917,8 +917,9 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
+ return DRM_GPU_SCHED_STAT_NOMINAL;
+ }
+
+- drm_notice(&xe->drm, "Timedout job: seqno=%u, guc_id=%d, flags=0x%lx",
+- xe_sched_job_seqno(job), q->guc->id, q->flags);
++ drm_notice(&xe->drm, "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx",
++ xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
++ q->guc->id, q->flags);
+ xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_KERNEL,
+ "Kernel-submitted job timed out\n");
+ xe_gt_WARN(q->gt, q->flags & EXEC_QUEUE_FLAG_VM && !exec_queue_killed(q),
+diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
+index aca7a9af6e846..3b6aad8dea99a 100644
+--- a/drivers/gpu/drm/xe/xe_ring_ops.c
++++ b/drivers/gpu/drm/xe/xe_ring_ops.c
+@@ -412,7 +412,7 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job)
+
+ __emit_job_gen12_simple(job, job->q->lrc,
+ job->batch_addr[0],
+- xe_sched_job_seqno(job));
++ xe_sched_job_lrc_seqno(job));
+ }
+
+ static void emit_job_gen12_copy(struct xe_sched_job *job)
+@@ -421,14 +421,14 @@ static void emit_job_gen12_copy(struct xe_sched_job *job)
+
+ if (xe_sched_job_is_migration(job->q)) {
+ emit_migration_job_gen12(job, job->q->lrc,
+- xe_sched_job_seqno(job));
++ xe_sched_job_lrc_seqno(job));
+ return;
+ }
+
+ for (i = 0; i < job->q->width; ++i)
+ __emit_job_gen12_simple(job, job->q->lrc + i,
+- job->batch_addr[i],
+- xe_sched_job_seqno(job));
++ job->batch_addr[i],
++ xe_sched_job_lrc_seqno(job));
+ }
+
+ static void emit_job_gen12_video(struct xe_sched_job *job)
+@@ -439,7 +439,7 @@ static void emit_job_gen12_video(struct xe_sched_job *job)
+ for (i = 0; i < job->q->width; ++i)
+ __emit_job_gen12_video(job, job->q->lrc + i,
+ job->batch_addr[i],
+- xe_sched_job_seqno(job));
++ xe_sched_job_lrc_seqno(job));
+ }
+
+ static void emit_job_gen12_render_compute(struct xe_sched_job *job)
+@@ -449,7 +449,7 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job)
+ for (i = 0; i < job->q->width; ++i)
+ __emit_job_gen12_render_compute(job, job->q->lrc + i,
+ job->batch_addr[i],
+- xe_sched_job_seqno(job));
++ xe_sched_job_lrc_seqno(job));
+ }
+
+ static const struct xe_ring_ops ring_ops_gen12_gsc = {
+diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
+index a4e030f5e019a..874450be327ec 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job.c
++++ b/drivers/gpu/drm/xe/xe_sched_job.c
+@@ -117,6 +117,7 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ err = PTR_ERR(job->fence);
+ goto err_sched_job;
+ }
++ job->lrc_seqno = job->fence->seqno;
+ } else {
+ struct dma_fence_array *cf;
+
+@@ -132,6 +133,8 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ err = PTR_ERR(fences[j]);
+ goto err_fences;
+ }
++ if (!j)
++ job->lrc_seqno = fences[0]->seqno;
+ }
+
+ cf = dma_fence_array_create(q->width, fences,
+@@ -144,10 +147,6 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ goto err_fences;
+ }
+
+- /* Sanity check */
+- for (j = 0; j < q->width; ++j)
+- xe_assert(job_to_xe(job), cf->base.seqno == fences[j]->seqno);
+-
+ job->fence = &cf->base;
+ }
+
+@@ -229,9 +228,9 @@ bool xe_sched_job_started(struct xe_sched_job *job)
+ {
+ struct xe_lrc *lrc = job->q->lrc;
+
+- return !__dma_fence_is_later(xe_sched_job_seqno(job),
++ return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job),
+ xe_lrc_start_seqno(lrc),
+- job->fence->ops);
++ dma_fence_array_first(job->fence)->ops);
+ }
+
+ bool xe_sched_job_completed(struct xe_sched_job *job)
+@@ -243,8 +242,9 @@ bool xe_sched_job_completed(struct xe_sched_job *job)
+ * parallel handshake is done.
+ */
+
+- return !__dma_fence_is_later(xe_sched_job_seqno(job), xe_lrc_seqno(lrc),
+- job->fence->ops);
++ return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job),
++ xe_lrc_seqno(lrc),
++ dma_fence_array_first(job->fence)->ops);
+ }
+
+ void xe_sched_job_arm(struct xe_sched_job *job)
+diff --git a/drivers/gpu/drm/xe/xe_sched_job.h b/drivers/gpu/drm/xe/xe_sched_job.h
+index c75018f4660dc..002c3b5c0a5cb 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job.h
++++ b/drivers/gpu/drm/xe/xe_sched_job.h
+@@ -73,6 +73,11 @@ static inline u32 xe_sched_job_seqno(struct xe_sched_job *job)
+ return job->fence->seqno;
+ }
+
++static inline u32 xe_sched_job_lrc_seqno(struct xe_sched_job *job)
++{
++ return job->lrc_seqno;
++}
++
+ static inline void
+ xe_sched_job_add_migrate_flush(struct xe_sched_job *job, u32 flags)
+ {
+diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h
+index 5e12724219fdd..990ddac55ed62 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job_types.h
++++ b/drivers/gpu/drm/xe/xe_sched_job_types.h
+@@ -37,6 +37,8 @@ struct xe_sched_job {
+ /** @user_fence.value: write back value */
+ u64 value;
+ } user_fence;
++ /** @lrc_seqno: LRC seqno */
++ u32 lrc_seqno;
+ /** @migrate_flush_flags: Additional flush flags for migration jobs */
+ u32 migrate_flush_flags;
+ /** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */
+diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
+index 2d56cfc09e421..6c6cecc58f63b 100644
+--- a/drivers/gpu/drm/xe/xe_trace.h
++++ b/drivers/gpu/drm/xe/xe_trace.h
+@@ -254,6 +254,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,
+
+ TP_STRUCT__entry(
+ __field(u32, seqno)
++ __field(u32, lrc_seqno)
+ __field(u16, guc_id)
+ __field(u32, guc_state)
+ __field(u32, flags)
+@@ -264,6 +265,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,
+
+ TP_fast_assign(
+ __entry->seqno = xe_sched_job_seqno(job);
++ __entry->lrc_seqno = xe_sched_job_lrc_seqno(job);
+ __entry->guc_id = job->q->guc->id;
+ __entry->guc_state =
+ atomic_read(&job->q->guc->state);
+@@ -273,8 +275,9 @@ DECLARE_EVENT_CLASS(xe_sched_job,
+ __entry->batch_addr = (u64)job->batch_addr[0];
+ ),
+
+- TP_printk("fence=%p, seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d",
+- __entry->fence, __entry->seqno, __entry->guc_id,
++ TP_printk("fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d",
++ __entry->fence, __entry->seqno,
++ __entry->lrc_seqno, __entry->guc_id,
+ __entry->batch_addr, __entry->guc_state,
+ __entry->flags, __entry->error)
+ );
+--
+2.43.0
+
--- /dev/null
+From d8feaf92f7c6d767e1691801c4f7f179a47f7717 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 May 2024 11:22:00 +0100
+Subject: drm/xe/display: stop calling domains_driver_remove twice
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+[ Upstream commit 48d74a0a45201de4efa016fb2f556889db37ed28 ]
+
+Unclear why we call this twice.
+
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Andrzej Hajda <andrzej.hajda@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240522102143.128069-35-matthew.auld@intel.com
+Stable-dep-of: f4b2a0ae1a31 ("drm/xe: Fix opregion leak")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/display/xe_display.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
+index 0de0566e5b394..6ecaf83264d55 100644
+--- a/drivers/gpu/drm/xe/display/xe_display.c
++++ b/drivers/gpu/drm/xe/display/xe_display.c
+@@ -134,7 +134,6 @@ static void xe_display_fini_noirq(struct drm_device *dev, void *dummy)
+ return;
+
+ intel_display_driver_remove_noirq(xe);
+- intel_power_domains_driver_remove(xe);
+ }
+
+ int xe_display_init_noirq(struct xe_device *xe)
+--
+2.43.0
+
--- /dev/null
+From 8f0ae1eaea33228f0f81df5441884e47f3c1c5da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 15:59:10 +0200
+Subject: drm/xe: Don't initialize fences at xe_sched_job_create()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+[ Upstream commit 0ac7a2c745e8a42803378b944fa0f4455b7240f6 ]
+
+Pre-allocate but don't initialize fences at xe_sched_job_create(),
+and initialize / arm them instead at xe_sched_job_arm(). This
+makes it possible to move xe_sched_job_create() with its memory
+allocation out of any lock that is required for fence
+initialization, and that may not allow memory allocation under it.
+
+Replaces the struct dma_fence_array for parallell jobs with a
+struct dma_fence_chain, since the former doesn't allow
+a split-up between allocation and initialization.
+
+v2:
+- Rebase.
+- Don't always use the first lrc when initializing parallel
+ lrc fences.
+- Use dma_fence_chain_contained() to access the lrc fences.
+
+v4:
+- Add an assert that job->lrc_seqno == fence->seqno.
+ (Matthew Brost)
+
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> #v2
+Link: https://patchwork.freedesktop.org/patch/msgid/20240527135912.152156-4-thomas.hellstrom@linux.intel.com
+Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_exec_queue.c | 5 -
+ drivers/gpu/drm/xe/xe_exec_queue_types.h | 10 --
+ drivers/gpu/drm/xe/xe_ring_ops.c | 12 +-
+ drivers/gpu/drm/xe/xe_sched_job.c | 161 +++++++++++++----------
+ drivers/gpu/drm/xe/xe_sched_job_types.h | 18 ++-
+ drivers/gpu/drm/xe/xe_trace.h | 2 +-
+ 6 files changed, 115 insertions(+), 93 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
+index 79d099e054916..2ae4420e29353 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue.c
++++ b/drivers/gpu/drm/xe/xe_exec_queue.c
+@@ -96,11 +96,6 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
+ }
+ }
+
+- if (xe_exec_queue_is_parallel(q)) {
+- q->parallel.composite_fence_ctx = dma_fence_context_alloc(1);
+- q->parallel.composite_fence_seqno = 0;
+- }
+-
+ return q;
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+index ee78d497d838a..f0c40e8ad80a1 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
++++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+@@ -103,16 +103,6 @@ struct xe_exec_queue {
+ struct xe_guc_exec_queue *guc;
+ };
+
+- /**
+- * @parallel: parallel submission state
+- */
+- struct {
+- /** @parallel.composite_fence_ctx: context composite fence */
+- u64 composite_fence_ctx;
+- /** @parallel.composite_fence_seqno: seqno for composite fence */
+- u32 composite_fence_seqno;
+- } parallel;
+-
+ /** @sched_props: scheduling properties */
+ struct {
+ /** @sched_props.timeslice_us: timeslice period in micro-seconds */
+diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
+index 3b6aad8dea99a..c59c4373aefad 100644
+--- a/drivers/gpu/drm/xe/xe_ring_ops.c
++++ b/drivers/gpu/drm/xe/xe_ring_ops.c
+@@ -380,7 +380,7 @@ static void emit_migration_job_gen12(struct xe_sched_job *job,
+
+ dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE; /* Enabled again below */
+
+- i = emit_bb_start(job->batch_addr[0], BIT(8), dw, i);
++ i = emit_bb_start(job->ptrs[0].batch_addr, BIT(8), dw, i);
+
+ if (!IS_SRIOV_VF(gt_to_xe(job->q->gt))) {
+ /* XXX: Do we need this? Leaving for now. */
+@@ -389,7 +389,7 @@ static void emit_migration_job_gen12(struct xe_sched_job *job,
+ dw[i++] = preparser_disable(false);
+ }
+
+- i = emit_bb_start(job->batch_addr[1], BIT(8), dw, i);
++ i = emit_bb_start(job->ptrs[1].batch_addr, BIT(8), dw, i);
+
+ dw[i++] = MI_FLUSH_DW | MI_INVALIDATE_TLB | job->migrate_flush_flags |
+ MI_FLUSH_DW_OP_STOREDW | MI_FLUSH_IMM_DW;
+@@ -411,7 +411,7 @@ static void emit_job_gen12_gsc(struct xe_sched_job *job)
+ xe_gt_assert(gt, job->q->width <= 1); /* no parallel submission for GSCCS */
+
+ __emit_job_gen12_simple(job, job->q->lrc,
+- job->batch_addr[0],
++ job->ptrs[0].batch_addr,
+ xe_sched_job_lrc_seqno(job));
+ }
+
+@@ -427,7 +427,7 @@ static void emit_job_gen12_copy(struct xe_sched_job *job)
+
+ for (i = 0; i < job->q->width; ++i)
+ __emit_job_gen12_simple(job, job->q->lrc + i,
+- job->batch_addr[i],
++ job->ptrs[i].batch_addr,
+ xe_sched_job_lrc_seqno(job));
+ }
+
+@@ -438,7 +438,7 @@ static void emit_job_gen12_video(struct xe_sched_job *job)
+ /* FIXME: Not doing parallel handshake for now */
+ for (i = 0; i < job->q->width; ++i)
+ __emit_job_gen12_video(job, job->q->lrc + i,
+- job->batch_addr[i],
++ job->ptrs[i].batch_addr,
+ xe_sched_job_lrc_seqno(job));
+ }
+
+@@ -448,7 +448,7 @@ static void emit_job_gen12_render_compute(struct xe_sched_job *job)
+
+ for (i = 0; i < job->q->width; ++i)
+ __emit_job_gen12_render_compute(job, job->q->lrc + i,
+- job->batch_addr[i],
++ job->ptrs[i].batch_addr,
+ xe_sched_job_lrc_seqno(job));
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
+index 874450be327ec..29f3201d7dfac 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job.c
++++ b/drivers/gpu/drm/xe/xe_sched_job.c
+@@ -6,7 +6,7 @@
+ #include "xe_sched_job.h"
+
+ #include <drm/xe_drm.h>
+-#include <linux/dma-fence-array.h>
++#include <linux/dma-fence-chain.h>
+ #include <linux/slab.h>
+
+ #include "xe_device.h"
+@@ -29,7 +29,7 @@ int __init xe_sched_job_module_init(void)
+ xe_sched_job_slab =
+ kmem_cache_create("xe_sched_job",
+ sizeof(struct xe_sched_job) +
+- sizeof(u64), 0,
++ sizeof(struct xe_job_ptrs), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!xe_sched_job_slab)
+ return -ENOMEM;
+@@ -37,7 +37,7 @@ int __init xe_sched_job_module_init(void)
+ xe_sched_job_parallel_slab =
+ kmem_cache_create("xe_sched_job_parallel",
+ sizeof(struct xe_sched_job) +
+- sizeof(u64) *
++ sizeof(struct xe_job_ptrs) *
+ XE_HW_ENGINE_MAX_INSTANCE, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!xe_sched_job_parallel_slab) {
+@@ -79,26 +79,33 @@ static struct xe_device *job_to_xe(struct xe_sched_job *job)
+ return gt_to_xe(job->q->gt);
+ }
+
++/* Free unused pre-allocated fences */
++static void xe_sched_job_free_fences(struct xe_sched_job *job)
++{
++ int i;
++
++ for (i = 0; i < job->q->width; ++i) {
++ struct xe_job_ptrs *ptrs = &job->ptrs[i];
++
++ if (ptrs->lrc_fence)
++ xe_lrc_free_seqno_fence(ptrs->lrc_fence);
++ if (ptrs->chain_fence)
++ dma_fence_chain_free(ptrs->chain_fence);
++ }
++}
++
+ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ u64 *batch_addr)
+ {
+- struct xe_sched_job *job;
+- struct dma_fence **fences;
+ bool is_migration = xe_sched_job_is_migration(q);
++ struct xe_sched_job *job;
+ int err;
+- int i, j;
++ int i;
+ u32 width;
+
+ /* only a kernel context can submit a vm-less job */
+ XE_WARN_ON(!q->vm && !(q->flags & EXEC_QUEUE_FLAG_KERNEL));
+
+- /* Migration and kernel engines have their own locking */
+- if (!(q->flags & (EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_VM))) {
+- lockdep_assert_held(&q->vm->lock);
+- if (!xe_vm_in_lr_mode(q->vm))
+- xe_vm_assert_held(q->vm);
+- }
+-
+ job = job_alloc(xe_exec_queue_is_parallel(q) || is_migration);
+ if (!job)
+ return ERR_PTR(-ENOMEM);
+@@ -111,43 +118,25 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ if (err)
+ goto err_free;
+
+- if (!xe_exec_queue_is_parallel(q)) {
+- job->fence = xe_lrc_create_seqno_fence(q->lrc);
+- if (IS_ERR(job->fence)) {
+- err = PTR_ERR(job->fence);
+- goto err_sched_job;
+- }
+- job->lrc_seqno = job->fence->seqno;
+- } else {
+- struct dma_fence_array *cf;
++ for (i = 0; i < q->width; ++i) {
++ struct dma_fence *fence = xe_lrc_alloc_seqno_fence();
++ struct dma_fence_chain *chain;
+
+- fences = kmalloc_array(q->width, sizeof(*fences), GFP_KERNEL);
+- if (!fences) {
+- err = -ENOMEM;
++ if (IS_ERR(fence)) {
++ err = PTR_ERR(fence);
+ goto err_sched_job;
+ }
++ job->ptrs[i].lrc_fence = fence;
+
+- for (j = 0; j < q->width; ++j) {
+- fences[j] = xe_lrc_create_seqno_fence(q->lrc + j);
+- if (IS_ERR(fences[j])) {
+- err = PTR_ERR(fences[j]);
+- goto err_fences;
+- }
+- if (!j)
+- job->lrc_seqno = fences[0]->seqno;
+- }
++ if (i + 1 == q->width)
++ continue;
+
+- cf = dma_fence_array_create(q->width, fences,
+- q->parallel.composite_fence_ctx,
+- q->parallel.composite_fence_seqno++,
+- false);
+- if (!cf) {
+- --q->parallel.composite_fence_seqno;
++ chain = dma_fence_chain_alloc();
++ if (!chain) {
+ err = -ENOMEM;
+- goto err_fences;
++ goto err_sched_job;
+ }
+-
+- job->fence = &cf->base;
++ job->ptrs[i].chain_fence = chain;
+ }
+
+ width = q->width;
+@@ -155,19 +144,14 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ width = 2;
+
+ for (i = 0; i < width; ++i)
+- job->batch_addr[i] = batch_addr[i];
++ job->ptrs[i].batch_addr = batch_addr[i];
+
+ xe_pm_runtime_get_noresume(job_to_xe(job));
+ trace_xe_sched_job_create(job);
+ return job;
+
+-err_fences:
+- for (j = j - 1; j >= 0; --j) {
+- --q->lrc[j].fence_ctx.next_seqno;
+- dma_fence_put(fences[j]);
+- }
+- kfree(fences);
+ err_sched_job:
++ xe_sched_job_free_fences(job);
+ drm_sched_job_cleanup(&job->drm);
+ err_free:
+ xe_exec_queue_put(q);
+@@ -188,6 +172,7 @@ void xe_sched_job_destroy(struct kref *ref)
+ container_of(ref, struct xe_sched_job, refcount);
+ struct xe_device *xe = job_to_xe(job);
+
++ xe_sched_job_free_fences(job);
+ xe_exec_queue_put(job->q);
+ dma_fence_put(job->fence);
+ drm_sched_job_cleanup(&job->drm);
+@@ -195,27 +180,32 @@ void xe_sched_job_destroy(struct kref *ref)
+ xe_pm_runtime_put(xe);
+ }
+
+-void xe_sched_job_set_error(struct xe_sched_job *job, int error)
++/* Set the error status under the fence to avoid racing with signaling */
++static bool xe_fence_set_error(struct dma_fence *fence, int error)
+ {
+- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags))
+- return;
++ unsigned long irq_flags;
++ bool signaled;
++
++ spin_lock_irqsave(fence->lock, irq_flags);
++ signaled = test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags);
++ if (!signaled)
++ dma_fence_set_error(fence, error);
++ spin_unlock_irqrestore(fence->lock, irq_flags);
+
+- dma_fence_set_error(job->fence, error);
++ return signaled;
++}
+
+- if (dma_fence_is_array(job->fence)) {
+- struct dma_fence_array *array =
+- to_dma_fence_array(job->fence);
+- struct dma_fence **child = array->fences;
+- unsigned int nchild = array->num_fences;
++void xe_sched_job_set_error(struct xe_sched_job *job, int error)
++{
++ if (xe_fence_set_error(job->fence, error))
++ return;
+
+- do {
+- struct dma_fence *current_fence = *child++;
++ if (dma_fence_is_chain(job->fence)) {
++ struct dma_fence *iter;
+
+- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+- ¤t_fence->flags))
+- continue;
+- dma_fence_set_error(current_fence, error);
+- } while (--nchild);
++ dma_fence_chain_for_each(iter, job->fence)
++ xe_fence_set_error(dma_fence_chain_contained(iter),
++ error);
+ }
+
+ trace_xe_sched_job_set_error(job);
+@@ -230,7 +220,7 @@ bool xe_sched_job_started(struct xe_sched_job *job)
+
+ return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job),
+ xe_lrc_start_seqno(lrc),
+- dma_fence_array_first(job->fence)->ops);
++ dma_fence_chain_contained(job->fence)->ops);
+ }
+
+ bool xe_sched_job_completed(struct xe_sched_job *job)
+@@ -244,13 +234,24 @@ bool xe_sched_job_completed(struct xe_sched_job *job)
+
+ return !__dma_fence_is_later(xe_sched_job_lrc_seqno(job),
+ xe_lrc_seqno(lrc),
+- dma_fence_array_first(job->fence)->ops);
++ dma_fence_chain_contained(job->fence)->ops);
+ }
+
+ void xe_sched_job_arm(struct xe_sched_job *job)
+ {
+ struct xe_exec_queue *q = job->q;
++ struct dma_fence *fence, *prev;
+ struct xe_vm *vm = q->vm;
++ u64 seqno = 0;
++ int i;
++
++ /* Migration and kernel engines have their own locking */
++ if (IS_ENABLED(CONFIG_LOCKDEP) &&
++ !(q->flags & (EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_VM))) {
++ lockdep_assert_held(&q->vm->lock);
++ if (!xe_vm_in_lr_mode(q->vm))
++ xe_vm_assert_held(q->vm);
++ }
+
+ if (vm && !xe_sched_job_is_migration(q) && !xe_vm_in_lr_mode(vm) &&
+ (vm->batch_invalidate_tlb || vm->tlb_flush_seqno != q->tlb_flush_seqno)) {
+@@ -259,6 +260,27 @@ void xe_sched_job_arm(struct xe_sched_job *job)
+ job->ring_ops_flush_tlb = true;
+ }
+
++ /* Arm the pre-allocated fences */
++ for (i = 0; i < q->width; prev = fence, ++i) {
++ struct dma_fence_chain *chain;
++
++ fence = job->ptrs[i].lrc_fence;
++ xe_lrc_init_seqno_fence(&q->lrc[i], fence);
++ job->ptrs[i].lrc_fence = NULL;
++ if (!i) {
++ job->lrc_seqno = fence->seqno;
++ continue;
++ } else {
++ xe_assert(gt_to_xe(q->gt), job->lrc_seqno == fence->seqno);
++ }
++
++ chain = job->ptrs[i - 1].chain_fence;
++ dma_fence_chain_init(chain, prev, fence, seqno++);
++ job->ptrs[i - 1].chain_fence = NULL;
++ fence = &chain->base;
++ }
++
++ job->fence = fence;
+ drm_sched_job_arm(&job->drm);
+ }
+
+@@ -318,7 +340,8 @@ xe_sched_job_snapshot_capture(struct xe_sched_job *job)
+
+ snapshot->batch_addr_len = q->width;
+ for (i = 0; i < q->width; i++)
+- snapshot->batch_addr[i] = xe_device_uncanonicalize_addr(xe, job->batch_addr[i]);
++ snapshot->batch_addr[i] =
++ xe_device_uncanonicalize_addr(xe, job->ptrs[i].batch_addr);
+
+ return snapshot;
+ }
+diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h
+index 990ddac55ed62..0d3f76fb05cea 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job_types.h
++++ b/drivers/gpu/drm/xe/xe_sched_job_types.h
+@@ -11,6 +11,20 @@
+ #include <drm/gpu_scheduler.h>
+
+ struct xe_exec_queue;
++struct dma_fence;
++struct dma_fence_chain;
++
++/**
++ * struct xe_job_ptrs - Per hw engine instance data
++ */
++struct xe_job_ptrs {
++ /** @lrc_fence: Pre-allocated uinitialized lrc fence.*/
++ struct dma_fence *lrc_fence;
++ /** @chain_fence: Pre-allocated ninitialized fence chain node. */
++ struct dma_fence_chain *chain_fence;
++ /** @batch_addr: Batch buffer address. */
++ u64 batch_addr;
++};
+
+ /**
+ * struct xe_sched_job - XE schedule job (batch buffer tracking)
+@@ -43,8 +57,8 @@ struct xe_sched_job {
+ u32 migrate_flush_flags;
+ /** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */
+ bool ring_ops_flush_tlb;
+- /** @batch_addr: batch buffer address of job */
+- u64 batch_addr[];
++ /** @ptrs: per instance pointers. */
++ struct xe_job_ptrs ptrs[];
+ };
+
+ struct xe_sched_job_snapshot {
+diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
+index 6c6cecc58f63b..450f407c66e8f 100644
+--- a/drivers/gpu/drm/xe/xe_trace.h
++++ b/drivers/gpu/drm/xe/xe_trace.h
+@@ -272,7 +272,7 @@ DECLARE_EVENT_CLASS(xe_sched_job,
+ __entry->flags = job->q->flags;
+ __entry->error = job->fence->error;
+ __entry->fence = job->fence;
+- __entry->batch_addr = (u64)job->batch_addr[0];
++ __entry->batch_addr = (u64)job->ptrs[0].batch_addr;
+ ),
+
+ TP_printk("fence=%p, seqno=%u, lrc_seqno=%u, guc_id=%d, batch_addr=0x%012llx, guc_state=0x%x, flags=0x%x, error=%d",
+--
+2.43.0
+
--- /dev/null
+From d666baaf55a89bec4b4780d5623ad813276d5322 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Aug 2024 02:47:30 +0000
+Subject: drm/xe: Fix missing workqueue destroy in xe_gt_pagefault
+
+From: Stuart Summers <stuart.summers@intel.com>
+
+[ Upstream commit a6f78359ac75f24cac3c1bdd753c49c1877bcd82 ]
+
+On driver reload we never free up the memory for the pagefault and
+access counter workqueues. Add those destroy calls here.
+
+Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
+Signed-off-by: Stuart Summers <stuart.summers@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/c9a951505271dc3a7aee76de7656679f69c11518.1723862633.git.stuart.summers@intel.com
+(cherry picked from commit 7586fc52b14e0b8edd0d1f8a434e0de2078b7b2b)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt_pagefault.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
+index fa9e9853c53ba..67e8efcaa93f1 100644
+--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
++++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
+@@ -402,6 +402,18 @@ static void pf_queue_work_func(struct work_struct *w)
+
+ static void acc_queue_work_func(struct work_struct *w);
+
++static void pagefault_fini(void *arg)
++{
++ struct xe_gt *gt = arg;
++ struct xe_device *xe = gt_to_xe(gt);
++
++ if (!xe->info.has_usm)
++ return;
++
++ destroy_workqueue(gt->usm.acc_wq);
++ destroy_workqueue(gt->usm.pf_wq);
++}
++
+ int xe_gt_pagefault_init(struct xe_gt *gt)
+ {
+ struct xe_device *xe = gt_to_xe(gt);
+@@ -429,10 +441,12 @@ int xe_gt_pagefault_init(struct xe_gt *gt)
+ gt->usm.acc_wq = alloc_workqueue("xe_gt_access_counter_work_queue",
+ WQ_UNBOUND | WQ_HIGHPRI,
+ NUM_ACC_QUEUE);
+- if (!gt->usm.acc_wq)
++ if (!gt->usm.acc_wq) {
++ destroy_workqueue(gt->usm.pf_wq);
+ return -ENOMEM;
++ }
+
+- return 0;
++ return devm_add_action_or_reset(xe->drm.dev, pagefault_fini, gt);
+ }
+
+ void xe_gt_pagefault_reset(struct xe_gt *gt)
+--
+2.43.0
+
--- /dev/null
+From d7b9cf1dcdf98c38c940215fdc3f639028630070 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jul 2024 14:53:09 -0700
+Subject: drm/xe: Fix opregion leak
+
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+
+[ Upstream commit f4b2a0ae1a31fd3d1b5ca18ee08319b479cf9b5f ]
+
+Being part o the display, ideally the setup and cleanup would be done by
+display itself. However this is a bigger refactor that needs to be done
+on both i915 and xe. For now, just fix the leak:
+
+unreferenced object 0xffff8881a0300008 (size 192):
+ comm "modprobe", pid 4354, jiffies 4295647021
+ hex dump (first 32 bytes):
+ 00 00 87 27 81 88 ff ff 18 80 9b 00 00 c9 ff ff ...'............
+ 18 81 9b 00 00 c9 ff ff 00 00 00 00 00 00 00 00 ................
+ backtrace (crc 99260e31):
+ [<ffffffff823ce65b>] kmemleak_alloc+0x4b/0x80
+ [<ffffffff81493be2>] kmalloc_trace_noprof+0x312/0x3d0
+ [<ffffffffa1345679>] intel_opregion_setup+0x89/0x700 [xe]
+ [<ffffffffa125bfaf>] xe_display_init_noirq+0x2f/0x90 [xe]
+ [<ffffffffa1199ec3>] xe_device_probe+0x7a3/0xbf0 [xe]
+ [<ffffffffa11f3713>] xe_pci_probe+0x333/0x5b0 [xe]
+ [<ffffffff81af6be8>] local_pci_probe+0x48/0xb0
+ [<ffffffff81af8778>] pci_device_probe+0xc8/0x280
+ [<ffffffff81d09048>] really_probe+0xf8/0x390
+ [<ffffffff81d0937a>] __driver_probe_device+0x8a/0x170
+ [<ffffffff81d09503>] driver_probe_device+0x23/0xb0
+ [<ffffffff81d097b7>] __driver_attach+0xc7/0x190
+ [<ffffffff81d0628d>] bus_for_each_dev+0x7d/0xd0
+ [<ffffffff81d0851e>] driver_attach+0x1e/0x30
+ [<ffffffff81d07ac7>] bus_add_driver+0x117/0x250
+
+Fixes: 44e694958b95 ("drm/xe/display: Implement display support")
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240724215309.644423-1-lucas.demarchi@intel.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+(cherry picked from commit 6f4e43a2f771b737d991142ec4f6d4b7ff31fbb4)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/display/xe_display.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c
+index 6ecaf83264d55..7cdc03dc40ed9 100644
+--- a/drivers/gpu/drm/xe/display/xe_display.c
++++ b/drivers/gpu/drm/xe/display/xe_display.c
+@@ -134,6 +134,7 @@ static void xe_display_fini_noirq(struct drm_device *dev, void *dummy)
+ return;
+
+ intel_display_driver_remove_noirq(xe);
++ intel_opregion_cleanup(xe);
+ }
+
+ int xe_display_init_noirq(struct xe_device *xe)
+@@ -159,8 +160,10 @@ int xe_display_init_noirq(struct xe_device *xe)
+ intel_display_device_info_runtime_init(xe);
+
+ err = intel_display_driver_probe_noirq(xe);
+- if (err)
++ if (err) {
++ intel_opregion_cleanup(xe);
+ return err;
++ }
+
+ return drmm_add_action_or_reset(&xe->drm, xe_display_fini_noirq, NULL);
+ }
+--
+2.43.0
+
--- /dev/null
+From 459c473d917a44e21abc18718853f4f24bf64745 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Aug 2024 16:28:30 -0700
+Subject: drm/xe: Fix tile fini sequence
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 15939ca77d4424f736e1e4953b4da2351cc9689d ]
+
+Only set tile->mmio.regs to NULL if not the root tile in tile_fini. The
+root tile mmio regs is setup ealier in MMIO init thus it should be set
+to NULL in mmio_fini.
+
+Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Reviewed-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240809232830.3302251-1-matthew.brost@intel.com
+(cherry picked from commit 3396900aa273903639a1792afa4d23dc09bec291)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_mmio.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
+index 9d8fafdf51453..beb4e276ba845 100644
+--- a/drivers/gpu/drm/xe/xe_mmio.c
++++ b/drivers/gpu/drm/xe/xe_mmio.c
+@@ -355,7 +355,8 @@ static void tiles_fini(void *arg)
+ int id;
+
+ for_each_tile(tile, xe, id)
+- tile->mmio.regs = NULL;
++ if (tile != xe_device_get_root_tile(xe))
++ tile->mmio.regs = NULL;
+ }
+
+ int xe_mmio_probe_tiles(struct xe_device *xe)
+@@ -416,9 +417,11 @@ int xe_mmio_probe_tiles(struct xe_device *xe)
+ static void mmio_fini(void *arg)
+ {
+ struct xe_device *xe = arg;
++ struct xe_tile *root_tile = xe_device_get_root_tile(xe);
+
+ pci_iounmap(to_pci_dev(xe->drm.dev), xe->mmio.regs);
+ xe->mmio.regs = NULL;
++ root_tile->mmio.regs = NULL;
+ }
+
+ int xe_mmio_init(struct xe_device *xe)
+--
+2.43.0
+
--- /dev/null
+From 3af646198a591741c8ac519ec6c8f16acf3e4a51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 13:23:09 -0700
+Subject: drm/xe: Free job before xe_exec_queue_put
+
+From: Matthew Brost <matthew.brost@intel.com>
+
+[ Upstream commit 9e7f30563677fbeff62d368d5d2a5ac7aaa9746a ]
+
+Free job depends on job->vm being valid, the last xe_exec_queue_put can
+destroy the VM. Prevent UAF by freeing job before xe_exec_queue_put.
+
+Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
+Reviewed-by: Jagmeet Randhawa <jagmeet.randhawa@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240820202309.1260755-1-matthew.brost@intel.com
+(cherry picked from commit 32a42c93b74c8ca6d0915ea3eba21bceff53042f)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_sched_job.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
+index 29f3201d7dfac..2b064680abb96 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job.c
++++ b/drivers/gpu/drm/xe/xe_sched_job.c
+@@ -171,12 +171,13 @@ void xe_sched_job_destroy(struct kref *ref)
+ struct xe_sched_job *job =
+ container_of(ref, struct xe_sched_job, refcount);
+ struct xe_device *xe = job_to_xe(job);
++ struct xe_exec_queue *q = job->q;
+
+ xe_sched_job_free_fences(job);
+- xe_exec_queue_put(job->q);
+ dma_fence_put(job->fence);
+ drm_sched_job_cleanup(&job->drm);
+ job_free(job);
++ xe_exec_queue_put(q);
+ xe_pm_runtime_put(xe);
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 3ee036f86d3041441eeda0b64c2f4920cf53464f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 May 2024 11:21:57 +0100
+Subject: drm/xe/mmio: move mmio_fini over to devm
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+[ Upstream commit a0b834c8957a7d2848face008a12382a0ad11ffc ]
+
+Not valid to touch mmio once the device is removed, so make sure we
+unmap on removal and not just when driver instance goes away. Also set
+the mmio pointers to NULL to hopefully catch such issues more easily.
+
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Andrzej Hajda <andrzej.hajda@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240522102143.128069-32-matthew.auld@intel.com
+Stable-dep-of: 15939ca77d44 ("drm/xe: Fix tile fini sequence")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_mmio.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
+index 334637511e750..2ebb2f0d6874e 100644
+--- a/drivers/gpu/drm/xe/xe_mmio.c
++++ b/drivers/gpu/drm/xe/xe_mmio.c
+@@ -386,13 +386,16 @@ void xe_mmio_probe_tiles(struct xe_device *xe)
+ }
+ }
+
+-static void mmio_fini(struct drm_device *drm, void *arg)
++static void mmio_fini(void *arg)
+ {
+ struct xe_device *xe = arg;
+
+ pci_iounmap(to_pci_dev(xe->drm.dev), xe->mmio.regs);
+ if (xe->mem.vram.mapping)
+ iounmap(xe->mem.vram.mapping);
++
++ xe->mem.vram.mapping = NULL;
++ xe->mmio.regs = NULL;
+ }
+
+ int xe_mmio_init(struct xe_device *xe)
+@@ -417,7 +420,7 @@ int xe_mmio_init(struct xe_device *xe)
+ root_tile->mmio.size = SZ_16M;
+ root_tile->mmio.regs = xe->mmio.regs;
+
+- return drmm_add_action_or_reset(&xe->drm, mmio_fini, xe);
++ return devm_add_action_or_reset(xe->drm.dev, mmio_fini, xe);
+ }
+
+ u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg)
+--
+2.43.0
+
--- /dev/null
+From c658360775890856ec80e584a44a87d25429aeee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 May 2024 13:01:01 -0400
+Subject: drm/xe: Relax runtime pm protection during execution
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rodrigo Vivi <rodrigo.vivi@intel.com>
+
+[ Upstream commit ad1e331fc451a2cffc72ae193b843682ce237e24 ]
+
+Limit the protection only during moments of actual job execution,
+and introduce protection for guc submit fini, which is currently
+unprotected due to the absence of exec_queue life protection.
+
+In the regular use case scenario, user space will create an
+exec queue, and keep it alive to reuse that until it is done
+with that kind of workload.
+
+For the regular desktop cases, it means that the exec_queue
+is alive even on idle scenarios where display goes off. This
+is unacceptable since this would entirely block runtime PM
+indefinitely, blocking deeper Package-C state. This would be
+a waste drainage of power.
+
+Cc: Matthew Brost <matthew.brost@intel.com>
+Tested-by: Francois Dugast <francois.dugast@intel.com>
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240522170105.327472-3-rodrigo.vivi@intel.com
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_exec_queue.c | 14 --------------
+ drivers/gpu/drm/xe/xe_guc_submit.c | 3 +++
+ drivers/gpu/drm/xe/xe_sched_job.c | 10 +++-------
+ 3 files changed, 6 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
+index 395de93579fa6..33b03605a1d15 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue.c
++++ b/drivers/gpu/drm/xe/xe_exec_queue.c
+@@ -106,7 +106,6 @@ static struct xe_exec_queue *__xe_exec_queue_alloc(struct xe_device *xe,
+
+ static int __xe_exec_queue_init(struct xe_exec_queue *q)
+ {
+- struct xe_device *xe = gt_to_xe(q->gt);
+ int i, err;
+
+ for (i = 0; i < q->width; ++i) {
+@@ -119,17 +118,6 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
+ if (err)
+ goto err_lrc;
+
+- /*
+- * Normally the user vm holds an rpm ref to keep the device
+- * awake, and the context holds a ref for the vm, however for
+- * some engines we use the kernels migrate vm underneath which offers no
+- * such rpm ref, or we lack a vm. Make sure we keep a ref here, so we
+- * can perform GuC CT actions when needed. Caller is expected to have
+- * already grabbed the rpm ref outside any sensitive locks.
+- */
+- if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && (q->flags & EXEC_QUEUE_FLAG_VM || !q->vm))
+- xe_pm_runtime_get_noresume(xe);
+-
+ return 0;
+
+ err_lrc:
+@@ -216,8 +204,6 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
+
+ for (i = 0; i < q->width; ++i)
+ xe_lrc_finish(q->lrc + i);
+- if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && (q->flags & EXEC_QUEUE_FLAG_VM || !q->vm))
+- xe_pm_runtime_put(gt_to_xe(q->gt));
+ __xe_exec_queue_free(q);
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index 0f42971ff0a83..8c75791cbc4fb 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -35,6 +35,7 @@
+ #include "xe_macros.h"
+ #include "xe_map.h"
+ #include "xe_mocs.h"
++#include "xe_pm.h"
+ #include "xe_ring_ops_types.h"
+ #include "xe_sched_job.h"
+ #include "xe_trace.h"
+@@ -1011,6 +1012,7 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)
+ struct xe_exec_queue *q = ge->q;
+ struct xe_guc *guc = exec_queue_to_guc(q);
+
++ xe_pm_runtime_get(guc_to_xe(guc));
+ trace_xe_exec_queue_destroy(q);
+
+ if (xe_exec_queue_is_lr(q))
+@@ -1021,6 +1023,7 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)
+
+ kfree(ge);
+ xe_exec_queue_fini(q);
++ xe_pm_runtime_put(guc_to_xe(guc));
+ }
+
+ static void guc_exec_queue_fini_async(struct xe_exec_queue *q)
+diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
+index cd8a2fba54389..a4e030f5e019a 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job.c
++++ b/drivers/gpu/drm/xe/xe_sched_job.c
+@@ -158,11 +158,7 @@ struct xe_sched_job *xe_sched_job_create(struct xe_exec_queue *q,
+ for (i = 0; i < width; ++i)
+ job->batch_addr[i] = batch_addr[i];
+
+- /* All other jobs require a VM to be open which has a ref */
+- if (unlikely(q->flags & EXEC_QUEUE_FLAG_KERNEL))
+- xe_pm_runtime_get_noresume(job_to_xe(job));
+- xe_device_assert_mem_access(job_to_xe(job));
+-
++ xe_pm_runtime_get_noresume(job_to_xe(job));
+ trace_xe_sched_job_create(job);
+ return job;
+
+@@ -191,13 +187,13 @@ void xe_sched_job_destroy(struct kref *ref)
+ {
+ struct xe_sched_job *job =
+ container_of(ref, struct xe_sched_job, refcount);
++ struct xe_device *xe = job_to_xe(job);
+
+- if (unlikely(job->q->flags & EXEC_QUEUE_FLAG_KERNEL))
+- xe_pm_runtime_put(job_to_xe(job));
+ xe_exec_queue_put(job->q);
+ dma_fence_put(job->fence);
+ drm_sched_job_cleanup(&job->drm);
+ job_free(job);
++ xe_pm_runtime_put(xe);
+ }
+
+ void xe_sched_job_set_error(struct xe_sched_job *job, int error)
+--
+2.43.0
+
--- /dev/null
+From aa27bef6d4f08db256a4d1b27313e91f98f75fc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 May 2024 11:21:58 +0100
+Subject: drm/xe: reset mmio mappings with devm
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+[ Upstream commit c7117419784f612d59ee565145f722e8b5541fe6 ]
+
+Set our various mmio mappings to NULL. This should make it easier to
+catch something rogue trying to mess with mmio after device removal. For
+example, we might unmap everything and then start hitting some mmio
+address which has already been unmamped by us and then remapped by
+something else, causing all kinds of carnage.
+
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Cc: Andrzej Hajda <andrzej.hajda@intel.com>
+Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Reviewed-by: Andrzej Hajda <andrzej.hajda@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240522102143.128069-33-matthew.auld@intel.com
+Stable-dep-of: 15939ca77d44 ("drm/xe: Fix tile fini sequence")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_device.c | 4 +++-
+ drivers/gpu/drm/xe/xe_mmio.c | 35 ++++++++++++++++++++++++++++------
+ drivers/gpu/drm/xe/xe_mmio.h | 2 +-
+ 3 files changed, 33 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
+index 5ef9b50a20d01..a1cbdafbff75e 100644
+--- a/drivers/gpu/drm/xe/xe_device.c
++++ b/drivers/gpu/drm/xe/xe_device.c
+@@ -551,7 +551,9 @@ int xe_device_probe(struct xe_device *xe)
+ if (err)
+ return err;
+
+- xe_mmio_probe_tiles(xe);
++ err = xe_mmio_probe_tiles(xe);
++ if (err)
++ return err;
+
+ xe_ttm_sys_mgr_init(xe);
+
+diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c
+index 2ebb2f0d6874e..9d8fafdf51453 100644
+--- a/drivers/gpu/drm/xe/xe_mmio.c
++++ b/drivers/gpu/drm/xe/xe_mmio.c
+@@ -254,6 +254,21 @@ static int xe_mmio_tile_vram_size(struct xe_tile *tile, u64 *vram_size,
+ return xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
+ }
+
++static void vram_fini(void *arg)
++{
++ struct xe_device *xe = arg;
++ struct xe_tile *tile;
++ int id;
++
++ if (xe->mem.vram.mapping)
++ iounmap(xe->mem.vram.mapping);
++
++ xe->mem.vram.mapping = NULL;
++
++ for_each_tile(tile, xe, id)
++ tile->mem.vram.mapping = NULL;
++}
++
+ int xe_mmio_probe_vram(struct xe_device *xe)
+ {
+ struct xe_tile *tile;
+@@ -330,10 +345,20 @@ int xe_mmio_probe_vram(struct xe_device *xe)
+ drm_info(&xe->drm, "Available VRAM: %pa, %pa\n", &xe->mem.vram.io_start,
+ &available_size);
+
+- return 0;
++ return devm_add_action_or_reset(xe->drm.dev, vram_fini, xe);
+ }
+
+-void xe_mmio_probe_tiles(struct xe_device *xe)
++static void tiles_fini(void *arg)
++{
++ struct xe_device *xe = arg;
++ struct xe_tile *tile;
++ int id;
++
++ for_each_tile(tile, xe, id)
++ tile->mmio.regs = NULL;
++}
++
++int xe_mmio_probe_tiles(struct xe_device *xe)
+ {
+ size_t tile_mmio_size = SZ_16M, tile_mmio_ext_size = xe->info.tile_mmio_ext_size;
+ u8 id, tile_count = xe->info.tile_count;
+@@ -384,6 +409,8 @@ void xe_mmio_probe_tiles(struct xe_device *xe)
+ regs += tile_mmio_ext_size;
+ }
+ }
++
++ return devm_add_action_or_reset(xe->drm.dev, tiles_fini, xe);
+ }
+
+ static void mmio_fini(void *arg)
+@@ -391,10 +418,6 @@ static void mmio_fini(void *arg)
+ struct xe_device *xe = arg;
+
+ pci_iounmap(to_pci_dev(xe->drm.dev), xe->mmio.regs);
+- if (xe->mem.vram.mapping)
+- iounmap(xe->mem.vram.mapping);
+-
+- xe->mem.vram.mapping = NULL;
+ xe->mmio.regs = NULL;
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_mmio.h b/drivers/gpu/drm/xe/xe_mmio.h
+index a3cd7b3036c73..a929d090bb2f1 100644
+--- a/drivers/gpu/drm/xe/xe_mmio.h
++++ b/drivers/gpu/drm/xe/xe_mmio.h
+@@ -21,7 +21,7 @@ struct xe_device;
+ #define LMEM_BAR 2
+
+ int xe_mmio_init(struct xe_device *xe);
+-void xe_mmio_probe_tiles(struct xe_device *xe);
++int xe_mmio_probe_tiles(struct xe_device *xe);
+
+ u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg);
+ u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg);
+--
+2.43.0
+
--- /dev/null
+From 3ab821a97aff3ace512b8751120aa396f747ab68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 May 2024 15:59:09 +0200
+Subject: drm/xe: Split lrc seqno fence creation up
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+
+[ Upstream commit e183910ae4015214475b3248ce0b4c70f104f254 ]
+
+Since sometimes a lock is required to initialize a seqno fence,
+and it might be desirable not to hold that lock while performing
+memory allocations, split the lrc seqno fence creation up into an
+allocation phase and an initialization phase.
+
+Since lrc seqno fences under the hood are hw_fences, do the same
+for these and remove the xe_hw_fence_create() function since it
+is not used anymore.
+
+Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Reviewed-by: Matthew Brost <matthew.brost@intel.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240527135912.152156-3-thomas.hellstrom@linux.intel.com
+Stable-dep-of: 9e7f30563677 ("drm/xe: Free job before xe_exec_queue_put")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_hw_fence.c | 59 +++++++++++++++++++++++++-------
+ drivers/gpu/drm/xe/xe_hw_fence.h | 7 ++--
+ drivers/gpu/drm/xe/xe_lrc.c | 48 ++++++++++++++++++++++++--
+ drivers/gpu/drm/xe/xe_lrc.h | 3 ++
+ 4 files changed, 101 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c
+index f872ef1031272..35c0063a831af 100644
+--- a/drivers/gpu/drm/xe/xe_hw_fence.c
++++ b/drivers/gpu/drm/xe/xe_hw_fence.c
+@@ -208,23 +208,58 @@ static struct xe_hw_fence *to_xe_hw_fence(struct dma_fence *fence)
+ return container_of(fence, struct xe_hw_fence, dma);
+ }
+
+-struct xe_hw_fence *xe_hw_fence_create(struct xe_hw_fence_ctx *ctx,
+- struct iosys_map seqno_map)
++/**
++ * xe_hw_fence_alloc() - Allocate an hw fence.
++ *
++ * Allocate but don't initialize an hw fence.
++ *
++ * Return: Pointer to the allocated fence or
++ * negative error pointer on error.
++ */
++struct dma_fence *xe_hw_fence_alloc(void)
+ {
+- struct xe_hw_fence *fence;
++ struct xe_hw_fence *hw_fence = fence_alloc();
+
+- fence = fence_alloc();
+- if (!fence)
++ if (!hw_fence)
+ return ERR_PTR(-ENOMEM);
+
+- fence->ctx = ctx;
+- fence->seqno_map = seqno_map;
+- INIT_LIST_HEAD(&fence->irq_link);
++ return &hw_fence->dma;
++}
+
+- dma_fence_init(&fence->dma, &xe_hw_fence_ops, &ctx->irq->lock,
+- ctx->dma_fence_ctx, ctx->next_seqno++);
++/**
++ * xe_hw_fence_free() - Free an hw fence.
++ * @fence: Pointer to the fence to free.
++ *
++ * Frees an hw fence that hasn't yet been
++ * initialized.
++ */
++void xe_hw_fence_free(struct dma_fence *fence)
++{
++ fence_free(&fence->rcu);
++}
+
+- trace_xe_hw_fence_create(fence);
++/**
++ * xe_hw_fence_init() - Initialize an hw fence.
++ * @fence: Pointer to the fence to initialize.
++ * @ctx: Pointer to the struct xe_hw_fence_ctx fence context.
++ * @seqno_map: Pointer to the map into where the seqno is blitted.
++ *
++ * Initializes a pre-allocated hw fence.
++ * After initialization, the fence is subject to normal
++ * dma-fence refcounting.
++ */
++void xe_hw_fence_init(struct dma_fence *fence, struct xe_hw_fence_ctx *ctx,
++ struct iosys_map seqno_map)
++{
++ struct xe_hw_fence *hw_fence =
++ container_of(fence, typeof(*hw_fence), dma);
++
++ hw_fence->ctx = ctx;
++ hw_fence->seqno_map = seqno_map;
++ INIT_LIST_HEAD(&hw_fence->irq_link);
++
++ dma_fence_init(fence, &xe_hw_fence_ops, &ctx->irq->lock,
++ ctx->dma_fence_ctx, ctx->next_seqno++);
+
+- return fence;
++ trace_xe_hw_fence_create(hw_fence);
+ }
+diff --git a/drivers/gpu/drm/xe/xe_hw_fence.h b/drivers/gpu/drm/xe/xe_hw_fence.h
+index cfe5fd603787e..f13a1c4982c73 100644
+--- a/drivers/gpu/drm/xe/xe_hw_fence.h
++++ b/drivers/gpu/drm/xe/xe_hw_fence.h
+@@ -24,7 +24,10 @@ void xe_hw_fence_ctx_init(struct xe_hw_fence_ctx *ctx, struct xe_gt *gt,
+ struct xe_hw_fence_irq *irq, const char *name);
+ void xe_hw_fence_ctx_finish(struct xe_hw_fence_ctx *ctx);
+
+-struct xe_hw_fence *xe_hw_fence_create(struct xe_hw_fence_ctx *ctx,
+- struct iosys_map seqno_map);
++struct dma_fence *xe_hw_fence_alloc(void);
+
++void xe_hw_fence_free(struct dma_fence *fence);
++
++void xe_hw_fence_init(struct dma_fence *fence, struct xe_hw_fence_ctx *ctx,
++ struct iosys_map seqno_map);
+ #endif
+diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
+index d7bf7bc9dc145..995f47eb365c3 100644
+--- a/drivers/gpu/drm/xe/xe_lrc.c
++++ b/drivers/gpu/drm/xe/xe_lrc.c
+@@ -901,10 +901,54 @@ u32 xe_lrc_seqno_ggtt_addr(struct xe_lrc *lrc)
+ return __xe_lrc_seqno_ggtt_addr(lrc);
+ }
+
++/**
++ * xe_lrc_alloc_seqno_fence() - Allocate an lrc seqno fence.
++ *
++ * Allocate but don't initialize an lrc seqno fence.
++ *
++ * Return: Pointer to the allocated fence or
++ * negative error pointer on error.
++ */
++struct dma_fence *xe_lrc_alloc_seqno_fence(void)
++{
++ return xe_hw_fence_alloc();
++}
++
++/**
++ * xe_lrc_free_seqno_fence() - Free an lrc seqno fence.
++ * @fence: Pointer to the fence to free.
++ *
++ * Frees an lrc seqno fence that hasn't yet been
++ * initialized.
++ */
++void xe_lrc_free_seqno_fence(struct dma_fence *fence)
++{
++ xe_hw_fence_free(fence);
++}
++
++/**
++ * xe_lrc_init_seqno_fence() - Initialize an lrc seqno fence.
++ * @lrc: Pointer to the lrc.
++ * @fence: Pointer to the fence to initialize.
++ *
++ * Initializes a pre-allocated lrc seqno fence.
++ * After initialization, the fence is subject to normal
++ * dma-fence refcounting.
++ */
++void xe_lrc_init_seqno_fence(struct xe_lrc *lrc, struct dma_fence *fence)
++{
++ xe_hw_fence_init(fence, &lrc->fence_ctx, __xe_lrc_seqno_map(lrc));
++}
++
+ struct dma_fence *xe_lrc_create_seqno_fence(struct xe_lrc *lrc)
+ {
+- return &xe_hw_fence_create(&lrc->fence_ctx,
+- __xe_lrc_seqno_map(lrc))->dma;
++ struct dma_fence *fence = xe_lrc_alloc_seqno_fence();
++
++ if (IS_ERR(fence))
++ return fence;
++
++ xe_lrc_init_seqno_fence(lrc, fence);
++ return fence;
+ }
+
+ s32 xe_lrc_seqno(struct xe_lrc *lrc)
+diff --git a/drivers/gpu/drm/xe/xe_lrc.h b/drivers/gpu/drm/xe/xe_lrc.h
+index d32fa31faa2cf..f57c5836dab87 100644
+--- a/drivers/gpu/drm/xe/xe_lrc.h
++++ b/drivers/gpu/drm/xe/xe_lrc.h
+@@ -38,6 +38,9 @@ void xe_lrc_write_ctx_reg(struct xe_lrc *lrc, int reg_nr, u32 val);
+ u64 xe_lrc_descriptor(struct xe_lrc *lrc);
+
+ u32 xe_lrc_seqno_ggtt_addr(struct xe_lrc *lrc);
++struct dma_fence *xe_lrc_alloc_seqno_fence(void);
++void xe_lrc_free_seqno_fence(struct dma_fence *fence);
++void xe_lrc_init_seqno_fence(struct xe_lrc *lrc, struct dma_fence *fence);
+ struct dma_fence *xe_lrc_create_seqno_fence(struct xe_lrc *lrc);
+ s32 xe_lrc_seqno(struct xe_lrc *lrc);
+
+--
+2.43.0
+
--- /dev/null
+From 6513e8ece426ad00a0c34fe6b9d700d2cc930213 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 18:31:58 -0600
+Subject: io_uring/kbuf: sanitize peek buffer setup
+
+From: Jens Axboe <axboe@kernel.dk>
+
+[ Upstream commit e0ee967630c8ee67bb47a5b38d235cd5a8789c48 ]
+
+Harden the buffer peeking a bit, by adding a sanity check for it having
+a valid size. Outside of that, arg->max_len is a size_t, though it's
+only ever set to a 32-bit value (as it's governed by MAX_RW_COUNT).
+Bump our needed check to a size_t so we know it fits. Finally, cap the
+calculated needed iov value to the PEEK_MAX_IMPORT, which is the
+maximum number of segments that should be peeked.
+
+Fixes: 35c8711c8fc4 ("io_uring/kbuf: add helpers for getting/peeking multiple buffers")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/kbuf.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
+index c95dc1736dd93..1af2bd56af44a 100644
+--- a/io_uring/kbuf.c
++++ b/io_uring/kbuf.c
+@@ -218,10 +218,13 @@ static int io_ring_buffers_peek(struct io_kiocb *req, struct buf_sel_arg *arg,
+
+ buf = io_ring_head_to_buf(br, head, bl->mask);
+ if (arg->max_len) {
+- int needed;
++ u32 len = READ_ONCE(buf->len);
++ size_t needed;
+
+- needed = (arg->max_len + buf->len - 1) / buf->len;
+- needed = min(needed, PEEK_MAX_IMPORT);
++ if (unlikely(!len))
++ return -ENOBUFS;
++ needed = (arg->max_len + len - 1) / len;
++ needed = min_not_zero(needed, (size_t) PEEK_MAX_IMPORT);
+ if (nr_avail > needed)
+ nr_avail = needed;
+ }
+--
+2.43.0
+
--- /dev/null
+From b25768055caea946b37dfb2fba4bc5a0271ac829 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Aug 2024 11:44:08 +0300
+Subject: mmc: mmc_test: Fix NULL dereference on allocation failure
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit a1e627af32ed60713941cbfc8075d44cad07f6dd ]
+
+If the "test->highmem = alloc_pages()" allocation fails then calling
+__free_pages(test->highmem) will result in a NULL dereference. Also
+change the error code to -ENOMEM instead of returning success.
+
+Fixes: 2661081f5ab9 ("mmc_test: highmem tests")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Link: https://lore.kernel.org/r/8c90be28-67b4-4b0d-a105-034dc72a0b31@stanley.mountain
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/core/mmc_test.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c
+index 8f7f587a0025b..b7f627a9fdeab 100644
+--- a/drivers/mmc/core/mmc_test.c
++++ b/drivers/mmc/core/mmc_test.c
+@@ -3125,13 +3125,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
+ test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+ #ifdef CONFIG_HIGHMEM
+ test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
++ if (!test->highmem) {
++ count = -ENOMEM;
++ goto free_test_buffer;
++ }
+ #endif
+
+-#ifdef CONFIG_HIGHMEM
+- if (test->buffer && test->highmem) {
+-#else
+ if (test->buffer) {
+-#endif
+ mutex_lock(&mmc_test_lock);
+ mmc_test_run(test, testcase);
+ mutex_unlock(&mmc_test_lock);
+@@ -3139,6 +3139,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
+
+ #ifdef CONFIG_HIGHMEM
+ __free_pages(test->highmem, BUFFER_ORDER);
++free_test_buffer:
+ #endif
+ kfree(test->buffer);
+ kfree(test);
+--
+2.43.0
+
--- /dev/null
+From 3a46b5b6dc39543d8eb658cd339e1853725c31d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Aug 2024 09:35:27 +0800
+Subject: nvme: move stopping keep-alive into nvme_uninit_ctrl()
+
+From: Ming Lei <ming.lei@redhat.com>
+
+[ Upstream commit a54a93d0e3599b05856971734e15418ac551a14c ]
+
+Commit 4733b65d82bd ("nvme: start keep-alive after admin queue setup")
+moves starting keep-alive from nvme_start_ctrl() into
+nvme_init_ctrl_finish(), but don't move stopping keep-alive into
+nvme_uninit_ctrl(), so keep-alive work can be started and keep pending
+after failing to start controller, finally use-after-free is triggered if
+nvme host driver is unloaded.
+
+This patch fixes kernel panic when running nvme/004 in case that connection
+failure is triggered, by moving stopping keep-alive into nvme_uninit_ctrl().
+
+This way is reasonable because keep-alive is now started in
+nvme_init_ctrl_finish().
+
+Fixes: 3af755a46881 ("nvme: move nvme_stop_keep_alive() back to original position")
+Cc: Hannes Reinecke <hare@suse.de>
+Cc: Mark O'Donovan <shiftee@posteo.net>
+Reported-by: Changhui Zhong <czhong@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Signed-off-by: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 782090ce0bc10..d973d063bbf50 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -4522,7 +4522,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
+ {
+ nvme_mpath_stop(ctrl);
+ nvme_auth_stop(ctrl);
+- nvme_stop_keep_alive(ctrl);
+ nvme_stop_failfast_work(ctrl);
+ flush_work(&ctrl->async_event_work);
+ cancel_work_sync(&ctrl->fw_act_work);
+@@ -4558,6 +4557,7 @@ EXPORT_SYMBOL_GPL(nvme_start_ctrl);
+
+ void nvme_uninit_ctrl(struct nvme_ctrl *ctrl)
+ {
++ nvme_stop_keep_alive(ctrl);
+ nvme_hwmon_exit(ctrl);
+ nvme_fault_inject_fini(&ctrl->fault_inject);
+ dev_pm_qos_hide_latency_tolerance(ctrl->device);
+--
+2.43.0
+
--- /dev/null
+From c9fc3e6f11c891837278d2aaa7345c20f3b378ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 18:55:06 +0200
+Subject: s390/boot: Avoid possible physmem_info segment corruption
+
+From: Alexander Gordeev <agordeev@linux.ibm.com>
+
+[ Upstream commit d7fd2941ae9a67423d1c7bee985f240e4686634f ]
+
+When physical memory for the kernel image is allocated it does not
+consider extra memory required for offsetting the image start to
+match it with the lower 20 bits of KASLR virtual base address. That
+might lead to kernel access beyond its memory range.
+
+Suggested-by: Vasily Gorbik <gor@linux.ibm.com>
+Fixes: 693d41f7c938 ("s390/mm: Restore mapping of kernel image using large pages")
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Acked-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/boot/startup.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
+index 5a36d5538dae8..7797446620b64 100644
+--- a/arch/s390/boot/startup.c
++++ b/arch/s390/boot/startup.c
+@@ -446,9 +446,9 @@ void startup_kernel(void)
+ */
+ kaslr_large_page_offset = __kaslr_offset & ~_SEGMENT_MASK;
+ if (kaslr_enabled()) {
+- unsigned long end = ident_map_size - kaslr_large_page_offset;
++ unsigned long size = kernel_size + kaslr_large_page_offset;
+
+- __kaslr_offset_phys = randomize_within_range(kernel_size, _SEGMENT_SIZE, 0, end);
++ __kaslr_offset_phys = randomize_within_range(size, _SEGMENT_SIZE, 0, ident_map_size);
+ }
+ if (!__kaslr_offset_phys)
+ __kaslr_offset_phys = nokaslr_offset_phys;
+--
+2.43.0
+
--- /dev/null
+From 30c85c77a391ce7fbda32de92fc79a72648fd6f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 18:55:07 +0200
+Subject: s390/boot: Fix KASLR base offset off by __START_KERNEL bytes
+
+From: Alexander Gordeev <agordeev@linux.ibm.com>
+
+[ Upstream commit 1642285e511c2a40b14e87a41aa8feace6123036 ]
+
+Symbol offsets to the KASLR base do not match symbol address in
+the vmlinux image. That is the result of setting the KASLR base
+to the beginning of .text section as result of an optimization.
+
+Revert that optimization and allocate virtual memory for the
+whole kernel image including __START_KERNEL bytes as per the
+linker script. That allows keeping the semantics of the KASLR
+base offset in sync with other architectures.
+
+Rename __START_KERNEL to TEXT_OFFSET, since it represents the
+offset of the .text section within the kernel image, rather than
+a virtual address.
+
+Still skip mapping TEXT_OFFSET bytes to save memory on pgtables
+and provoke exceptions in case an attempt to access this area is
+made, as no kernel symbol may reside there.
+
+In case CONFIG_KASAN is enabled the location counter might exceed
+the value of TEXT_OFFSET, while the decompressor linker script
+forcefully resets it to TEXT_OFFSET, which leads to a sections
+overlap link failure. Use MAX() expression to avoid that.
+
+Reported-by: Omar Sandoval <osandov@osandov.com>
+Closes: https://lore.kernel.org/linux-s390/ZnS8dycxhtXBZVky@telecaster.dhcp.thefacebook.com/
+Fixes: 56b1069c40c7 ("s390/boot: Rework deployment of the kernel image")
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Acked-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/boot/startup.c | 55 ++++++++++++++++++----------------
+ arch/s390/boot/vmem.c | 14 +++++++--
+ arch/s390/boot/vmlinux.lds.S | 7 ++++-
+ arch/s390/include/asm/page.h | 3 +-
+ arch/s390/kernel/vmlinux.lds.S | 2 +-
+ arch/s390/tools/relocs.c | 2 +-
+ 6 files changed, 52 insertions(+), 31 deletions(-)
+
+diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
+index 7797446620b64..6d88f241dd43a 100644
+--- a/arch/s390/boot/startup.c
++++ b/arch/s390/boot/startup.c
+@@ -161,7 +161,7 @@ static void kaslr_adjust_relocs(unsigned long min_addr, unsigned long max_addr,
+ loc = (long)*reloc + phys_offset;
+ if (loc < min_addr || loc > max_addr)
+ error("64-bit relocation outside of kernel!\n");
+- *(u64 *)loc += offset - __START_KERNEL;
++ *(u64 *)loc += offset;
+ }
+ }
+
+@@ -176,7 +176,7 @@ static void kaslr_adjust_got(unsigned long offset)
+ */
+ for (entry = (u64 *)vmlinux.got_start; entry < (u64 *)vmlinux.got_end; entry++) {
+ if (*entry)
+- *entry += offset - __START_KERNEL;
++ *entry += offset;
+ }
+ }
+
+@@ -251,7 +251,7 @@ static unsigned long setup_kernel_memory_layout(unsigned long kernel_size)
+ vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page);
+
+ /* choose kernel address space layout: 4 or 3 levels. */
+- BUILD_BUG_ON(!IS_ALIGNED(__START_KERNEL, THREAD_SIZE));
++ BUILD_BUG_ON(!IS_ALIGNED(TEXT_OFFSET, THREAD_SIZE));
+ BUILD_BUG_ON(!IS_ALIGNED(__NO_KASLR_START_KERNEL, THREAD_SIZE));
+ BUILD_BUG_ON(__NO_KASLR_END_KERNEL > _REGION1_SIZE);
+ vsize = get_vmem_size(ident_map_size, vmemmap_size, vmalloc_size, _REGION3_SIZE);
+@@ -378,31 +378,25 @@ static void kaslr_adjust_vmlinux_info(long offset)
+ #endif
+ }
+
+-static void fixup_vmlinux_info(void)
+-{
+- vmlinux.entry -= __START_KERNEL;
+- kaslr_adjust_vmlinux_info(-__START_KERNEL);
+-}
+-
+ void startup_kernel(void)
+ {
+- unsigned long kernel_size = vmlinux.image_size + vmlinux.bss_size;
+- unsigned long nokaslr_offset_phys, kaslr_large_page_offset;
+- unsigned long amode31_lma = 0;
++ unsigned long vmlinux_size = vmlinux.image_size + vmlinux.bss_size;
++ unsigned long nokaslr_text_lma, text_lma = 0, amode31_lma = 0;
++ unsigned long kernel_size = TEXT_OFFSET + vmlinux_size;
++ unsigned long kaslr_large_page_offset;
+ unsigned long max_physmem_end;
+ unsigned long asce_limit;
+ unsigned long safe_addr;
+ psw_t psw;
+
+- fixup_vmlinux_info();
+ setup_lpp();
+
+ /*
+ * Non-randomized kernel physical start address must be _SEGMENT_SIZE
+ * aligned (see blow).
+ */
+- nokaslr_offset_phys = ALIGN(mem_safe_offset(), _SEGMENT_SIZE);
+- safe_addr = PAGE_ALIGN(nokaslr_offset_phys + kernel_size);
++ nokaslr_text_lma = ALIGN(mem_safe_offset(), _SEGMENT_SIZE);
++ safe_addr = PAGE_ALIGN(nokaslr_text_lma + vmlinux_size);
+
+ /*
+ * Reserve decompressor memory together with decompression heap,
+@@ -446,16 +440,27 @@ void startup_kernel(void)
+ */
+ kaslr_large_page_offset = __kaslr_offset & ~_SEGMENT_MASK;
+ if (kaslr_enabled()) {
+- unsigned long size = kernel_size + kaslr_large_page_offset;
++ unsigned long size = vmlinux_size + kaslr_large_page_offset;
+
+- __kaslr_offset_phys = randomize_within_range(size, _SEGMENT_SIZE, 0, ident_map_size);
++ text_lma = randomize_within_range(size, _SEGMENT_SIZE, TEXT_OFFSET, ident_map_size);
+ }
+- if (!__kaslr_offset_phys)
+- __kaslr_offset_phys = nokaslr_offset_phys;
+- __kaslr_offset_phys |= kaslr_large_page_offset;
++ if (!text_lma)
++ text_lma = nokaslr_text_lma;
++ text_lma |= kaslr_large_page_offset;
++
++ /*
++ * [__kaslr_offset_phys..__kaslr_offset_phys + TEXT_OFFSET] region is
++ * never accessed via the kernel image mapping as per the linker script:
++ *
++ * . = TEXT_OFFSET;
++ *
++ * Therefore, this region could be used for something else and does
++ * not need to be reserved. See how it is skipped in setup_vmem().
++ */
++ __kaslr_offset_phys = text_lma - TEXT_OFFSET;
+ kaslr_adjust_vmlinux_info(__kaslr_offset_phys);
+- physmem_reserve(RR_VMLINUX, __kaslr_offset_phys, kernel_size);
+- deploy_kernel((void *)__kaslr_offset_phys);
++ physmem_reserve(RR_VMLINUX, text_lma, vmlinux_size);
++ deploy_kernel((void *)text_lma);
+
+ /* vmlinux decompression is done, shrink reserved low memory */
+ physmem_reserve(RR_DECOMPRESSOR, 0, (unsigned long)_decompressor_end);
+@@ -474,7 +479,7 @@ void startup_kernel(void)
+ if (kaslr_enabled())
+ amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, 0, SZ_2G);
+ if (!amode31_lma)
+- amode31_lma = __kaslr_offset_phys - vmlinux.amode31_size;
++ amode31_lma = text_lma - vmlinux.amode31_size;
+ physmem_reserve(RR_AMODE31, amode31_lma, vmlinux.amode31_size);
+
+ /*
+@@ -490,8 +495,8 @@ void startup_kernel(void)
+ * - copy_bootdata() must follow setup_vmem() to propagate changes
+ * to bootdata made by setup_vmem()
+ */
+- clear_bss_section(__kaslr_offset_phys);
+- kaslr_adjust_relocs(__kaslr_offset_phys, __kaslr_offset_phys + vmlinux.image_size,
++ clear_bss_section(text_lma);
++ kaslr_adjust_relocs(text_lma, text_lma + vmlinux.image_size,
+ __kaslr_offset, __kaslr_offset_phys);
+ kaslr_adjust_got(__kaslr_offset);
+ setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit);
+diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c
+index 40cfce2687c43..3d4dae9905cd8 100644
+--- a/arch/s390/boot/vmem.c
++++ b/arch/s390/boot/vmem.c
+@@ -89,7 +89,7 @@ static void kasan_populate_shadow(unsigned long kernel_start, unsigned long kern
+ }
+ memgap_start = end;
+ }
+- kasan_populate(kernel_start, kernel_end, POPULATE_KASAN_MAP_SHADOW);
++ kasan_populate(kernel_start + TEXT_OFFSET, kernel_end, POPULATE_KASAN_MAP_SHADOW);
+ kasan_populate(0, (unsigned long)__identity_va(0), POPULATE_KASAN_ZERO_SHADOW);
+ kasan_populate(AMODE31_START, AMODE31_END, POPULATE_KASAN_ZERO_SHADOW);
+ if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+@@ -466,7 +466,17 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l
+ (unsigned long)__identity_va(end),
+ POPULATE_IDENTITY);
+ }
+- pgtable_populate(kernel_start, kernel_end, POPULATE_KERNEL);
++
++ /*
++ * [kernel_start..kernel_start + TEXT_OFFSET] region is never
++ * accessed as per the linker script:
++ *
++ * . = TEXT_OFFSET;
++ *
++ * Therefore, skip mapping TEXT_OFFSET bytes to prevent access to
++ * [__kaslr_offset_phys..__kaslr_offset_phys + TEXT_OFFSET] region.
++ */
++ pgtable_populate(kernel_start + TEXT_OFFSET, kernel_end, POPULATE_KERNEL);
+ pgtable_populate(AMODE31_START, AMODE31_END, POPULATE_DIRECT);
+ pgtable_populate(__abs_lowcore, __abs_lowcore + sizeof(struct lowcore),
+ POPULATE_ABS_LOWCORE);
+diff --git a/arch/s390/boot/vmlinux.lds.S b/arch/s390/boot/vmlinux.lds.S
+index a750711d44c86..66670212a3611 100644
+--- a/arch/s390/boot/vmlinux.lds.S
++++ b/arch/s390/boot/vmlinux.lds.S
+@@ -109,7 +109,12 @@ SECTIONS
+ #ifdef CONFIG_KERNEL_UNCOMPRESSED
+ . = ALIGN(PAGE_SIZE);
+ . += AMODE31_SIZE; /* .amode31 section */
+- . = ALIGN(1 << 20); /* _SEGMENT_SIZE */
++
++ /*
++ * Make sure the location counter is not less than TEXT_OFFSET.
++ * _SEGMENT_SIZE is not available, use ALIGN(1 << 20) instead.
++ */
++ . = MAX(TEXT_OFFSET, ALIGN(1 << 20));
+ #else
+ . = ALIGN(8);
+ #endif
+diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
+index 224ff9d433ead..8cac1a737424d 100644
+--- a/arch/s390/include/asm/page.h
++++ b/arch/s390/include/asm/page.h
+@@ -276,8 +276,9 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
+ #define AMODE31_SIZE (3 * PAGE_SIZE)
+
+ #define KERNEL_IMAGE_SIZE (512 * 1024 * 1024)
+-#define __START_KERNEL 0x100000
+ #define __NO_KASLR_START_KERNEL CONFIG_KERNEL_IMAGE_BASE
+ #define __NO_KASLR_END_KERNEL (__NO_KASLR_START_KERNEL + KERNEL_IMAGE_SIZE)
+
++#define TEXT_OFFSET 0x100000
++
+ #endif /* _S390_PAGE_H */
+diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
+index a1ce3925ec719..52bd969b28283 100644
+--- a/arch/s390/kernel/vmlinux.lds.S
++++ b/arch/s390/kernel/vmlinux.lds.S
+@@ -39,7 +39,7 @@ PHDRS {
+
+ SECTIONS
+ {
+- . = __START_KERNEL;
++ . = TEXT_OFFSET;
+ .text : {
+ _stext = .; /* Start of text section */
+ _text = .; /* Text and read-only data */
+diff --git a/arch/s390/tools/relocs.c b/arch/s390/tools/relocs.c
+index a74dbd5c9896a..30a732c808f35 100644
+--- a/arch/s390/tools/relocs.c
++++ b/arch/s390/tools/relocs.c
+@@ -280,7 +280,7 @@ static int do_reloc(struct section *sec, Elf_Rel *rel)
+ case R_390_GOTOFF64:
+ break;
+ case R_390_64:
+- add_reloc(&relocs64, offset - ehdr.e_entry);
++ add_reloc(&relocs64, offset);
+ break;
+ default:
+ die("Unsupported relocation type: %d\n", r_type);
+--
+2.43.0
+
net-xilinx-axienet-fix-dangling-multicast-addresses.patch
net-ovs-fix-ovs_drop_reasons-error.patch
s390-iucv-fix-vargs-handling-in-iucv_alloc_device.patch
+drm-msm-dpu-don-t-play-tricks-with-debug-macros.patch
+drm-msm-dp-fix-the-max-supported-bpp-logic.patch
+drm-msm-dpu-move-dpu_encoder-s-connector-assignment-.patch
+drm-msm-dp-reset-the-link-phy-params-before-link-tra.patch
+drm-msm-dpu-cleanup-fb-if-dpu_format_populate_layout.patch
+drm-msm-dpu-limit-qcm2290-to-rgb-formats-only.patch
+drm-msm-dpu-relax-yuv-requirements.patch
+drm-msm-dpu-take-plane-rotation-into-account-for-wid.patch
+workqueue-fix-ubsan-subtraction-overflow-error-in-sh.patch
+workqueue-fix-spruious-data-race-in-__flush_work.patch
+drm-msm-fix-the-highest_bank_bit-for-sc7180.patch
+spi-spi-cadence-quadspi-fix-ospi-nor-failures-during.patch
+drm-i915-hdcp-use-correct-cp_irq_count.patch
+drm-xe-display-stop-calling-domains_driver_remove-tw.patch
+drm-xe-fix-opregion-leak.patch
+drm-xe-mmio-move-mmio_fini-over-to-devm.patch
+drm-xe-reset-mmio-mappings-with-devm.patch
+drm-xe-fix-tile-fini-sequence.patch
+mmc-mmc_test-fix-null-dereference-on-allocation-fail.patch
+io_uring-kbuf-sanitize-peek-buffer-setup.patch
+drm-xe-fix-missing-workqueue-destroy-in-xe_gt_pagefa.patch
+drm-xe-relax-runtime-pm-protection-during-execution.patch
+drm-xe-decouple-job-seqno-and-lrc-seqno.patch
+drm-xe-split-lrc-seqno-fence-creation-up.patch
+drm-xe-don-t-initialize-fences-at-xe_sched_job_creat.patch
+drm-xe-free-job-before-xe_exec_queue_put.patch
+thermal-debugfs-fix-the-null-vs-is_err-confusion-in-.patch
+s390-boot-avoid-possible-physmem_info-segment-corrup.patch
+s390-boot-fix-kaslr-base-offset-off-by-__start_kerne.patch
+smb-client-ignore-unhandled-reparse-tags.patch
+nvme-move-stopping-keep-alive-into-nvme_uninit_ctrl.patch
--- /dev/null
+From b17c68d9dba3f16bd0440a8f1ef5f59acf208e11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 00:45:03 -0300
+Subject: smb: client: ignore unhandled reparse tags
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+[ Upstream commit ec686804117a0421cf31d54427768aaf93aa0069 ]
+
+Just ignore reparse points that the client can't parse rather than
+bailing out and not opening the file or directory.
+
+Reported-by: Marc <1marc1@gmail.com>
+Closes: https://lore.kernel.org/r/CAMHwNVv-B+Q6wa0FEXrAuzdchzcJRsPKDDRrNaYZJd6X-+iJzw@mail.gmail.com
+Fixes: 539aad7f14da ("smb: client: introduce ->parse_reparse_point()")
+Tested-by: Anthony Nandaa (Microsoft) <profnandaa@gmail.com>
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/client/reparse.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
+index 689d8a506d459..48c27581ec511 100644
+--- a/fs/smb/client/reparse.c
++++ b/fs/smb/client/reparse.c
+@@ -378,6 +378,8 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
+ u32 plen, struct cifs_sb_info *cifs_sb,
+ bool unicode, struct cifs_open_info_data *data)
+ {
++ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
++
+ data->reparse.buf = buf;
+
+ /* See MS-FSCC 2.1.2 */
+@@ -394,12 +396,13 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
+ case IO_REPARSE_TAG_LX_FIFO:
+ case IO_REPARSE_TAG_LX_CHR:
+ case IO_REPARSE_TAG_LX_BLK:
+- return 0;
++ break;
+ default:
+- cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n",
+- __func__, le32_to_cpu(buf->ReparseTag));
+- return -EOPNOTSUPP;
++ cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n",
++ le32_to_cpu(buf->ReparseTag));
++ break;
+ }
++ return 0;
+ }
+
+ int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+--
+2.43.0
+
--- /dev/null
+From e85e394d4232677c13e5d5fde6ed488e29fabe95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Aug 2024 20:42:37 +0530
+Subject: spi: spi-cadence-quadspi: Fix OSPI NOR failures during system resume
+
+From: Vignesh Raghavendra <vigneshr@ti.com>
+
+[ Upstream commit 57d5af2660e9443b081eeaf1c373b3ce48477828 ]
+
+Its necessary to call pm_runtime_force_*() hooks as part of system
+suspend/resume calls so that the runtime_pm hooks get called. This
+ensures latest state of the IP is cached and restored during system
+sleep. This is especially true if runtime autosuspend is enabled as
+runtime suspend hooks may not be called at all before system sleeps.
+
+Without this patch, OSPI NOR enumeration (READ_ID) fails during resume
+as context saved during suspend path is inconsistent.
+
+Fixes: 078d62de433b ("spi: cadence-qspi: add system-wide suspend and resume callbacks")
+Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
+Link: https://patch.msgid.link/20240814151237.3856184-1-vigneshr@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi-cadence-quadspi.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
+index 05ebb03d319fc..d4607cb89c484 100644
+--- a/drivers/spi/spi-cadence-quadspi.c
++++ b/drivers/spi/spi-cadence-quadspi.c
+@@ -2000,13 +2000,25 @@ static int cqspi_runtime_resume(struct device *dev)
+ static int cqspi_suspend(struct device *dev)
+ {
+ struct cqspi_st *cqspi = dev_get_drvdata(dev);
++ int ret;
+
+- return spi_controller_suspend(cqspi->host);
++ ret = spi_controller_suspend(cqspi->host);
++ if (ret)
++ return ret;
++
++ return pm_runtime_force_suspend(dev);
+ }
+
+ static int cqspi_resume(struct device *dev)
+ {
+ struct cqspi_st *cqspi = dev_get_drvdata(dev);
++ int ret;
++
++ ret = pm_runtime_force_resume(dev);
++ if (ret) {
++ dev_err(dev, "pm_runtime_force_resume failed on resume\n");
++ return ret;
++ }
+
+ return spi_controller_resume(cqspi->host);
+ }
+--
+2.43.0
+
--- /dev/null
+From e1fe8197b0f5296d2ec666817f75c5d6b83b8522 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 03:59:33 -0400
+Subject: thermal/debugfs: Fix the NULL vs IS_ERR() confusion in
+ debugfs_create_dir()
+
+From: Yang Ruibin <11162571@vivo.com>
+
+[ Upstream commit 57df60e1f981fa8c288a49012a4bbb02ae0ecdbc ]
+
+The debugfs_create_dir() return value is never NULL, it is either a
+valid pointer or an error one.
+
+Use IS_ERR() to check it.
+
+Fixes: 7ef01f228c9f ("thermal/debugfs: Add thermal debugfs information for mitigation episodes")
+Fixes: 755113d76786 ("thermal/debugfs: Add thermal cooling device debugfs information")
+Signed-off-by: Yang Ruibin <11162571@vivo.com>
+Link: https://patch.msgid.link/20240821075934.12145-1-11162571@vivo.com
+[ rjw: Subject and changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/thermal_debugfs.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c
+index 9424472291570..6d55f5fc4ca0f 100644
+--- a/drivers/thermal/thermal_debugfs.c
++++ b/drivers/thermal/thermal_debugfs.c
+@@ -178,11 +178,11 @@ struct thermal_debugfs {
+ void thermal_debug_init(void)
+ {
+ d_root = debugfs_create_dir("thermal", NULL);
+- if (!d_root)
++ if (IS_ERR(d_root))
+ return;
+
+ d_cdev = debugfs_create_dir("cooling_devices", d_root);
+- if (!d_cdev)
++ if (IS_ERR(d_cdev))
+ return;
+
+ d_tz = debugfs_create_dir("thermal_zones", d_root);
+@@ -202,7 +202,7 @@ static struct thermal_debugfs *thermal_debugfs_add_id(struct dentry *d, int id)
+ snprintf(ids, IDSLENGTH, "%d", id);
+
+ thermal_dbg->d_top = debugfs_create_dir(ids, d);
+- if (!thermal_dbg->d_top) {
++ if (IS_ERR(thermal_dbg->d_top)) {
+ kfree(thermal_dbg);
+ return NULL;
+ }
+--
+2.43.0
+
--- /dev/null
+From aa9797bef1f118706e73b6719191b83e35e696e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Aug 2024 09:37:25 -1000
+Subject: workqueue: Fix spruious data race in __flush_work()
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 8bc35475ef1a23b0e224f3242eb11c76cab0ea88 ]
+
+When flushing a work item for cancellation, __flush_work() knows that it
+exclusively owns the work item through its PENDING bit. 134874e2eee9
+("workqueue: Allow cancel_work_sync() and disable_work() from atomic
+contexts on BH work items") added a read of @work->data to determine whether
+to use busy wait for BH work items that are being canceled. While the read
+is safe when @from_cancel, @work->data was read before testing @from_cancel
+to simplify code structure:
+
+ data = *work_data_bits(work);
+ if (from_cancel &&
+ !WARN_ON_ONCE(data & WORK_STRUCT_PWQ) && (data & WORK_OFFQ_BH)) {
+
+While the read data was never used if !@from_cancel, this could trigger
+KCSAN data race detection spuriously:
+
+ ==================================================================
+ BUG: KCSAN: data-race in __flush_work / __flush_work
+
+ write to 0xffff8881223aa3e8 of 8 bytes by task 3998 on cpu 0:
+ instrument_write include/linux/instrumented.h:41 [inline]
+ ___set_bit include/asm-generic/bitops/instrumented-non-atomic.h:28 [inline]
+ insert_wq_barrier kernel/workqueue.c:3790 [inline]
+ start_flush_work kernel/workqueue.c:4142 [inline]
+ __flush_work+0x30b/0x570 kernel/workqueue.c:4178
+ flush_work kernel/workqueue.c:4229 [inline]
+ ...
+
+ read to 0xffff8881223aa3e8 of 8 bytes by task 50 on cpu 1:
+ __flush_work+0x42a/0x570 kernel/workqueue.c:4188
+ flush_work kernel/workqueue.c:4229 [inline]
+ flush_delayed_work+0x66/0x70 kernel/workqueue.c:4251
+ ...
+
+ value changed: 0x0000000000400000 -> 0xffff88810006c00d
+
+Reorganize the code so that @from_cancel is tested before @work->data is
+accessed. The only problem is triggering KCSAN detection spuriously. This
+shouldn't need READ_ONCE() or other access qualifiers.
+
+No functional changes.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: syzbot+b3e4f2f51ed645fd5df2@syzkaller.appspotmail.com
+Fixes: 134874e2eee9 ("workqueue: Allow cancel_work_sync() and disable_work() from atomic contexts on BH work items")
+Link: http://lkml.kernel.org/r/000000000000ae429e061eea2157@google.com
+Cc: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/workqueue.c | 45 +++++++++++++++++++++++++--------------------
+ 1 file changed, 25 insertions(+), 20 deletions(-)
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index c8687c0ab3645..c970eec25c5a0 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -4190,7 +4190,6 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,
+ static bool __flush_work(struct work_struct *work, bool from_cancel)
+ {
+ struct wq_barrier barr;
+- unsigned long data;
+
+ if (WARN_ON(!wq_online))
+ return false;
+@@ -4208,29 +4207,35 @@ static bool __flush_work(struct work_struct *work, bool from_cancel)
+ * was queued on a BH workqueue, we also know that it was running in the
+ * BH context and thus can be busy-waited.
+ */
+- data = *work_data_bits(work);
+- if (from_cancel &&
+- !WARN_ON_ONCE(data & WORK_STRUCT_PWQ) && (data & WORK_OFFQ_BH)) {
+- /*
+- * On RT, prevent a live lock when %current preempted soft
+- * interrupt processing or prevents ksoftirqd from running by
+- * keeping flipping BH. If the BH work item runs on a different
+- * CPU then this has no effect other than doing the BH
+- * disable/enable dance for nothing. This is copied from
+- * kernel/softirq.c::tasklet_unlock_spin_wait().
+- */
+- while (!try_wait_for_completion(&barr.done)) {
+- if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
+- local_bh_disable();
+- local_bh_enable();
+- } else {
+- cpu_relax();
++ if (from_cancel) {
++ unsigned long data = *work_data_bits(work);
++
++ if (!WARN_ON_ONCE(data & WORK_STRUCT_PWQ) &&
++ (data & WORK_OFFQ_BH)) {
++ /*
++ * On RT, prevent a live lock when %current preempted
++ * soft interrupt processing or prevents ksoftirqd from
++ * running by keeping flipping BH. If the BH work item
++ * runs on a different CPU then this has no effect other
++ * than doing the BH disable/enable dance for nothing.
++ * This is copied from
++ * kernel/softirq.c::tasklet_unlock_spin_wait().
++ */
++ while (!try_wait_for_completion(&barr.done)) {
++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
++ local_bh_disable();
++ local_bh_enable();
++ } else {
++ cpu_relax();
++ }
+ }
++ goto out_destroy;
+ }
+- } else {
+- wait_for_completion(&barr.done);
+ }
+
++ wait_for_completion(&barr.done);
++
++out_destroy:
+ destroy_work_on_stack(&barr.work);
+ return true;
+ }
+--
+2.43.0
+
--- /dev/null
+From ccfc760de58a533ae59b73d57676f4720ddf508a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Jul 2024 12:44:31 +0100
+Subject: workqueue: Fix UBSAN 'subtraction overflow' error in shift_and_mask()
+
+From: Will Deacon <will@kernel.org>
+
+[ Upstream commit 38f7e14519d39cf524ddc02d4caee9b337dad703 ]
+
+UBSAN reports the following 'subtraction overflow' error when booting
+in a virtual machine on Android:
+
+ | Internal error: UBSAN: integer subtraction overflow: 00000000f2005515 [#1] PREEMPT SMP
+ | Modules linked in:
+ | CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.10.0-00006-g3cbe9e5abd46-dirty #4
+ | Hardware name: linux,dummy-virt (DT)
+ | pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+ | pc : cancel_delayed_work+0x34/0x44
+ | lr : cancel_delayed_work+0x2c/0x44
+ | sp : ffff80008002ba60
+ | x29: ffff80008002ba60 x28: 0000000000000000 x27: 0000000000000000
+ | x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
+ | x23: 0000000000000000 x22: 0000000000000000 x21: ffff1f65014cd3c0
+ | x20: ffffc0e84c9d0da0 x19: ffffc0e84cab3558 x18: ffff800080009058
+ | x17: 00000000247ee1f8 x16: 00000000247ee1f8 x15: 00000000bdcb279d
+ | x14: 0000000000000001 x13: 0000000000000075 x12: 00000a0000000000
+ | x11: ffff1f6501499018 x10: 00984901651fffff x9 : ffff5e7cc35af000
+ | x8 : 0000000000000001 x7 : 3d4d455453595342 x6 : 000000004e514553
+ | x5 : ffff1f6501499265 x4 : ffff1f650ff60b10 x3 : 0000000000000620
+ | x2 : ffff80008002ba78 x1 : 0000000000000000 x0 : 0000000000000000
+ | Call trace:
+ | cancel_delayed_work+0x34/0x44
+ | deferred_probe_extend_timeout+0x20/0x70
+ | driver_register+0xa8/0x110
+ | __platform_driver_register+0x28/0x3c
+ | syscon_init+0x24/0x38
+ | do_one_initcall+0xe4/0x338
+ | do_initcall_level+0xac/0x178
+ | do_initcalls+0x5c/0xa0
+ | do_basic_setup+0x20/0x30
+ | kernel_init_freeable+0x8c/0xf8
+ | kernel_init+0x28/0x1b4
+ | ret_from_fork+0x10/0x20
+ | Code: f9000fbf 97fffa2f 39400268 37100048 (d42aa2a0)
+ | ---[ end trace 0000000000000000 ]---
+ | Kernel panic - not syncing: UBSAN: integer subtraction overflow: Fatal exception
+
+This is due to shift_and_mask() using a signed immediate to construct
+the mask and being called with a shift of 31 (WORK_OFFQ_POOL_SHIFT) so
+that it ends up decrementing from INT_MIN.
+
+Use an unsigned constant '1U' to generate the mask in shift_and_mask().
+
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Lai Jiangshan <jiangshanlai@gmail.com>
+Fixes: 1211f3b21c2a ("workqueue: Preserve OFFQ bits in cancel[_sync] paths")
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/workqueue.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index f98247ec99c20..c8687c0ab3645 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -896,7 +896,7 @@ static struct worker_pool *get_work_pool(struct work_struct *work)
+
+ static unsigned long shift_and_mask(unsigned long v, u32 shift, u32 bits)
+ {
+- return (v >> shift) & ((1 << bits) - 1);
++ return (v >> shift) & ((1U << bits) - 1);
+ }
+
+ static void work_offqd_unpack(struct work_offq_data *offqd, unsigned long data)
+--
+2.43.0
+