From ced1cbbaaa46ef00319b2769badb950e08ba241a Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 26 Apr 2025 09:23:08 -0400 Subject: [PATCH] Fixes for 6.14 Signed-off-by: Sasha Levin --- ...e-add-performance-tunings-to-debugfs.patch | 218 +++++ ...xed_slice_mode-gets-set-after-ccs_mo.patch | 63 ++ .../drm-xe-ptl-apply-wa_14023061436.patch | 61 ++ ...sentinels-from-arg-to-xe_rtp_process.patch | 282 ++++++ .../drm-xe-xe3lpg-add-wa_13012615864.patch | 52 ++ ...-ad7768-1-fix-conversion-result-sign.patch | 55 ++ ...-move-setting-of-val-a-bit-later-to-.patch | 47 + ...rzv2h-add-struct-rzv2h_hw_info-with-.patch | 179 ++++ ...rzv2h-prevent-tint-spurious-interrup.patch | 47 + ...enesas-rzv2h-simplify-rzv2h_icu_init.patch | 110 +++ ...n-remove-default-ubsan-from-ubsan_in.patch | 53 ++ ...-check-number-of-lanes-from-device-t.patch | 78 ++ ...-convert-to-cci-register-access-help.patch | 858 ++++++++++++++++++ ...imx214-fix-link-frequency-validation.patch | 94 ++ ...-replace-register-addresses-with-mac.patch | 545 +++++++++++ ...c-imx214-simplify-with-dev_err_probe.patch | 137 +++ ...a-i2c-imx214-use-subdev-active-state.patch | 331 +++++++ ...d-missing-ov08x40_identify_module-ca.patch | 48 + ...ve-ov08x40_identify_module-function-.patch | 98 ++ ...-don-t-try-to-reclaim-hwpoison-folio.patch | 106 +++ ...x-dev-reference-leaked-through-of_qc.patch | 42 + ...ires-msix-entry_data-fields-touch-be.patch | 86 ++ ...device-node-refcount-leakage-in-of_r.patch | 45 + ...lify-of_resolve_phandles-using-__fre.patch | 114 +++ ...ption-to-write-msix-entry_data-befor.patch | 59 ++ ...pci_msi_ignore_mask-to-per-msi-domai.patch | 222 +++++ ...he-nomask-flag-correctly-for-all-pci.patch | 105 +++ ...-address-rcu-related-sparse-warnings.patch | 252 +++++ ...m-use-kfree_rcu-to-simplify-the-code.patch | 53 ++ ...-mmap-of-pci-resources-except-for-is.patch | 155 ++++ ...x-dev-reference-leaked-through-of_qc.patch | 42 + queue-6.14/series | 33 + ...m-ice-introduce-devm_of_qcom_ice_get.patch | 107 +++ ...ework-integer-overflow-sanitizer-opt.patch | 277 ++++++ 34 files changed, 5054 insertions(+) create mode 100644 queue-6.14/drm-xe-add-performance-tunings-to-debugfs.patch create mode 100644 queue-6.14/drm-xe-ensure-fixed_slice_mode-gets-set-after-ccs_mo.patch create mode 100644 queue-6.14/drm-xe-ptl-apply-wa_14023061436.patch create mode 100644 queue-6.14/drm-xe-rtp-drop-sentinels-from-arg-to-xe_rtp_process.patch create mode 100644 queue-6.14/drm-xe-xe3lpg-add-wa_13012615864.patch create mode 100644 queue-6.14/iio-adc-ad7768-1-fix-conversion-result-sign.patch create mode 100644 queue-6.14/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch create mode 100644 queue-6.14/irqchip-renesas-rzv2h-add-struct-rzv2h_hw_info-with-.patch create mode 100644 queue-6.14/irqchip-renesas-rzv2h-prevent-tint-spurious-interrup.patch create mode 100644 queue-6.14/irqchip-renesas-rzv2h-simplify-rzv2h_icu_init.patch create mode 100644 queue-6.14/lib-kconfig.ubsan-remove-default-ubsan-from-ubsan_in.patch create mode 100644 queue-6.14/media-i2c-imx214-check-number-of-lanes-from-device-t.patch create mode 100644 queue-6.14/media-i2c-imx214-convert-to-cci-register-access-help.patch create mode 100644 queue-6.14/media-i2c-imx214-fix-link-frequency-validation.patch create mode 100644 queue-6.14/media-i2c-imx214-replace-register-addresses-with-mac.patch create mode 100644 queue-6.14/media-i2c-imx214-simplify-with-dev_err_probe.patch create mode 100644 queue-6.14/media-i2c-imx214-use-subdev-active-state.patch create mode 100644 queue-6.14/media-ov08x40-add-missing-ov08x40_identify_module-ca.patch create mode 100644 queue-6.14/media-ov08x40-move-ov08x40_identify_module-function-.patch create mode 100644 queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch create mode 100644 queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch create mode 100644 queue-6.14/net-niu-niu-requires-msix-entry_data-fields-touch-be.patch create mode 100644 queue-6.14/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch create mode 100644 queue-6.14/of-resolver-simplify-of_resolve_phandles-using-__fre.patch create mode 100644 queue-6.14/pci-msi-add-an-option-to-write-msix-entry_data-befor.patch create mode 100644 queue-6.14/pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch create mode 100644 queue-6.14/pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch create mode 100644 queue-6.14/pm-em-address-rcu-related-sparse-warnings.patch create mode 100644 queue-6.14/pm-em-use-kfree_rcu-to-simplify-the-code.patch create mode 100644 queue-6.14/s390-pci-support-mmap-of-pci-resources-except-for-is.patch create mode 100644 queue-6.14/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch create mode 100644 queue-6.14/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch create mode 100644 queue-6.14/ubsan-overflow-rework-integer-overflow-sanitizer-opt.patch diff --git a/queue-6.14/drm-xe-add-performance-tunings-to-debugfs.patch b/queue-6.14/drm-xe-add-performance-tunings-to-debugfs.patch new file mode 100644 index 00000000000..b0d8a6adcf8 --- /dev/null +++ b/queue-6.14/drm-xe-add-performance-tunings-to-debugfs.patch @@ -0,0 +1,218 @@ +From f5f414f7335a68fdd10b1ee0a150ff904d765c3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Feb 2025 10:13:04 +0000 +Subject: drm/xe: Add performance tunings to debugfs + +From: Tvrtko Ursulin + +[ 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 +Cc: Lucas De Marchi +Cc: Matt Roper +Reviewed-by: Lucas De Marchi +Link: https://patchwork.freedesktop.org/patch/msgid/20250227101304.46660-6-tvrtko.ursulin@igalia.com +Signed-off-by: Lucas De Marchi +Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change") +Signed-off-by: Sasha Levin +--- + 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 + ++#include ++ + #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 + diff --git a/queue-6.14/drm-xe-ensure-fixed_slice_mode-gets-set-after-ccs_mo.patch b/queue-6.14/drm-xe-ensure-fixed_slice_mode-gets-set-after-ccs_mo.patch new file mode 100644 index 00000000000..666cb813f16 --- /dev/null +++ b/queue-6.14/drm-xe-ensure-fixed_slice_mode-gets-set-after-ccs_mo.patch @@ -0,0 +1,63 @@ +From 98dbe574df630abc958636526793cefa2a5a6921 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Matt Roper +Signed-off-by: Matthew Brost +Link: https://lore.kernel.org/r/20250327185604.18230-1-niranjana.vishwanathapura@intel.com +(cherry picked from commit 12468e519f98e4d93370712e3607fab61df9dae9) +Signed-off-by: Lucas De Marchi +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/drm-xe-ptl-apply-wa_14023061436.patch b/queue-6.14/drm-xe-ptl-apply-wa_14023061436.patch new file mode 100644 index 00000000000..21095663d5d --- /dev/null +++ b/queue-6.14/drm-xe-ptl-apply-wa_14023061436.patch @@ -0,0 +1,61 @@ +From 68b1acf9351779aaac1102c2826c747fbb4a1ffb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jan 2025 15:13:23 +0100 +Subject: drm/xe/ptl: Apply Wa_14023061436 + +From: Nirmoy Das + +[ 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 +Cc: Matt Roper +Reviewed-by: Matt Roper +Link: https://patchwork.freedesktop.org/patch/msgid/20250108141323.311601-1-nirmoy.das@intel.com +Signed-off-by: Nirmoy Das +Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/drm-xe-rtp-drop-sentinels-from-arg-to-xe_rtp_process.patch b/queue-6.14/drm-xe-rtp-drop-sentinels-from-arg-to-xe_rtp_process.patch new file mode 100644 index 00000000000..41250513189 --- /dev/null +++ b/queue-6.14/drm-xe-rtp-drop-sentinels-from-arg-to-xe_rtp_process.patch @@ -0,0 +1,282 @@ +From 65c01faede743e6ef965f56e0b7f2aa1201b924d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/oe-kbuild-all/202503021906.P2MwAvyK-lkp@intel.com/ +Cc: Tvrtko Ursulin +Reviewed-by: Tvrtko Ursulin +Link: https://patchwork.freedesktop.org/patch/msgid/20250306-fix-print-warning-v1-1-979c3dc03c0d@intel.com +Signed-off-by: Lucas De Marchi +(cherry picked from commit 8aa8c2d4214e1771c32101d70740002662d31bb7) +Signed-off-by: Lucas De Marchi +Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/drm-xe-xe3lpg-add-wa_13012615864.patch b/queue-6.14/drm-xe-xe3lpg-add-wa_13012615864.patch new file mode 100644 index 00000000000..125c4511fc4 --- /dev/null +++ b/queue-6.14/drm-xe-xe3lpg-add-wa_13012615864.patch @@ -0,0 +1,52 @@ +From 70e253df8a141f3aba232f0e8c0af20988af4ff2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Feb 2025 16:52:00 +0530 +Subject: drm/xe/xe3lpg: Add Wa_13012615864 + +From: Tejas Upadhyay + +[ Upstream commit 2399bcc07c01189737858e0a88ac4ffdd1d4b03d ] + +Wa_13012615864 applies to xe3lpg + +Reviewed-by: Matt Roper +Link: https://patchwork.freedesktop.org/patch/msgid/20250221112200.388612-1-tejas.upadhyay@intel.com +Signed-off-by: Tejas Upadhyay +Stable-dep-of: 262de94a3a7e ("drm/xe: Ensure fixed_slice_mode gets set after ccs_mode change") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/iio-adc-ad7768-1-fix-conversion-result-sign.patch b/queue-6.14/iio-adc-ad7768-1-fix-conversion-result-sign.patch new file mode 100644 index 00000000000..5ccf485796d --- /dev/null +++ b/queue-6.14/iio-adc-ad7768-1-fix-conversion-result-sign.patch @@ -0,0 +1,55 @@ +From f251bba0d699fdad2d59896495b5f3ed47e6236d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 18:00:29 -0300 +Subject: iio: adc: ad7768-1: Fix conversion result sign + +From: Sergiu Cuciurean + +[ 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 +Reviewed-by: Marcelo Schmitt +Signed-off-by: Sergiu Cuciurean +Signed-off-by: Jonathan Santos +Cc: +Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch b/queue-6.14/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch new file mode 100644 index 00000000000..7cdb41c2241 --- /dev/null +++ b/queue-6.14/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch @@ -0,0 +1,47 @@ +From 9261fdf9bd1370d4bbea0f7efd6a1dd146932392 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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á +Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/irqchip-renesas-rzv2h-add-struct-rzv2h_hw_info-with-.patch b/queue-6.14/irqchip-renesas-rzv2h-add-struct-rzv2h_hw_info-with-.patch new file mode 100644 index 00000000000..aadb20d76ba --- /dev/null +++ b/queue-6.14/irqchip-renesas-rzv2h-add-struct-rzv2h_hw_info-with-.patch @@ -0,0 +1,179 @@ +From 5a96a94b338875c0e3b145df8638f6306eafdd24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Thomas Gleixner +Reviewed-by: Fabrizio Castro +Reviewed-by: Tommaso Merciai +Reviewed-by: Geert Uytterhoeven +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 +--- + 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 + diff --git a/queue-6.14/irqchip-renesas-rzv2h-prevent-tint-spurious-interrup.patch b/queue-6.14/irqchip-renesas-rzv2h-prevent-tint-spurious-interrup.patch new file mode 100644 index 00000000000..291eea150fc --- /dev/null +++ b/queue-6.14/irqchip-renesas-rzv2h-prevent-tint-spurious-interrup.patch @@ -0,0 +1,47 @@ +From dd482d36ba426ba338c97dab13b91be003b10cbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Apr 2025 11:33:41 +0100 +Subject: irqchip/renesas-rzv2h: Prevent TINT spurious interrupt + +From: Biju Das + +[ 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 +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/irqchip-renesas-rzv2h-simplify-rzv2h_icu_init.patch b/queue-6.14/irqchip-renesas-rzv2h-simplify-rzv2h_icu_init.patch new file mode 100644 index 00000000000..3dde5a192cb --- /dev/null +++ b/queue-6.14/irqchip-renesas-rzv2h-simplify-rzv2h_icu_init.patch @@ -0,0 +1,110 @@ +From 1b063148ab837edfe205f3e57f3dcad16ee736c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 13:11:20 +0000 +Subject: irqchip/renesas-rzv2h: Simplify rzv2h_icu_init() + +From: Biju Das + +[ 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 +Signed-off-by: Thomas Gleixner +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Philipp Zabel +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 +--- + 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 + diff --git a/queue-6.14/lib-kconfig.ubsan-remove-default-ubsan-from-ubsan_in.patch b/queue-6.14/lib-kconfig.ubsan-remove-default-ubsan-from-ubsan_in.patch new file mode 100644 index 00000000000..2ccfcf3c25c --- /dev/null +++ b/queue-6.14/lib-kconfig.ubsan-remove-default-ubsan-from-ubsan_in.patch @@ -0,0 +1,53 @@ +From 559e377ae6ac36746e3d33d8d6a0f65c11bfe0fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Apr 2025 15:00:59 -0700 +Subject: lib/Kconfig.ubsan: Remove 'default UBSAN' from UBSAN_INTEGER_WRAP + +From: Nathan Chancellor + +[ 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 +Link: https://lore.kernel.org/r/20250414-drop-default-ubsan-integer-wrap-v1-1-392522551d6b@kernel.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-i2c-imx214-check-number-of-lanes-from-device-t.patch b/queue-6.14/media-i2c-imx214-check-number-of-lanes-from-device-t.patch new file mode 100644 index 00000000000..4d0a3731072 --- /dev/null +++ b/queue-6.14/media-i2c-imx214-check-number-of-lanes-from-device-t.patch @@ -0,0 +1,78 @@ +From 9811d7f6f8dbabda22c5061daec604201c1af696 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: André Apitzsch +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-i2c-imx214-convert-to-cci-register-access-help.patch b/queue-6.14/media-i2c-imx214-convert-to-cci-register-access-help.patch new file mode 100644 index 00000000000..e6c200a406b --- /dev/null +++ b/queue-6.14/media-i2c-imx214-convert-to-cci-register-access-help.patch @@ -0,0 +1,858 @@ +From 868252bb20620a9c5788c35232652871a8f4ff5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: André Apitzsch +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include + +-#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 + diff --git a/queue-6.14/media-i2c-imx214-fix-link-frequency-validation.patch b/queue-6.14/media-i2c-imx214-fix-link-frequency-validation.patch new file mode 100644 index 00000000000..7d21a614300 --- /dev/null +++ b/queue-6.14/media-i2c-imx214-fix-link-frequency-validation.patch @@ -0,0 +1,94 @@ +From 2b4357eb8767d5088a1f164d31df55393093e6de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: André Apitzsch +Fixes: 436190596241 ("media: imx214: Add imx214 camera sensor driver") +Cc: stable@vger.kernel.org +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-i2c-imx214-replace-register-addresses-with-mac.patch b/queue-6.14/media-i2c-imx214-replace-register-addresses-with-mac.patch new file mode 100644 index 00000000000..e50a9695e73 --- /dev/null +++ b/queue-6.14/media-i2c-imx214-replace-register-addresses-with-mac.patch @@ -0,0 +1,545 @@ +From 5104e0fb3eaebfe4cb7765ae2217890b37794c31 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: André Apitzsch +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-i2c-imx214-simplify-with-dev_err_probe.patch b/queue-6.14/media-i2c-imx214-simplify-with-dev_err_probe.patch new file mode 100644 index 00000000000..3302e303217 --- /dev/null +++ b/queue-6.14/media-i2c-imx214-simplify-with-dev_err_probe.patch @@ -0,0 +1,137 @@ +From 085651117d620dc25a706427daa319af18426dba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit 5d6dc133e6e4053b4b92a15a2e1b99d54b3f8adb ] + +Error handling in probe() can be a bit simpler with dev_err_probe(). + +Acked-by: Ricardo Ribalda +Signed-off-by: André Apitzsch +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-i2c-imx214-use-subdev-active-state.patch b/queue-6.14/media-i2c-imx214-use-subdev-active-state.patch new file mode 100644 index 00000000000..b3286242b31 --- /dev/null +++ b/queue-6.14/media-i2c-imx214-use-subdev-active-state.patch @@ -0,0 +1,331 @@ +From 71b5bf5de1977e58f9f99b0a4932801748b29c57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: acc294519f17 ("media: i2c: imx214: Fix link frequency validation") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-ov08x40-add-missing-ov08x40_identify_module-ca.patch b/queue-6.14/media-ov08x40-add-missing-ov08x40_identify_module-ca.patch new file mode 100644 index 00000000000..5df68a48d68 --- /dev/null +++ b/queue-6.14/media-ov08x40-add-missing-ov08x40_identify_module-ca.patch @@ -0,0 +1,48 @@ +From ef09e79585143b3478eac27f2cc0d5f47ca27e38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Fixes: b1a42fde6e07 ("media: ov08x40: Avoid sensor probing in D0 state") +Cc: stable@vger.kernel.org +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/media-ov08x40-move-ov08x40_identify_module-function-.patch b/queue-6.14/media-ov08x40-move-ov08x40_identify_module-function-.patch new file mode 100644 index 00000000000..c3066cd9654 --- /dev/null +++ b/queue-6.14/media-ov08x40-move-ov08x40_identify_module-function-.patch @@ -0,0 +1,98 @@ +From c0c8d6ffa08c499ef8ea191c2b8d73cee393967d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 15:41:25 +0100 +Subject: media: ov08x40: Move ov08x40_identify_module() function up + +From: Hans de Goede + +[ 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 +Signed-off-by: Hans de Goede +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: ebf185efadb7 ("media: ov08x40: Add missing ov08x40_identify_module() call on stream-start") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch b/queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch new file mode 100644 index 00000000000..dfbf4c515d4 --- /dev/null +++ b/queue-6.14/mm-vmscan-don-t-try-to-reclaim-hwpoison-folio.patch @@ -0,0 +1,106 @@ +From 97ce8265a3bd40f0600f7888b1c51970f74a228c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Mar 2025 16:39:39 +0800 +Subject: mm/vmscan: don't try to reclaim hwpoison folio + +From: Jinjiang Tu + +[ 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 +Acked-by: Miaohe Lin +Cc: David Hildenbrand +Cc: Kefeng Wang +Cc: Nanyong Sun +Cc: Naoya Horiguchi +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch b/queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch new file mode 100644 index 00000000000..fc92d58813d --- /dev/null +++ b/queue-6.14/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch @@ -0,0 +1,42 @@ +From c8064ddd4b435aed4f9cd1846a09d429dbd352b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Krzysztof Kozlowski +Acked-by: Ulf Hansson +Reviewed-by: Abel Vesa +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-2-1ffa5b6884cb@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/net-niu-niu-requires-msix-entry_data-fields-touch-be.patch b/queue-6.14/net-niu-niu-requires-msix-entry_data-fields-touch-be.patch new file mode 100644 index 00000000000..cf41734f0c4 --- /dev/null +++ b/queue-6.14/net-niu-niu-requires-msix-entry_data-fields-touch-be.patch @@ -0,0 +1,86 @@ +From 355be9663f58813713f209467b486f0ff8a1020b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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] +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: +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: +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 +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/all/20241117234843.19236-3-dullfire@yahoo.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch b/queue-6.14/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch new file mode 100644 index 00000000000..04da786e143 --- /dev/null +++ b/queue-6.14/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch @@ -0,0 +1,45 @@ +From 743b33202040c68a1384b3ca76a28af0bbaebcf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 17:01:55 -0600 +Subject: of: resolver: Fix device node refcount leakage in + of_resolve_phandles() + +From: Zijun Hu + +[ 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 +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) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/of-resolver-simplify-of_resolve_phandles-using-__fre.patch b/queue-6.14/of-resolver-simplify-of_resolve_phandles-using-__fre.patch new file mode 100644 index 00000000000..65be4056bbc --- /dev/null +++ b/queue-6.14/of-resolver-simplify-of_resolve_phandles-using-__fre.patch @@ -0,0 +1,114 @@ +From 06e459d90e3edb57fca8f381ea9afe3133d7af3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 20:59:02 +0800 +Subject: of: resolver: Simplify of_resolve_phandles() using __free() + +From: Rob Herring (Arm) + +[ Upstream commit 5275e8b5293f65cc82a5ee5eab02dd573b911d6e ] + +Use the __free() cleanup to simplify of_resolve_phandles() and remove +all the goto's. + +Signed-off-by: Rob Herring (Arm) +Stable-dep-of: a46a0805635d ("of: resolver: Fix device node refcount leakage in of_resolve_phandles()") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/pci-msi-add-an-option-to-write-msix-entry_data-befor.patch b/queue-6.14/pci-msi-add-an-option-to-write-msix-entry_data-befor.patch new file mode 100644 index 00000000000..07cf2871337 --- /dev/null +++ b/queue-6.14/pci-msi-add-an-option-to-write-msix-entry_data-befor.patch @@ -0,0 +1,59 @@ +From 99df92a026311b5b0c88f8a67b33e271210b05e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Thomas Gleixner +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/all/20241117234843.19236-2-dullfire@yahoo.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch b/queue-6.14/pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch new file mode 100644 index 00000000000..abb0c20ab35 --- /dev/null +++ b/queue-6.14/pci-msi-convert-pci_msi_ignore_mask-to-per-msi-domai.patch @@ -0,0 +1,222 @@ +From 646c2795d1777b4edc580db32cbf62dc955b7db9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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é +Reviewed-by: Thomas Gleixner +Acked-by: Juergen Gross +Acked-by: Bjorn Helgaas +Message-ID: <20250219092059.90850-4-roger.pau@citrix.com> +Signed-off-by: Juergen Gross +Stable-dep-of: cf761e3dacc6 ("PCI/MSI: Add an option to write MSIX ENTRY_DATA before any reads") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + + #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 + diff --git a/queue-6.14/pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch b/queue-6.14/pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch new file mode 100644 index 00000000000..8b9ef5e50da --- /dev/null +++ b/queue-6.14/pci-msi-handle-the-nomask-flag-correctly-for-all-pci.patch @@ -0,0 +1,105 @@ +From 25159432a7b357b21bfc80f9ebeb35ad6d3df29c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: Borislav Petkov +Signed-off-by: Thomas Gleixner +Reviewed-by: Juergen Gross +Tested-by: Marek Szyprowski +Tested-by: Borislav Petkov +Tested-by: Daniel Gomez +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 +--- + 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 + diff --git a/queue-6.14/pm-em-address-rcu-related-sparse-warnings.patch b/queue-6.14/pm-em-address-rcu-related-sparse-warnings.patch new file mode 100644 index 00000000000..34452f1bc33 --- /dev/null +++ b/queue-6.14/pm-em-address-rcu-related-sparse-warnings.patch @@ -0,0 +1,252 @@ +From a70ba0e70a8457348d469243dadc4cb60121cecb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 17:49:20 +0100 +Subject: PM: EM: Address RCU-related sparse warnings + +From: Rafael J. Wysocki + +[ 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 +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Lukasz Luba +Link: https://patch.msgid.link/5885405.DvuYhMxLoT@rjwysocki.net +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/pm-em-use-kfree_rcu-to-simplify-the-code.patch b/queue-6.14/pm-em-use-kfree_rcu-to-simplify-the-code.patch new file mode 100644 index 00000000000..6f880749c57 --- /dev/null +++ b/queue-6.14/pm-em-use-kfree_rcu-to-simplify-the-code.patch @@ -0,0 +1,53 @@ +From 75894af67ad0311f21e3a3e4c8159d3a0479061e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Feb 2025 16:20:21 +0800 +Subject: PM: EM: use kfree_rcu() to simplify the code + +From: Li RongQing + +[ 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 +Reviewed-by: Lukasz Luba +Link: https://patch.msgid.link/20250218082021.2766-1-lirongqing@baidu.com +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: 3ee7be9e10dd ("PM: EM: Address RCU-related sparse warnings") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/s390-pci-support-mmap-of-pci-resources-except-for-is.patch b/queue-6.14/s390-pci-support-mmap-of-pci-resources-except-for-is.patch new file mode 100644 index 00000000000..c490d8b99d2 --- /dev/null +++ b/queue-6.14/s390-pci-support-mmap-of-pci-resources-except-for-is.patch @@ -0,0 +1,155 @@ +From d04b275636d31a1ff5237a9df364ee69693d75f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 13:07:47 +0100 +Subject: s390/pci: Support mmap() of PCI resources except for ISM devices + +From: Niklas Schnelle + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + 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 + #include + ++#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 ++ */ ++#include ++ ++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 + diff --git a/queue-6.14/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch b/queue-6.14/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch new file mode 100644 index 00000000000..dad41fb4a19 --- /dev/null +++ b/queue-6.14/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch @@ -0,0 +1,42 @@ +From 9ab4f7145217a8908bafb56c7ae423f1428f0302 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Abel Vesa +Acked-by: Martin K. Petersen # SCSI +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-3-1ffa5b6884cb@linaro.org +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.14/series b/queue-6.14/series index e69de29bb2d..a946189e574 100644 --- a/queue-6.14/series +++ b/queue-6.14/series @@ -0,0 +1,33 @@ +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 diff --git a/queue-6.14/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch b/queue-6.14/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch new file mode 100644 index 00000000000..61a0185256c --- /dev/null +++ b/queue-6.14/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch @@ -0,0 +1,107 @@ +From 759b595dfe0f3d671a4c3a02fc54240a739e9738 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2025 14:18:50 +0000 +Subject: soc: qcom: ice: introduce devm_of_qcom_ice_get + +From: Tudor Ambarus + +[ 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 +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Abel Vesa +Reviewed-by: Manivannan Sadhasivam +Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-1-1ffa5b6884cb@linaro.org +Signed-off-by: Bjorn Andersson +Stable-dep-of: cbef7442fba5 ("mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-6.14/ubsan-overflow-rework-integer-overflow-sanitizer-opt.patch b/queue-6.14/ubsan-overflow-rework-integer-overflow-sanitizer-opt.patch new file mode 100644 index 00000000000..bfa4ced13af --- /dev/null +++ b/queue-6.14/ubsan-overflow-rework-integer-overflow-sanitizer-opt.patch @@ -0,0 +1,277 @@ +From fb97229c8a9bdfc8d6a35894f08aa20b22b9a932 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 20:19:09 -0800 +Subject: ubsan/overflow: Rework integer overflow sanitizer option to turn on + everything + +From: Kees Cook + +[ 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 +Stable-dep-of: cdc2e1d9d929 ("lib/Kconfig.ubsan: Remove 'default UBSAN' from UBSAN_INTEGER_WRAP") +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.3