--- /dev/null
+From f5f414f7335a68fdd10b1ee0a150ff904d765c3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Feb 2025 10:13:04 +0000
+Subject: drm/xe: Add performance tunings to debugfs
+
+From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
+
+[ Upstream commit 067a974fd8a9ea43f97ca184e2768b583f2f8c44 ]
+
+Add a list of active tunings to debugfs, analogous to the existing
+list of workarounds.
+
+Rationale being that it seems to make sense to either have both or none.
+
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
+Cc: Lucas De Marchi <lucas.demarchi@intel.com>
+Cc: Matt Roper <matthew.d.roper@intel.com>
+Reviewed-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250227101304.46660-6-tvrtko.ursulin@igalia.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_gt.c | 4 ++
+ drivers/gpu/drm/xe/xe_gt_debugfs.c | 11 ++++++
+ drivers/gpu/drm/xe/xe_gt_types.h | 10 +++++
+ drivers/gpu/drm/xe/xe_tuning.c | 59 ++++++++++++++++++++++++++++++
+ drivers/gpu/drm/xe/xe_tuning.h | 3 ++
+ 5 files changed, 87 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
+index 8a20e6744836c..94eed1315b0f1 100644
+--- a/drivers/gpu/drm/xe/xe_gt.c
++++ b/drivers/gpu/drm/xe/xe_gt.c
+@@ -381,6 +381,10 @@ int xe_gt_init_early(struct xe_gt *gt)
+ if (err)
+ return err;
+
++ err = xe_tuning_init(gt);
++ if (err)
++ return err;
++
+ xe_wa_process_oob(gt);
+
+ xe_force_wake_init_gt(gt, gt_to_fw(gt));
+diff --git a/drivers/gpu/drm/xe/xe_gt_debugfs.c b/drivers/gpu/drm/xe/xe_gt_debugfs.c
+index e7792858b1e46..2d63a69cbfa38 100644
+--- a/drivers/gpu/drm/xe/xe_gt_debugfs.c
++++ b/drivers/gpu/drm/xe/xe_gt_debugfs.c
+@@ -30,6 +30,7 @@
+ #include "xe_reg_sr.h"
+ #include "xe_reg_whitelist.h"
+ #include "xe_sriov.h"
++#include "xe_tuning.h"
+ #include "xe_uc_debugfs.h"
+ #include "xe_wa.h"
+
+@@ -217,6 +218,15 @@ static int workarounds(struct xe_gt *gt, struct drm_printer *p)
+ return 0;
+ }
+
++static int tunings(struct xe_gt *gt, struct drm_printer *p)
++{
++ xe_pm_runtime_get(gt_to_xe(gt));
++ xe_tuning_dump(gt, p);
++ xe_pm_runtime_put(gt_to_xe(gt));
++
++ return 0;
++}
++
+ static int pat(struct xe_gt *gt, struct drm_printer *p)
+ {
+ xe_pm_runtime_get(gt_to_xe(gt));
+@@ -300,6 +310,7 @@ static const struct drm_info_list debugfs_list[] = {
+ {"powergate_info", .show = xe_gt_debugfs_simple_show, .data = powergate_info},
+ {"register-save-restore", .show = xe_gt_debugfs_simple_show, .data = register_save_restore},
+ {"workarounds", .show = xe_gt_debugfs_simple_show, .data = workarounds},
++ {"tunings", .show = xe_gt_debugfs_simple_show, .data = tunings},
+ {"pat", .show = xe_gt_debugfs_simple_show, .data = pat},
+ {"mocs", .show = xe_gt_debugfs_simple_show, .data = mocs},
+ {"default_lrc_rcs", .show = xe_gt_debugfs_simple_show, .data = rcs_default_lrc},
+diff --git a/drivers/gpu/drm/xe/xe_gt_types.h b/drivers/gpu/drm/xe/xe_gt_types.h
+index 6e66bf0e8b3f7..dd2969a1846dd 100644
+--- a/drivers/gpu/drm/xe/xe_gt_types.h
++++ b/drivers/gpu/drm/xe/xe_gt_types.h
+@@ -413,6 +413,16 @@ struct xe_gt {
+ bool oob_initialized;
+ } wa_active;
+
++ /** @tuning_active: keep track of active tunings */
++ struct {
++ /** @tuning_active.gt: bitmap with active GT tunings */
++ unsigned long *gt;
++ /** @tuning_active.engine: bitmap with active engine tunings */
++ unsigned long *engine;
++ /** @tuning_active.lrc: bitmap with active LRC tunings */
++ unsigned long *lrc;
++ } tuning_active;
++
+ /** @user_engines: engines present in GT and available to userspace */
+ struct {
+ /**
+diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c
+index 3c78f3d715591..23c46dd85e149 100644
+--- a/drivers/gpu/drm/xe/xe_tuning.c
++++ b/drivers/gpu/drm/xe/xe_tuning.c
+@@ -7,6 +7,8 @@
+
+ #include <kunit/visibility.h>
+
++#include <drm/drm_managed.h>
++
+ #include "regs/xe_gt_regs.h"
+ #include "xe_gt_types.h"
+ #include "xe_platform_types.h"
+@@ -135,10 +137,44 @@ static const struct xe_rtp_entry_sr lrc_tunings[] = {
+ {}
+ };
+
++/**
++ * xe_tuning_init - initialize gt with tunings bookkeeping
++ * @gt: GT instance to initialize
++ *
++ * Returns 0 for success, negative error code otherwise.
++ */
++int xe_tuning_init(struct xe_gt *gt)
++{
++ struct xe_device *xe = gt_to_xe(gt);
++ size_t n_lrc, n_engine, n_gt, total;
++ unsigned long *p;
++
++ n_gt = BITS_TO_LONGS(ARRAY_SIZE(gt_tunings));
++ n_engine = BITS_TO_LONGS(ARRAY_SIZE(engine_tunings));
++ n_lrc = BITS_TO_LONGS(ARRAY_SIZE(lrc_tunings));
++ total = n_gt + n_engine + n_lrc;
++
++ p = drmm_kzalloc(&xe->drm, sizeof(*p) * total, GFP_KERNEL);
++ if (!p)
++ return -ENOMEM;
++
++ gt->tuning_active.gt = p;
++ p += n_gt;
++ gt->tuning_active.engine = p;
++ p += n_engine;
++ gt->tuning_active.lrc = p;
++
++ return 0;
++}
++ALLOW_ERROR_INJECTION(xe_tuning_init, ERRNO); /* See xe_pci_probe() */
++
+ void xe_tuning_process_gt(struct xe_gt *gt)
+ {
+ struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(gt);
+
++ xe_rtp_process_ctx_enable_active_tracking(&ctx,
++ gt->tuning_active.gt,
++ ARRAY_SIZE(gt_tunings));
+ xe_rtp_process_to_sr(&ctx, gt_tunings, >->reg_sr);
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_tuning_process_gt);
+@@ -147,6 +183,9 @@ void xe_tuning_process_engine(struct xe_hw_engine *hwe)
+ {
+ struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
+
++ xe_rtp_process_ctx_enable_active_tracking(&ctx,
++ hwe->gt->tuning_active.engine,
++ ARRAY_SIZE(engine_tunings));
+ xe_rtp_process_to_sr(&ctx, engine_tunings, &hwe->reg_sr);
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_tuning_process_engine);
+@@ -163,5 +202,25 @@ void xe_tuning_process_lrc(struct xe_hw_engine *hwe)
+ {
+ struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
+
++ xe_rtp_process_ctx_enable_active_tracking(&ctx,
++ hwe->gt->tuning_active.lrc,
++ ARRAY_SIZE(lrc_tunings));
+ xe_rtp_process_to_sr(&ctx, lrc_tunings, &hwe->reg_lrc);
+ }
++
++void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p)
++{
++ size_t idx;
++
++ drm_printf(p, "GT Tunings\n");
++ for_each_set_bit(idx, gt->tuning_active.gt, ARRAY_SIZE(gt_tunings))
++ drm_printf_indent(p, 1, "%s\n", gt_tunings[idx].name);
++
++ drm_printf(p, "\nEngine Tunings\n");
++ for_each_set_bit(idx, gt->tuning_active.engine, ARRAY_SIZE(engine_tunings))
++ drm_printf_indent(p, 1, "%s\n", engine_tunings[idx].name);
++
++ drm_printf(p, "\nLRC Tunings\n");
++ for_each_set_bit(idx, gt->tuning_active.lrc, ARRAY_SIZE(lrc_tunings))
++ drm_printf_indent(p, 1, "%s\n", lrc_tunings[idx].name);
++}
+diff --git a/drivers/gpu/drm/xe/xe_tuning.h b/drivers/gpu/drm/xe/xe_tuning.h
+index 4f9c3ac3b5162..dd0d3ccc9c654 100644
+--- a/drivers/gpu/drm/xe/xe_tuning.h
++++ b/drivers/gpu/drm/xe/xe_tuning.h
+@@ -6,11 +6,14 @@
+ #ifndef _XE_TUNING_
+ #define _XE_TUNING_
+
++struct drm_printer;
+ struct xe_gt;
+ struct xe_hw_engine;
+
++int xe_tuning_init(struct xe_gt *gt);
+ void xe_tuning_process_gt(struct xe_gt *gt);
+ void xe_tuning_process_engine(struct xe_hw_engine *hwe);
+ void xe_tuning_process_lrc(struct xe_hw_engine *hwe);
++void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p);
+
+ #endif
+--
+2.39.5
+
--- /dev/null
+From 98dbe574df630abc958636526793cefa2a5a6921 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 11:56:04 -0700
+Subject: drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change
+
+From: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
+
+[ Upstream commit 262de94a3a7ef23c326534b3d9483602b7af841e ]
+
+The RCU_MODE_FIXED_SLICE_CCS_MODE setting is not getting invoked
+in the gt reset path after the ccs_mode setting by the user.
+Add it to engine register update list (in hw_engine_setup_default_state())
+which ensures it gets set in the gt reset and engine reset paths.
+
+v2: Add register update to engine list to ensure it gets updated
+after engine reset also.
+
+Fixes: 0d97ecce16bd ("drm/xe: Enable Fixed CCS mode setting")
+Cc: stable@vger.kernel.org
+Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Signed-off-by: Matthew Brost <matthew.brost@intel.com>
+Link: https://lore.kernel.org/r/20250327185604.18230-1-niranjana.vishwanathapura@intel.com
+(cherry picked from commit 12468e519f98e4d93370712e3607fab61df9dae9)
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_hw_engine.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
+index 223b95de388cb..b26b6fb5cdb5d 100644
+--- a/drivers/gpu/drm/xe/xe_hw_engine.c
++++ b/drivers/gpu/drm/xe/xe_hw_engine.c
+@@ -386,12 +386,6 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
+ blit_cctl_val,
+ XE_RTP_ACTION_FLAG(ENGINE_BASE)))
+ },
+- /* Use Fixed slice CCS mode */
+- { XE_RTP_NAME("RCU_MODE_FIXED_SLICE_CCS_MODE"),
+- XE_RTP_RULES(FUNC(xe_hw_engine_match_fixed_cslice_mode)),
+- XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE,
+- RCU_MODE_FIXED_SLICE_CCS_MODE))
+- },
+ /* Disable WMTP if HW doesn't support it */
+ { XE_RTP_NAME("DISABLE_WMTP_ON_UNSUPPORTED_HW"),
+ XE_RTP_RULES(FUNC(xe_rtp_cfeg_wmtp_disabled)),
+@@ -458,6 +452,12 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
+ XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0), CS_PRIORITY_MEM_READ,
+ XE_RTP_ACTION_FLAG(ENGINE_BASE)))
+ },
++ /* Use Fixed slice CCS mode */
++ { XE_RTP_NAME("RCU_MODE_FIXED_SLICE_CCS_MODE"),
++ XE_RTP_RULES(FUNC(xe_hw_engine_match_fixed_cslice_mode)),
++ XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE,
++ RCU_MODE_FIXED_SLICE_CCS_MODE))
++ },
+ };
+
+ xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries), &hwe->reg_sr);
+--
+2.39.5
+
--- /dev/null
+From 68b1acf9351779aaac1102c2826c747fbb4a1ffb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 15:13:23 +0100
+Subject: drm/xe/ptl: Apply Wa_14023061436
+
+From: Nirmoy Das <nirmoy.das@intel.com>
+
+[ Upstream commit 92029e0baa5313ba208103f90086f59070bbf93b ]
+
+Enable WMTP for the BTD kernel to address Wa14023061436 by setting the
+proper TDL Chicken Bit.
+
+v2: Apply it on engine_was[] as this register is not part of LRC(Matt)
+ Apply it for first_render_or_compute in case this gets extended to
+ compute only platforms(Matt).
+
+Cc: Gustavo Sousa <gustavo.sousa@intel.com>
+Cc: Matt Roper <matthew.d.roper@intel.com>
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250108141323.311601-1-nirmoy.das@intel.com
+Signed-off-by: Nirmoy Das <nirmoy.das@intel.com>
+Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/regs/xe_gt_regs.h | 3 +++
+ drivers/gpu/drm/xe/xe_wa.c | 5 +++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+index 162f18e975dae..b4283ac030f41 100644
+--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
++++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+@@ -500,6 +500,9 @@
+ #define LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK REG_GENMASK(13, 11)
+ #define DIS_ATOMIC_CHAINING_TYPED_WRITES REG_BIT(3)
+
++#define TDL_CHICKEN XE_REG_MCR(0xe5f4, XE_REG_OPTION_MASKED)
++#define QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE REG_BIT(12)
++
+ #define LSC_CHICKEN_BIT_0 XE_REG_MCR(0xe7c8)
+ #define DISABLE_D8_D16_COASLESCE REG_BIT(30)
+ #define WR_REQ_CHAINING_DIS REG_BIT(26)
+diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
+index 2553accf8c517..ac471e2454d34 100644
+--- a/drivers/gpu/drm/xe/xe_wa.c
++++ b/drivers/gpu/drm/xe/xe_wa.c
+@@ -613,6 +613,11 @@ static const struct xe_rtp_entry_sr engine_was[] = {
+ XE_RTP_ACTIONS(FIELD_SET(SAMPLER_MODE, SMP_WAIT_FETCH_MERGING_COUNTER,
+ SMP_FORCE_128B_OVERFETCH))
+ },
++ { XE_RTP_NAME("14023061436"),
++ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001),
++ FUNC(xe_rtp_match_first_render_or_compute)),
++ XE_RTP_ACTIONS(SET(TDL_CHICKEN, QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE))
++ },
+
+ {}
+ };
+--
+2.39.5
+
--- /dev/null
+From 65c01faede743e6ef965f56e0b7f2aa1201b924d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 20:00:05 -0800
+Subject: drm/xe/rtp: Drop sentinels from arg to xe_rtp_process_to_sr()
+
+From: Lucas De Marchi <lucas.demarchi@intel.com>
+
+[ Upstream commit cedf23842d7433eb32cb782a637bb870fb096a3b ]
+
+There's a mismatch on API: while xe_rtp_process_to_sr() processes
+entries until an entry without name, the active tracking with
+xe_rtp_process_ctx_enable_active_tracking() needs to use the number of
+elements. The number of elements is taken everywhere using ARRAY_SIZE(),
+but that will have one entry too many. This leads to the following
+warning, as reported by lkp:
+
+ drivers/gpu/drm/xe/xe_tuning.c: In function 'xe_tuning_dump':
+>> include/drm/drm_print.h:228:31: warning: '%s' directive argument is null [-Wformat-overflow=]
+ 228 | drm_printf((printer), "%.*s" fmt, (indent), "\t\t\t\t\tX", ##__VA_ARGS__)
+ | ^~~~~~
+ drivers/gpu/drm/xe/xe_tuning.c:226:17: note: in expansion of macro 'drm_printf_indent'
+ 226 | drm_printf_indent(p, 1, "%s\n", engine_tunings[idx].name);
+ | ^~~~~~~~~~~~~~~~~
+
+That's because it will still process the last entry when tracking the
+active tunings. The same issue exists in the WAs. Change
+xe_rtp_process_to_sr() to also take the number of elements so the empty
+entry can be removed and the warning should go away. Fixing on the
+active-tracking side would more fragile as the it would need a `- 1`
+everywhere and continue to use a different approach for number of
+elements.
+
+Aside from the warning, it's a non-issue as there would always be enough
+bits allocated and the last entry would never be active since
+xe_rtp_process_to_sr() stops on the sentinel.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202503021906.P2MwAvyK-lkp@intel.com/
+Cc: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
+Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250306-fix-print-warning-v1-1-979c3dc03c0d@intel.com
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+(cherry picked from commit 8aa8c2d4214e1771c32101d70740002662d31bb7)
+Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
+Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/tests/xe_rtp_test.c | 2 +-
+ drivers/gpu/drm/xe/xe_hw_engine.c | 6 ++----
+ drivers/gpu/drm/xe/xe_reg_whitelist.c | 4 ++--
+ drivers/gpu/drm/xe/xe_rtp.c | 6 +++++-
+ drivers/gpu/drm/xe/xe_rtp.h | 2 +-
+ drivers/gpu/drm/xe/xe_tuning.c | 12 ++++--------
+ drivers/gpu/drm/xe/xe_wa.c | 12 +++---------
+ 7 files changed, 18 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/xe/tests/xe_rtp_test.c b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
+index 36a3b5420fef6..b0254b014fe45 100644
+--- a/drivers/gpu/drm/xe/tests/xe_rtp_test.c
++++ b/drivers/gpu/drm/xe/tests/xe_rtp_test.c
+@@ -320,7 +320,7 @@ static void xe_rtp_process_to_sr_tests(struct kunit *test)
+ count_rtp_entries++;
+
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, &active, count_rtp_entries);
+- xe_rtp_process_to_sr(&ctx, param->entries, reg_sr);
++ xe_rtp_process_to_sr(&ctx, param->entries, count_rtp_entries, reg_sr);
+
+ xa_for_each(®_sr->xa, idx, sre) {
+ if (idx == param->expected_reg.addr)
+diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
+index fc447751fe786..223b95de388cb 100644
+--- a/drivers/gpu/drm/xe/xe_hw_engine.c
++++ b/drivers/gpu/drm/xe/xe_hw_engine.c
+@@ -400,10 +400,9 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
+ PREEMPT_GPGPU_THREAD_GROUP_LEVEL)),
+ XE_RTP_ENTRY_FLAG(FOREACH_ENGINE)
+ },
+- {}
+ };
+
+- xe_rtp_process_to_sr(&ctx, lrc_setup, &hwe->reg_lrc);
++ xe_rtp_process_to_sr(&ctx, lrc_setup, ARRAY_SIZE(lrc_setup), &hwe->reg_lrc);
+ }
+
+ static void
+@@ -459,10 +458,9 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
+ XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0), CS_PRIORITY_MEM_READ,
+ XE_RTP_ACTION_FLAG(ENGINE_BASE)))
+ },
+- {}
+ };
+
+- xe_rtp_process_to_sr(&ctx, engine_entries, &hwe->reg_sr);
++ xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries), &hwe->reg_sr);
+ }
+
+ static const struct engine_info *find_engine_info(enum xe_engine_class class, int instance)
+diff --git a/drivers/gpu/drm/xe/xe_reg_whitelist.c b/drivers/gpu/drm/xe/xe_reg_whitelist.c
+index edab5d4e3ba5e..23f6c81d99946 100644
+--- a/drivers/gpu/drm/xe/xe_reg_whitelist.c
++++ b/drivers/gpu/drm/xe/xe_reg_whitelist.c
+@@ -88,7 +88,6 @@ static const struct xe_rtp_entry_sr register_whitelist[] = {
+ RING_FORCE_TO_NONPRIV_ACCESS_RD |
+ RING_FORCE_TO_NONPRIV_RANGE_4))
+ },
+- {}
+ };
+
+ static void whitelist_apply_to_hwe(struct xe_hw_engine *hwe)
+@@ -137,7 +136,8 @@ void xe_reg_whitelist_process_engine(struct xe_hw_engine *hwe)
+ {
+ struct xe_rtp_process_ctx ctx = XE_RTP_PROCESS_CTX_INITIALIZER(hwe);
+
+- xe_rtp_process_to_sr(&ctx, register_whitelist, &hwe->reg_whitelist);
++ xe_rtp_process_to_sr(&ctx, register_whitelist, ARRAY_SIZE(register_whitelist),
++ &hwe->reg_whitelist);
+ whitelist_apply_to_hwe(hwe);
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c
+index 7a1c78fdfc92e..13bb62d3e615e 100644
+--- a/drivers/gpu/drm/xe/xe_rtp.c
++++ b/drivers/gpu/drm/xe/xe_rtp.c
+@@ -237,6 +237,7 @@ static void rtp_mark_active(struct xe_device *xe,
+ * the save-restore argument.
+ * @ctx: The context for processing the table, with one of device, gt or hwe
+ * @entries: Table with RTP definitions
++ * @n_entries: Number of entries to process, usually ARRAY_SIZE(entries)
+ * @sr: Save-restore struct where matching rules execute the action. This can be
+ * viewed as the "coalesced view" of multiple the tables. The bits for each
+ * register set are expected not to collide with previously added entries
+@@ -247,6 +248,7 @@ static void rtp_mark_active(struct xe_device *xe,
+ */
+ void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
+ const struct xe_rtp_entry_sr *entries,
++ size_t n_entries,
+ struct xe_reg_sr *sr)
+ {
+ const struct xe_rtp_entry_sr *entry;
+@@ -259,7 +261,9 @@ void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
+ if (IS_SRIOV_VF(xe))
+ return;
+
+- for (entry = entries; entry && entry->name; entry++) {
++ xe_assert(xe, entries);
++
++ for (entry = entries; entry - entries < n_entries; entry++) {
+ bool match = false;
+
+ if (entry->flags & XE_RTP_ENTRY_FLAG_FOREACH_ENGINE) {
+diff --git a/drivers/gpu/drm/xe/xe_rtp.h b/drivers/gpu/drm/xe/xe_rtp.h
+index 38b9f13bba5e5..4fe736a11c42b 100644
+--- a/drivers/gpu/drm/xe/xe_rtp.h
++++ b/drivers/gpu/drm/xe/xe_rtp.h
+@@ -430,7 +430,7 @@ void xe_rtp_process_ctx_enable_active_tracking(struct xe_rtp_process_ctx *ctx,
+
+ void xe_rtp_process_to_sr(struct xe_rtp_process_ctx *ctx,
+ const struct xe_rtp_entry_sr *entries,
+- struct xe_reg_sr *sr);
++ size_t n_entries, struct xe_reg_sr *sr);
+
+ void xe_rtp_process(struct xe_rtp_process_ctx *ctx,
+ const struct xe_rtp_entry *entries);
+diff --git a/drivers/gpu/drm/xe/xe_tuning.c b/drivers/gpu/drm/xe/xe_tuning.c
+index 23c46dd85e149..a61a2917590fe 100644
+--- a/drivers/gpu/drm/xe/xe_tuning.c
++++ b/drivers/gpu/drm/xe/xe_tuning.c
+@@ -85,8 +85,6 @@ static const struct xe_rtp_entry_sr gt_tunings[] = {
+ XE_RTP_RULES(MEDIA_VERSION(2000)),
+ XE_RTP_ACTIONS(SET(XE2LPM_SCRATCH3_LBCF, RWFLUSHALLEN))
+ },
+-
+- {}
+ };
+
+ static const struct xe_rtp_entry_sr engine_tunings[] = {
+@@ -95,7 +93,6 @@ static const struct xe_rtp_entry_sr engine_tunings[] = {
+ ENGINE_CLASS(RENDER)),
+ XE_RTP_ACTIONS(SET(SAMPLER_MODE, INDIRECT_STATE_BASE_ADDR_OVERRIDE))
+ },
+- {}
+ };
+
+ static const struct xe_rtp_entry_sr lrc_tunings[] = {
+@@ -133,8 +130,6 @@ static const struct xe_rtp_entry_sr lrc_tunings[] = {
+ XE_RTP_ACTIONS(FIELD_SET(FF_MODE, VS_HIT_MAX_VALUE_MASK,
+ REG_FIELD_PREP(VS_HIT_MAX_VALUE_MASK, 0x3f)))
+ },
+-
+- {}
+ };
+
+ /**
+@@ -175,7 +170,7 @@ void xe_tuning_process_gt(struct xe_gt *gt)
+ xe_rtp_process_ctx_enable_active_tracking(&ctx,
+ gt->tuning_active.gt,
+ ARRAY_SIZE(gt_tunings));
+- xe_rtp_process_to_sr(&ctx, gt_tunings, >->reg_sr);
++ xe_rtp_process_to_sr(&ctx, gt_tunings, ARRAY_SIZE(gt_tunings), >->reg_sr);
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_tuning_process_gt);
+
+@@ -186,7 +181,8 @@ void xe_tuning_process_engine(struct xe_hw_engine *hwe)
+ xe_rtp_process_ctx_enable_active_tracking(&ctx,
+ hwe->gt->tuning_active.engine,
+ ARRAY_SIZE(engine_tunings));
+- xe_rtp_process_to_sr(&ctx, engine_tunings, &hwe->reg_sr);
++ xe_rtp_process_to_sr(&ctx, engine_tunings, ARRAY_SIZE(engine_tunings),
++ &hwe->reg_sr);
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_tuning_process_engine);
+
+@@ -205,7 +201,7 @@ void xe_tuning_process_lrc(struct xe_hw_engine *hwe)
+ xe_rtp_process_ctx_enable_active_tracking(&ctx,
+ hwe->gt->tuning_active.lrc,
+ ARRAY_SIZE(lrc_tunings));
+- xe_rtp_process_to_sr(&ctx, lrc_tunings, &hwe->reg_lrc);
++ xe_rtp_process_to_sr(&ctx, lrc_tunings, ARRAY_SIZE(lrc_tunings), &hwe->reg_lrc);
+ }
+
+ void xe_tuning_dump(struct xe_gt *gt, struct drm_printer *p)
+diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
+index db99663963010..65bfb2f894d00 100644
+--- a/drivers/gpu/drm/xe/xe_wa.c
++++ b/drivers/gpu/drm/xe/xe_wa.c
+@@ -279,8 +279,6 @@ static const struct xe_rtp_entry_sr gt_was[] = {
+ XE_RTP_ACTIONS(SET(VDBOX_CGCTL3F10(0), RAMDFTUNIT_CLKGATE_DIS)),
+ XE_RTP_ENTRY_FLAG(FOREACH_ENGINE),
+ },
+-
+- {}
+ };
+
+ static const struct xe_rtp_entry_sr engine_was[] = {
+@@ -623,8 +621,6 @@ static const struct xe_rtp_entry_sr engine_was[] = {
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
+ },
+-
+- {}
+ };
+
+ static const struct xe_rtp_entry_sr lrc_was[] = {
+@@ -817,8 +813,6 @@ static const struct xe_rtp_entry_sr lrc_was[] = {
+ DIS_PARTIAL_AUTOSTRIP |
+ DIS_AUTOSTRIP))
+ },
+-
+- {}
+ };
+
+ static __maybe_unused const struct xe_rtp_entry oob_was[] = {
+@@ -860,7 +854,7 @@ void xe_wa_process_gt(struct xe_gt *gt)
+
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, gt->wa_active.gt,
+ ARRAY_SIZE(gt_was));
+- xe_rtp_process_to_sr(&ctx, gt_was, >->reg_sr);
++ xe_rtp_process_to_sr(&ctx, gt_was, ARRAY_SIZE(gt_was), >->reg_sr);
+ }
+ EXPORT_SYMBOL_IF_KUNIT(xe_wa_process_gt);
+
+@@ -878,7 +872,7 @@ void xe_wa_process_engine(struct xe_hw_engine *hwe)
+
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, hwe->gt->wa_active.engine,
+ ARRAY_SIZE(engine_was));
+- xe_rtp_process_to_sr(&ctx, engine_was, &hwe->reg_sr);
++ xe_rtp_process_to_sr(&ctx, engine_was, ARRAY_SIZE(engine_was), &hwe->reg_sr);
+ }
+
+ /**
+@@ -895,7 +889,7 @@ void xe_wa_process_lrc(struct xe_hw_engine *hwe)
+
+ xe_rtp_process_ctx_enable_active_tracking(&ctx, hwe->gt->wa_active.lrc,
+ ARRAY_SIZE(lrc_was));
+- xe_rtp_process_to_sr(&ctx, lrc_was, &hwe->reg_lrc);
++ xe_rtp_process_to_sr(&ctx, lrc_was, ARRAY_SIZE(lrc_was), &hwe->reg_lrc);
+ }
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From 70e253df8a141f3aba232f0e8c0af20988af4ff2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Feb 2025 16:52:00 +0530
+Subject: drm/xe/xe3lpg: Add Wa_13012615864
+
+From: Tejas Upadhyay <tejas.upadhyay@intel.com>
+
+[ Upstream commit 2399bcc07c01189737858e0a88ac4ffdd1d4b03d ]
+
+Wa_13012615864 applies to xe3lpg
+
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250221112200.388612-1-tejas.upadhyay@intel.com
+Signed-off-by: Tejas Upadhyay <tejas.upadhyay@intel.com>
+Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/regs/xe_gt_regs.h | 1 +
+ drivers/gpu/drm/xe/xe_wa.c | 5 +++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+index b4283ac030f41..d0ea8a55fd9c2 100644
+--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
++++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+@@ -475,6 +475,7 @@
+ #define TDL_TSL_CHICKEN XE_REG_MCR(0xe4c4, XE_REG_OPTION_MASKED)
+ #define STK_ID_RESTRICT REG_BIT(12)
+ #define SLM_WMTP_RESTORE REG_BIT(11)
++#define RES_CHK_SPR_DIS REG_BIT(6)
+
+ #define ROW_CHICKEN XE_REG_MCR(0xe4f0, XE_REG_OPTION_MASKED)
+ #define UGM_BACKUP_MODE REG_BIT(13)
+diff --git a/drivers/gpu/drm/xe/xe_wa.c b/drivers/gpu/drm/xe/xe_wa.c
+index ac471e2454d34..db99663963010 100644
+--- a/drivers/gpu/drm/xe/xe_wa.c
++++ b/drivers/gpu/drm/xe/xe_wa.c
+@@ -618,6 +618,11 @@ static const struct xe_rtp_entry_sr engine_was[] = {
+ FUNC(xe_rtp_match_first_render_or_compute)),
+ XE_RTP_ACTIONS(SET(TDL_CHICKEN, QID_WAIT_FOR_THREAD_NOT_RUN_DISABLE))
+ },
++ { XE_RTP_NAME("13012615864"),
++ XE_RTP_RULES(GRAPHICS_VERSION_RANGE(3000, 3001),
++ FUNC(xe_rtp_match_first_render_or_compute)),
++ XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
++ },
+
+ {}
+ };
+--
+2.39.5
+
--- /dev/null
+From f251bba0d699fdad2d59896495b5f3ed47e6236d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 18:00:29 -0300
+Subject: iio: adc: ad7768-1: Fix conversion result sign
+
+From: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+
+[ Upstream commit 8236644f5ecb180e80ad92d691c22bc509b747bb ]
+
+The ad7768-1 ADC output code is two's complement, meaning that the voltage
+conversion result is a signed value.. Since the value is a 24 bit one,
+stored in a 32 bit variable, the sign should be extended in order to get
+the correct representation.
+
+Also the channel description has been updated to signed representation,
+to match the ADC specifications.
+
+Fixes: a5f8c7da3dbe ("iio: adc: Add AD7768-1 ADC basic support")
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Reviewed-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
+Signed-off-by: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
+Cc: <Stable@vger.kernel.org>
+Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7768-1.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
+index c78243a68b6e0..157a0df97f971 100644
+--- a/drivers/iio/adc/ad7768-1.c
++++ b/drivers/iio/adc/ad7768-1.c
+@@ -142,7 +142,7 @@ static const struct iio_chan_spec ad7768_channels[] = {
+ .channel = 0,
+ .scan_index = 0,
+ .scan_type = {
+- .sign = 'u',
++ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ .shift = 8,
+@@ -374,7 +374,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
+- *val = ret;
++ *val = sign_extend32(ret, chan->scan_type.realbits - 1);
+
+ return IIO_VAL_INT;
+
+--
+2.39.5
+
--- /dev/null
+From 9261fdf9bd1370d4bbea0f7efd6a1dd146932392 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:16:12 +0000
+Subject: iio: adc: ad7768-1: Move setting of val a bit later to avoid
+ unnecessary return value check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 0af1c801a15225304a6328258efbf2bee245c654 ]
+
+The data used is all in local variables so there is no advantage
+in setting *val = ret with the direct mode claim held.
+Move it later to after error check.
+
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7768-1.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
+index 6f8816483f1a0..c78243a68b6e0 100644
+--- a/drivers/iio/adc/ad7768-1.c
++++ b/drivers/iio/adc/ad7768-1.c
+@@ -370,12 +370,11 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
+ return ret;
+
+ ret = ad7768_scan_direct(indio_dev);
+- if (ret >= 0)
+- *val = ret;
+
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
++ *val = ret;
+
+ return IIO_VAL_INT;
+
+--
+2.39.5
+
--- /dev/null
+From 5a96a94b338875c0e3b145df8638f6306eafdd24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 13:11:23 +0000
+Subject: irqchip/renesas-rzv2h: Add struct rzv2h_hw_info with t_offs variable
+
+From: Biju Das <biju.das.jz@bp.renesas.com>
+
+[ Upstream commit 0a9d6ef64e5e917f93db98935cd09bac38507ebf ]
+
+The ICU block on the RZ/G3E SoC is almost identical to the one found on
+the RZ/V2H SoC, with the following differences:
+
+ - The TINT register base offset is 0x800 instead of zero.
+ - The number of GPIO interrupts for TINT selection is 141 instead of 86.
+ - The pin index and TINT selection index are not in the 1:1 map
+ - The number of TSSR registers is 16 instead of 8
+ - Each TSSR register can program 2 TINTs instead of 4 TINTs
+
+Introduce struct rzv2h_hw_info to describe the SoC properties and refactor
+the code by moving rzv2h_icu_init() into rzv2h_icu_init_common() and pass
+the variable containing hw difference to support both these SoCs.
+
+As a first step add t_offs to the new struct and replace the hardcoded
+constants in the code.
+
+Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
+Reviewed-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/all/20250224131253.134199-8-biju.das.jz@bp.renesas.com
+Stable-dep-of: 28e89cdac648 ("irqchip/renesas-rzv2h: Prevent TINT spurious interrupt")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-renesas-rzv2h.c | 46 +++++++++++++++++++++--------
+ 1 file changed, 34 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
+index 6be38aa86f9b8..5fcc6ed4086cd 100644
+--- a/drivers/irqchip/irq-renesas-rzv2h.c
++++ b/drivers/irqchip/irq-renesas-rzv2h.c
+@@ -80,18 +80,28 @@
+ #define ICU_TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
+ #define ICU_PB5_TINT 0x55
+
++/**
++ * struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure.
++ * @t_offs: TINT offset
++ */
++struct rzv2h_hw_info {
++ u16 t_offs;
++};
++
+ /**
+ * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure.
+ * @base: Controller's base address
+ * @irqchip: Pointer to struct irq_chip
+ * @fwspec: IRQ firmware specific data
+ * @lock: Lock to serialize access to hardware registers
++ * @info: Pointer to struct rzv2h_hw_info
+ */
+ struct rzv2h_icu_priv {
+ void __iomem *base;
+ const struct irq_chip *irqchip;
+ struct irq_fwspec fwspec[ICU_NUM_IRQ];
+ raw_spinlock_t lock;
++ const struct rzv2h_hw_info *info;
+ };
+
+ static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data)
+@@ -111,7 +121,7 @@ static void rzv2h_icu_eoi(struct irq_data *d)
+ tintirq_nr = hw_irq - ICU_TINT_START;
+ bit = BIT(tintirq_nr);
+ if (!irqd_is_level_type(d))
+- writel_relaxed(bit, priv->base + ICU_TSCLR);
++ writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR);
+ } else if (hw_irq >= ICU_IRQ_START) {
+ tintirq_nr = hw_irq - ICU_IRQ_START;
+ bit = BIT(tintirq_nr);
+@@ -139,12 +149,12 @@ static void rzv2h_tint_irq_endisable(struct irq_data *d, bool enable)
+ tssel_n = ICU_TSSR_TSSEL_N(tint_nr);
+
+ guard(raw_spinlock)(&priv->lock);
+- tssr = readl_relaxed(priv->base + ICU_TSSR(k));
++ tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(k));
+ if (enable)
+ tssr |= ICU_TSSR_TIEN(tssel_n);
+ else
+ tssr &= ~ICU_TSSR_TIEN(tssel_n);
+- writel_relaxed(tssr, priv->base + ICU_TSSR(k));
++ writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(k));
+ }
+
+ static void rzv2h_icu_irq_disable(struct irq_data *d)
+@@ -247,8 +257,8 @@ static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq
+ u32 bit = BIT(tint_nr);
+ int k = tint_nr / 16;
+
+- tsctr = readl_relaxed(priv->base + ICU_TSCTR);
+- titsr = readl_relaxed(priv->base + ICU_TITSR(k));
++ tsctr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSCTR);
++ titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(k));
+ titsel = ICU_TITSR_TITSEL_GET(titsr, titsel_n);
+
+ /*
+@@ -257,7 +267,7 @@ static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq
+ */
+ if ((tsctr & bit) && ((titsel == ICU_TINT_EDGE_RISING) ||
+ (titsel == ICU_TINT_EDGE_FALLING)))
+- writel_relaxed(bit, priv->base + ICU_TSCLR);
++ writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR);
+ }
+
+ static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
+@@ -308,21 +318,21 @@ static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
+
+ guard(raw_spinlock)(&priv->lock);
+
+- tssr = readl_relaxed(priv->base + ICU_TSSR(tssr_k));
++ tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
+ tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n) | tien);
+ tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n);
+
+- writel_relaxed(tssr, priv->base + ICU_TSSR(tssr_k));
++ writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
+
+- titsr = readl_relaxed(priv->base + ICU_TITSR(titsr_k));
++ titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
+ titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n);
+ titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n);
+
+- writel_relaxed(titsr, priv->base + ICU_TITSR(titsr_k));
++ writel_relaxed(titsr, priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
+
+ rzv2h_clear_tint_int(priv, hwirq);
+
+- writel_relaxed(tssr | tien, priv->base + ICU_TSSR(tssr_k));
++ writel_relaxed(tssr | tien, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
+
+ return 0;
+ }
+@@ -426,7 +436,8 @@ static void rzv2h_icu_put_device(void *data)
+ put_device(data);
+ }
+
+-static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
++static int rzv2h_icu_init_common(struct device_node *node, struct device_node *parent,
++ const struct rzv2h_hw_info *hw_info)
+ {
+ struct irq_domain *irq_domain, *parent_domain;
+ struct rzv2h_icu_priv *rzv2h_icu_data;
+@@ -492,6 +503,8 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+ goto pm_put;
+ }
+
++ rzv2h_icu_data->info = hw_info;
++
+ /*
+ * coccicheck complains about a missing put_device call before returning, but it's a false
+ * positive. We still need &pdev->dev after successfully returning from this function.
+@@ -507,6 +520,15 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+ return ret;
+ }
+
++static const struct rzv2h_hw_info rzv2h_hw_params = {
++ .t_offs = 0,
++};
++
++static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
++{
++ return rzv2h_icu_init_common(node, parent, &rzv2h_hw_params);
++}
++
+ IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu)
+ IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_init)
+ IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu)
+--
+2.39.5
+
--- /dev/null
+From dd482d36ba426ba338c97dab13b91be003b10cbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Apr 2025 11:33:41 +0100
+Subject: irqchip/renesas-rzv2h: Prevent TINT spurious interrupt
+
+From: Biju Das <biju.das.jz@bp.renesas.com>
+
+[ Upstream commit 28e89cdac6482f3c980df3e2e245db7366269124 ]
+
+A spurious TINT interrupt is seen during boot on RZ/G3E SMARC EVK.
+
+A glitch in the edge detection circuit can cause a spurious interrupt.
+
+Clear the status flag after setting the ICU_TSSRk registers, which is
+recommended in the hardware manual as a countermeasure.
+
+Fixes: 0d7605e75ac2 ("irqchip: Add RZ/V2H(P) Interrupt Control Unit (ICU) driver")
+Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-renesas-rzv2h.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
+index 5fcc6ed4086cd..21d01ce2da5cf 100644
+--- a/drivers/irqchip/irq-renesas-rzv2h.c
++++ b/drivers/irqchip/irq-renesas-rzv2h.c
+@@ -155,6 +155,14 @@ static void rzv2h_tint_irq_endisable(struct irq_data *d, bool enable)
+ else
+ tssr &= ~ICU_TSSR_TIEN(tssel_n);
+ writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(k));
++
++ /*
++ * A glitch in the edge detection circuit can cause a spurious
++ * interrupt. Clear the status flag after setting the ICU_TSSRk
++ * registers, which is recommended by the hardware manual as a
++ * countermeasure.
++ */
++ writel_relaxed(BIT(tint_nr), priv->base + priv->info->t_offs + ICU_TSCLR);
+ }
+
+ static void rzv2h_icu_irq_disable(struct irq_data *d)
+--
+2.39.5
+
--- /dev/null
+From 1b063148ab837edfe205f3e57f3dcad16ee736c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 13:11:20 +0000
+Subject: irqchip/renesas-rzv2h: Simplify rzv2h_icu_init()
+
+From: Biju Das <biju.das.jz@bp.renesas.com>
+
+[ Upstream commit f5de95438834a3bc3ad747f67c9da93cd08e5008 ]
+
+Use devm_add_action_or_reset() for calling put_device in error path of
+rzv2h_icu_init() to simplify the code by using the recently added devm_*
+helpers.
+
+Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Link: https://lore.kernel.org/all/20250224131253.134199-5-biju.das.jz@bp.renesas.com
+Stable-dep-of: 28e89cdac648 ("irqchip/renesas-rzv2h: Prevent TINT spurious interrupt")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/irqchip/irq-renesas-rzv2h.c | 37 +++++++++++++++--------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c
+index f6363246a71a0..6be38aa86f9b8 100644
+--- a/drivers/irqchip/irq-renesas-rzv2h.c
++++ b/drivers/irqchip/irq-renesas-rzv2h.c
+@@ -421,6 +421,11 @@ static int rzv2h_icu_parse_interrupts(struct rzv2h_icu_priv *priv, struct device
+ return 0;
+ }
+
++static void rzv2h_icu_put_device(void *data)
++{
++ put_device(data);
++}
++
+ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+ {
+ struct irq_domain *irq_domain, *parent_domain;
+@@ -433,43 +438,41 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+ if (!pdev)
+ return -ENODEV;
+
++ ret = devm_add_action_or_reset(&pdev->dev, rzv2h_icu_put_device,
++ &pdev->dev);
++ if (ret < 0)
++ return ret;
++
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ dev_err(&pdev->dev, "cannot find parent domain\n");
+- ret = -ENODEV;
+- goto put_dev;
++ return -ENODEV;
+ }
+
+ rzv2h_icu_data = devm_kzalloc(&pdev->dev, sizeof(*rzv2h_icu_data), GFP_KERNEL);
+- if (!rzv2h_icu_data) {
+- ret = -ENOMEM;
+- goto put_dev;
+- }
++ if (!rzv2h_icu_data)
++ return -ENOMEM;
+
+ rzv2h_icu_data->irqchip = &rzv2h_icu_chip;
+
+ rzv2h_icu_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
+- if (IS_ERR(rzv2h_icu_data->base)) {
+- ret = PTR_ERR(rzv2h_icu_data->base);
+- goto put_dev;
+- }
++ if (IS_ERR(rzv2h_icu_data->base))
++ return PTR_ERR(rzv2h_icu_data->base);
+
+ ret = rzv2h_icu_parse_interrupts(rzv2h_icu_data, node);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
+- goto put_dev;
++ return ret;
+ }
+
+ resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+- if (IS_ERR(resetn)) {
+- ret = PTR_ERR(resetn);
+- goto put_dev;
+- }
++ if (IS_ERR(resetn))
++ return PTR_ERR(resetn);
+
+ ret = reset_control_deassert(resetn);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret);
+- goto put_dev;
++ return ret;
+ }
+
+ pm_runtime_enable(&pdev->dev);
+@@ -500,8 +503,6 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
+ pm_disable:
+ pm_runtime_disable(&pdev->dev);
+ reset_control_assert(resetn);
+-put_dev:
+- put_device(&pdev->dev);
+
+ return ret;
+ }
+--
+2.39.5
+
--- /dev/null
+From 559e377ae6ac36746e3d33d8d6a0f65c11bfe0fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Apr 2025 15:00:59 -0700
+Subject: lib/Kconfig.ubsan: Remove 'default UBSAN' from UBSAN_INTEGER_WRAP
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit cdc2e1d9d929d7f7009b3a5edca52388a2b0891f ]
+
+CONFIG_UBSAN_INTEGER_WRAP is 'default UBSAN', which is problematic for a
+couple of reasons.
+
+The first is that this sanitizer is under active development on the
+compiler side to come up with a solution that is maintainable on the
+compiler side and usable on the kernel side. As a result of this, there
+are many warnings when the sanitizer is enabled that have no clear path
+to resolution yet but users may see them and report them in the meantime.
+
+The second is that this option was renamed from
+CONFIG_UBSAN_SIGNED_WRAP, meaning that if a configuration has
+CONFIG_UBSAN=y but CONFIG_UBSAN_SIGNED_WRAP=n and it is upgraded via
+olddefconfig (common in non-interactive scenarios such as CI),
+CONFIG_UBSAN_INTEGER_WRAP will be silently enabled again.
+
+Remove 'default UBSAN' from CONFIG_UBSAN_INTEGER_WRAP until it is ready
+for regular usage and testing from a broader community than the folks
+actively working on the feature.
+
+Cc: stable@vger.kernel.org
+Fixes: 557f8c582a9b ("ubsan: Reintroduce signed overflow sanitizer")
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Link: https://lore.kernel.org/r/20250414-drop-default-ubsan-integer-wrap-v1-1-392522551d6b@kernel.org
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/Kconfig.ubsan | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan
+index 63e5622010e0f..37b2839bd442f 100644
+--- a/lib/Kconfig.ubsan
++++ b/lib/Kconfig.ubsan
+@@ -118,7 +118,6 @@ config UBSAN_UNREACHABLE
+
+ config UBSAN_INTEGER_WRAP
+ bool "Perform checking for integer arithmetic wrap-around"
+- default UBSAN
+ depends on !COMPILE_TEST
+ depends on $(cc-option,-fsanitize=signed-integer-overflow)
+ depends on $(cc-option,-fsanitize=unsigned-integer-overflow)
+--
+2.39.5
+
--- /dev/null
+From 9811d7f6f8dbabda22c5061daec604201c1af696 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 14:26:05 +0100
+Subject: media: i2c: imx214: Check number of lanes from device tree
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Apitzsch <git@apitzsch.eu>
+
+[ Upstream commit 3d55f4eb03fce69f3a72615fe9c5ca171f7b846b ]
+
+The imx214 camera is capable of either two-lane or four-lane operation.
+
+Currently only the four-lane mode is supported, as proper pixel rates
+and link frequences for the two-lane mode are unknown.
+
+Acked-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: André Apitzsch <git@apitzsch.eu>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx214.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
+index 8bac5a1f1cb18..fdc2dfb4ebcdd 100644
+--- a/drivers/media/i2c/imx214.c
++++ b/drivers/media/i2c/imx214.c
+@@ -197,7 +197,6 @@ struct imx214 {
+
+ /*From imx214_mode_tbls.h*/
+ static const struct cci_reg_sequence mode_4096x2304[] = {
+- { IMX214_REG_CSI_LANE_MODE, IMX214_CSI_4_LANE_MODE },
+ { IMX214_REG_HDR_MODE, IMX214_HDR_MODE_OFF },
+ { IMX214_REG_HDR_RES_REDUCTION, IMX214_HDR_RES_REDU_THROUGH },
+ { IMX214_REG_EXPOSURE_RATIO, 1 },
+@@ -271,7 +270,6 @@ static const struct cci_reg_sequence mode_4096x2304[] = {
+ };
+
+ static const struct cci_reg_sequence mode_1920x1080[] = {
+- { IMX214_REG_CSI_LANE_MODE, IMX214_CSI_4_LANE_MODE },
+ { IMX214_REG_HDR_MODE, IMX214_HDR_MODE_OFF },
+ { IMX214_REG_HDR_RES_REDUCTION, IMX214_HDR_RES_REDU_THROUGH },
+ { IMX214_REG_EXPOSURE_RATIO, 1 },
+@@ -789,6 +787,13 @@ static int imx214_start_streaming(struct imx214 *imx214)
+ return ret;
+ }
+
++ ret = cci_write(imx214->regmap, IMX214_REG_CSI_LANE_MODE,
++ IMX214_CSI_4_LANE_MODE, NULL);
++ if (ret) {
++ dev_err(imx214->dev, "failed to configure lanes\n");
++ return ret;
++ }
++
+ state = v4l2_subdev_get_locked_active_state(&imx214->sd);
+ fmt = v4l2_subdev_state_get_format(state, 0);
+ mode = v4l2_find_nearest_size(imx214_modes, ARRAY_SIZE(imx214_modes),
+@@ -953,6 +958,13 @@ static int imx214_parse_fwnode(struct device *dev)
+ goto done;
+ }
+
++ /* Check the number of MIPI CSI2 data lanes */
++ if (bus_cfg.bus.mipi_csi2.num_data_lanes != 4) {
++ ret = dev_err_probe(dev, -EINVAL,
++ "only 4 data lanes are currently supported\n");
++ goto done;
++ }
++
+ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
+ if (bus_cfg.link_frequencies[i] == IMX214_DEFAULT_LINK_FREQ)
+ break;
+--
+2.39.5
+
--- /dev/null
+From 868252bb20620a9c5788c35232652871a8f4ff5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 14:26:02 +0100
+Subject: media: i2c: imx214: Convert to CCI register access helpers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Apitzsch <git@apitzsch.eu>
+
+[ Upstream commit 4f0aeba4f1556f829f09073bf267093c5b6f1821 ]
+
+Use the new common CCI register access helpers to replace the private
+register access helpers in the imx214 driver. This simplifies the driver
+by reducing the amount of code.
+
+Acked-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: André Apitzsch <git@apitzsch.eu>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/Kconfig | 1 +
+ drivers/media/i2c/imx214.c | 672 +++++++++++++++++--------------------
+ 2 files changed, 310 insertions(+), 363 deletions(-)
+
+diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
+index 8ba096b8ebca2..85ecb2aeefdbf 100644
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -140,6 +140,7 @@ config VIDEO_IMX214
+ tristate "Sony IMX214 sensor support"
+ depends on GPIOLIB
+ select REGMAP_I2C
++ select V4L2_CCI_I2C
+ help
+ This is a Video4Linux2 sensor driver for the Sony
+ IMX214 camera.
+diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
+index db6cdc3b65e37..20d1ebebf13af 100644
+--- a/drivers/media/i2c/imx214.c
++++ b/drivers/media/i2c/imx214.c
+@@ -15,11 +15,12 @@
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+ #include <media/media-entity.h>
++#include <media/v4l2-cci.h>
+ #include <media/v4l2-ctrls.h>
+ #include <media/v4l2-fwnode.h>
+ #include <media/v4l2-subdev.h>
+
+-#define IMX214_REG_MODE_SELECT 0x0100
++#define IMX214_REG_MODE_SELECT CCI_REG8(0x0100)
+ #define IMX214_MODE_STANDBY 0x00
+ #define IMX214_MODE_STREAMING 0x01
+
+@@ -30,7 +31,7 @@
+ #define IMX214_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10
+
+ /* Exposure control */
+-#define IMX214_REG_EXPOSURE 0x0202
++#define IMX214_REG_EXPOSURE CCI_REG16(0x0202)
+ #define IMX214_EXPOSURE_MIN 0
+ #define IMX214_EXPOSURE_MAX 3184
+ #define IMX214_EXPOSURE_STEP 1
+@@ -71,345 +72,324 @@ struct imx214 {
+ struct gpio_desc *enable_gpio;
+ };
+
+-struct reg_8 {
+- u16 addr;
+- u8 val;
+-};
+-
+-enum {
+- IMX214_TABLE_WAIT_MS = 0,
+- IMX214_TABLE_END,
+- IMX214_MAX_RETRIES,
+- IMX214_WAIT_MS
+-};
+-
+ /*From imx214_mode_tbls.h*/
+-static const struct reg_8 mode_4096x2304[] = {
+- {0x0114, 0x03},
+- {0x0220, 0x00},
+- {0x0221, 0x11},
+- {0x0222, 0x01},
+- {0x0340, 0x0C},
+- {0x0341, 0x7A},
+- {0x0342, 0x13},
+- {0x0343, 0x90},
+- {0x0344, 0x00},
+- {0x0345, 0x38},
+- {0x0346, 0x01},
+- {0x0347, 0x98},
+- {0x0348, 0x10},
+- {0x0349, 0x37},
+- {0x034A, 0x0A},
+- {0x034B, 0x97},
+- {0x0381, 0x01},
+- {0x0383, 0x01},
+- {0x0385, 0x01},
+- {0x0387, 0x01},
+- {0x0900, 0x00},
+- {0x0901, 0x00},
+- {0x0902, 0x00},
+- {0x3000, 0x35},
+- {0x3054, 0x01},
+- {0x305C, 0x11},
+-
+- {0x0112, 0x0A},
+- {0x0113, 0x0A},
+- {0x034C, 0x10},
+- {0x034D, 0x00},
+- {0x034E, 0x09},
+- {0x034F, 0x00},
+- {0x0401, 0x00},
+- {0x0404, 0x00},
+- {0x0405, 0x10},
+- {0x0408, 0x00},
+- {0x0409, 0x00},
+- {0x040A, 0x00},
+- {0x040B, 0x00},
+- {0x040C, 0x10},
+- {0x040D, 0x00},
+- {0x040E, 0x09},
+- {0x040F, 0x00},
+-
+- {0x0301, 0x05},
+- {0x0303, 0x02},
+- {0x0305, 0x03},
+- {0x0306, 0x00},
+- {0x0307, 0x96},
+- {0x0309, 0x0A},
+- {0x030B, 0x01},
+- {0x0310, 0x00},
+-
+- {0x0820, 0x12},
+- {0x0821, 0xC0},
+- {0x0822, 0x00},
+- {0x0823, 0x00},
+-
+- {0x3A03, 0x09},
+- {0x3A04, 0x50},
+- {0x3A05, 0x01},
+-
+- {0x0B06, 0x01},
+- {0x30A2, 0x00},
+-
+- {0x30B4, 0x00},
+-
+- {0x3A02, 0xFF},
+-
+- {0x3011, 0x00},
+- {0x3013, 0x01},
+-
+- {0x0202, 0x0C},
+- {0x0203, 0x70},
+- {0x0224, 0x01},
+- {0x0225, 0xF4},
+-
+- {0x0204, 0x00},
+- {0x0205, 0x00},
+- {0x020E, 0x01},
+- {0x020F, 0x00},
+- {0x0210, 0x01},
+- {0x0211, 0x00},
+- {0x0212, 0x01},
+- {0x0213, 0x00},
+- {0x0214, 0x01},
+- {0x0215, 0x00},
+- {0x0216, 0x00},
+- {0x0217, 0x00},
+-
+- {0x4170, 0x00},
+- {0x4171, 0x10},
+- {0x4176, 0x00},
+- {0x4177, 0x3C},
+- {0xAE20, 0x04},
+- {0xAE21, 0x5C},
+-
+- {IMX214_TABLE_WAIT_MS, 10},
+- {0x0138, 0x01},
+- {IMX214_TABLE_END, 0x00}
++static const struct cci_reg_sequence mode_4096x2304[] = {
++ { CCI_REG8(0x0114), 0x03 },
++ { CCI_REG8(0x0220), 0x00 },
++ { CCI_REG8(0x0221), 0x11 },
++ { CCI_REG8(0x0222), 0x01 },
++ { CCI_REG8(0x0340), 0x0C },
++ { CCI_REG8(0x0341), 0x7A },
++ { CCI_REG8(0x0342), 0x13 },
++ { CCI_REG8(0x0343), 0x90 },
++ { CCI_REG8(0x0344), 0x00 },
++ { CCI_REG8(0x0345), 0x38 },
++ { CCI_REG8(0x0346), 0x01 },
++ { CCI_REG8(0x0347), 0x98 },
++ { CCI_REG8(0x0348), 0x10 },
++ { CCI_REG8(0x0349), 0x37 },
++ { CCI_REG8(0x034A), 0x0A },
++ { CCI_REG8(0x034B), 0x97 },
++ { CCI_REG8(0x0381), 0x01 },
++ { CCI_REG8(0x0383), 0x01 },
++ { CCI_REG8(0x0385), 0x01 },
++ { CCI_REG8(0x0387), 0x01 },
++ { CCI_REG8(0x0900), 0x00 },
++ { CCI_REG8(0x0901), 0x00 },
++ { CCI_REG8(0x0902), 0x00 },
++ { CCI_REG8(0x3000), 0x35 },
++ { CCI_REG8(0x3054), 0x01 },
++ { CCI_REG8(0x305C), 0x11 },
++
++ { CCI_REG8(0x0112), 0x0A },
++ { CCI_REG8(0x0113), 0x0A },
++ { CCI_REG8(0x034C), 0x10 },
++ { CCI_REG8(0x034D), 0x00 },
++ { CCI_REG8(0x034E), 0x09 },
++ { CCI_REG8(0x034F), 0x00 },
++ { CCI_REG8(0x0401), 0x00 },
++ { CCI_REG8(0x0404), 0x00 },
++ { CCI_REG8(0x0405), 0x10 },
++ { CCI_REG8(0x0408), 0x00 },
++ { CCI_REG8(0x0409), 0x00 },
++ { CCI_REG8(0x040A), 0x00 },
++ { CCI_REG8(0x040B), 0x00 },
++ { CCI_REG8(0x040C), 0x10 },
++ { CCI_REG8(0x040D), 0x00 },
++ { CCI_REG8(0x040E), 0x09 },
++ { CCI_REG8(0x040F), 0x00 },
++
++ { CCI_REG8(0x0301), 0x05 },
++ { CCI_REG8(0x0303), 0x02 },
++ { CCI_REG8(0x0305), 0x03 },
++ { CCI_REG8(0x0306), 0x00 },
++ { CCI_REG8(0x0307), 0x96 },
++ { CCI_REG8(0x0309), 0x0A },
++ { CCI_REG8(0x030B), 0x01 },
++ { CCI_REG8(0x0310), 0x00 },
++
++ { CCI_REG8(0x0820), 0x12 },
++ { CCI_REG8(0x0821), 0xC0 },
++ { CCI_REG8(0x0822), 0x00 },
++ { CCI_REG8(0x0823), 0x00 },
++
++ { CCI_REG8(0x3A03), 0x09 },
++ { CCI_REG8(0x3A04), 0x50 },
++ { CCI_REG8(0x3A05), 0x01 },
++
++ { CCI_REG8(0x0B06), 0x01 },
++ { CCI_REG8(0x30A2), 0x00 },
++
++ { CCI_REG8(0x30B4), 0x00 },
++
++ { CCI_REG8(0x3A02), 0xFF },
++
++ { CCI_REG8(0x3011), 0x00 },
++ { CCI_REG8(0x3013), 0x01 },
++
++ { CCI_REG8(0x0202), 0x0C },
++ { CCI_REG8(0x0203), 0x70 },
++ { CCI_REG8(0x0224), 0x01 },
++ { CCI_REG8(0x0225), 0xF4 },
++
++ { CCI_REG8(0x0204), 0x00 },
++ { CCI_REG8(0x0205), 0x00 },
++ { CCI_REG8(0x020E), 0x01 },
++ { CCI_REG8(0x020F), 0x00 },
++ { CCI_REG8(0x0210), 0x01 },
++ { CCI_REG8(0x0211), 0x00 },
++ { CCI_REG8(0x0212), 0x01 },
++ { CCI_REG8(0x0213), 0x00 },
++ { CCI_REG8(0x0214), 0x01 },
++ { CCI_REG8(0x0215), 0x00 },
++ { CCI_REG8(0x0216), 0x00 },
++ { CCI_REG8(0x0217), 0x00 },
++
++ { CCI_REG8(0x4170), 0x00 },
++ { CCI_REG8(0x4171), 0x10 },
++ { CCI_REG8(0x4176), 0x00 },
++ { CCI_REG8(0x4177), 0x3C },
++ { CCI_REG8(0xAE20), 0x04 },
++ { CCI_REG8(0xAE21), 0x5C },
+ };
+
+-static const struct reg_8 mode_1920x1080[] = {
+- {0x0114, 0x03},
+- {0x0220, 0x00},
+- {0x0221, 0x11},
+- {0x0222, 0x01},
+- {0x0340, 0x0C},
+- {0x0341, 0x7A},
+- {0x0342, 0x13},
+- {0x0343, 0x90},
+- {0x0344, 0x04},
+- {0x0345, 0x78},
+- {0x0346, 0x03},
+- {0x0347, 0xFC},
+- {0x0348, 0x0B},
+- {0x0349, 0xF7},
+- {0x034A, 0x08},
+- {0x034B, 0x33},
+- {0x0381, 0x01},
+- {0x0383, 0x01},
+- {0x0385, 0x01},
+- {0x0387, 0x01},
+- {0x0900, 0x00},
+- {0x0901, 0x00},
+- {0x0902, 0x00},
+- {0x3000, 0x35},
+- {0x3054, 0x01},
+- {0x305C, 0x11},
+-
+- {0x0112, 0x0A},
+- {0x0113, 0x0A},
+- {0x034C, 0x07},
+- {0x034D, 0x80},
+- {0x034E, 0x04},
+- {0x034F, 0x38},
+- {0x0401, 0x00},
+- {0x0404, 0x00},
+- {0x0405, 0x10},
+- {0x0408, 0x00},
+- {0x0409, 0x00},
+- {0x040A, 0x00},
+- {0x040B, 0x00},
+- {0x040C, 0x07},
+- {0x040D, 0x80},
+- {0x040E, 0x04},
+- {0x040F, 0x38},
+-
+- {0x0301, 0x05},
+- {0x0303, 0x02},
+- {0x0305, 0x03},
+- {0x0306, 0x00},
+- {0x0307, 0x96},
+- {0x0309, 0x0A},
+- {0x030B, 0x01},
+- {0x0310, 0x00},
+-
+- {0x0820, 0x12},
+- {0x0821, 0xC0},
+- {0x0822, 0x00},
+- {0x0823, 0x00},
+-
+- {0x3A03, 0x04},
+- {0x3A04, 0xF8},
+- {0x3A05, 0x02},
+-
+- {0x0B06, 0x01},
+- {0x30A2, 0x00},
+-
+- {0x30B4, 0x00},
+-
+- {0x3A02, 0xFF},
+-
+- {0x3011, 0x00},
+- {0x3013, 0x01},
+-
+- {0x0202, 0x0C},
+- {0x0203, 0x70},
+- {0x0224, 0x01},
+- {0x0225, 0xF4},
+-
+- {0x0204, 0x00},
+- {0x0205, 0x00},
+- {0x020E, 0x01},
+- {0x020F, 0x00},
+- {0x0210, 0x01},
+- {0x0211, 0x00},
+- {0x0212, 0x01},
+- {0x0213, 0x00},
+- {0x0214, 0x01},
+- {0x0215, 0x00},
+- {0x0216, 0x00},
+- {0x0217, 0x00},
+-
+- {0x4170, 0x00},
+- {0x4171, 0x10},
+- {0x4176, 0x00},
+- {0x4177, 0x3C},
+- {0xAE20, 0x04},
+- {0xAE21, 0x5C},
+-
+- {IMX214_TABLE_WAIT_MS, 10},
+- {0x0138, 0x01},
+- {IMX214_TABLE_END, 0x00}
++static const struct cci_reg_sequence mode_1920x1080[] = {
++ { CCI_REG8(0x0114), 0x03 },
++ { CCI_REG8(0x0220), 0x00 },
++ { CCI_REG8(0x0221), 0x11 },
++ { CCI_REG8(0x0222), 0x01 },
++ { CCI_REG8(0x0340), 0x0C },
++ { CCI_REG8(0x0341), 0x7A },
++ { CCI_REG8(0x0342), 0x13 },
++ { CCI_REG8(0x0343), 0x90 },
++ { CCI_REG8(0x0344), 0x04 },
++ { CCI_REG8(0x0345), 0x78 },
++ { CCI_REG8(0x0346), 0x03 },
++ { CCI_REG8(0x0347), 0xFC },
++ { CCI_REG8(0x0348), 0x0B },
++ { CCI_REG8(0x0349), 0xF7 },
++ { CCI_REG8(0x034A), 0x08 },
++ { CCI_REG8(0x034B), 0x33 },
++ { CCI_REG8(0x0381), 0x01 },
++ { CCI_REG8(0x0383), 0x01 },
++ { CCI_REG8(0x0385), 0x01 },
++ { CCI_REG8(0x0387), 0x01 },
++ { CCI_REG8(0x0900), 0x00 },
++ { CCI_REG8(0x0901), 0x00 },
++ { CCI_REG8(0x0902), 0x00 },
++ { CCI_REG8(0x3000), 0x35 },
++ { CCI_REG8(0x3054), 0x01 },
++ { CCI_REG8(0x305C), 0x11 },
++
++ { CCI_REG8(0x0112), 0x0A },
++ { CCI_REG8(0x0113), 0x0A },
++ { CCI_REG8(0x034C), 0x07 },
++ { CCI_REG8(0x034D), 0x80 },
++ { CCI_REG8(0x034E), 0x04 },
++ { CCI_REG8(0x034F), 0x38 },
++ { CCI_REG8(0x0401), 0x00 },
++ { CCI_REG8(0x0404), 0x00 },
++ { CCI_REG8(0x0405), 0x10 },
++ { CCI_REG8(0x0408), 0x00 },
++ { CCI_REG8(0x0409), 0x00 },
++ { CCI_REG8(0x040A), 0x00 },
++ { CCI_REG8(0x040B), 0x00 },
++ { CCI_REG8(0x040C), 0x07 },
++ { CCI_REG8(0x040D), 0x80 },
++ { CCI_REG8(0x040E), 0x04 },
++ { CCI_REG8(0x040F), 0x38 },
++
++ { CCI_REG8(0x0301), 0x05 },
++ { CCI_REG8(0x0303), 0x02 },
++ { CCI_REG8(0x0305), 0x03 },
++ { CCI_REG8(0x0306), 0x00 },
++ { CCI_REG8(0x0307), 0x96 },
++ { CCI_REG8(0x0309), 0x0A },
++ { CCI_REG8(0x030B), 0x01 },
++ { CCI_REG8(0x0310), 0x00 },
++
++ { CCI_REG8(0x0820), 0x12 },
++ { CCI_REG8(0x0821), 0xC0 },
++ { CCI_REG8(0x0822), 0x00 },
++ { CCI_REG8(0x0823), 0x00 },
++
++ { CCI_REG8(0x3A03), 0x04 },
++ { CCI_REG8(0x3A04), 0xF8 },
++ { CCI_REG8(0x3A05), 0x02 },
++
++ { CCI_REG8(0x0B06), 0x01 },
++ { CCI_REG8(0x30A2), 0x00 },
++
++ { CCI_REG8(0x30B4), 0x00 },
++
++ { CCI_REG8(0x3A02), 0xFF },
++
++ { CCI_REG8(0x3011), 0x00 },
++ { CCI_REG8(0x3013), 0x01 },
++
++ { CCI_REG8(0x0202), 0x0C },
++ { CCI_REG8(0x0203), 0x70 },
++ { CCI_REG8(0x0224), 0x01 },
++ { CCI_REG8(0x0225), 0xF4 },
++
++ { CCI_REG8(0x0204), 0x00 },
++ { CCI_REG8(0x0205), 0x00 },
++ { CCI_REG8(0x020E), 0x01 },
++ { CCI_REG8(0x020F), 0x00 },
++ { CCI_REG8(0x0210), 0x01 },
++ { CCI_REG8(0x0211), 0x00 },
++ { CCI_REG8(0x0212), 0x01 },
++ { CCI_REG8(0x0213), 0x00 },
++ { CCI_REG8(0x0214), 0x01 },
++ { CCI_REG8(0x0215), 0x00 },
++ { CCI_REG8(0x0216), 0x00 },
++ { CCI_REG8(0x0217), 0x00 },
++
++ { CCI_REG8(0x4170), 0x00 },
++ { CCI_REG8(0x4171), 0x10 },
++ { CCI_REG8(0x4176), 0x00 },
++ { CCI_REG8(0x4177), 0x3C },
++ { CCI_REG8(0xAE20), 0x04 },
++ { CCI_REG8(0xAE21), 0x5C },
+ };
+
+-static const struct reg_8 mode_table_common[] = {
++static const struct cci_reg_sequence mode_table_common[] = {
+ /* software reset */
+
+ /* software standby settings */
+- {0x0100, 0x00},
++ { CCI_REG8(0x0100), 0x00 },
+
+ /* ATR setting */
+- {0x9300, 0x02},
++ { CCI_REG8(0x9300), 0x02 },
+
+ /* external clock setting */
+- {0x0136, 0x18},
+- {0x0137, 0x00},
++ { CCI_REG8(0x0136), 0x18 },
++ { CCI_REG8(0x0137), 0x00 },
+
+ /* global setting */
+ /* basic config */
+- {0x0101, 0x00},
+- {0x0105, 0x01},
+- {0x0106, 0x01},
+- {0x4550, 0x02},
+- {0x4601, 0x00},
+- {0x4642, 0x05},
+- {0x6227, 0x11},
+- {0x6276, 0x00},
+- {0x900E, 0x06},
+- {0xA802, 0x90},
+- {0xA803, 0x11},
+- {0xA804, 0x62},
+- {0xA805, 0x77},
+- {0xA806, 0xAE},
+- {0xA807, 0x34},
+- {0xA808, 0xAE},
+- {0xA809, 0x35},
+- {0xA80A, 0x62},
+- {0xA80B, 0x83},
+- {0xAE33, 0x00},
++ { CCI_REG8(0x0101), 0x00 },
++ { CCI_REG8(0x0105), 0x01 },
++ { CCI_REG8(0x0106), 0x01 },
++ { CCI_REG8(0x4550), 0x02 },
++ { CCI_REG8(0x4601), 0x00 },
++ { CCI_REG8(0x4642), 0x05 },
++ { CCI_REG8(0x6227), 0x11 },
++ { CCI_REG8(0x6276), 0x00 },
++ { CCI_REG8(0x900E), 0x06 },
++ { CCI_REG8(0xA802), 0x90 },
++ { CCI_REG8(0xA803), 0x11 },
++ { CCI_REG8(0xA804), 0x62 },
++ { CCI_REG8(0xA805), 0x77 },
++ { CCI_REG8(0xA806), 0xAE },
++ { CCI_REG8(0xA807), 0x34 },
++ { CCI_REG8(0xA808), 0xAE },
++ { CCI_REG8(0xA809), 0x35 },
++ { CCI_REG8(0xA80A), 0x62 },
++ { CCI_REG8(0xA80B), 0x83 },
++ { CCI_REG8(0xAE33), 0x00 },
+
+ /* analog setting */
+- {0x4174, 0x00},
+- {0x4175, 0x11},
+- {0x4612, 0x29},
+- {0x461B, 0x12},
+- {0x461F, 0x06},
+- {0x4635, 0x07},
+- {0x4637, 0x30},
+- {0x463F, 0x18},
+- {0x4641, 0x0D},
+- {0x465B, 0x12},
+- {0x465F, 0x11},
+- {0x4663, 0x11},
+- {0x4667, 0x0F},
+- {0x466F, 0x0F},
+- {0x470E, 0x09},
+- {0x4909, 0xAB},
+- {0x490B, 0x95},
+- {0x4915, 0x5D},
+- {0x4A5F, 0xFF},
+- {0x4A61, 0xFF},
+- {0x4A73, 0x62},
+- {0x4A85, 0x00},
+- {0x4A87, 0xFF},
++ { CCI_REG8(0x4174), 0x00 },
++ { CCI_REG8(0x4175), 0x11 },
++ { CCI_REG8(0x4612), 0x29 },
++ { CCI_REG8(0x461B), 0x12 },
++ { CCI_REG8(0x461F), 0x06 },
++ { CCI_REG8(0x4635), 0x07 },
++ { CCI_REG8(0x4637), 0x30 },
++ { CCI_REG8(0x463F), 0x18 },
++ { CCI_REG8(0x4641), 0x0D },
++ { CCI_REG8(0x465B), 0x12 },
++ { CCI_REG8(0x465F), 0x11 },
++ { CCI_REG8(0x4663), 0x11 },
++ { CCI_REG8(0x4667), 0x0F },
++ { CCI_REG8(0x466F), 0x0F },
++ { CCI_REG8(0x470E), 0x09 },
++ { CCI_REG8(0x4909), 0xAB },
++ { CCI_REG8(0x490B), 0x95 },
++ { CCI_REG8(0x4915), 0x5D },
++ { CCI_REG8(0x4A5F), 0xFF },
++ { CCI_REG8(0x4A61), 0xFF },
++ { CCI_REG8(0x4A73), 0x62 },
++ { CCI_REG8(0x4A85), 0x00 },
++ { CCI_REG8(0x4A87), 0xFF },
+
+ /* embedded data */
+- {0x5041, 0x04},
+- {0x583C, 0x04},
+- {0x620E, 0x04},
+- {0x6EB2, 0x01},
+- {0x6EB3, 0x00},
+- {0x9300, 0x02},
++ { CCI_REG8(0x5041), 0x04 },
++ { CCI_REG8(0x583C), 0x04 },
++ { CCI_REG8(0x620E), 0x04 },
++ { CCI_REG8(0x6EB2), 0x01 },
++ { CCI_REG8(0x6EB3), 0x00 },
++ { CCI_REG8(0x9300), 0x02 },
+
+ /* imagequality */
+ /* HDR setting */
+- {0x3001, 0x07},
+- {0x6D12, 0x3F},
+- {0x6D13, 0xFF},
+- {0x9344, 0x03},
+- {0x9706, 0x10},
+- {0x9707, 0x03},
+- {0x9708, 0x03},
+- {0x9E04, 0x01},
+- {0x9E05, 0x00},
+- {0x9E0C, 0x01},
+- {0x9E0D, 0x02},
+- {0x9E24, 0x00},
+- {0x9E25, 0x8C},
+- {0x9E26, 0x00},
+- {0x9E27, 0x94},
+- {0x9E28, 0x00},
+- {0x9E29, 0x96},
++ { CCI_REG8(0x3001), 0x07 },
++ { CCI_REG8(0x6D12), 0x3F },
++ { CCI_REG8(0x6D13), 0xFF },
++ { CCI_REG8(0x9344), 0x03 },
++ { CCI_REG8(0x9706), 0x10 },
++ { CCI_REG8(0x9707), 0x03 },
++ { CCI_REG8(0x9708), 0x03 },
++ { CCI_REG8(0x9E04), 0x01 },
++ { CCI_REG8(0x9E05), 0x00 },
++ { CCI_REG8(0x9E0C), 0x01 },
++ { CCI_REG8(0x9E0D), 0x02 },
++ { CCI_REG8(0x9E24), 0x00 },
++ { CCI_REG8(0x9E25), 0x8C },
++ { CCI_REG8(0x9E26), 0x00 },
++ { CCI_REG8(0x9E27), 0x94 },
++ { CCI_REG8(0x9E28), 0x00 },
++ { CCI_REG8(0x9E29), 0x96 },
+
+ /* CNR parameter setting */
+- {0x69DB, 0x01},
++ { CCI_REG8(0x69DB), 0x01 },
+
+ /* Moire reduction */
+- {0x6957, 0x01},
++ { CCI_REG8(0x6957), 0x01 },
+
+ /* image enhancement */
+- {0x6987, 0x17},
+- {0x698A, 0x03},
+- {0x698B, 0x03},
++ { CCI_REG8(0x6987), 0x17 },
++ { CCI_REG8(0x698A), 0x03 },
++ { CCI_REG8(0x698B), 0x03 },
+
+ /* white balanace */
+- {0x0B8E, 0x01},
+- {0x0B8F, 0x00},
+- {0x0B90, 0x01},
+- {0x0B91, 0x00},
+- {0x0B92, 0x01},
+- {0x0B93, 0x00},
+- {0x0B94, 0x01},
+- {0x0B95, 0x00},
++ { CCI_REG8(0x0B8E), 0x01 },
++ { CCI_REG8(0x0B8F), 0x00 },
++ { CCI_REG8(0x0B90), 0x01 },
++ { CCI_REG8(0x0B91), 0x00 },
++ { CCI_REG8(0x0B92), 0x01 },
++ { CCI_REG8(0x0B93), 0x00 },
++ { CCI_REG8(0x0B94), 0x01 },
++ { CCI_REG8(0x0B95), 0x00 },
+
+ /* ATR setting */
+- {0x6E50, 0x00},
+- {0x6E51, 0x32},
+- {0x9340, 0x00},
+- {0x9341, 0x3C},
+- {0x9342, 0x03},
+- {0x9343, 0xFF},
+- {IMX214_TABLE_END, 0x00}
++ { CCI_REG8(0x6E50), 0x00 },
++ { CCI_REG8(0x6E51), 0x32 },
++ { CCI_REG8(0x9340), 0x00 },
++ { CCI_REG8(0x9341), 0x3C },
++ { CCI_REG8(0x9342), 0x03 },
++ { CCI_REG8(0x9343), 0xFF },
+ };
+
+ /*
+@@ -419,16 +399,19 @@ static const struct reg_8 mode_table_common[] = {
+ static const struct imx214_mode {
+ u32 width;
+ u32 height;
+- const struct reg_8 *reg_table;
++ unsigned int num_of_regs;
++ const struct cci_reg_sequence *reg_table;
+ } imx214_modes[] = {
+ {
+ .width = 4096,
+ .height = 2304,
++ .num_of_regs = ARRAY_SIZE(mode_4096x2304),
+ .reg_table = mode_4096x2304,
+ },
+ {
+ .width = 1920,
+ .height = 1080,
++ .num_of_regs = ARRAY_SIZE(mode_1920x1080),
+ .reg_table = mode_1920x1080,
+ },
+ };
+@@ -630,7 +613,6 @@ static int imx214_set_ctrl(struct v4l2_ctrl *ctrl)
+ {
+ struct imx214 *imx214 = container_of(ctrl->handler,
+ struct imx214, ctrls);
+- u8 vals[2];
+ int ret;
+
+ /*
+@@ -642,12 +624,7 @@ static int imx214_set_ctrl(struct v4l2_ctrl *ctrl)
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+- vals[1] = ctrl->val;
+- vals[0] = ctrl->val >> 8;
+- ret = regmap_bulk_write(imx214->regmap, IMX214_REG_EXPOSURE, vals, 2);
+- if (ret < 0)
+- dev_err(imx214->dev, "Error %d\n", ret);
+- ret = 0;
++ cci_write(imx214->regmap, IMX214_REG_EXPOSURE, ctrl->val, &ret);
+ break;
+
+ default:
+@@ -733,40 +710,6 @@ static int imx214_ctrls_init(struct imx214 *imx214)
+ return 0;
+ };
+
+-#define MAX_CMD 4
+-static int imx214_write_table(struct imx214 *imx214,
+- const struct reg_8 table[])
+-{
+- u8 vals[MAX_CMD];
+- int i;
+- int ret;
+-
+- for (; table->addr != IMX214_TABLE_END ; table++) {
+- if (table->addr == IMX214_TABLE_WAIT_MS) {
+- usleep_range(table->val * 1000,
+- table->val * 1000 + 500);
+- continue;
+- }
+-
+- for (i = 0; i < MAX_CMD; i++) {
+- if (table[i].addr != (table[0].addr + i))
+- break;
+- vals[i] = table[i].val;
+- }
+-
+- ret = regmap_bulk_write(imx214->regmap, table->addr, vals, i);
+-
+- if (ret) {
+- dev_err(imx214->dev, "write_table error: %d\n", ret);
+- return ret;
+- }
+-
+- table += i - 1;
+- }
+-
+- return 0;
+-}
+-
+ static int imx214_start_streaming(struct imx214 *imx214)
+ {
+ const struct v4l2_mbus_framefmt *fmt;
+@@ -774,7 +717,8 @@ static int imx214_start_streaming(struct imx214 *imx214)
+ const struct imx214_mode *mode;
+ int ret;
+
+- ret = imx214_write_table(imx214, mode_table_common);
++ ret = cci_multi_reg_write(imx214->regmap, mode_table_common,
++ ARRAY_SIZE(mode_table_common), NULL);
+ if (ret < 0) {
+ dev_err(imx214->dev, "could not sent common table %d\n", ret);
+ return ret;
+@@ -784,17 +728,24 @@ static int imx214_start_streaming(struct imx214 *imx214)
+ fmt = v4l2_subdev_state_get_format(state, 0);
+ mode = v4l2_find_nearest_size(imx214_modes, ARRAY_SIZE(imx214_modes),
+ width, height, fmt->width, fmt->height);
+- ret = imx214_write_table(imx214, mode->reg_table);
++ ret = cci_multi_reg_write(imx214->regmap, mode->reg_table,
++ mode->num_of_regs, NULL);
+ if (ret < 0) {
+ dev_err(imx214->dev, "could not sent mode table %d\n", ret);
+ return ret;
+ }
++
++ usleep_range(10000, 10500);
++
++ cci_write(imx214->regmap, CCI_REG8(0x0138), 0x01, NULL);
++
+ ret = __v4l2_ctrl_handler_setup(&imx214->ctrls);
+ if (ret < 0) {
+ dev_err(imx214->dev, "could not sync v4l2 controls\n");
+ return ret;
+ }
+- ret = regmap_write(imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STREAMING);
++ ret = cci_write(imx214->regmap, IMX214_REG_MODE_SELECT,
++ IMX214_MODE_STREAMING, NULL);
+ if (ret < 0)
+ dev_err(imx214->dev, "could not sent start table %d\n", ret);
+
+@@ -805,7 +756,8 @@ static int imx214_stop_streaming(struct imx214 *imx214)
+ {
+ int ret;
+
+- ret = regmap_write(imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STANDBY);
++ ret = cci_write(imx214->regmap, IMX214_REG_MODE_SELECT,
++ IMX214_MODE_STANDBY, NULL);
+ if (ret < 0)
+ dev_err(imx214->dev, "could not sent stop table %d\n", ret);
+
+@@ -906,12 +858,6 @@ static const struct v4l2_subdev_internal_ops imx214_internal_ops = {
+ .init_state = imx214_entity_init_state,
+ };
+
+-static const struct regmap_config sensor_regmap_config = {
+- .reg_bits = 16,
+- .val_bits = 8,
+- .cache_type = REGCACHE_MAPLE,
+-};
+-
+ static int imx214_get_regulators(struct device *dev, struct imx214 *imx214)
+ {
+ unsigned int i;
+@@ -995,10 +941,10 @@ static int imx214_probe(struct i2c_client *client)
+ return dev_err_probe(dev, PTR_ERR(imx214->enable_gpio),
+ "failed to get enable gpio\n");
+
+- imx214->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config);
++ imx214->regmap = devm_cci_regmap_init_i2c(client, 16);
+ if (IS_ERR(imx214->regmap))
+ return dev_err_probe(dev, PTR_ERR(imx214->regmap),
+- "regmap init failed\n");
++ "failed to initialize CCI\n");
+
+ v4l2_i2c_subdev_init(&imx214->sd, client, &imx214_subdev_ops);
+ imx214->sd.internal_ops = &imx214_internal_ops;
+--
+2.39.5
+
--- /dev/null
+From 2b4357eb8767d5088a1f164d31df55393093e6de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 14:26:12 +0100
+Subject: media: i2c: imx214: Fix link frequency validation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Apitzsch <git@apitzsch.eu>
+
+[ Upstream commit acc294519f1749041e1b8c74d46bbf6c57d8b061 ]
+
+The driver defines IMX214_DEFAULT_LINK_FREQ 480000000, and then
+IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10),
+which works out as 384MPix/s. (The 8 is 4 lanes and DDR.)
+
+Parsing the PLL registers with the defined 24MHz input. We're in single
+PLL mode, so MIPI frequency is directly linked to pixel rate. VTCK ends
+up being 1200MHz, and VTPXCK and OPPXCK both are 120MHz. Section 5.3
+"Frame rate calculation formula" says "Pixel rate
+[pixels/s] = VTPXCK [MHz] * 4", so 120 * 4 = 480MPix/s, which basically
+agrees with my number above.
+
+3.1.4. MIPI global timing setting says "Output bitrate = OPPXCK * reg
+0x113[7:0]", so 120MHz * 10, or 1200Mbit/s. That would be a link
+frequency of 600MHz due to DDR.
+That also matches to 480MPix/s * 10bpp / 4 lanes / 2 for DDR.
+
+Keep the previous link frequency for backward compatibility.
+
+Acked-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: André Apitzsch <git@apitzsch.eu>
+Fixes: 436190596241 ("media: imx214: Add imx214 camera sensor driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx214.c | 28 +++++++++++++++++++---------
+ 1 file changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
+index fdc2dfb4ebcdd..bdf2396c2482b 100644
+--- a/drivers/media/i2c/imx214.c
++++ b/drivers/media/i2c/imx214.c
+@@ -27,7 +27,9 @@
+ #define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106)
+
+ #define IMX214_DEFAULT_CLK_FREQ 24000000
+-#define IMX214_DEFAULT_LINK_FREQ 480000000
++#define IMX214_DEFAULT_LINK_FREQ 600000000
++/* Keep wrong link frequency for backward compatibility */
++#define IMX214_DEFAULT_LINK_FREQ_LEGACY 480000000
+ #define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10)
+ #define IMX214_FPS 30
+ #define IMX214_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10
+@@ -965,18 +967,26 @@ static int imx214_parse_fwnode(struct device *dev)
+ goto done;
+ }
+
+- for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++)
++ if (bus_cfg.nr_of_link_frequencies != 1)
++ dev_warn(dev, "Only one link-frequency supported, please review your DT. Continuing anyway\n");
++
++ for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) {
+ if (bus_cfg.link_frequencies[i] == IMX214_DEFAULT_LINK_FREQ)
+ break;
+-
+- if (i == bus_cfg.nr_of_link_frequencies) {
+- dev_err_probe(dev, -EINVAL,
+- "link-frequencies %d not supported, Please review your DT\n",
+- IMX214_DEFAULT_LINK_FREQ);
+- ret = -EINVAL;
+- goto done;
++ if (bus_cfg.link_frequencies[i] ==
++ IMX214_DEFAULT_LINK_FREQ_LEGACY) {
++ dev_warn(dev,
++ "link-frequencies %d not supported, please review your DT. Continuing anyway\n",
++ IMX214_DEFAULT_LINK_FREQ);
++ break;
++ }
+ }
+
++ if (i == bus_cfg.nr_of_link_frequencies)
++ ret = dev_err_probe(dev, -EINVAL,
++ "link-frequencies %d not supported, please review your DT\n",
++ IMX214_DEFAULT_LINK_FREQ);
++
+ done:
+ v4l2_fwnode_endpoint_free(&bus_cfg);
+ fwnode_handle_put(endpoint);
+--
+2.39.5
+
--- /dev/null
+From 5104e0fb3eaebfe4cb7765ae2217890b37794c31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 14:26:03 +0100
+Subject: media: i2c: imx214: Replace register addresses with macros
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Apitzsch <git@apitzsch.eu>
+
+[ Upstream commit 341a133beb43f9009ebdde9eff276dfacbac114a ]
+
+Define macros for all the known registers used in the register arrays,
+and use them to replace the numerical addresses. This improves
+readability.
+
+Acked-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: André Apitzsch <git@apitzsch.eu>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx214.c | 407 +++++++++++++++++++++----------------
+ 1 file changed, 236 insertions(+), 171 deletions(-)
+
+diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
+index 20d1ebebf13af..8bac5a1f1cb18 100644
+--- a/drivers/media/i2c/imx214.c
++++ b/drivers/media/i2c/imx214.c
+@@ -24,18 +24,141 @@
+ #define IMX214_MODE_STANDBY 0x00
+ #define IMX214_MODE_STREAMING 0x01
+
++#define IMX214_REG_FAST_STANDBY_CTRL CCI_REG8(0x0106)
++
+ #define IMX214_DEFAULT_CLK_FREQ 24000000
+ #define IMX214_DEFAULT_LINK_FREQ 480000000
+ #define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10)
+ #define IMX214_FPS 30
+ #define IMX214_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10
+
++/* V-TIMING internal */
++#define IMX214_REG_FRM_LENGTH_LINES CCI_REG16(0x0340)
++
+ /* Exposure control */
+ #define IMX214_REG_EXPOSURE CCI_REG16(0x0202)
+ #define IMX214_EXPOSURE_MIN 0
+ #define IMX214_EXPOSURE_MAX 3184
+ #define IMX214_EXPOSURE_STEP 1
+ #define IMX214_EXPOSURE_DEFAULT 3184
++#define IMX214_REG_EXPOSURE_RATIO CCI_REG8(0x0222)
++#define IMX214_REG_SHORT_EXPOSURE CCI_REG16(0x0224)
++
++/* Analog gain control */
++#define IMX214_REG_ANALOG_GAIN CCI_REG16(0x0204)
++#define IMX214_REG_SHORT_ANALOG_GAIN CCI_REG16(0x0216)
++
++/* Digital gain control */
++#define IMX214_REG_DIG_GAIN_GREENR CCI_REG16(0x020e)
++#define IMX214_REG_DIG_GAIN_RED CCI_REG16(0x0210)
++#define IMX214_REG_DIG_GAIN_BLUE CCI_REG16(0x0212)
++#define IMX214_REG_DIG_GAIN_GREENB CCI_REG16(0x0214)
++
++#define IMX214_REG_ORIENTATION CCI_REG8(0x0101)
++
++#define IMX214_REG_MASK_CORR_FRAMES CCI_REG8(0x0105)
++#define IMX214_CORR_FRAMES_TRANSMIT 0
++#define IMX214_CORR_FRAMES_MASK 1
++
++#define IMX214_REG_CSI_DATA_FORMAT CCI_REG16(0x0112)
++#define IMX214_CSI_DATA_FORMAT_RAW8 0x0808
++#define IMX214_CSI_DATA_FORMAT_RAW10 0x0A0A
++#define IMX214_CSI_DATA_FORMAT_COMP6 0x0A06
++#define IMX214_CSI_DATA_FORMAT_COMP8 0x0A08
++
++#define IMX214_REG_CSI_LANE_MODE CCI_REG8(0x0114)
++#define IMX214_CSI_2_LANE_MODE 1
++#define IMX214_CSI_4_LANE_MODE 3
++
++#define IMX214_REG_EXCK_FREQ CCI_REG16(0x0136)
++#define IMX214_EXCK_FREQ(n) ((n) * 256) /* n expressed in MHz */
++
++#define IMX214_REG_TEMP_SENSOR_CONTROL CCI_REG8(0x0138)
++
++#define IMX214_REG_HDR_MODE CCI_REG8(0x0220)
++#define IMX214_HDR_MODE_OFF 0
++#define IMX214_HDR_MODE_ON 1
++
++#define IMX214_REG_HDR_RES_REDUCTION CCI_REG8(0x0221)
++#define IMX214_HDR_RES_REDU_THROUGH 0x11
++#define IMX214_HDR_RES_REDU_2_BINNING 0x22
++
++/* PLL settings */
++#define IMX214_REG_VTPXCK_DIV CCI_REG8(0x0301)
++#define IMX214_REG_VTSYCK_DIV CCI_REG8(0x0303)
++#define IMX214_REG_PREPLLCK_VT_DIV CCI_REG8(0x0305)
++#define IMX214_REG_PLL_VT_MPY CCI_REG16(0x0306)
++#define IMX214_REG_OPPXCK_DIV CCI_REG8(0x0309)
++#define IMX214_REG_OPSYCK_DIV CCI_REG8(0x030b)
++#define IMX214_REG_PLL_MULT_DRIV CCI_REG8(0x0310)
++#define IMX214_PLL_SINGLE 0
++#define IMX214_PLL_DUAL 1
++
++#define IMX214_REG_LINE_LENGTH_PCK CCI_REG16(0x0342)
++#define IMX214_REG_X_ADD_STA CCI_REG16(0x0344)
++#define IMX214_REG_Y_ADD_STA CCI_REG16(0x0346)
++#define IMX214_REG_X_ADD_END CCI_REG16(0x0348)
++#define IMX214_REG_Y_ADD_END CCI_REG16(0x034a)
++#define IMX214_REG_X_OUTPUT_SIZE CCI_REG16(0x034c)
++#define IMX214_REG_Y_OUTPUT_SIZE CCI_REG16(0x034e)
++#define IMX214_REG_X_EVEN_INC CCI_REG8(0x0381)
++#define IMX214_REG_X_ODD_INC CCI_REG8(0x0383)
++#define IMX214_REG_Y_EVEN_INC CCI_REG8(0x0385)
++#define IMX214_REG_Y_ODD_INC CCI_REG8(0x0387)
++
++#define IMX214_REG_SCALE_MODE CCI_REG8(0x0401)
++#define IMX214_SCALE_NONE 0
++#define IMX214_SCALE_HORIZONTAL 1
++#define IMX214_SCALE_FULL 2
++#define IMX214_REG_SCALE_M CCI_REG16(0x0404)
++
++#define IMX214_REG_DIG_CROP_X_OFFSET CCI_REG16(0x0408)
++#define IMX214_REG_DIG_CROP_Y_OFFSET CCI_REG16(0x040a)
++#define IMX214_REG_DIG_CROP_WIDTH CCI_REG16(0x040c)
++#define IMX214_REG_DIG_CROP_HEIGHT CCI_REG16(0x040e)
++
++#define IMX214_REG_REQ_LINK_BIT_RATE CCI_REG32(0x0820)
++#define IMX214_LINK_BIT_RATE_MBPS(n) ((n) << 16)
++
++/* Binning mode */
++#define IMX214_REG_BINNING_MODE CCI_REG8(0x0900)
++#define IMX214_BINNING_NONE 0
++#define IMX214_BINNING_ENABLE 1
++#define IMX214_REG_BINNING_TYPE CCI_REG8(0x0901)
++#define IMX214_REG_BINNING_WEIGHTING CCI_REG8(0x0902)
++#define IMX214_BINNING_AVERAGE 0x00
++#define IMX214_BINNING_SUMMED 0x01
++#define IMX214_BINNING_BAYER 0x02
++
++#define IMX214_REG_SING_DEF_CORR_EN CCI_REG8(0x0b06)
++#define IMX214_SING_DEF_CORR_OFF 0
++#define IMX214_SING_DEF_CORR_ON 1
++
++/* AWB control */
++#define IMX214_REG_ABS_GAIN_GREENR CCI_REG16(0x0b8e)
++#define IMX214_REG_ABS_GAIN_RED CCI_REG16(0x0b90)
++#define IMX214_REG_ABS_GAIN_BLUE CCI_REG16(0x0b92)
++#define IMX214_REG_ABS_GAIN_GREENB CCI_REG16(0x0b94)
++
++#define IMX214_REG_RMSC_NR_MODE CCI_REG8(0x3001)
++#define IMX214_REG_STATS_OUT_EN CCI_REG8(0x3013)
++#define IMX214_STATS_OUT_OFF 0
++#define IMX214_STATS_OUT_ON 1
++
++/* Chroma noise reduction */
++#define IMX214_REG_NML_NR_EN CCI_REG8(0x30a2)
++#define IMX214_NML_NR_OFF 0
++#define IMX214_NML_NR_ON 1
++
++#define IMX214_REG_EBD_SIZE_V CCI_REG8(0x5041)
++#define IMX214_EBD_NO 0
++#define IMX214_EBD_4_LINE 4
++
++#define IMX214_REG_RG_STATS_LMT CCI_REG16(0x6d12)
++#define IMX214_RG_STATS_LMT_10_BIT 0x03FF
++#define IMX214_RG_STATS_LMT_14_BIT 0x3FFF
++
++#define IMX214_REG_ATR_FAST_MOVE CCI_REG8(0x9300)
+
+ /* IMX214 native and active pixel array size */
+ #define IMX214_NATIVE_WIDTH 4224U
+@@ -74,96 +197,70 @@ struct imx214 {
+
+ /*From imx214_mode_tbls.h*/
+ static const struct cci_reg_sequence mode_4096x2304[] = {
+- { CCI_REG8(0x0114), 0x03 },
+- { CCI_REG8(0x0220), 0x00 },
+- { CCI_REG8(0x0221), 0x11 },
+- { CCI_REG8(0x0222), 0x01 },
+- { CCI_REG8(0x0340), 0x0C },
+- { CCI_REG8(0x0341), 0x7A },
+- { CCI_REG8(0x0342), 0x13 },
+- { CCI_REG8(0x0343), 0x90 },
+- { CCI_REG8(0x0344), 0x00 },
+- { CCI_REG8(0x0345), 0x38 },
+- { CCI_REG8(0x0346), 0x01 },
+- { CCI_REG8(0x0347), 0x98 },
+- { CCI_REG8(0x0348), 0x10 },
+- { CCI_REG8(0x0349), 0x37 },
+- { CCI_REG8(0x034A), 0x0A },
+- { CCI_REG8(0x034B), 0x97 },
+- { CCI_REG8(0x0381), 0x01 },
+- { CCI_REG8(0x0383), 0x01 },
+- { CCI_REG8(0x0385), 0x01 },
+- { CCI_REG8(0x0387), 0x01 },
+- { CCI_REG8(0x0900), 0x00 },
+- { CCI_REG8(0x0901), 0x00 },
+- { CCI_REG8(0x0902), 0x00 },
++ { IMX214_REG_CSI_LANE_MODE, IMX214_CSI_4_LANE_MODE },
++ { IMX214_REG_HDR_MODE, IMX214_HDR_MODE_OFF },
++ { IMX214_REG_HDR_RES_REDUCTION, IMX214_HDR_RES_REDU_THROUGH },
++ { IMX214_REG_EXPOSURE_RATIO, 1 },
++ { IMX214_REG_FRM_LENGTH_LINES, 3194 },
++ { IMX214_REG_LINE_LENGTH_PCK, 5008 },
++ { IMX214_REG_X_ADD_STA, 56 },
++ { IMX214_REG_Y_ADD_STA, 408 },
++ { IMX214_REG_X_ADD_END, 4151 },
++ { IMX214_REG_Y_ADD_END, 2711 },
++ { IMX214_REG_X_EVEN_INC, 1 },
++ { IMX214_REG_X_ODD_INC, 1 },
++ { IMX214_REG_Y_EVEN_INC, 1 },
++ { IMX214_REG_Y_ODD_INC, 1 },
++ { IMX214_REG_BINNING_MODE, IMX214_BINNING_NONE },
++ { IMX214_REG_BINNING_TYPE, 0 },
++ { IMX214_REG_BINNING_WEIGHTING, IMX214_BINNING_AVERAGE },
+ { CCI_REG8(0x3000), 0x35 },
+ { CCI_REG8(0x3054), 0x01 },
+ { CCI_REG8(0x305C), 0x11 },
+
+- { CCI_REG8(0x0112), 0x0A },
+- { CCI_REG8(0x0113), 0x0A },
+- { CCI_REG8(0x034C), 0x10 },
+- { CCI_REG8(0x034D), 0x00 },
+- { CCI_REG8(0x034E), 0x09 },
+- { CCI_REG8(0x034F), 0x00 },
+- { CCI_REG8(0x0401), 0x00 },
+- { CCI_REG8(0x0404), 0x00 },
+- { CCI_REG8(0x0405), 0x10 },
+- { CCI_REG8(0x0408), 0x00 },
+- { CCI_REG8(0x0409), 0x00 },
+- { CCI_REG8(0x040A), 0x00 },
+- { CCI_REG8(0x040B), 0x00 },
+- { CCI_REG8(0x040C), 0x10 },
+- { CCI_REG8(0x040D), 0x00 },
+- { CCI_REG8(0x040E), 0x09 },
+- { CCI_REG8(0x040F), 0x00 },
+-
+- { CCI_REG8(0x0301), 0x05 },
+- { CCI_REG8(0x0303), 0x02 },
+- { CCI_REG8(0x0305), 0x03 },
+- { CCI_REG8(0x0306), 0x00 },
+- { CCI_REG8(0x0307), 0x96 },
+- { CCI_REG8(0x0309), 0x0A },
+- { CCI_REG8(0x030B), 0x01 },
+- { CCI_REG8(0x0310), 0x00 },
+-
+- { CCI_REG8(0x0820), 0x12 },
+- { CCI_REG8(0x0821), 0xC0 },
+- { CCI_REG8(0x0822), 0x00 },
+- { CCI_REG8(0x0823), 0x00 },
++ { IMX214_REG_CSI_DATA_FORMAT, IMX214_CSI_DATA_FORMAT_RAW10 },
++ { IMX214_REG_X_OUTPUT_SIZE, 4096 },
++ { IMX214_REG_Y_OUTPUT_SIZE, 2304 },
++ { IMX214_REG_SCALE_MODE, IMX214_SCALE_NONE },
++ { IMX214_REG_SCALE_M, 2 },
++ { IMX214_REG_DIG_CROP_X_OFFSET, 0 },
++ { IMX214_REG_DIG_CROP_Y_OFFSET, 0 },
++ { IMX214_REG_DIG_CROP_WIDTH, 4096 },
++ { IMX214_REG_DIG_CROP_HEIGHT, 2304 },
++
++ { IMX214_REG_VTPXCK_DIV, 5 },
++ { IMX214_REG_VTSYCK_DIV, 2 },
++ { IMX214_REG_PREPLLCK_VT_DIV, 3 },
++ { IMX214_REG_PLL_VT_MPY, 150 },
++ { IMX214_REG_OPPXCK_DIV, 10 },
++ { IMX214_REG_OPSYCK_DIV, 1 },
++ { IMX214_REG_PLL_MULT_DRIV, IMX214_PLL_SINGLE },
++
++ { IMX214_REG_REQ_LINK_BIT_RATE, IMX214_LINK_BIT_RATE_MBPS(4800) },
+
+ { CCI_REG8(0x3A03), 0x09 },
+ { CCI_REG8(0x3A04), 0x50 },
+ { CCI_REG8(0x3A05), 0x01 },
+
+- { CCI_REG8(0x0B06), 0x01 },
+- { CCI_REG8(0x30A2), 0x00 },
++ { IMX214_REG_SING_DEF_CORR_EN, IMX214_SING_DEF_CORR_ON },
++ { IMX214_REG_NML_NR_EN, IMX214_NML_NR_OFF },
+
+ { CCI_REG8(0x30B4), 0x00 },
+
+ { CCI_REG8(0x3A02), 0xFF },
+
+ { CCI_REG8(0x3011), 0x00 },
+- { CCI_REG8(0x3013), 0x01 },
+-
+- { CCI_REG8(0x0202), 0x0C },
+- { CCI_REG8(0x0203), 0x70 },
+- { CCI_REG8(0x0224), 0x01 },
+- { CCI_REG8(0x0225), 0xF4 },
+-
+- { CCI_REG8(0x0204), 0x00 },
+- { CCI_REG8(0x0205), 0x00 },
+- { CCI_REG8(0x020E), 0x01 },
+- { CCI_REG8(0x020F), 0x00 },
+- { CCI_REG8(0x0210), 0x01 },
+- { CCI_REG8(0x0211), 0x00 },
+- { CCI_REG8(0x0212), 0x01 },
+- { CCI_REG8(0x0213), 0x00 },
+- { CCI_REG8(0x0214), 0x01 },
+- { CCI_REG8(0x0215), 0x00 },
+- { CCI_REG8(0x0216), 0x00 },
+- { CCI_REG8(0x0217), 0x00 },
++ { IMX214_REG_STATS_OUT_EN, IMX214_STATS_OUT_ON },
++
++ { IMX214_REG_EXPOSURE, IMX214_EXPOSURE_DEFAULT },
++ { IMX214_REG_SHORT_EXPOSURE, 500 },
++
++ { IMX214_REG_ANALOG_GAIN, 0 },
++ { IMX214_REG_DIG_GAIN_GREENR, 256 },
++ { IMX214_REG_DIG_GAIN_RED, 256 },
++ { IMX214_REG_DIG_GAIN_BLUE, 256 },
++ { IMX214_REG_DIG_GAIN_GREENB, 256 },
++ { IMX214_REG_SHORT_ANALOG_GAIN, 0 },
+
+ { CCI_REG8(0x4170), 0x00 },
+ { CCI_REG8(0x4171), 0x10 },
+@@ -174,96 +271,70 @@ static const struct cci_reg_sequence mode_4096x2304[] = {
+ };
+
+ static const struct cci_reg_sequence mode_1920x1080[] = {
+- { CCI_REG8(0x0114), 0x03 },
+- { CCI_REG8(0x0220), 0x00 },
+- { CCI_REG8(0x0221), 0x11 },
+- { CCI_REG8(0x0222), 0x01 },
+- { CCI_REG8(0x0340), 0x0C },
+- { CCI_REG8(0x0341), 0x7A },
+- { CCI_REG8(0x0342), 0x13 },
+- { CCI_REG8(0x0343), 0x90 },
+- { CCI_REG8(0x0344), 0x04 },
+- { CCI_REG8(0x0345), 0x78 },
+- { CCI_REG8(0x0346), 0x03 },
+- { CCI_REG8(0x0347), 0xFC },
+- { CCI_REG8(0x0348), 0x0B },
+- { CCI_REG8(0x0349), 0xF7 },
+- { CCI_REG8(0x034A), 0x08 },
+- { CCI_REG8(0x034B), 0x33 },
+- { CCI_REG8(0x0381), 0x01 },
+- { CCI_REG8(0x0383), 0x01 },
+- { CCI_REG8(0x0385), 0x01 },
+- { CCI_REG8(0x0387), 0x01 },
+- { CCI_REG8(0x0900), 0x00 },
+- { CCI_REG8(0x0901), 0x00 },
+- { CCI_REG8(0x0902), 0x00 },
++ { IMX214_REG_CSI_LANE_MODE, IMX214_CSI_4_LANE_MODE },
++ { IMX214_REG_HDR_MODE, IMX214_HDR_MODE_OFF },
++ { IMX214_REG_HDR_RES_REDUCTION, IMX214_HDR_RES_REDU_THROUGH },
++ { IMX214_REG_EXPOSURE_RATIO, 1 },
++ { IMX214_REG_FRM_LENGTH_LINES, 3194 },
++ { IMX214_REG_LINE_LENGTH_PCK, 5008 },
++ { IMX214_REG_X_ADD_STA, 1144 },
++ { IMX214_REG_Y_ADD_STA, 1020 },
++ { IMX214_REG_X_ADD_END, 3063 },
++ { IMX214_REG_Y_ADD_END, 2099 },
++ { IMX214_REG_X_EVEN_INC, 1 },
++ { IMX214_REG_X_ODD_INC, 1 },
++ { IMX214_REG_Y_EVEN_INC, 1 },
++ { IMX214_REG_Y_ODD_INC, 1 },
++ { IMX214_REG_BINNING_MODE, IMX214_BINNING_NONE },
++ { IMX214_REG_BINNING_TYPE, 0 },
++ { IMX214_REG_BINNING_WEIGHTING, IMX214_BINNING_AVERAGE },
+ { CCI_REG8(0x3000), 0x35 },
+ { CCI_REG8(0x3054), 0x01 },
+ { CCI_REG8(0x305C), 0x11 },
+
+- { CCI_REG8(0x0112), 0x0A },
+- { CCI_REG8(0x0113), 0x0A },
+- { CCI_REG8(0x034C), 0x07 },
+- { CCI_REG8(0x034D), 0x80 },
+- { CCI_REG8(0x034E), 0x04 },
+- { CCI_REG8(0x034F), 0x38 },
+- { CCI_REG8(0x0401), 0x00 },
+- { CCI_REG8(0x0404), 0x00 },
+- { CCI_REG8(0x0405), 0x10 },
+- { CCI_REG8(0x0408), 0x00 },
+- { CCI_REG8(0x0409), 0x00 },
+- { CCI_REG8(0x040A), 0x00 },
+- { CCI_REG8(0x040B), 0x00 },
+- { CCI_REG8(0x040C), 0x07 },
+- { CCI_REG8(0x040D), 0x80 },
+- { CCI_REG8(0x040E), 0x04 },
+- { CCI_REG8(0x040F), 0x38 },
+-
+- { CCI_REG8(0x0301), 0x05 },
+- { CCI_REG8(0x0303), 0x02 },
+- { CCI_REG8(0x0305), 0x03 },
+- { CCI_REG8(0x0306), 0x00 },
+- { CCI_REG8(0x0307), 0x96 },
+- { CCI_REG8(0x0309), 0x0A },
+- { CCI_REG8(0x030B), 0x01 },
+- { CCI_REG8(0x0310), 0x00 },
+-
+- { CCI_REG8(0x0820), 0x12 },
+- { CCI_REG8(0x0821), 0xC0 },
+- { CCI_REG8(0x0822), 0x00 },
+- { CCI_REG8(0x0823), 0x00 },
++ { IMX214_REG_CSI_DATA_FORMAT, IMX214_CSI_DATA_FORMAT_RAW10 },
++ { IMX214_REG_X_OUTPUT_SIZE, 1920 },
++ { IMX214_REG_Y_OUTPUT_SIZE, 1080 },
++ { IMX214_REG_SCALE_MODE, IMX214_SCALE_NONE },
++ { IMX214_REG_SCALE_M, 2 },
++ { IMX214_REG_DIG_CROP_X_OFFSET, 0 },
++ { IMX214_REG_DIG_CROP_Y_OFFSET, 0 },
++ { IMX214_REG_DIG_CROP_WIDTH, 1920 },
++ { IMX214_REG_DIG_CROP_HEIGHT, 1080 },
++
++ { IMX214_REG_VTPXCK_DIV, 5 },
++ { IMX214_REG_VTSYCK_DIV, 2 },
++ { IMX214_REG_PREPLLCK_VT_DIV, 3 },
++ { IMX214_REG_PLL_VT_MPY, 150 },
++ { IMX214_REG_OPPXCK_DIV, 10 },
++ { IMX214_REG_OPSYCK_DIV, 1 },
++ { IMX214_REG_PLL_MULT_DRIV, IMX214_PLL_SINGLE },
++
++ { IMX214_REG_REQ_LINK_BIT_RATE, IMX214_LINK_BIT_RATE_MBPS(4800) },
+
+ { CCI_REG8(0x3A03), 0x04 },
+ { CCI_REG8(0x3A04), 0xF8 },
+ { CCI_REG8(0x3A05), 0x02 },
+
+- { CCI_REG8(0x0B06), 0x01 },
+- { CCI_REG8(0x30A2), 0x00 },
++ { IMX214_REG_SING_DEF_CORR_EN, IMX214_SING_DEF_CORR_ON },
++ { IMX214_REG_NML_NR_EN, IMX214_NML_NR_OFF },
+
+ { CCI_REG8(0x30B4), 0x00 },
+
+ { CCI_REG8(0x3A02), 0xFF },
+
+ { CCI_REG8(0x3011), 0x00 },
+- { CCI_REG8(0x3013), 0x01 },
+-
+- { CCI_REG8(0x0202), 0x0C },
+- { CCI_REG8(0x0203), 0x70 },
+- { CCI_REG8(0x0224), 0x01 },
+- { CCI_REG8(0x0225), 0xF4 },
+-
+- { CCI_REG8(0x0204), 0x00 },
+- { CCI_REG8(0x0205), 0x00 },
+- { CCI_REG8(0x020E), 0x01 },
+- { CCI_REG8(0x020F), 0x00 },
+- { CCI_REG8(0x0210), 0x01 },
+- { CCI_REG8(0x0211), 0x00 },
+- { CCI_REG8(0x0212), 0x01 },
+- { CCI_REG8(0x0213), 0x00 },
+- { CCI_REG8(0x0214), 0x01 },
+- { CCI_REG8(0x0215), 0x00 },
+- { CCI_REG8(0x0216), 0x00 },
+- { CCI_REG8(0x0217), 0x00 },
++ { IMX214_REG_STATS_OUT_EN, IMX214_STATS_OUT_ON },
++
++ { IMX214_REG_EXPOSURE, IMX214_EXPOSURE_DEFAULT },
++ { IMX214_REG_SHORT_EXPOSURE, 500 },
++
++ { IMX214_REG_ANALOG_GAIN, 0 },
++ { IMX214_REG_DIG_GAIN_GREENR, 256 },
++ { IMX214_REG_DIG_GAIN_RED, 256 },
++ { IMX214_REG_DIG_GAIN_BLUE, 256 },
++ { IMX214_REG_DIG_GAIN_GREENB, 256 },
++ { IMX214_REG_SHORT_ANALOG_GAIN, 0 },
+
+ { CCI_REG8(0x4170), 0x00 },
+ { CCI_REG8(0x4171), 0x10 },
+@@ -277,20 +348,19 @@ static const struct cci_reg_sequence mode_table_common[] = {
+ /* software reset */
+
+ /* software standby settings */
+- { CCI_REG8(0x0100), 0x00 },
++ { IMX214_REG_MODE_SELECT, IMX214_MODE_STANDBY },
+
+ /* ATR setting */
+- { CCI_REG8(0x9300), 0x02 },
++ { IMX214_REG_ATR_FAST_MOVE, 2 },
+
+ /* external clock setting */
+- { CCI_REG8(0x0136), 0x18 },
+- { CCI_REG8(0x0137), 0x00 },
++ { IMX214_REG_EXCK_FREQ, IMX214_EXCK_FREQ(IMX214_DEFAULT_CLK_FREQ / 1000000) },
+
+ /* global setting */
+ /* basic config */
+- { CCI_REG8(0x0101), 0x00 },
+- { CCI_REG8(0x0105), 0x01 },
+- { CCI_REG8(0x0106), 0x01 },
++ { IMX214_REG_ORIENTATION, 0 },
++ { IMX214_REG_MASK_CORR_FRAMES, IMX214_CORR_FRAMES_MASK },
++ { IMX214_REG_FAST_STANDBY_CTRL, 1 },
+ { CCI_REG8(0x4550), 0x02 },
+ { CCI_REG8(0x4601), 0x00 },
+ { CCI_REG8(0x4642), 0x05 },
+@@ -335,18 +405,17 @@ static const struct cci_reg_sequence mode_table_common[] = {
+ { CCI_REG8(0x4A87), 0xFF },
+
+ /* embedded data */
+- { CCI_REG8(0x5041), 0x04 },
++ { IMX214_REG_EBD_SIZE_V, IMX214_EBD_4_LINE },
+ { CCI_REG8(0x583C), 0x04 },
+ { CCI_REG8(0x620E), 0x04 },
+ { CCI_REG8(0x6EB2), 0x01 },
+ { CCI_REG8(0x6EB3), 0x00 },
+- { CCI_REG8(0x9300), 0x02 },
++ { IMX214_REG_ATR_FAST_MOVE, 2 },
+
+ /* imagequality */
+ /* HDR setting */
+- { CCI_REG8(0x3001), 0x07 },
+- { CCI_REG8(0x6D12), 0x3F },
+- { CCI_REG8(0x6D13), 0xFF },
++ { IMX214_REG_RMSC_NR_MODE, 0x07 },
++ { IMX214_REG_RG_STATS_LMT, IMX214_RG_STATS_LMT_14_BIT },
+ { CCI_REG8(0x9344), 0x03 },
+ { CCI_REG8(0x9706), 0x10 },
+ { CCI_REG8(0x9707), 0x03 },
+@@ -374,14 +443,10 @@ static const struct cci_reg_sequence mode_table_common[] = {
+ { CCI_REG8(0x698B), 0x03 },
+
+ /* white balanace */
+- { CCI_REG8(0x0B8E), 0x01 },
+- { CCI_REG8(0x0B8F), 0x00 },
+- { CCI_REG8(0x0B90), 0x01 },
+- { CCI_REG8(0x0B91), 0x00 },
+- { CCI_REG8(0x0B92), 0x01 },
+- { CCI_REG8(0x0B93), 0x00 },
+- { CCI_REG8(0x0B94), 0x01 },
+- { CCI_REG8(0x0B95), 0x00 },
++ { IMX214_REG_ABS_GAIN_GREENR, 0x0100 },
++ { IMX214_REG_ABS_GAIN_RED, 0x0100 },
++ { IMX214_REG_ABS_GAIN_BLUE, 0x0100 },
++ { IMX214_REG_ABS_GAIN_GREENB, 0x0100 },
+
+ /* ATR setting */
+ { CCI_REG8(0x6E50), 0x00 },
+@@ -737,7 +802,7 @@ static int imx214_start_streaming(struct imx214 *imx214)
+
+ usleep_range(10000, 10500);
+
+- cci_write(imx214->regmap, CCI_REG8(0x0138), 0x01, NULL);
++ cci_write(imx214->regmap, IMX214_REG_TEMP_SENSOR_CONTROL, 0x01, NULL);
+
+ ret = __v4l2_ctrl_handler_setup(&imx214->ctrls);
+ if (ret < 0) {
+--
+2.39.5
+
--- /dev/null
+From 085651117d620dc25a706427daa319af18426dba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 14:26:01 +0100
+Subject: media: i2c: imx214: Simplify with dev_err_probe()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Apitzsch <git@apitzsch.eu>
+
+[ Upstream commit 5d6dc133e6e4053b4b92a15a2e1b99d54b3f8adb ]
+
+Error handling in probe() can be a bit simpler with dev_err_probe().
+
+Acked-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: André Apitzsch <git@apitzsch.eu>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx214.c | 54 +++++++++++++++++---------------------
+ 1 file changed, 24 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
+index af6a3859c3f13..db6cdc3b65e37 100644
+--- a/drivers/media/i2c/imx214.c
++++ b/drivers/media/i2c/imx214.c
+@@ -933,14 +933,12 @@ static int imx214_parse_fwnode(struct device *dev)
+ int ret;
+
+ endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
+- if (!endpoint) {
+- dev_err(dev, "endpoint node not found\n");
+- return -EINVAL;
+- }
++ if (!endpoint)
++ return dev_err_probe(dev, -EINVAL, "endpoint node not found\n");
+
+ ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &bus_cfg);
+ if (ret) {
+- dev_err(dev, "parsing endpoint node failed\n");
++ dev_err_probe(dev, ret, "parsing endpoint node failed\n");
+ goto done;
+ }
+
+@@ -949,8 +947,9 @@ static int imx214_parse_fwnode(struct device *dev)
+ break;
+
+ if (i == bus_cfg.nr_of_link_frequencies) {
+- dev_err(dev, "link-frequencies %d not supported, Please review your DT\n",
+- IMX214_DEFAULT_LINK_FREQ);
++ dev_err_probe(dev, -EINVAL,
++ "link-frequencies %d not supported, Please review your DT\n",
++ IMX214_DEFAULT_LINK_FREQ);
+ ret = -EINVAL;
+ goto done;
+ }
+@@ -978,34 +977,28 @@ static int imx214_probe(struct i2c_client *client)
+ imx214->dev = dev;
+
+ imx214->xclk = devm_clk_get(dev, NULL);
+- if (IS_ERR(imx214->xclk)) {
+- dev_err(dev, "could not get xclk");
+- return PTR_ERR(imx214->xclk);
+- }
++ if (IS_ERR(imx214->xclk))
++ return dev_err_probe(dev, PTR_ERR(imx214->xclk),
++ "failed to get xclk\n");
+
+ ret = clk_set_rate(imx214->xclk, IMX214_DEFAULT_CLK_FREQ);
+- if (ret) {
+- dev_err(dev, "could not set xclk frequency\n");
+- return ret;
+- }
++ if (ret)
++ return dev_err_probe(dev, ret,
++ "failed to set xclk frequency\n");
+
+ ret = imx214_get_regulators(dev, imx214);
+- if (ret < 0) {
+- dev_err(dev, "cannot get regulators\n");
+- return ret;
+- }
++ if (ret < 0)
++ return dev_err_probe(dev, ret, "failed to get regulators\n");
+
+ imx214->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+- if (IS_ERR(imx214->enable_gpio)) {
+- dev_err(dev, "cannot get enable gpio\n");
+- return PTR_ERR(imx214->enable_gpio);
+- }
++ if (IS_ERR(imx214->enable_gpio))
++ return dev_err_probe(dev, PTR_ERR(imx214->enable_gpio),
++ "failed to get enable gpio\n");
+
+ imx214->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config);
+- if (IS_ERR(imx214->regmap)) {
+- dev_err(dev, "regmap init failed\n");
+- return PTR_ERR(imx214->regmap);
+- }
++ if (IS_ERR(imx214->regmap))
++ return dev_err_probe(dev, PTR_ERR(imx214->regmap),
++ "regmap init failed\n");
+
+ v4l2_i2c_subdev_init(&imx214->sd, client, &imx214_subdev_ops);
+ imx214->sd.internal_ops = &imx214_internal_ops;
+@@ -1027,14 +1020,14 @@ static int imx214_probe(struct i2c_client *client)
+
+ ret = media_entity_pads_init(&imx214->sd.entity, 1, &imx214->pad);
+ if (ret < 0) {
+- dev_err(dev, "could not register media entity\n");
++ dev_err_probe(dev, ret, "failed to init entity pads\n");
+ goto free_ctrl;
+ }
+
+ imx214->sd.state_lock = imx214->ctrls.lock;
+ ret = v4l2_subdev_init_finalize(&imx214->sd);
+ if (ret < 0) {
+- dev_err(dev, "subdev init error: %d\n", ret);
++ dev_err_probe(dev, ret, "subdev init error\n");
+ goto free_entity;
+ }
+
+@@ -1043,7 +1036,8 @@ static int imx214_probe(struct i2c_client *client)
+
+ ret = v4l2_async_register_subdev_sensor(&imx214->sd);
+ if (ret < 0) {
+- dev_err(dev, "could not register v4l2 device\n");
++ dev_err_probe(dev, ret,
++ "failed to register sensor sub-device\n");
+ goto error_subdev_cleanup;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 71b5bf5de1977e58f9f99b0a4932801748b29c57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 14:26:00 +0100
+Subject: media: i2c: imx214: Use subdev active state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: André Apitzsch <git@apitzsch.eu>
+
+[ Upstream commit b6832ff659f55f86198bb8de40f278a20bda0920 ]
+
+Port the imx214 sensor driver to use the subdev active state.
+
+Move all the format configuration to the subdevice state and simplify
+the format handling, locking and initialization.
+
+While at it, simplify imx214_start_streaming() by removing unneeded goto
+statements and the corresponding error label.
+
+Signed-off-by: André Apitzsch <git@apitzsch.eu>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/imx214.c | 155 ++++++++++++-------------------------
+ 1 file changed, 50 insertions(+), 105 deletions(-)
+
+diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c
+index 6a393e18267f4..af6a3859c3f13 100644
+--- a/drivers/media/i2c/imx214.c
++++ b/drivers/media/i2c/imx214.c
+@@ -59,8 +59,6 @@ struct imx214 {
+
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+- struct v4l2_mbus_framefmt fmt;
+- struct v4l2_rect crop;
+
+ struct v4l2_ctrl_handler ctrls;
+ struct v4l2_ctrl *pixel_rate;
+@@ -71,12 +69,6 @@ struct imx214 {
+ struct regulator_bulk_data supplies[IMX214_NUM_SUPPLIES];
+
+ struct gpio_desc *enable_gpio;
+-
+- /*
+- * Serialize control access, get/set format, get selection
+- * and start streaming.
+- */
+- struct mutex mutex;
+ };
+
+ struct reg_8 {
+@@ -490,6 +482,22 @@ static int __maybe_unused imx214_power_off(struct device *dev)
+ return 0;
+ }
+
++static void imx214_update_pad_format(struct imx214 *imx214,
++ const struct imx214_mode *mode,
++ struct v4l2_mbus_framefmt *fmt, u32 code)
++{
++ fmt->code = IMX214_MBUS_CODE;
++ fmt->width = mode->width;
++ fmt->height = mode->height;
++ fmt->field = V4L2_FIELD_NONE;
++ fmt->colorspace = V4L2_COLORSPACE_SRGB;
++ fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
++ fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
++ fmt->colorspace,
++ fmt->ycbcr_enc);
++ fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
++}
++
+ static int imx214_enum_mbus_code(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_mbus_code_enum *code)
+@@ -549,52 +557,6 @@ static const struct v4l2_subdev_core_ops imx214_core_ops = {
+ #endif
+ };
+
+-static struct v4l2_mbus_framefmt *
+-__imx214_get_pad_format(struct imx214 *imx214,
+- struct v4l2_subdev_state *sd_state,
+- unsigned int pad,
+- enum v4l2_subdev_format_whence which)
+-{
+- switch (which) {
+- case V4L2_SUBDEV_FORMAT_TRY:
+- return v4l2_subdev_state_get_format(sd_state, pad);
+- case V4L2_SUBDEV_FORMAT_ACTIVE:
+- return &imx214->fmt;
+- default:
+- return NULL;
+- }
+-}
+-
+-static int imx214_get_format(struct v4l2_subdev *sd,
+- struct v4l2_subdev_state *sd_state,
+- struct v4l2_subdev_format *format)
+-{
+- struct imx214 *imx214 = to_imx214(sd);
+-
+- mutex_lock(&imx214->mutex);
+- format->format = *__imx214_get_pad_format(imx214, sd_state,
+- format->pad,
+- format->which);
+- mutex_unlock(&imx214->mutex);
+-
+- return 0;
+-}
+-
+-static struct v4l2_rect *
+-__imx214_get_pad_crop(struct imx214 *imx214,
+- struct v4l2_subdev_state *sd_state,
+- unsigned int pad, enum v4l2_subdev_format_whence which)
+-{
+- switch (which) {
+- case V4L2_SUBDEV_FORMAT_TRY:
+- return v4l2_subdev_state_get_crop(sd_state, pad);
+- case V4L2_SUBDEV_FORMAT_ACTIVE:
+- return &imx214->crop;
+- default:
+- return NULL;
+- }
+-}
+-
+ static int imx214_set_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_format *format)
+@@ -604,34 +566,20 @@ static int imx214_set_format(struct v4l2_subdev *sd,
+ struct v4l2_rect *__crop;
+ const struct imx214_mode *mode;
+
+- mutex_lock(&imx214->mutex);
+-
+- __crop = __imx214_get_pad_crop(imx214, sd_state, format->pad,
+- format->which);
+-
+ mode = v4l2_find_nearest_size(imx214_modes,
+ ARRAY_SIZE(imx214_modes), width, height,
+ format->format.width,
+ format->format.height);
+
+- __crop->width = mode->width;
+- __crop->height = mode->height;
+-
+- __format = __imx214_get_pad_format(imx214, sd_state, format->pad,
+- format->which);
+- __format->width = __crop->width;
+- __format->height = __crop->height;
+- __format->code = IMX214_MBUS_CODE;
+- __format->field = V4L2_FIELD_NONE;
+- __format->colorspace = V4L2_COLORSPACE_SRGB;
+- __format->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(__format->colorspace);
+- __format->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
+- __format->colorspace, __format->ycbcr_enc);
+- __format->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(__format->colorspace);
++ imx214_update_pad_format(imx214, mode, &format->format,
++ format->format.code);
++ __format = v4l2_subdev_state_get_format(sd_state, 0);
+
+- format->format = *__format;
++ *__format = format->format;
+
+- mutex_unlock(&imx214->mutex);
++ __crop = v4l2_subdev_state_get_crop(sd_state, 0);
++ __crop->width = mode->width;
++ __crop->height = mode->height;
+
+ return 0;
+ }
+@@ -640,14 +588,9 @@ static int imx214_get_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *sd_state,
+ struct v4l2_subdev_selection *sel)
+ {
+- struct imx214 *imx214 = to_imx214(sd);
+-
+ switch (sel->target) {
+ case V4L2_SEL_TGT_CROP:
+- mutex_lock(&imx214->mutex);
+- sel->r = *__imx214_get_pad_crop(imx214, sd_state, sel->pad,
+- sel->which);
+- mutex_unlock(&imx214->mutex);
++ sel->r = *v4l2_subdev_state_get_crop(sd_state, 0);
+ return 0;
+
+ case V4L2_SEL_TGT_NATIVE_SIZE:
+@@ -826,40 +769,35 @@ static int imx214_write_table(struct imx214 *imx214,
+
+ static int imx214_start_streaming(struct imx214 *imx214)
+ {
++ const struct v4l2_mbus_framefmt *fmt;
++ struct v4l2_subdev_state *state;
+ const struct imx214_mode *mode;
+ int ret;
+
+- mutex_lock(&imx214->mutex);
+ ret = imx214_write_table(imx214, mode_table_common);
+ if (ret < 0) {
+ dev_err(imx214->dev, "could not sent common table %d\n", ret);
+- goto error;
++ return ret;
+ }
+
+- mode = v4l2_find_nearest_size(imx214_modes,
+- ARRAY_SIZE(imx214_modes), width, height,
+- imx214->fmt.width, imx214->fmt.height);
++ state = v4l2_subdev_get_locked_active_state(&imx214->sd);
++ fmt = v4l2_subdev_state_get_format(state, 0);
++ mode = v4l2_find_nearest_size(imx214_modes, ARRAY_SIZE(imx214_modes),
++ width, height, fmt->width, fmt->height);
+ ret = imx214_write_table(imx214, mode->reg_table);
+ if (ret < 0) {
+ dev_err(imx214->dev, "could not sent mode table %d\n", ret);
+- goto error;
++ return ret;
+ }
+ ret = __v4l2_ctrl_handler_setup(&imx214->ctrls);
+ if (ret < 0) {
+ dev_err(imx214->dev, "could not sync v4l2 controls\n");
+- goto error;
++ return ret;
+ }
+ ret = regmap_write(imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STREAMING);
+- if (ret < 0) {
++ if (ret < 0)
+ dev_err(imx214->dev, "could not sent start table %d\n", ret);
+- goto error;
+- }
+
+- mutex_unlock(&imx214->mutex);
+- return 0;
+-
+-error:
+- mutex_unlock(&imx214->mutex);
+ return ret;
+ }
+
+@@ -877,6 +815,7 @@ static int imx214_stop_streaming(struct imx214 *imx214)
+ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable)
+ {
+ struct imx214 *imx214 = to_imx214(subdev);
++ struct v4l2_subdev_state *state;
+ int ret;
+
+ if (enable) {
+@@ -884,7 +823,9 @@ static int imx214_s_stream(struct v4l2_subdev *subdev, int enable)
+ if (ret < 0)
+ return ret;
+
++ state = v4l2_subdev_lock_and_get_active_state(subdev);
+ ret = imx214_start_streaming(imx214);
++ v4l2_subdev_unlock_state(state);
+ if (ret < 0)
+ goto err_rpm_put;
+ } else {
+@@ -948,7 +889,7 @@ static const struct v4l2_subdev_pad_ops imx214_subdev_pad_ops = {
+ .enum_mbus_code = imx214_enum_mbus_code,
+ .enum_frame_size = imx214_enum_frame_size,
+ .enum_frame_interval = imx214_enum_frame_interval,
+- .get_fmt = imx214_get_format,
++ .get_fmt = v4l2_subdev_get_fmt,
+ .set_fmt = imx214_set_format,
+ .get_selection = imx214_get_selection,
+ .get_frame_interval = imx214_get_frame_interval,
+@@ -1079,9 +1020,6 @@ static int imx214_probe(struct i2c_client *client)
+ if (ret < 0)
+ goto error_power_off;
+
+- mutex_init(&imx214->mutex);
+- imx214->ctrls.lock = &imx214->mutex;
+-
+ imx214->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ imx214->pad.flags = MEDIA_PAD_FL_SOURCE;
+ imx214->sd.dev = &client->dev;
+@@ -1093,7 +1031,12 @@ static int imx214_probe(struct i2c_client *client)
+ goto free_ctrl;
+ }
+
+- imx214_entity_init_state(&imx214->sd, NULL);
++ imx214->sd.state_lock = imx214->ctrls.lock;
++ ret = v4l2_subdev_init_finalize(&imx214->sd);
++ if (ret < 0) {
++ dev_err(dev, "subdev init error: %d\n", ret);
++ goto free_entity;
++ }
+
+ pm_runtime_set_active(imx214->dev);
+ pm_runtime_enable(imx214->dev);
+@@ -1101,20 +1044,22 @@ static int imx214_probe(struct i2c_client *client)
+ ret = v4l2_async_register_subdev_sensor(&imx214->sd);
+ if (ret < 0) {
+ dev_err(dev, "could not register v4l2 device\n");
+- goto free_entity;
++ goto error_subdev_cleanup;
+ }
+
+ pm_runtime_idle(imx214->dev);
+
+ return 0;
+
+-free_entity:
++error_subdev_cleanup:
+ pm_runtime_disable(imx214->dev);
+ pm_runtime_set_suspended(&client->dev);
++ v4l2_subdev_cleanup(&imx214->sd);
++
++free_entity:
+ media_entity_cleanup(&imx214->sd.entity);
+
+ free_ctrl:
+- mutex_destroy(&imx214->mutex);
+ v4l2_ctrl_handler_free(&imx214->ctrls);
+
+ error_power_off:
+@@ -1129,9 +1074,9 @@ static void imx214_remove(struct i2c_client *client)
+ struct imx214 *imx214 = to_imx214(sd);
+
+ v4l2_async_unregister_subdev(&imx214->sd);
++ v4l2_subdev_cleanup(sd);
+ media_entity_cleanup(&imx214->sd.entity);
+ v4l2_ctrl_handler_free(&imx214->ctrls);
+- mutex_destroy(&imx214->mutex);
+ pm_runtime_disable(&client->dev);
+ if (!pm_runtime_status_suspended(&client->dev)) {
+ imx214_power_off(imx214->dev);
+--
+2.39.5
+
--- /dev/null
+From ef09e79585143b3478eac27f2cc0d5f47ca27e38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 15:41:28 +0100
+Subject: media: ov08x40: Add missing ov08x40_identify_module() call on
+ stream-start
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit ebf185efadb71bd5344877be683895b6b18d7edf ]
+
+The driver might skip the ov08x40_identify_module() on probe() based on
+the acpi_dev_state_d0() check done in probe().
+
+If the ov08x40_identify_module() call is skipped on probe() it should
+be done on the first stream start. Add the missing call.
+
+Note ov08x40_identify_module() will only do something on its first call,
+subsequent calls are no-ops.
+
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Fixes: b1a42fde6e07 ("media: ov08x40: Avoid sensor probing in D0 state")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/ov08x40.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
+index 580d902977b68..625fbcd39068e 100644
+--- a/drivers/media/i2c/ov08x40.c
++++ b/drivers/media/i2c/ov08x40.c
+@@ -1976,6 +1976,10 @@ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable)
+ if (ret < 0)
+ goto err_unlock;
+
++ ret = ov08x40_identify_module(ov08x);
++ if (ret)
++ goto err_rpm_put;
++
+ /*
+ * Apply default & customized values
+ * and then start streaming.
+--
+2.39.5
+
--- /dev/null
+From c0c8d6ffa08c499ef8ea191c2b8d73cee393967d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Dec 2024 15:41:25 +0100
+Subject: media: ov08x40: Move ov08x40_identify_module() function up
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 7a39639e448f070cbe37317ac922886b6080ff43 ]
+
+Move the ov08x40_identify_module() function to above ov08x40_set_stream()
+this is a preparation patch for adding a missing ov08x40_identify_module()
+call to ov08x40_set_stream().
+
+No functional changes, just moving code around.
+
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Stable-dep-of: ebf185efadb7 ("media: ov08x40: Add missing ov08x40_identify_module() call on stream-start")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/i2c/ov08x40.c | 52 ++++++++++++++++++-------------------
+ 1 file changed, 26 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/media/i2c/ov08x40.c b/drivers/media/i2c/ov08x40.c
+index 83b49cf114acc..580d902977b68 100644
+--- a/drivers/media/i2c/ov08x40.c
++++ b/drivers/media/i2c/ov08x40.c
+@@ -1937,6 +1937,32 @@ static int ov08x40_stop_streaming(struct ov08x40 *ov08x)
+ OV08X40_REG_VALUE_08BIT, OV08X40_MODE_STANDBY);
+ }
+
++/* Verify chip ID */
++static int ov08x40_identify_module(struct ov08x40 *ov08x)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
++ int ret;
++ u32 val;
++
++ if (ov08x->identified)
++ return 0;
++
++ ret = ov08x40_read_reg(ov08x, OV08X40_REG_CHIP_ID,
++ OV08X40_REG_VALUE_24BIT, &val);
++ if (ret)
++ return ret;
++
++ if (val != OV08X40_CHIP_ID) {
++ dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
++ OV08X40_CHIP_ID, val);
++ return -ENXIO;
++ }
++
++ ov08x->identified = true;
++
++ return 0;
++}
++
+ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable)
+ {
+ struct ov08x40 *ov08x = to_ov08x40(sd);
+@@ -1974,32 +2000,6 @@ static int ov08x40_set_stream(struct v4l2_subdev *sd, int enable)
+ return ret;
+ }
+
+-/* Verify chip ID */
+-static int ov08x40_identify_module(struct ov08x40 *ov08x)
+-{
+- struct i2c_client *client = v4l2_get_subdevdata(&ov08x->sd);
+- int ret;
+- u32 val;
+-
+- if (ov08x->identified)
+- return 0;
+-
+- ret = ov08x40_read_reg(ov08x, OV08X40_REG_CHIP_ID,
+- OV08X40_REG_VALUE_24BIT, &val);
+- if (ret)
+- return ret;
+-
+- if (val != OV08X40_CHIP_ID) {
+- dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
+- OV08X40_CHIP_ID, val);
+- return -ENXIO;
+- }
+-
+- ov08x->identified = true;
+-
+- return 0;
+-}
+-
+ static const struct v4l2_subdev_video_ops ov08x40_video_ops = {
+ .s_stream = ov08x40_set_stream,
+ };
+--
+2.39.5
+
--- /dev/null
+From 97ce8265a3bd40f0600f7888b1c51970f74a228c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Mar 2025 16:39:39 +0800
+Subject: mm/vmscan: don't try to reclaim hwpoison folio
+
+From: Jinjiang Tu <tujinjiang@huawei.com>
+
+[ Upstream commit 1b0449544c6482179ac84530b61fc192a6527bfd ]
+
+Syzkaller reports a bug as follows:
+
+Injecting memory failure for pfn 0x18b00e at process virtual address 0x20ffd000
+Memory failure: 0x18b00e: dirty swapcache page still referenced by 2 users
+Memory failure: 0x18b00e: recovery action for dirty swapcache page: Failed
+page: refcount:2 mapcount:0 mapping:0000000000000000 index:0x20ffd pfn:0x18b00e
+memcg:ffff0000dd6d9000
+anon flags: 0x5ffffe00482011(locked|dirty|arch_1|swapbacked|hwpoison|node=0|zone=2|lastcpupid=0xfffff)
+raw: 005ffffe00482011 dead000000000100 dead000000000122 ffff0000e232a7c9
+raw: 0000000000020ffd 0000000000000000 00000002ffffffff ffff0000dd6d9000
+page dumped because: VM_BUG_ON_FOLIO(!folio_test_uptodate(folio))
+------------[ cut here ]------------
+kernel BUG at mm/swap_state.c:184!
+Internal error: Oops - BUG: 00000000f2000800 [#1] SMP
+Modules linked in:
+CPU: 0 PID: 60 Comm: kswapd0 Not tainted 6.6.0-gcb097e7de84e #3
+Hardware name: linux,dummy-virt (DT)
+pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : add_to_swap+0xbc/0x158
+lr : add_to_swap+0xbc/0x158
+sp : ffff800087f37340
+x29: ffff800087f37340 x28: fffffc00052c0380 x27: ffff800087f37780
+x26: ffff800087f37490 x25: ffff800087f37c78 x24: ffff800087f377a0
+x23: ffff800087f37c50 x22: 0000000000000000 x21: fffffc00052c03b4
+x20: 0000000000000000 x19: fffffc00052c0380 x18: 0000000000000000
+x17: 296f696c6f662865 x16: 7461646f7470755f x15: 747365745f6f696c
+x14: 6f6621284f494c4f x13: 0000000000000001 x12: ffff600036d8b97b
+x11: 1fffe00036d8b97a x10: ffff600036d8b97a x9 : dfff800000000000
+x8 : 00009fffc9274686 x7 : ffff0001b6c5cbd3 x6 : 0000000000000001
+x5 : ffff0000c25896c0 x4 : 0000000000000000 x3 : 0000000000000000
+x2 : 0000000000000000 x1 : ffff0000c25896c0 x0 : 0000000000000000
+Call trace:
+ add_to_swap+0xbc/0x158
+ shrink_folio_list+0x12ac/0x2648
+ shrink_inactive_list+0x318/0x948
+ shrink_lruvec+0x450/0x720
+ shrink_node_memcgs+0x280/0x4a8
+ shrink_node+0x128/0x978
+ balance_pgdat+0x4f0/0xb20
+ kswapd+0x228/0x438
+ kthread+0x214/0x230
+ ret_from_fork+0x10/0x20
+
+I can reproduce this issue with the following steps:
+
+1) When a dirty swapcache page is isolated by reclaim process and the
+ page isn't locked, inject memory failure for the page.
+ me_swapcache_dirty() clears uptodate flag and tries to delete from lru,
+ but fails. Reclaim process will put the hwpoisoned page back to lru.
+
+2) The process that maps the hwpoisoned page exits, the page is deleted
+ the page will never be freed and will be in the lru forever.
+
+3) If we trigger a reclaim again and tries to reclaim the page,
+ add_to_swap() will trigger VM_BUG_ON_FOLIO due to the uptodate flag is
+ cleared.
+
+To fix it, skip the hwpoisoned page in shrink_folio_list(). Besides, the
+hwpoison folio may not be unmapped by hwpoison_user_mappings() yet, unmap
+it in shrink_folio_list(), otherwise the folio will fail to be unmaped by
+hwpoison_user_mappings() since the folio isn't in lru list.
+
+Link: https://lkml.kernel.org/r/20250318083939.987651-3-tujinjiang@huawei.com
+Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
+Acked-by: Miaohe Lin <linmiaohe@huawei.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Kefeng Wang <wangkefeng.wang@huawei.com>
+Cc: Nanyong Sun <sunnanyong@huawei.com>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: <stable@vger,kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/vmscan.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index fada3b35aff83..e9f3ae8158a66 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1112,6 +1112,13 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,
+ if (!folio_trylock(folio))
+ goto keep;
+
++ if (folio_contain_hwpoisoned_page(folio)) {
++ unmap_poisoned_folio(folio, folio_pfn(folio), false);
++ folio_unlock(folio);
++ folio_put(folio);
++ continue;
++ }
++
+ VM_BUG_ON_FOLIO(folio_test_active(folio), folio);
+
+ nr_pages = folio_nr_pages(folio);
+--
+2.39.5
+
--- /dev/null
+From c8064ddd4b435aed4f9cd1846a09d429dbd352b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 14:18:51 +0000
+Subject: mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit cbef7442fba510b7eb229dcc9f39d3dde4a159a4 ]
+
+The driver leaks the device reference taken with
+of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get().
+
+Fixes: c7eed31e235c ("mmc: sdhci-msm: Switch to the new ICE API")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-2-1ffa5b6884cb@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci-msm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
+index e3d39311fdc75..3fd898647237f 100644
+--- a/drivers/mmc/host/sdhci-msm.c
++++ b/drivers/mmc/host/sdhci-msm.c
+@@ -1873,7 +1873,7 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
+ if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS))
+ return 0;
+
+- ice = of_qcom_ice_get(dev);
++ ice = devm_of_qcom_ice_get(dev);
+ if (ice == ERR_PTR(-EOPNOTSUPP)) {
+ dev_warn(dev, "Disabling inline encryption support\n");
+ ice = NULL;
+--
+2.39.5
+
--- /dev/null
+From 355be9663f58813713f209467b486f0ff8a1020b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Nov 2024 17:48:43 -0600
+Subject: net/niu: Niu requires MSIX ENTRY_DATA fields touch before entry reads
+
+From: Jonathan Currier <dullfire@yahoo.com>
+
+[ Upstream commit fbb429ddff5c8e479edcc7dde5a542c9295944e6 ]
+
+Fix niu_try_msix() to not cause a fatal trap on sparc systems.
+
+Set PCI_DEV_FLAGS_MSIX_TOUCH_ENTRY_DATA_FIRST on the struct pci_dev to
+work around a bug in the hardware or firmware.
+
+For each vector entry in the msix table, niu chips will cause a fatal
+trap if any registers in that entry are read before that entries'
+ENTRY_DATA register is written to. Testing indicates writes to other
+registers are not sufficient to prevent the fatal trap, however the value
+does not appear to matter. This only needs to happen once after power up,
+so simply rebooting into a kernel lacking this fix will NOT cause the
+trap.
+
+NON-RESUMABLE ERROR: Reporting on cpu 64
+NON-RESUMABLE ERROR: TPC [0x00000000005f6900] <msix_prepare_msi_desc+0x90/0xa0>
+NON-RESUMABLE ERROR: RAW [4010000000000016:00000e37f93e32ff:0000000202000080:ffffffffffffffff
+NON-RESUMABLE ERROR: 0000000800000000:0000000000000000:0000000000000000:0000000000000000]
+NON-RESUMABLE ERROR: handle [0x4010000000000016] stick [0x00000e37f93e32ff]
+NON-RESUMABLE ERROR: type [precise nonresumable]
+NON-RESUMABLE ERROR: attrs [0x02000080] < ASI sp-faulted priv >
+NON-RESUMABLE ERROR: raddr [0xffffffffffffffff]
+NON-RESUMABLE ERROR: insn effective address [0x000000c50020000c]
+NON-RESUMABLE ERROR: size [0x8]
+NON-RESUMABLE ERROR: asi [0x00]
+CPU: 64 UID: 0 PID: 745 Comm: kworker/64:1 Not tainted 6.11.5 #63
+Workqueue: events work_for_cpu_fn
+TSTATE: 0000000011001602 TPC: 00000000005f6900 TNPC: 00000000005f6904 Y: 00000000 Not tainted
+TPC: <msix_prepare_msi_desc+0x90/0xa0>
+g0: 00000000000002e9 g1: 000000000000000c g2: 000000c50020000c g3: 0000000000000100
+g4: ffff8000470307c0 g5: ffff800fec5be000 g6: ffff800047a08000 g7: 0000000000000000
+o0: ffff800014feb000 o1: ffff800047a0b620 o2: 0000000000000011 o3: ffff800047a0b620
+o4: 0000000000000080 o5: 0000000000000011 sp: ffff800047a0ad51 ret_pc: 00000000005f7128
+RPC: <__pci_enable_msix_range+0x3cc/0x460>
+l0: 000000000000000d l1: 000000000000c01f l2: ffff800014feb0a8 l3: 0000000000000020
+l4: 000000000000c000 l5: 0000000000000001 l6: 0000000020000000 l7: ffff800047a0b734
+i0: ffff800014feb000 i1: ffff800047a0b730 i2: 0000000000000001 i3: 000000000000000d
+i4: 0000000000000000 i5: 0000000000000000 i6: ffff800047a0ae81 i7: 00000000101888b0
+I7: <niu_try_msix.constprop.0+0xc0/0x130 [niu]>
+Call Trace:
+[<00000000101888b0>] niu_try_msix.constprop.0+0xc0/0x130 [niu]
+[<000000001018f840>] niu_get_invariants+0x183c/0x207c [niu]
+[<00000000101902fc>] niu_pci_init_one+0x27c/0x2fc [niu]
+[<00000000005ef3e4>] local_pci_probe+0x28/0x74
+[<0000000000469240>] work_for_cpu_fn+0x8/0x1c
+[<000000000046b008>] process_scheduled_works+0x144/0x210
+[<000000000046b518>] worker_thread+0x13c/0x1c0
+[<00000000004710e0>] kthread+0xb8/0xc8
+[<00000000004060c8>] ret_from_fork+0x1c/0x2c
+[<0000000000000000>] 0x0
+Kernel panic - not syncing: Non-resumable error.
+
+Fixes: 7d5ec3d36123 ("PCI/MSI: Mask all unused MSI-X entries")
+Signed-off-by: Jonathan Currier <dullfire@yahoo.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/all/20241117234843.19236-3-dullfire@yahoo.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/sun/niu.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
+index 72177fea1cfb3..edc3165f00774 100644
+--- a/drivers/net/ethernet/sun/niu.c
++++ b/drivers/net/ethernet/sun/niu.c
+@@ -9064,6 +9064,8 @@ static void niu_try_msix(struct niu *np, u8 *ldg_num_map)
+ msi_vec[i].entry = i;
+ }
+
++ pdev->dev_flags |= PCI_DEV_FLAGS_MSIX_TOUCH_ENTRY_DATA_FIRST;
++
+ num_irqs = pci_enable_msix_range(pdev, msi_vec, 1, num_irqs);
+ if (num_irqs < 0) {
+ np->flags &= ~NIU_FLAGS_MSIX;
+--
+2.39.5
+
--- /dev/null
+From 743b33202040c68a1384b3ca76a28af0bbaebcf6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 17:01:55 -0600
+Subject: of: resolver: Fix device node refcount leakage in
+ of_resolve_phandles()
+
+From: Zijun Hu <quic_zijuhu@quicinc.com>
+
+[ Upstream commit a46a0805635d07de50c2ac71588345323c13b2f9 ]
+
+In of_resolve_phandles(), refcount of device node @local_fixups will be
+increased if the for_each_child_of_node() exits early, but nowhere to
+decrease the refcount, so cause refcount leakage for the node.
+
+Fix by using __free() on @local_fixups.
+
+Fixes: da56d04c806a ("of/resolver: Switch to new local fixups format.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
+Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-9-93e3a2659aa7@quicinc.com
+[robh: Use __free() instead]
+Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/resolver.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
+index c871e35d49217..2caad365a665c 100644
+--- a/drivers/of/resolver.c
++++ b/drivers/of/resolver.c
+@@ -249,8 +249,9 @@ static int adjust_local_phandle_references(const struct device_node *local_fixup
+ */
+ int of_resolve_phandles(struct device_node *overlay)
+ {
+- struct device_node *child, *local_fixups, *refnode;
++ struct device_node *child, *refnode;
+ struct device_node *overlay_fixups;
++ struct device_node __free(device_node) *local_fixups = NULL;
+ struct property *prop;
+ const char *refpath;
+ phandle phandle, phandle_delta;
+--
+2.39.5
+
--- /dev/null
+From 06e459d90e3edb57fca8f381ea9afe3133d7af3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 20:59:02 +0800
+Subject: of: resolver: Simplify of_resolve_phandles() using __free()
+
+From: Rob Herring (Arm) <robh@kernel.org>
+
+[ Upstream commit 5275e8b5293f65cc82a5ee5eab02dd573b911d6e ]
+
+Use the __free() cleanup to simplify of_resolve_phandles() and remove
+all the goto's.
+
+Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
+Stable-dep-of: a46a0805635d ("of: resolver: Fix device node refcount leakage in of_resolve_phandles()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/resolver.c | 34 +++++++++++-----------------------
+ 1 file changed, 11 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
+index 779db058c42f5..c871e35d49217 100644
+--- a/drivers/of/resolver.c
++++ b/drivers/of/resolver.c
+@@ -250,24 +250,20 @@ static int adjust_local_phandle_references(const struct device_node *local_fixup
+ int of_resolve_phandles(struct device_node *overlay)
+ {
+ struct device_node *child, *local_fixups, *refnode;
+- struct device_node *tree_symbols, *overlay_fixups;
++ struct device_node *overlay_fixups;
+ struct property *prop;
+ const char *refpath;
+ phandle phandle, phandle_delta;
+ int err;
+
+- tree_symbols = NULL;
+-
+ if (!overlay) {
+ pr_err("null overlay\n");
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ if (!of_node_check_flag(overlay, OF_DETACHED)) {
+ pr_err("overlay not detached\n");
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ phandle_delta = live_tree_max_phandle() + 1;
+@@ -279,7 +275,7 @@ int of_resolve_phandles(struct device_node *overlay)
+
+ err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
+ if (err)
+- goto out;
++ return err;
+
+ overlay_fixups = NULL;
+
+@@ -288,16 +284,13 @@ int of_resolve_phandles(struct device_node *overlay)
+ overlay_fixups = child;
+ }
+
+- if (!overlay_fixups) {
+- err = 0;
+- goto out;
+- }
++ if (!overlay_fixups)
++ return 0;
+
+- tree_symbols = of_find_node_by_path("/__symbols__");
++ struct device_node __free(device_node) *tree_symbols = of_find_node_by_path("/__symbols__");
+ if (!tree_symbols) {
+ pr_err("no symbols in root of device tree.\n");
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ for_each_property_of_node(overlay_fixups, prop) {
+@@ -311,14 +304,12 @@ int of_resolve_phandles(struct device_node *overlay)
+ if (err) {
+ pr_err("node label '%s' not found in live devicetree symbols table\n",
+ prop->name);
+- goto out;
++ return err;
+ }
+
+ refnode = of_find_node_by_path(refpath);
+- if (!refnode) {
+- err = -ENOENT;
+- goto out;
+- }
++ if (!refnode)
++ return -ENOENT;
+
+ phandle = refnode->phandle;
+ of_node_put(refnode);
+@@ -328,11 +319,8 @@ int of_resolve_phandles(struct device_node *overlay)
+ break;
+ }
+
+-out:
+ if (err)
+ pr_err("overlay phandle fixup failed: %d\n", err);
+- of_node_put(tree_symbols);
+-
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(of_resolve_phandles);
+--
+2.39.5
+
--- /dev/null
+From 99df92a026311b5b0c88f8a67b33e271210b05e9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Nov 2024 17:48:42 -0600
+Subject: PCI/MSI: Add an option to write MSIX ENTRY_DATA before any reads
+
+From: Jonathan Currier <dullfire@yahoo.com>
+
+[ Upstream commit cf761e3dacc6ad5f65a4886d00da1f9681e6805a ]
+
+Commit 7d5ec3d36123 ("PCI/MSI: Mask all unused MSI-X entries") introduced a
+readl() from ENTRY_VECTOR_CTRL before the writel() to ENTRY_DATA.
+
+This is correct, however some hardware, like the Sun Neptune chips, the NIU
+module, will cause an error and/or fatal trap if any MSIX table entry is
+read before the corresponding ENTRY_DATA field is written to.
+
+Add an optional early writel() in msix_prepare_msi_desc().
+
+Fixes: 7d5ec3d36123 ("PCI/MSI: Mask all unused MSI-X entries")
+Signed-off-by: Jonathan Currier <dullfire@yahoo.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/all/20241117234843.19236-2-dullfire@yahoo.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/msi/msi.c | 3 +++
+ include/linux/pci.h | 2 ++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
+index 6569ba3577fe6..8b88487886184 100644
+--- a/drivers/pci/msi/msi.c
++++ b/drivers/pci/msi/msi.c
+@@ -615,6 +615,9 @@ void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc)
+ void __iomem *addr = pci_msix_desc_addr(desc);
+
+ desc->pci.msi_attrib.can_mask = 1;
++ /* Workaround for SUN NIU insanity, which requires write before read */
++ if (dev->dev_flags & PCI_DEV_FLAGS_MSIX_TOUCH_ENTRY_DATA_FIRST)
++ writel(0, addr + PCI_MSIX_ENTRY_DATA);
+ desc->pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
+ }
+ }
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 47b31ad724fa5..8e028620642f3 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -245,6 +245,8 @@ enum pci_dev_flags {
+ PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11),
+ /* Device does honor MSI masking despite saying otherwise */
+ PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12),
++ /* Device requires write to PCI_MSIX_ENTRY_DATA before any MSIX reads */
++ PCI_DEV_FLAGS_MSIX_TOUCH_ENTRY_DATA_FIRST = (__force pci_dev_flags_t) (1 << 13),
+ };
+
+ enum pci_irq_reroute_variant {
+--
+2.39.5
+
--- /dev/null
+From 646c2795d1777b4edc580db32cbf62dc955b7db9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2025 10:20:57 +0100
+Subject: PCI/MSI: Convert pci_msi_ignore_mask to per MSI domain flag
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+[ Upstream commit c3164d2e0d181027da8fc94f8179d8607c3d440f ]
+
+Setting pci_msi_ignore_mask inhibits the toggling of the mask bit for both
+MSI and MSI-X entries globally, regardless of the IRQ chip they are using.
+Only Xen sets the pci_msi_ignore_mask when routing physical interrupts over
+event channels, to prevent PCI code from attempting to toggle the maskbit,
+as it's Xen that controls the bit.
+
+However, the pci_msi_ignore_mask being global will affect devices that use
+MSI interrupts but are not routing those interrupts over event channels
+(not using the Xen pIRQ chip). One example is devices behind a VMD PCI
+bridge. In that scenario the VMD bridge configures MSI(-X) using the
+normal IRQ chip (the pIRQ one in the Xen case), and devices behind the
+bridge configure the MSI entries using indexes into the VMD bridge MSI
+table. The VMD bridge then demultiplexes such interrupts and delivers to
+the destination device(s). Having pci_msi_ignore_mask set in that scenario
+prevents (un)masking of MSI entries for devices behind the VMD bridge.
+
+Move the signaling of no entry masking into the MSI domain flags, as that
+allows setting it on a per-domain basis. Set it for the Xen MSI domain
+that uses the pIRQ chip, while leaving it unset for the rest of the
+cases.
+
+Remove pci_msi_ignore_mask at once, since it was only used by Xen code, and
+with Xen dropping usage the variable is unneeded.
+
+This fixes using devices behind a VMD bridge on Xen PV hardware domains.
+
+Albeit Devices behind a VMD bridge are not known to Xen, that doesn't mean
+Linux cannot use them. By inhibiting the usage of
+VMD_FEAT_CAN_BYPASS_MSI_REMAP and the removal of the pci_msi_ignore_mask
+bodge devices behind a VMD bridge do work fine when use from a Linux Xen
+hardware domain. That's the whole point of the series.
+
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Juergen Gross <jgross@suse.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Message-ID: <20250219092059.90850-4-roger.pau@citrix.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Stable-dep-of: cf761e3dacc6 ("PCI/MSI: Add an option to write MSIX ENTRY_DATA before any reads")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/pci/xen.c | 8 ++------
+ drivers/pci/msi/msi.c | 37 +++++++++++++++++++++----------------
+ include/linux/msi.h | 3 ++-
+ kernel/irq/msi.c | 2 +-
+ 4 files changed, 26 insertions(+), 24 deletions(-)
+
+diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
+index 0f2fe524f60dc..b8755cde24199 100644
+--- a/arch/x86/pci/xen.c
++++ b/arch/x86/pci/xen.c
+@@ -436,7 +436,8 @@ static struct msi_domain_ops xen_pci_msi_domain_ops = {
+ };
+
+ static struct msi_domain_info xen_pci_msi_domain_info = {
+- .flags = MSI_FLAG_PCI_MSIX | MSI_FLAG_FREE_MSI_DESCS | MSI_FLAG_DEV_SYSFS,
++ .flags = MSI_FLAG_PCI_MSIX | MSI_FLAG_FREE_MSI_DESCS |
++ MSI_FLAG_DEV_SYSFS | MSI_FLAG_NO_MASK,
+ .ops = &xen_pci_msi_domain_ops,
+ };
+
+@@ -484,11 +485,6 @@ static __init void xen_setup_pci_msi(void)
+ * in allocating the native domain and never use it.
+ */
+ x86_init.irqs.create_pci_msi_domain = xen_create_pci_msi_domain;
+- /*
+- * With XEN PIRQ/Eventchannels in use PCI/MSI[-X] masking is solely
+- * controlled by the hypervisor.
+- */
+- pci_msi_ignore_mask = 1;
+ }
+
+ #else /* CONFIG_PCI_MSI */
+diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
+index 2f647cac4cae3..4c8c2b57b5f61 100644
+--- a/drivers/pci/msi/msi.c
++++ b/drivers/pci/msi/msi.c
+@@ -10,12 +10,12 @@
+ #include <linux/err.h>
+ #include <linux/export.h>
+ #include <linux/irq.h>
++#include <linux/irqdomain.h>
+
+ #include "../pci.h"
+ #include "msi.h"
+
+ int pci_msi_enable = 1;
+-int pci_msi_ignore_mask;
+
+ /**
+ * pci_msi_supported - check whether MSI may be enabled on a device
+@@ -285,6 +285,8 @@ static void pci_msi_set_enable(struct pci_dev *dev, int enable)
+ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
+ struct irq_affinity_desc *masks)
+ {
++ const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
++ const struct msi_domain_info *info = d->host_data;
+ struct msi_desc desc;
+ u16 control;
+
+@@ -295,8 +297,7 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
+ /* Lies, damned lies, and MSIs */
+ if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
+ control |= PCI_MSI_FLAGS_MASKBIT;
+- /* Respect XEN's mask disabling */
+- if (pci_msi_ignore_mask)
++ if (info->flags & MSI_FLAG_NO_MASK)
+ control &= ~PCI_MSI_FLAGS_MASKBIT;
+
+ desc.nvec_used = nvec;
+@@ -604,12 +605,15 @@ static void __iomem *msix_map_region(struct pci_dev *dev,
+ */
+ void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc)
+ {
++ const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
++ const struct msi_domain_info *info = d->host_data;
++
+ desc->nvec_used = 1;
+ desc->pci.msi_attrib.is_msix = 1;
+ desc->pci.msi_attrib.is_64 = 1;
+ desc->pci.msi_attrib.default_irq = dev->irq;
+ desc->pci.mask_base = dev->msix_base;
+- desc->pci.msi_attrib.can_mask = !pci_msi_ignore_mask &&
++ desc->pci.msi_attrib.can_mask = !(info->flags & MSI_FLAG_NO_MASK) &&
+ !desc->pci.msi_attrib.is_virtual;
+
+ if (desc->pci.msi_attrib.can_mask) {
+@@ -659,9 +663,6 @@ static void msix_mask_all(void __iomem *base, int tsize)
+ u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT;
+ int i;
+
+- if (pci_msi_ignore_mask)
+- return;
+-
+ for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE)
+ writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL);
+ }
+@@ -714,6 +715,8 @@ static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries
+ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
+ int nvec, struct irq_affinity *affd)
+ {
++ const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
++ const struct msi_domain_info *info = d->host_data;
+ int ret, tsize;
+ u16 control;
+
+@@ -744,15 +747,17 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
+ /* Disable INTX */
+ pci_intx_for_msi(dev, 0);
+
+- /*
+- * Ensure that all table entries are masked to prevent
+- * stale entries from firing in a crash kernel.
+- *
+- * Done late to deal with a broken Marvell NVME device
+- * which takes the MSI-X mask bits into account even
+- * when MSI-X is disabled, which prevents MSI delivery.
+- */
+- msix_mask_all(dev->msix_base, tsize);
++ if (!(info->flags & MSI_FLAG_NO_MASK)) {
++ /*
++ * Ensure that all table entries are masked to prevent
++ * stale entries from firing in a crash kernel.
++ *
++ * Done late to deal with a broken Marvell NVME device
++ * which takes the MSI-X mask bits into account even
++ * when MSI-X is disabled, which prevents MSI delivery.
++ */
++ msix_mask_all(dev->msix_base, tsize);
++ }
+ pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
+
+ pcibios_free_irq(dev);
+diff --git a/include/linux/msi.h b/include/linux/msi.h
+index b10093c4d00ea..59a421fc42bf0 100644
+--- a/include/linux/msi.h
++++ b/include/linux/msi.h
+@@ -73,7 +73,6 @@ struct msi_msg {
+ };
+ };
+
+-extern int pci_msi_ignore_mask;
+ /* Helper functions */
+ struct msi_desc;
+ struct pci_dev;
+@@ -556,6 +555,8 @@ enum {
+ MSI_FLAG_PCI_MSIX_ALLOC_DYN = (1 << 20),
+ /* PCI MSIs cannot be steered separately to CPU cores */
+ MSI_FLAG_NO_AFFINITY = (1 << 21),
++ /* Inhibit usage of entry masking */
++ MSI_FLAG_NO_MASK = (1 << 22),
+ };
+
+ /**
+diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
+index 396a067a8a56b..7682c36cbccc6 100644
+--- a/kernel/irq/msi.c
++++ b/kernel/irq/msi.c
+@@ -1143,7 +1143,7 @@ static bool msi_check_reservation_mode(struct irq_domain *domain,
+ if (!(info->flags & MSI_FLAG_MUST_REACTIVATE))
+ return false;
+
+- if (IS_ENABLED(CONFIG_PCI_MSI) && pci_msi_ignore_mask)
++ if (info->flags & MSI_FLAG_NO_MASK)
+ return false;
+
+ /*
+--
+2.39.5
+
--- /dev/null
+From 25159432a7b357b21bfc80f9ebeb35ad6d3df29c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Mar 2025 13:05:35 +0100
+Subject: PCI/MSI: Handle the NOMASK flag correctly for all PCI/MSI backends
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 3ece3e8e5976c49c3f887e5923f998eabd54ff40 ]
+
+The conversion of the XEN specific global variable pci_msi_ignore_mask to a
+MSI domain flag, missed the facts that:
+
+ 1) Legacy architectures do not provide a interrupt domain
+ 2) Parent MSI domains do not necessarily have a domain info attached
+
+Both cases result in an unconditional NULL pointer dereference. This was
+unfortunatly missed in review and testing revealed it late.
+
+Cure this by using the existing pci_msi_domain_supports() helper, which
+handles all possible cases correctly.
+
+Fixes: c3164d2e0d18 ("PCI/MSI: Convert pci_msi_ignore_mask to per MSI domain flag")
+Reported-by: Daniel Gomez <da.gomez@kernel.org>
+Reported-by: Borislav Petkov <bp@alien8.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Borislav Petkov <bp@alien8.de>
+Tested-by: Daniel Gomez <da.gomez@kernel.org>
+Link: https://lore.kernel.org/all/87iknwyp2o.ffs@tglx
+Closes: https://lore.kernel.org/all/qn7fzggcj6qe6r6gdbwcz23pzdz2jx64aldccmsuheabhmjgrt@tawf5nfwuvw7
+Stable-dep-of: cf761e3dacc6 ("PCI/MSI: Add an option to write MSIX ENTRY_DATA before any reads")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/msi/msi.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
+index 4c8c2b57b5f61..6569ba3577fe6 100644
+--- a/drivers/pci/msi/msi.c
++++ b/drivers/pci/msi/msi.c
+@@ -285,8 +285,6 @@ static void pci_msi_set_enable(struct pci_dev *dev, int enable)
+ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
+ struct irq_affinity_desc *masks)
+ {
+- const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
+- const struct msi_domain_info *info = d->host_data;
+ struct msi_desc desc;
+ u16 control;
+
+@@ -297,7 +295,7 @@ static int msi_setup_msi_desc(struct pci_dev *dev, int nvec,
+ /* Lies, damned lies, and MSIs */
+ if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
+ control |= PCI_MSI_FLAGS_MASKBIT;
+- if (info->flags & MSI_FLAG_NO_MASK)
++ if (pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY))
+ control &= ~PCI_MSI_FLAGS_MASKBIT;
+
+ desc.nvec_used = nvec;
+@@ -605,20 +603,18 @@ static void __iomem *msix_map_region(struct pci_dev *dev,
+ */
+ void msix_prepare_msi_desc(struct pci_dev *dev, struct msi_desc *desc)
+ {
+- const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
+- const struct msi_domain_info *info = d->host_data;
+-
+ desc->nvec_used = 1;
+ desc->pci.msi_attrib.is_msix = 1;
+ desc->pci.msi_attrib.is_64 = 1;
+ desc->pci.msi_attrib.default_irq = dev->irq;
+ desc->pci.mask_base = dev->msix_base;
+- desc->pci.msi_attrib.can_mask = !(info->flags & MSI_FLAG_NO_MASK) &&
+- !desc->pci.msi_attrib.is_virtual;
+
+- if (desc->pci.msi_attrib.can_mask) {
++
++ if (!pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY) &&
++ !desc->pci.msi_attrib.is_virtual) {
+ void __iomem *addr = pci_msix_desc_addr(desc);
+
++ desc->pci.msi_attrib.can_mask = 1;
+ desc->pci.msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
+ }
+ }
+@@ -715,8 +711,6 @@ static int msix_setup_interrupts(struct pci_dev *dev, struct msix_entry *entries
+ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
+ int nvec, struct irq_affinity *affd)
+ {
+- const struct irq_domain *d = dev_get_msi_domain(&dev->dev);
+- const struct msi_domain_info *info = d->host_data;
+ int ret, tsize;
+ u16 control;
+
+@@ -747,7 +741,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
+ /* Disable INTX */
+ pci_intx_for_msi(dev, 0);
+
+- if (!(info->flags & MSI_FLAG_NO_MASK)) {
++ if (!pci_msi_domain_supports(dev, MSI_FLAG_NO_MASK, DENY_LEGACY)) {
+ /*
+ * Ensure that all table entries are masked to prevent
+ * stale entries from firing in a crash kernel.
+--
+2.39.5
+
--- /dev/null
+From a70ba0e70a8457348d469243dadc4cb60121cecb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 17:49:20 +0100
+Subject: PM: EM: Address RCU-related sparse warnings
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 3ee7be9e10dd5f79448788b899591d4bd2bf0c19 ]
+
+The usage of __rcu in the Energy Model code is quite inconsistent
+which causes the following sparse warnings to trigger:
+
+kernel/power/energy_model.c:169:15: warning: incorrect type in assignment (different address spaces)
+kernel/power/energy_model.c:169:15: expected struct em_perf_table [noderef] __rcu *table
+kernel/power/energy_model.c:169:15: got struct em_perf_table *
+kernel/power/energy_model.c:171:9: warning: incorrect type in argument 1 (different address spaces)
+kernel/power/energy_model.c:171:9: expected struct callback_head *head
+kernel/power/energy_model.c:171:9: got struct callback_head [noderef] __rcu *
+kernel/power/energy_model.c:171:9: warning: cast removes address space '__rcu' of expression
+kernel/power/energy_model.c:182:19: warning: incorrect type in argument 1 (different address spaces)
+kernel/power/energy_model.c:182:19: expected struct kref *kref
+kernel/power/energy_model.c:182:19: got struct kref [noderef] __rcu *
+kernel/power/energy_model.c:200:15: warning: incorrect type in assignment (different address spaces)
+kernel/power/energy_model.c:200:15: expected struct em_perf_table [noderef] __rcu *table
+kernel/power/energy_model.c:200:15: got void *[assigned] _res
+kernel/power/energy_model.c:204:20: warning: incorrect type in argument 1 (different address spaces)
+kernel/power/energy_model.c:204:20: expected struct kref *kref
+kernel/power/energy_model.c:204:20: got struct kref [noderef] __rcu *
+kernel/power/energy_model.c:320:19: warning: incorrect type in argument 1 (different address spaces)
+kernel/power/energy_model.c:320:19: expected struct kref *kref
+kernel/power/energy_model.c:320:19: got struct kref [noderef] __rcu *
+kernel/power/energy_model.c:325:45: warning: incorrect type in argument 2 (different address spaces)
+kernel/power/energy_model.c:325:45: expected struct em_perf_state *table
+kernel/power/energy_model.c:325:45: got struct em_perf_state [noderef] __rcu *
+kernel/power/energy_model.c:425:45: warning: incorrect type in argument 3 (different address spaces)
+kernel/power/energy_model.c:425:45: expected struct em_perf_state *table
+kernel/power/energy_model.c:425:45: got struct em_perf_state [noderef] __rcu *
+kernel/power/energy_model.c:442:15: warning: incorrect type in argument 1 (different address spaces)
+kernel/power/energy_model.c:442:15: expected void const *objp
+kernel/power/energy_model.c:442:15: got struct em_perf_table [noderef] __rcu *[assigned] em_table
+kernel/power/energy_model.c:626:55: warning: incorrect type in argument 2 (different address spaces)
+kernel/power/energy_model.c:626:55: expected struct em_perf_state *table
+kernel/power/energy_model.c:626:55: got struct em_perf_state [noderef] __rcu *
+kernel/power/energy_model.c:681:16: warning: incorrect type in assignment (different address spaces)
+kernel/power/energy_model.c:681:16: expected struct em_perf_state *new_ps
+kernel/power/energy_model.c:681:16: got struct em_perf_state [noderef] __rcu *
+kernel/power/energy_model.c:699:37: warning: incorrect type in argument 2 (different address spaces)
+kernel/power/energy_model.c:699:37: expected struct em_perf_state *table
+kernel/power/energy_model.c:699:37: got struct em_perf_state [noderef] __rcu *
+kernel/power/energy_model.c:733:38: warning: incorrect type in argument 3 (different address spaces)
+kernel/power/energy_model.c:733:38: expected struct em_perf_state *table
+kernel/power/energy_model.c:733:38: got struct em_perf_state [noderef] __rcu *
+kernel/power/energy_model.c:855:53: warning: dereference of noderef expression
+kernel/power/energy_model.c:864:32: warning: dereference of noderef expression
+
+This is because the __rcu annotation for sparse is only applicable to
+pointers that need rcu_dereference() or equivalent for protection, which
+basically means pointers assigned with rcu_assign_pointer().
+
+Make all of the above sparse warnings go away by cleaning up the usage
+of __rcu and using rcu_dereference_protected() where applicable.
+
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
+Link: https://patch.msgid.link/5885405.DvuYhMxLoT@rjwysocki.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/energy_model.h | 12 +++++------
+ kernel/power/energy_model.c | 39 ++++++++++++++++++------------------
+ 2 files changed, 26 insertions(+), 25 deletions(-)
+
+diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
+index 78318d49276dc..b3b8389e9480d 100644
+--- a/include/linux/energy_model.h
++++ b/include/linux/energy_model.h
+@@ -167,13 +167,13 @@ struct em_data_callback {
+ struct em_perf_domain *em_cpu_get(int cpu);
+ struct em_perf_domain *em_pd_get(struct device *dev);
+ int em_dev_update_perf_domain(struct device *dev,
+- struct em_perf_table __rcu *new_table);
++ struct em_perf_table *new_table);
+ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
+ struct em_data_callback *cb, cpumask_t *span,
+ bool microwatts);
+ void em_dev_unregister_perf_domain(struct device *dev);
+-struct em_perf_table __rcu *em_table_alloc(struct em_perf_domain *pd);
+-void em_table_free(struct em_perf_table __rcu *table);
++struct em_perf_table *em_table_alloc(struct em_perf_domain *pd);
++void em_table_free(struct em_perf_table *table);
+ int em_dev_compute_costs(struct device *dev, struct em_perf_state *table,
+ int nr_states);
+ int em_dev_update_chip_binning(struct device *dev);
+@@ -373,14 +373,14 @@ static inline int em_pd_nr_perf_states(struct em_perf_domain *pd)
+ return 0;
+ }
+ static inline
+-struct em_perf_table __rcu *em_table_alloc(struct em_perf_domain *pd)
++struct em_perf_table *em_table_alloc(struct em_perf_domain *pd)
+ {
+ return NULL;
+ }
+-static inline void em_table_free(struct em_perf_table __rcu *table) {}
++static inline void em_table_free(struct em_perf_table *table) {}
+ static inline
+ int em_dev_update_perf_domain(struct device *dev,
+- struct em_perf_table __rcu *new_table)
++ struct em_perf_table *new_table)
+ {
+ return -EINVAL;
+ }
+diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
+index 72655eff6fc52..76c4343796893 100644
+--- a/kernel/power/energy_model.c
++++ b/kernel/power/energy_model.c
+@@ -163,12 +163,8 @@ static void em_debug_remove_pd(struct device *dev) {}
+
+ static void em_release_table_kref(struct kref *kref)
+ {
+- struct em_perf_table __rcu *table;
+-
+ /* It was the last owner of this table so we can free */
+- table = container_of(kref, struct em_perf_table, kref);
+-
+- kfree_rcu(table, rcu);
++ kfree_rcu(container_of(kref, struct em_perf_table, kref), rcu);
+ }
+
+ /**
+@@ -177,7 +173,7 @@ static void em_release_table_kref(struct kref *kref)
+ *
+ * No return values.
+ */
+-void em_table_free(struct em_perf_table __rcu *table)
++void em_table_free(struct em_perf_table *table)
+ {
+ kref_put(&table->kref, em_release_table_kref);
+ }
+@@ -190,9 +186,9 @@ void em_table_free(struct em_perf_table __rcu *table)
+ * has a user.
+ * Returns allocated table or NULL.
+ */
+-struct em_perf_table __rcu *em_table_alloc(struct em_perf_domain *pd)
++struct em_perf_table *em_table_alloc(struct em_perf_domain *pd)
+ {
+- struct em_perf_table __rcu *table;
++ struct em_perf_table *table;
+ int table_size;
+
+ table_size = sizeof(struct em_perf_state) * pd->nr_perf_states;
+@@ -300,9 +296,9 @@ int em_dev_compute_costs(struct device *dev, struct em_perf_state *table,
+ * Return 0 on success or an error code on failure.
+ */
+ int em_dev_update_perf_domain(struct device *dev,
+- struct em_perf_table __rcu *new_table)
++ struct em_perf_table *new_table)
+ {
+- struct em_perf_table __rcu *old_table;
++ struct em_perf_table *old_table;
+ struct em_perf_domain *pd;
+
+ if (!dev)
+@@ -319,7 +315,8 @@ int em_dev_update_perf_domain(struct device *dev,
+
+ kref_get(&new_table->kref);
+
+- old_table = pd->em_table;
++ old_table = rcu_dereference_protected(pd->em_table,
++ lockdep_is_held(&em_pd_mutex));
+ rcu_assign_pointer(pd->em_table, new_table);
+
+ em_cpufreq_update_efficiencies(dev, new_table->state);
+@@ -391,7 +388,7 @@ static int em_create_pd(struct device *dev, int nr_states,
+ struct em_data_callback *cb, cpumask_t *cpus,
+ unsigned long flags)
+ {
+- struct em_perf_table __rcu *em_table;
++ struct em_perf_table *em_table;
+ struct em_perf_domain *pd;
+ struct device *cpu_dev;
+ int cpu, ret, num_cpus;
+@@ -551,6 +548,7 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
+ struct em_data_callback *cb, cpumask_t *cpus,
+ bool microwatts)
+ {
++ struct em_perf_table *em_table;
+ unsigned long cap, prev_cap = 0;
+ unsigned long flags = 0;
+ int cpu, ret;
+@@ -623,7 +621,9 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
+ dev->em_pd->min_perf_state = 0;
+ dev->em_pd->max_perf_state = nr_states - 1;
+
+- em_cpufreq_update_efficiencies(dev, dev->em_pd->em_table->state);
++ em_table = rcu_dereference_protected(dev->em_pd->em_table,
++ lockdep_is_held(&em_pd_mutex));
++ em_cpufreq_update_efficiencies(dev, em_table->state);
+
+ em_debug_create_pd(dev);
+ dev_info(dev, "EM: created perf domain\n");
+@@ -660,7 +660,8 @@ void em_dev_unregister_perf_domain(struct device *dev)
+ mutex_lock(&em_pd_mutex);
+ em_debug_remove_pd(dev);
+
+- em_table_free(dev->em_pd->em_table);
++ em_table_free(rcu_dereference_protected(dev->em_pd->em_table,
++ lockdep_is_held(&em_pd_mutex)));
+
+ kfree(dev->em_pd);
+ dev->em_pd = NULL;
+@@ -668,9 +669,9 @@ void em_dev_unregister_perf_domain(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(em_dev_unregister_perf_domain);
+
+-static struct em_perf_table __rcu *em_table_dup(struct em_perf_domain *pd)
++static struct em_perf_table *em_table_dup(struct em_perf_domain *pd)
+ {
+- struct em_perf_table __rcu *em_table;
++ struct em_perf_table *em_table;
+ struct em_perf_state *ps, *new_ps;
+ int ps_size;
+
+@@ -692,7 +693,7 @@ static struct em_perf_table __rcu *em_table_dup(struct em_perf_domain *pd)
+ }
+
+ static int em_recalc_and_update(struct device *dev, struct em_perf_domain *pd,
+- struct em_perf_table __rcu *em_table)
++ struct em_perf_table *em_table)
+ {
+ int ret;
+
+@@ -723,7 +724,7 @@ static void em_adjust_new_capacity(struct device *dev,
+ struct em_perf_domain *pd,
+ u64 max_cap)
+ {
+- struct em_perf_table __rcu *em_table;
++ struct em_perf_table *em_table;
+
+ em_table = em_table_dup(pd);
+ if (!em_table) {
+@@ -814,7 +815,7 @@ static void em_update_workfn(struct work_struct *work)
+ */
+ int em_dev_update_chip_binning(struct device *dev)
+ {
+- struct em_perf_table __rcu *em_table;
++ struct em_perf_table *em_table;
+ struct em_perf_domain *pd;
+ int i, ret;
+
+--
+2.39.5
+
--- /dev/null
+From 75894af67ad0311f21e3a3e4c8159d3a0479061e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Feb 2025 16:20:21 +0800
+Subject: PM: EM: use kfree_rcu() to simplify the code
+
+From: Li RongQing <lirongqing@baidu.com>
+
+[ Upstream commit 1618f635bdf56f3ac158171114e9bf18db234cbf ]
+
+The callback function of call_rcu() just calls kfree(), so use
+kfree_rcu() instead of call_rcu() + callback function.
+
+Signed-off-by: Li RongQing <lirongqing@baidu.com>
+Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
+Link: https://patch.msgid.link/20250218082021.2766-1-lirongqing@baidu.com
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 3ee7be9e10dd ("PM: EM: Address RCU-related sparse warnings")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/power/energy_model.c | 10 +---------
+ 1 file changed, 1 insertion(+), 9 deletions(-)
+
+diff --git a/kernel/power/energy_model.c b/kernel/power/energy_model.c
+index 3874f0e97651e..72655eff6fc52 100644
+--- a/kernel/power/energy_model.c
++++ b/kernel/power/energy_model.c
+@@ -161,14 +161,6 @@ static void em_debug_create_pd(struct device *dev) {}
+ static void em_debug_remove_pd(struct device *dev) {}
+ #endif
+
+-static void em_destroy_table_rcu(struct rcu_head *rp)
+-{
+- struct em_perf_table __rcu *table;
+-
+- table = container_of(rp, struct em_perf_table, rcu);
+- kfree(table);
+-}
+-
+ static void em_release_table_kref(struct kref *kref)
+ {
+ struct em_perf_table __rcu *table;
+@@ -176,7 +168,7 @@ static void em_release_table_kref(struct kref *kref)
+ /* It was the last owner of this table so we can free */
+ table = container_of(kref, struct em_perf_table, kref);
+
+- call_rcu(&table->rcu, em_destroy_table_rcu);
++ kfree_rcu(table, rcu);
+ }
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From d04b275636d31a1ff5237a9df364ee69693d75f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 13:07:47 +0100
+Subject: s390/pci: Support mmap() of PCI resources except for ISM devices
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit aa9f168d55dc47c0de564f7dfe0e90467c9fee71 ]
+
+So far s390 does not allow mmap() of PCI resources to user-space via the
+usual mechanisms, though it does use it for RDMA. For the PCI sysfs
+resource files and /proc/bus/pci it defines neither HAVE_PCI_MMAP nor
+ARCH_GENERIC_PCI_MMAP_RESOURCE. For vfio-pci s390 previously relied on
+disabled VFIO_PCI_MMAP and now relies on setting pdev->non_mappable_bars
+for all devices.
+
+This is partly because access to mapped PCI resources from user-space
+requires special PCI load/store memory-I/O (MIO) instructions, or the
+special MMIO syscalls when these are not available. Still, such access is
+possible and useful not just for RDMA, in fact not being able to mmap() PCI
+resources has previously caused extra work when testing devices.
+
+One thing that doesn't work with PCI resources mapped to user-space though
+is the s390 specific virtual ISM device. Not only because the BAR size of
+256 TiB prevents mapping the whole BAR but also because access requires use
+of the legacy PCI instructions which are not accessible to user-space on
+systems with the newer MIO PCI instructions.
+
+Now with the pdev->non_mappable_bars flag ISM can be excluded from mapping
+its resources while making this functionality available for all other PCI
+devices. To this end introduce a minimal implementation of PCI_QUIRKS and
+use that to set pdev->non_mappable_bars for ISM devices only. Then also set
+ARCH_GENERIC_PCI_MMAP_RESOURCE to take advantage of the generic
+implementation of pci_mmap_resource_range() enabling only the newer sysfs
+mmap() interface. This follows the recommendation in
+Documentation/PCI/sysfs-pci.rst.
+
+Link: https://lore.kernel.org/r/20250226-vfio_pci_mmap-v7-3-c5c0f1d26efd@linux.ibm.com
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/Kconfig | 4 +---
+ arch/s390/include/asm/pci.h | 3 +++
+ arch/s390/pci/Makefile | 2 +-
+ arch/s390/pci/pci_fixup.c | 23 +++++++++++++++++++++++
+ drivers/s390/net/ism_drv.c | 1 -
+ include/linux/pci_ids.h | 1 +
+ 6 files changed, 29 insertions(+), 5 deletions(-)
+ create mode 100644 arch/s390/pci/pci_fixup.c
+
+diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
+index 9c9ec08d78c71..e48741e001476 100644
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -41,9 +41,6 @@ config AUDIT_ARCH
+ config NO_IOPORT_MAP
+ def_bool y
+
+-config PCI_QUIRKS
+- def_bool n
+-
+ config ARCH_SUPPORTS_UPROBES
+ def_bool y
+
+@@ -258,6 +255,7 @@ config S390
+ select PCI_DOMAINS if PCI
+ select PCI_MSI if PCI
+ select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
++ select PCI_QUIRKS if PCI
+ select SPARSE_IRQ
+ select SWIOTLB
+ select SYSCTL_EXCEPTION_TRACE
+diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
+index 474e1f8d1d3c2..d2086af3434c0 100644
+--- a/arch/s390/include/asm/pci.h
++++ b/arch/s390/include/asm/pci.h
+@@ -11,6 +11,9 @@
+ #include <asm/pci_insn.h>
+ #include <asm/sclp.h>
+
++#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
++#define arch_can_pci_mmap_wc() 1
++
+ #define PCIBIOS_MIN_IO 0x1000
+ #define PCIBIOS_MIN_MEM 0x10000000
+
+diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
+index df73c5182990a..1810e0944a4ed 100644
+--- a/arch/s390/pci/Makefile
++++ b/arch/s390/pci/Makefile
+@@ -5,6 +5,6 @@
+
+ obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_clp.o \
+ pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
+- pci_bus.o pci_kvm_hook.o pci_report.o
++ pci_bus.o pci_kvm_hook.o pci_report.o pci_fixup.o
+ obj-$(CONFIG_PCI_IOV) += pci_iov.o
+ obj-$(CONFIG_SYSFS) += pci_sysfs.o
+diff --git a/arch/s390/pci/pci_fixup.c b/arch/s390/pci/pci_fixup.c
+new file mode 100644
+index 0000000000000..35688b6450983
+--- /dev/null
++++ b/arch/s390/pci/pci_fixup.c
+@@ -0,0 +1,23 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Exceptions for specific devices,
++ *
++ * Copyright IBM Corp. 2025
++ *
++ * Author(s):
++ * Niklas Schnelle <schnelle@linux.ibm.com>
++ */
++#include <linux/pci.h>
++
++static void zpci_ism_bar_no_mmap(struct pci_dev *pdev)
++{
++ /*
++ * ISM's BAR is special. Drivers written for ISM know
++ * how to handle this but others need to be aware of their
++ * special nature e.g. to prevent attempts to mmap() it.
++ */
++ pdev->non_mappable_bars = 1;
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM,
++ PCI_DEVICE_ID_IBM_ISM,
++ zpci_ism_bar_no_mmap);
+diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
+index 2f34761e64135..60ed70a39d2cc 100644
+--- a/drivers/s390/net/ism_drv.c
++++ b/drivers/s390/net/ism_drv.c
+@@ -20,7 +20,6 @@
+ MODULE_DESCRIPTION("ISM driver for s390");
+ MODULE_LICENSE("GPL");
+
+-#define PCI_DEVICE_ID_IBM_ISM 0x04ED
+ #define DRV_NAME "ism"
+
+ static const struct pci_device_id ism_device_table[] = {
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 2a9ca3dbaa0e9..5bd122a9afdc6 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -518,6 +518,7 @@
+ #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251
+ #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
+ #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
++#define PCI_DEVICE_ID_IBM_ISM 0x04ed
+
+ #define PCI_SUBVENDOR_ID_IBM 0x1014
+ #define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4
+--
+2.39.5
+
--- /dev/null
+From 9ab4f7145217a8908bafb56c7ae423f1428f0302 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 14:18:52 +0000
+Subject: scsi: ufs: qcom: fix dev reference leaked through of_qcom_ice_get
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit ded40f32b55f7f2f4ed9627dd3c37a1fe89ed8c6 ]
+
+The driver leaks the device reference taken with
+of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get().
+
+Fixes: 56541c7c4468 ("scsi: ufs: ufs-qcom: Switch to the new ICE API")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Acked-by: Martin K. Petersen <martin.petersen@oracle.com> # SCSI
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-3-1ffa5b6884cb@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ufs/host/ufs-qcom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index 23b9f6efa0475..a455a95f65fc6 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -125,7 +125,7 @@ static int ufs_qcom_ice_init(struct ufs_qcom_host *host)
+ int err;
+ int i;
+
+- ice = of_qcom_ice_get(dev);
++ ice = devm_of_qcom_ice_get(dev);
+ if (ice == ERR_PTR(-EOPNOTSUPP)) {
+ dev_warn(dev, "Disabling inline encryption support\n");
+ ice = NULL;
+--
+2.39.5
+
+mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch
+soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch
+mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch
+pm-em-use-kfree_rcu-to-simplify-the-code.patch
+pm-em-address-rcu-related-sparse-warnings.patch
+media-i2c-imx214-use-subdev-active-state.patch
+media-i2c-imx214-simplify-with-dev_err_probe.patch
+media-i2c-imx214-convert-to-cci-register-access-help.patch
+media-i2c-imx214-replace-register-addresses-with-mac.patch
+media-i2c-imx214-check-number-of-lanes-from-device-t.patch
+media-i2c-imx214-fix-link-frequency-validation.patch
+media-ov08x40-move-ov08x40_identify_module-function-.patch
+media-ov08x40-add-missing-ov08x40_identify_module-ca.patch
+iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch
+iio-adc-ad7768-1-fix-conversion-result-sign.patch
+of-resolver-simplify-of_resolve_phandles-using-__fre.patch
+of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
+scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch
+s390-pci-support-mmap-of-pci-resources-except-for-is.patch
+pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch
+pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch
+pci-msi-add-an-option-to-write-msix-entry_data-befor.patch
+ubsan-overflow-rework-integer-overflow-sanitizer-opt.patch
+lib-kconfig.ubsan-remove-default-ubsan-from-ubsan_in.patch
+irqchip-renesas-rzv2h-simplify-rzv2h_icu_init.patch
+irqchip-renesas-rzv2h-add-struct-rzv2h_hw_info-with-.patch
+irqchip-renesas-rzv2h-prevent-tint-spurious-interrup.patch
+net-niu-niu-requires-msix-entry_data-fields-touch-be.patch
+drm-xe-ptl-apply-wa_14023061436.patch
+drm-xe-xe3lpg-add-wa_13012615864.patch
+drm-xe-add-performance-tunings-to-debugfs.patch
+drm-xe-rtp-drop-sentinels-from-arg-to-xe_rtp_process.patch
+drm-xe-ensure-fixed_slice_mode-gets-set-after-ccs_mo.patch
--- /dev/null
+From 759b595dfe0f3d671a4c3a02fc54240a739e9738 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 14:18:50 +0000
+Subject: soc: qcom: ice: introduce devm_of_qcom_ice_get
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit 1c13d6060d612601a61423f2e8fbf9e48126acca ]
+
+Callers of of_qcom_ice_get() leak the device reference taken by
+of_find_device_by_node(). Introduce devm variant for of_qcom_ice_get().
+Existing consumers need the ICE instance for the entire life of their
+device, thus exporting qcom_ice_put() is not required.
+
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-1-1ffa5b6884cb@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: cbef7442fba5 ("mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 48 ++++++++++++++++++++++++++++++++++++++++++
+ include/soc/qcom/ice.h | 2 ++
+ 2 files changed, 50 insertions(+)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index 393d2d1d275f1..79e04bff3e331 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -11,6 +11,7 @@
+ #include <linux/cleanup.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
++#include <linux/device.h>
+ #include <linux/iopoll.h>
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+@@ -324,6 +325,53 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(of_qcom_ice_get);
+
++static void qcom_ice_put(const struct qcom_ice *ice)
++{
++ struct platform_device *pdev = to_platform_device(ice->dev);
++
++ if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"))
++ platform_device_put(pdev);
++}
++
++static void devm_of_qcom_ice_put(struct device *dev, void *res)
++{
++ qcom_ice_put(*(struct qcom_ice **)res);
++}
++
++/**
++ * devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from
++ * a DT node.
++ * @dev: device pointer for the consumer device.
++ *
++ * This function will provide an ICE instance either by creating one for the
++ * consumer device if its DT node provides the 'ice' reg range and the 'ice'
++ * clock (for legacy DT style). On the other hand, if consumer provides a
++ * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
++ * be created and so this function will return that instead.
++ *
++ * Return: ICE pointer on success, NULL if there is no ICE data provided by the
++ * consumer or ERR_PTR() on error.
++ */
++struct qcom_ice *devm_of_qcom_ice_get(struct device *dev)
++{
++ struct qcom_ice *ice, **dr;
++
++ dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return ERR_PTR(-ENOMEM);
++
++ ice = of_qcom_ice_get(dev);
++ if (!IS_ERR_OR_NULL(ice)) {
++ *dr = ice;
++ devres_add(dev, dr);
++ } else {
++ devres_free(dr);
++ }
++
++ return ice;
++}
++EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get);
++
+ static int qcom_ice_probe(struct platform_device *pdev)
+ {
+ struct qcom_ice *engine;
+diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
+index 5870a94599a25..d5f6a228df659 100644
+--- a/include/soc/qcom/ice.h
++++ b/include/soc/qcom/ice.h
+@@ -34,4 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice,
+ int slot);
+ int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
+ struct qcom_ice *of_qcom_ice_get(struct device *dev);
++struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
++
+ #endif /* __QCOM_ICE_H__ */
+--
+2.39.5
+
--- /dev/null
+From fb97229c8a9bdfc8d6a35894f08aa20b22b9a932 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 20:19:09 -0800
+Subject: ubsan/overflow: Rework integer overflow sanitizer option to turn on
+ everything
+
+From: Kees Cook <kees@kernel.org>
+
+[ Upstream commit ed2b548f1017586c44f50654ef9febb42d491f31 ]
+
+Since we're going to approach integer overflow mitigation a type at a
+time, we need to enable all of the associated sanitizers, and then opt
+into types one at a time.
+
+Rename the existing "signed wrap" sanitizer to just the entire topic area:
+"integer wrap". Enable the implicit integer truncation sanitizers, with
+required callbacks and tests.
+
+Notably, this requires features (currently) only available in Clang,
+so we can depend on the cc-option tests to determine availability
+instead of doing version tests.
+
+Link: https://lore.kernel.org/r/20250307041914.937329-1-kees@kernel.org
+Signed-off-by: Kees Cook <kees@kernel.org>
+Stable-dep-of: cdc2e1d9d929 ("lib/Kconfig.ubsan: Remove 'default UBSAN' from UBSAN_INTEGER_WRAP")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/compiler_types.h | 2 +-
+ kernel/configs/hardening.config | 2 +-
+ lib/Kconfig.ubsan | 23 +++++++++++------------
+ lib/test_ubsan.c | 18 ++++++++++++++----
+ lib/ubsan.c | 28 ++++++++++++++++++++++++++--
+ lib/ubsan.h | 8 ++++++++
+ scripts/Makefile.lib | 4 ++--
+ scripts/Makefile.ubsan | 8 ++++++--
+ 8 files changed, 69 insertions(+), 24 deletions(-)
+
+diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
+index 981cc3d7e3aa5..352ad20830733 100644
+--- a/include/linux/compiler_types.h
++++ b/include/linux/compiler_types.h
+@@ -360,7 +360,7 @@ struct ftrace_likely_data {
+ #endif
+
+ /* Do not trap wrapping arithmetic within an annotated function. */
+-#ifdef CONFIG_UBSAN_SIGNED_WRAP
++#ifdef CONFIG_UBSAN_INTEGER_WRAP
+ # define __signed_wrap __attribute__((no_sanitize("signed-integer-overflow")))
+ #else
+ # define __signed_wrap
+diff --git a/kernel/configs/hardening.config b/kernel/configs/hardening.config
+index 3fabb8f55ef6e..dd7c32fb5ac1b 100644
+--- a/kernel/configs/hardening.config
++++ b/kernel/configs/hardening.config
+@@ -46,7 +46,7 @@ CONFIG_UBSAN_BOUNDS=y
+ # CONFIG_UBSAN_SHIFT is not set
+ # CONFIG_UBSAN_DIV_ZERO is not set
+ # CONFIG_UBSAN_UNREACHABLE is not set
+-# CONFIG_UBSAN_SIGNED_WRAP is not set
++# CONFIG_UBSAN_INTEGER_WRAP is not set
+ # CONFIG_UBSAN_BOOL is not set
+ # CONFIG_UBSAN_ENUM is not set
+ # CONFIG_UBSAN_ALIGNMENT is not set
+diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan
+index 1d4aa7a83b3a5..63e5622010e0f 100644
+--- a/lib/Kconfig.ubsan
++++ b/lib/Kconfig.ubsan
+@@ -116,21 +116,20 @@ config UBSAN_UNREACHABLE
+ This option enables -fsanitize=unreachable which checks for control
+ flow reaching an expected-to-be-unreachable position.
+
+-config UBSAN_SIGNED_WRAP
+- bool "Perform checking for signed arithmetic wrap-around"
++config UBSAN_INTEGER_WRAP
++ bool "Perform checking for integer arithmetic wrap-around"
+ default UBSAN
+ depends on !COMPILE_TEST
+- # The no_sanitize attribute was introduced in GCC with version 8.
+- depends on !CC_IS_GCC || GCC_VERSION >= 80000
+ depends on $(cc-option,-fsanitize=signed-integer-overflow)
+- help
+- This option enables -fsanitize=signed-integer-overflow which checks
+- for wrap-around of any arithmetic operations with signed integers.
+- This currently performs nearly no instrumentation due to the
+- kernel's use of -fno-strict-overflow which converts all would-be
+- arithmetic undefined behavior into wrap-around arithmetic. Future
+- sanitizer versions will allow for wrap-around checking (rather than
+- exclusively undefined behavior).
++ depends on $(cc-option,-fsanitize=unsigned-integer-overflow)
++ depends on $(cc-option,-fsanitize=implicit-signed-integer-truncation)
++ depends on $(cc-option,-fsanitize=implicit-unsigned-integer-truncation)
++ help
++ This option enables all of the sanitizers involved in integer overflow
++ (wrap-around) mitigation: signed-integer-overflow, unsigned-integer-overflow,
++ implicit-signed-integer-truncation, and implicit-unsigned-integer-truncation.
++ This is currently limited only to the size_t type while testing and
++ compiler development continues.
+
+ config UBSAN_BOOL
+ bool "Perform checking for non-boolean values used as boolean"
+diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c
+index 5d7b10e986107..8772e5edaa4fa 100644
+--- a/lib/test_ubsan.c
++++ b/lib/test_ubsan.c
+@@ -15,7 +15,7 @@ static void test_ubsan_add_overflow(void)
+ {
+ volatile int val = INT_MAX;
+
+- UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
++ UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP);
+ val += 2;
+ }
+
+@@ -24,7 +24,7 @@ static void test_ubsan_sub_overflow(void)
+ volatile int val = INT_MIN;
+ volatile int val2 = 2;
+
+- UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
++ UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP);
+ val -= val2;
+ }
+
+@@ -32,7 +32,7 @@ static void test_ubsan_mul_overflow(void)
+ {
+ volatile int val = INT_MAX / 2;
+
+- UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
++ UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP);
+ val *= 3;
+ }
+
+@@ -40,7 +40,7 @@ static void test_ubsan_negate_overflow(void)
+ {
+ volatile int val = INT_MIN;
+
+- UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
++ UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP);
+ val = -val;
+ }
+
+@@ -53,6 +53,15 @@ static void test_ubsan_divrem_overflow(void)
+ val /= val2;
+ }
+
++static void test_ubsan_truncate_signed(void)
++{
++ volatile long val = LONG_MAX;
++ volatile int val2 = 0;
++
++ UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP);
++ val2 = val;
++}
++
+ static void test_ubsan_shift_out_of_bounds(void)
+ {
+ volatile int neg = -1, wrap = 4;
+@@ -127,6 +136,7 @@ static const test_ubsan_fp test_ubsan_array[] = {
+ test_ubsan_sub_overflow,
+ test_ubsan_mul_overflow,
+ test_ubsan_negate_overflow,
++ test_ubsan_truncate_signed,
+ test_ubsan_shift_out_of_bounds,
+ test_ubsan_out_of_bounds,
+ test_ubsan_load_invalid_value,
+diff --git a/lib/ubsan.c b/lib/ubsan.c
+index a1c983d148f16..cdc1d31c3821b 100644
+--- a/lib/ubsan.c
++++ b/lib/ubsan.c
+@@ -44,7 +44,7 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
+ case ubsan_shift_out_of_bounds:
+ return "UBSAN: shift out of bounds";
+ #endif
+-#if defined(CONFIG_UBSAN_DIV_ZERO) || defined(CONFIG_UBSAN_SIGNED_WRAP)
++#if defined(CONFIG_UBSAN_DIV_ZERO) || defined(CONFIG_UBSAN_INTEGER_WRAP)
+ /*
+ * SanitizerKind::IntegerDivideByZero and
+ * SanitizerKind::SignedIntegerOverflow emit
+@@ -79,7 +79,7 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
+ case ubsan_type_mismatch:
+ return "UBSAN: type mismatch";
+ #endif
+-#ifdef CONFIG_UBSAN_SIGNED_WRAP
++#ifdef CONFIG_UBSAN_INTEGER_WRAP
+ /*
+ * SanitizerKind::SignedIntegerOverflow emits
+ * SanitizerHandler::AddOverflow, SanitizerHandler::SubOverflow,
+@@ -303,6 +303,30 @@ void __ubsan_handle_negate_overflow(void *_data, void *old_val)
+ }
+ EXPORT_SYMBOL(__ubsan_handle_negate_overflow);
+
++void __ubsan_handle_implicit_conversion(void *_data, void *from_val, void *to_val)
++{
++ struct implicit_conversion_data *data = _data;
++ char from_val_str[VALUE_LENGTH];
++ char to_val_str[VALUE_LENGTH];
++
++ if (suppress_report(&data->location))
++ return;
++
++ val_to_string(from_val_str, sizeof(from_val_str), data->from_type, from_val);
++ val_to_string(to_val_str, sizeof(to_val_str), data->to_type, to_val);
++
++ ubsan_prologue(&data->location, "implicit-conversion");
++
++ pr_err("cannot represent %s value %s during %s %s, truncated to %s\n",
++ data->from_type->type_name,
++ from_val_str,
++ type_check_kinds[data->type_check_kind],
++ data->to_type->type_name,
++ to_val_str);
++
++ ubsan_epilogue();
++}
++EXPORT_SYMBOL(__ubsan_handle_implicit_conversion);
+
+ void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
+ {
+diff --git a/lib/ubsan.h b/lib/ubsan.h
+index 07e37d4429b4b..b37e22374e774 100644
+--- a/lib/ubsan.h
++++ b/lib/ubsan.h
+@@ -62,6 +62,13 @@ struct overflow_data {
+ struct type_descriptor *type;
+ };
+
++struct implicit_conversion_data {
++ struct source_location location;
++ struct type_descriptor *from_type;
++ struct type_descriptor *to_type;
++ unsigned char type_check_kind;
++};
++
+ struct type_mismatch_data {
+ struct source_location location;
+ struct type_descriptor *type;
+@@ -142,6 +149,7 @@ void ubsan_linkage __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs)
+ void ubsan_linkage __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs);
+ void ubsan_linkage __ubsan_handle_negate_overflow(void *_data, void *old_val);
+ void ubsan_linkage __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs);
++void ubsan_linkage __ubsan_handle_implicit_conversion(void *_data, void *lhs, void *rhs);
+ void ubsan_linkage __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr);
+ void ubsan_linkage __ubsan_handle_type_mismatch_v1(void *_data, void *ptr);
+ void ubsan_linkage __ubsan_handle_out_of_bounds(void *_data, void *index);
+diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
+index cad20f0e66ee9..981d14ef9db29 100644
+--- a/scripts/Makefile.lib
++++ b/scripts/Makefile.lib
+@@ -166,8 +166,8 @@ _c_flags += $(if $(patsubst n%,, \
+ $(UBSAN_SANITIZE_$(target-stem).o)$(UBSAN_SANITIZE)$(is-kernel-object)), \
+ $(CFLAGS_UBSAN))
+ _c_flags += $(if $(patsubst n%,, \
+- $(UBSAN_SIGNED_WRAP_$(target-stem).o)$(UBSAN_SANITIZE_$(target-stem).o)$(UBSAN_SIGNED_WRAP)$(UBSAN_SANITIZE)$(is-kernel-object)), \
+- $(CFLAGS_UBSAN_SIGNED_WRAP))
++ $(UBSAN_INTEGER_WRAP_$(target-stem).o)$(UBSAN_SANITIZE_$(target-stem).o)$(UBSAN_INTEGER_WRAP)$(UBSAN_SANITIZE)$(is-kernel-object)), \
++ $(CFLAGS_UBSAN_INTEGER_WRAP))
+ endif
+
+ ifeq ($(CONFIG_KCOV),y)
+diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan
+index b2d3b273b8028..4fad9afed24cf 100644
+--- a/scripts/Makefile.ubsan
++++ b/scripts/Makefile.ubsan
+@@ -14,5 +14,9 @@ ubsan-cflags-$(CONFIG_UBSAN_TRAP) += $(call cc-option,-fsanitize-trap=undefined
+
+ export CFLAGS_UBSAN := $(ubsan-cflags-y)
+
+-ubsan-signed-wrap-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow
+-export CFLAGS_UBSAN_SIGNED_WRAP := $(ubsan-signed-wrap-cflags-y)
++ubsan-integer-wrap-cflags-$(CONFIG_UBSAN_INTEGER_WRAP) += \
++ -fsanitize=signed-integer-overflow \
++ -fsanitize=unsigned-integer-overflow \
++ -fsanitize=implicit-signed-integer-truncation \
++ -fsanitize=implicit-unsigned-integer-truncation
++export CFLAGS_UBSAN_INTEGER_WRAP := $(ubsan-integer-wrap-cflags-y)
+--
+2.39.5
+