summaryrefslogtreecommitdiffstats
path: root/debian/patches
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:28:00 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:28:00 +0000
commit3565071f226432336a54d0193d729fa4508a3394 (patch)
tree4cde13f078f84c0a7785d234fd52edce7c90546a /debian/patches
parentAdding upstream version 6.6.15. (diff)
downloadlinux-3565071f226432336a54d0193d729fa4508a3394.tar.xz
linux-3565071f226432336a54d0193d729fa4508a3394.zip
Adding debian version 6.6.15-2.debian/6.6.15-2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch75
-rw-r--r--debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch36
-rw-r--r--debian/patches-rt/0001-drm-amd-display-Remove-migrate_en-dis-from-dc_fpu_be.patch86
-rw-r--r--debian/patches-rt/0001-sched-Constrain-locks-in-sched_submit_work.patch49
-rw-r--r--debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch54
-rw-r--r--debian/patches-rt/0001-signal-Add-proper-comment-about-the-preempt-disable-.patch47
-rw-r--r--debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch44
-rw-r--r--debian/patches-rt/0002-drm-amd-display-Simplify-the-per-CPU-usage.patch127
-rw-r--r--debian/patches-rt/0002-locking-rtmutex-Avoid-unconditional-slowpath-for-DEB.patch79
-rw-r--r--debian/patches-rt/0002-serial-core-Use-lock-wrappers.patch93
-rw-r--r--debian/patches-rt/0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch48
-rw-r--r--debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch60
-rw-r--r--debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch48
-rw-r--r--debian/patches-rt/0003-drm-amd-display-Add-a-warning-if-the-FPU-is-used-out.patch26
-rw-r--r--debian/patches-rt/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch56
-rw-r--r--debian/patches-rt/0003-sched-Extract-__schedule_loop.patch58
-rw-r--r--debian/patches-rt/0003-serial-21285-Use-port-lock-wrappers.patch75
-rw-r--r--debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch47
-rw-r--r--debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch121
-rw-r--r--debian/patches-rt/0004-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch87
-rw-r--r--debian/patches-rt/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch85
-rw-r--r--debian/patches-rt/0004-sched-Provide-rt_mutex-specific-scheduler-helpers.patch128
-rw-r--r--debian/patches-rt/0004-serial-8250_aspeed_vuart-Use-port-lock-wrappers.patch61
-rw-r--r--debian/patches-rt/0005-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch121
-rw-r--r--debian/patches-rt/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch30
-rw-r--r--debian/patches-rt/0005-locking-rtmutex-Use-rt_mutex-specific-scheduler-help.patch177
-rw-r--r--debian/patches-rt/0005-serial-8250_bcm7271-Use-port-lock-wrappers.patch151
-rw-r--r--debian/patches-rt/0006-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch45
-rw-r--r--debian/patches-rt/0006-locking-rtmutex-Add-a-lockdep-assert-to-catch-potent.patch57
-rw-r--r--debian/patches-rt/0006-serial-8250-Use-port-lock-wrappers.patch465
-rw-r--r--debian/patches-rt/0007-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch29
-rw-r--r--debian/patches-rt/0007-futex-pi-Fix-recursive-rt_mutex-waiter-state.patch198
-rw-r--r--debian/patches-rt/0007-serial-8250_dma-Use-port-lock-wrappers.patch80
-rw-r--r--debian/patches-rt/0008-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch42
-rw-r--r--debian/patches-rt/0008-serial-8250_dw-Use-port-lock-wrappers.patch69
-rw-r--r--debian/patches-rt/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch89
-rw-r--r--debian/patches-rt/0009-serial-8250_exar-Use-port-lock-wrappers.patch52
-rw-r--r--debian/patches-rt/0010-drm-i915-Drop-the-irqs_disabled-check.patch39
-rw-r--r--debian/patches-rt/0010-serial-8250_fsl-Use-port-lock-wrappers.patch63
-rw-r--r--debian/patches-rt/0011-serial-8250_mtk-Use-port-lock-wrappers.patch77
-rw-r--r--debian/patches-rt/0012-serial-8250_omap-Use-port-lock-wrappers.patch236
-rw-r--r--debian/patches-rt/0013-serial-8250_pci1xxxx-Use-port-lock-wrappers.patch66
-rw-r--r--debian/patches-rt/0014-serial-altera_jtaguart-Use-port-lock-wrappers.patch133
-rw-r--r--debian/patches-rt/0015-serial-altera_uart-Use-port-lock-wrappers.patch116
-rw-r--r--debian/patches-rt/0016-serial-amba-pl010-Use-port-lock-wrappers.patch112
-rw-r--r--debian/patches-rt/0017-serial-amba-pl011-Use-port-lock-wrappers.patch327
-rw-r--r--debian/patches-rt/0018-serial-apb-Use-port-lock-wrappers.patch76
-rw-r--r--debian/patches-rt/0019-serial-ar933x-Use-port-lock-wrappers.patch144
-rw-r--r--debian/patches-rt/0020-serial-arc_uart-Use-port-lock-wrappers.patch97
-rw-r--r--debian/patches-rt/0021-serial-atmel-Use-port-lock-wrappers.patch119
-rw-r--r--debian/patches-rt/0022-serial-bcm63xx-uart-Use-port-lock-wrappers.patch128
-rw-r--r--debian/patches-rt/0023-serial-cpm_uart-Use-port-lock-wrappers.patch70
-rw-r--r--debian/patches-rt/0024-serial-digicolor-Use-port-lock-wrappers.patch113
-rw-r--r--debian/patches-rt/0025-serial-dz-Use-port-lock-wrappers.patch161
-rw-r--r--debian/patches-rt/0026-serial-linflexuart-Use-port-lock-wrappers.patch143
-rw-r--r--debian/patches-rt/0027-serial-fsl_lpuart-Use-port-lock-wrappers.patch389
-rw-r--r--debian/patches-rt/0028-serial-icom-Use-port-lock-wrappers.patch151
-rw-r--r--debian/patches-rt/0029-serial-imx-Use-port-lock-wrappers.patch354
-rw-r--r--debian/patches-rt/0030-serial-ip22zilog-Use-port-lock-wrappers.patch185
-rw-r--r--debian/patches-rt/0031-serial-jsm-Use-port-lock-wrappers.patch124
-rw-r--r--debian/patches-rt/0032-serial-liteuart-Use-port-lock-wrappers.patch110
-rw-r--r--debian/patches-rt/0033-serial-lpc32xx_hs-Use-port-lock-wrappers.patch148
-rw-r--r--debian/patches-rt/0034-serial-ma35d1-Use-port-lock-wrappers.patch117
-rw-r--r--debian/patches-rt/0035-serial-mcf-Use-port-lock-wrappers.patch127
-rw-r--r--debian/patches-rt/0036-serial-men_z135_uart-Use-port-lock-wrappers.patch76
-rw-r--r--debian/patches-rt/0037-serial-meson-Use-port-lock-wrappers.patch168
-rw-r--r--debian/patches-rt/0038-serial-milbeaut_usio-Use-port-lock-wrappers.patch101
-rw-r--r--debian/patches-rt/0039-serial-mpc52xx-Use-port-lock-wrappers.patch89
-rw-r--r--debian/patches-rt/0040-serial-mps2-uart-Use-port-lock-wrappers.patch103
-rw-r--r--debian/patches-rt/0041-serial-msm-Use-port-lock-wrappers.patch185
-rw-r--r--debian/patches-rt/0042-serial-mvebu-uart-Use-port-lock-wrappers.patch108
-rw-r--r--debian/patches-rt/0043-serial-omap-Use-port-lock-wrappers.patch180
-rw-r--r--debian/patches-rt/0044-serial-owl-Use-port-lock-wrappers.patch147
-rw-r--r--debian/patches-rt/0045-serial-pch-Use-port-lock-wrappers.patch80
-rw-r--r--debian/patches-rt/0046-serial-pic32-Use-port-lock-wrappers.patch118
-rw-r--r--debian/patches-rt/0047-serial-pmac_zilog-Use-port-lock-wrappers.patch232
-rw-r--r--debian/patches-rt/0048-serial-pxa-Use-port-lock-wrappers.patch150
-rw-r--r--debian/patches-rt/0049-serial-qcom-geni-Use-port-lock-wrappers.patch71
-rw-r--r--debian/patches-rt/0050-serial-rda-Use-port-lock-wrappers.patch177
-rw-r--r--debian/patches-rt/0051-serial-rp2-Use-port-lock-wrappers.patch114
-rw-r--r--debian/patches-rt/0052-serial-sa1100-Use-port-lock-wrappers.patch117
-rw-r--r--debian/patches-rt/0053-serial-samsung_tty-Use-port-lock-wrappers.patch245
-rw-r--r--debian/patches-rt/0054-serial-sb1250-duart-Use-port-lock-wrappers.patch85
-rw-r--r--debian/patches-rt/0056-serial-tegra-Use-port-lock-wrappers.patch176
-rw-r--r--debian/patches-rt/0057-serial-core-Use-port-lock-wrappers.patch365
-rw-r--r--debian/patches-rt/0058-serial-mctrl_gpio-Use-port-lock-wrappers.patch58
-rw-r--r--debian/patches-rt/0059-serial-txx9-Use-port-lock-wrappers.patch134
-rw-r--r--debian/patches-rt/0060-serial-sh-sci-Use-port-lock-wrappers.patch302
-rw-r--r--debian/patches-rt/0061-serial-sifive-Use-port-lock-wrappers.patch102
-rw-r--r--debian/patches-rt/0062-serial-sprd-Use-port-lock-wrappers.patch162
-rw-r--r--debian/patches-rt/0063-serial-st-asc-Use-port-lock-wrappers.patch110
-rw-r--r--debian/patches-rt/0064-serial-stm32-Use-port-lock-wrappers.patch184
-rw-r--r--debian/patches-rt/0065-serial-sunhv-Use-port-lock-wrappers.patch149
-rw-r--r--debian/patches-rt/0066-serial-sunplus-uart-Use-port-lock-wrappers.patch146
-rw-r--r--debian/patches-rt/0067-serial-sunsab-Use-port-lock-wrappers.patch176
-rw-r--r--debian/patches-rt/0068-serial-sunsu-Use-port-lock-wrappers.patch219
-rw-r--r--debian/patches-rt/0069-serial-sunzilog-Use-port-lock-wrappers.patch211
-rw-r--r--debian/patches-rt/0070-serial-timbuart-Use-port-lock-wrappers.patch71
-rw-r--r--debian/patches-rt/0071-serial-uartlite-Use-port-lock-wrappers.patch105
-rw-r--r--debian/patches-rt/0072-serial-ucc_uart-Use-port-lock-wrappers.patch59
-rw-r--r--debian/patches-rt/0073-serial-vt8500-Use-port-lock-wrappers.patch76
-rw-r--r--debian/patches-rt/0074-serial-xilinx_uartps-Use-port-lock-wrappers.patch276
-rw-r--r--debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch261
-rw-r--r--debian/patches-rt/0076-printk-nbcon-Add-acquire-release-logic.patch705
-rw-r--r--debian/patches-rt/0077-printk-Make-static-printk-buffers-available-to-nbcon.patch65
-rw-r--r--debian/patches-rt/0078-printk-nbcon-Add-buffer-management.patch311
-rw-r--r--debian/patches-rt/0079-printk-nbcon-Add-ownership-state-functions.patch179
-rw-r--r--debian/patches-rt/0080-printk-nbcon-Add-sequence-handling.patch311
-rw-r--r--debian/patches-rt/0081-printk-nbcon-Add-emit-function-and-callback-function.patch262
-rw-r--r--debian/patches-rt/0082-printk-nbcon-Allow-drivers-to-mark-unsafe-regions-an.patch136
-rw-r--r--debian/patches-rt/0083-printk-fix-illegal-pbufs-access-for-CONFIG_PRINTK.patch134
-rw-r--r--debian/patches-rt/0084-printk-Reduce-pr_flush-pooling-time.patch102
-rw-r--r--debian/patches-rt/0085-printk-nbcon-Relocate-32bit-seq-macros.patch141
-rw-r--r--debian/patches-rt/0086-printk-Adjust-mapping-for-32bit-seq-macros.patch71
-rw-r--r--debian/patches-rt/0087-printk-Use-prb_first_seq-as-base-for-32bit-seq-macro.patch71
-rw-r--r--debian/patches-rt/0088-printk-ringbuffer-Do-not-skip-non-finalized-records-.patch304
-rw-r--r--debian/patches-rt/0089-printk-ringbuffer-Clarify-special-lpos-values.patch92
-rw-r--r--debian/patches-rt/0090-printk-For-suppress_panic_printk-check-for-other-CPU.patch34
-rw-r--r--debian/patches-rt/0091-printk-Add-this_cpu_in_panic.patch88
-rw-r--r--debian/patches-rt/0092-printk-ringbuffer-Cleanup-reader-terminology.patch67
-rw-r--r--debian/patches-rt/0093-printk-Wait-for-all-reserved-records-with-pr_flush.patch170
-rw-r--r--debian/patches-rt/0094-printk-ringbuffer-Skip-non-finalized-records-in-pani.patch68
-rw-r--r--debian/patches-rt/0095-printk-ringbuffer-Consider-committed-as-finalized-in.patch62
-rw-r--r--debian/patches-rt/0096-printk-Disable-passing-console-lock-owner-completely.patch107
-rw-r--r--debian/patches-rt/0097-printk-Avoid-non-panic-CPUs-writing-to-ringbuffer.patch78
-rw-r--r--debian/patches-rt/0098-panic-Flush-kernel-log-buffer-at-the-end.patch38
-rw-r--r--debian/patches-rt/0099-printk-Consider-nbcon-boot-consoles-on-seq-init.patch51
-rw-r--r--debian/patches-rt/0100-printk-Add-sparse-notation-to-console_srcu-locking.patch36
-rw-r--r--debian/patches-rt/0101-printk-nbcon-Ensure-ownership-release-on-failed-emit.patch58
-rw-r--r--debian/patches-rt/0102-printk-Check-printk_deferred_enter-_exit-usage.patch58
-rw-r--r--debian/patches-rt/0103-printk-nbcon-Implement-processing-in-port-lock-wrapp.patch244
-rw-r--r--debian/patches-rt/0104-printk-nbcon-Add-driver_enter-driver_exit-console-ca.patch42
-rw-r--r--debian/patches-rt/0105-printk-Make-console_is_usable-available-to-nbcon.patch103
-rw-r--r--debian/patches-rt/0106-printk-Let-console_is_usable-handle-nbcon.patch43
-rw-r--r--debian/patches-rt/0107-printk-Add-flags-argument-for-console_is_usable.patch67
-rw-r--r--debian/patches-rt/0108-printk-nbcon-Provide-function-to-flush-using-write_a.patch186
-rw-r--r--debian/patches-rt/0109-printk-Track-registered-boot-consoles.patch78
-rw-r--r--debian/patches-rt/0110-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch173
-rw-r--r--debian/patches-rt/0111-printk-nbcon-Assign-priority-based-on-CPU-state.patch113
-rw-r--r--debian/patches-rt/0112-printk-nbcon-Add-unsafe-flushing-on-panic.patch96
-rw-r--r--debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch211
-rw-r--r--debian/patches-rt/0114-printk-Track-nbcon-consoles.patch67
-rw-r--r--debian/patches-rt/0115-printk-Coordinate-direct-printing-in-panic.patch134
-rw-r--r--debian/patches-rt/0116-printk-nbcon-Implement-emergency-sections.patch232
-rw-r--r--debian/patches-rt/0117-panic-Mark-emergency-section-in-warn.patch38
-rw-r--r--debian/patches-rt/0118-panic-Mark-emergency-section-in-oops.patch39
-rw-r--r--debian/patches-rt/0119-rcu-Mark-emergency-section-in-rcu-stalls.patch45
-rw-r--r--debian/patches-rt/0120-lockdep-Mark-emergency-section-in-lockdep-splats.patch45
-rw-r--r--debian/patches-rt/0121-printk-nbcon-Introduce-printing-kthreads.patch441
-rw-r--r--debian/patches-rt/0122-printk-Atomic-print-in-printk-context-on-shutdown.patch41
-rw-r--r--debian/patches-rt/0123-printk-nbcon-Add-context-to-console_is_usable.patch111
-rw-r--r--debian/patches-rt/0124-printk-nbcon-Add-printer-thread-wakeups.patch164
-rw-r--r--debian/patches-rt/0125-printk-nbcon-Stop-threads-on-shutdown-reboot.patch60
-rw-r--r--debian/patches-rt/0126-printk-nbcon-Start-printing-threads.patch135
-rw-r--r--debian/patches-rt/0127-proc-Add-nbcon-support-for-proc-consoles.patch53
-rw-r--r--debian/patches-rt/0128-tty-sysfs-Add-nbcon-support-for-active.patch33
-rw-r--r--debian/patches-rt/0129-printk-nbcon-Provide-function-to-reacquire-ownership.patch92
-rw-r--r--debian/patches-rt/0130-serial-core-Provide-low-level-functions-to-port-lock.patch43
-rw-r--r--debian/patches-rt/0131-serial-8250-Switch-to-nbcon-console.patch335
-rw-r--r--debian/patches-rt/0132-printk-Add-kthread-for-all-legacy-consoles.patch422
-rw-r--r--debian/patches-rt/0133-serial-8250-revert-drop-lockdep-annotation-from-seri.patch29
-rw-r--r--debian/patches-rt/0134-printk-Avoid-false-positive-lockdep-report-for-legac.patch64
-rw-r--r--debian/patches-rt/ARM64__Allow_to_enable_RT.patch27
-rw-r--r--debian/patches-rt/ARM__Allow_to_enable_RT.patch35
-rw-r--r--debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch91
-rw-r--r--debian/patches-rt/Add_localversion_for_-RT_release.patch19
-rw-r--r--debian/patches-rt/POWERPC__Allow_to_enable_RT.patch35
-rw-r--r--debian/patches-rt/PREEMPT_AUTO.patch779
-rw-r--r--debian/patches-rt/RISC-V-Probe-misaligned-access-speed-in-parallel.patch197
-rw-r--r--debian/patches-rt/Revert-drm-i915-Depend-on-PREEMPT_RT.patch23
-rw-r--r--debian/patches-rt/drm-i915-Do-not-disable-preemption-for-resets.patch99
-rw-r--r--debian/patches-rt/drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch29
-rw-r--r--debian/patches-rt/net-Avoid-the-IPI-to-free-the.patch119
-rw-r--r--debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch27
-rw-r--r--debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch38
-rw-r--r--debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch43
-rw-r--r--debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch115
-rw-r--r--debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch37
-rw-r--r--debian/patches-rt/preempt-Put-preempt_enable-within-an-instrumentation.patch47
-rw-r--r--debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch71
-rw-r--r--debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch44
-rw-r--r--debian/patches-rt/riscv-allow-to-enable-RT.patch23
-rw-r--r--debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch58
-rw-r--r--debian/patches-rt/series255
-rw-r--r--debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch222
-rw-r--r--debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch44
-rw-r--r--debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch53
-rw-r--r--debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch106
-rw-r--r--debian/patches-rt/tty_serial_omap__Make_the_locking_RT_aware.patch47
-rw-r--r--debian/patches-rt/tty_serial_pl011__Make_the_locking_work_on_RT.patch46
-rw-r--r--debian/patches-rt/x86__Allow_to_enable_RT.patch27
-rw-r--r--debian/patches-rt/x86__Enable_RT_also_on_32bit.patch33
-rw-r--r--debian/patches-rt/zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch94
-rw-r--r--debian/patches/bugfix/all/cpupower-fix-checks-for-cpu-existence.patch49
-rw-r--r--debian/patches/bugfix/all/disable-some-marvell-phys.patch91
-rw-r--r--debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch2396
-rw-r--r--debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch83
-rw-r--r--debian/patches/bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch61
-rw-r--r--debian/patches/bugfix/all/kbuild-fix-recordmcount-dependency.patch23
-rw-r--r--debian/patches/bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch18
-rw-r--r--debian/patches/bugfix/all/module-disable-matching-missing-version-crc.patch23
-rw-r--r--debian/patches/bugfix/all/perf-tools-support-extra-cxxflags.patch30
-rw-r--r--debian/patches/bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch88
-rw-r--r--debian/patches/bugfix/all/tools-build-remove-bpf-run-time-check-at-build-time.patch27
-rw-r--r--debian/patches/bugfix/all/tools-perf-fix-missing-ldflags-for-some-programs.patch17
-rw-r--r--debian/patches/bugfix/all/tools-perf-man-date.patch44
-rw-r--r--debian/patches/bugfix/all/tools-perf-remove-shebangs.patch39
-rw-r--r--debian/patches/bugfix/all/tools_lib_symbol_use_d_fortify_source_2_for_non_debug_builds.patch31
-rw-r--r--debian/patches/bugfix/all/usbip-document-tcp-wrappers.patch29
-rw-r--r--debian/patches/bugfix/alpha/alpha-fix-missing-symbol-versions-for-str-n-cat-cpy.patch75
-rw-r--r--debian/patches/bugfix/arm/arm-dts-kirkwood-fix-sata-pinmux-ing-for-ts419.patch35
-rw-r--r--debian/patches/bugfix/arm/arm-mm-export-__sync_icache_dcache-for-xen-privcmd.patch31
-rw-r--r--debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch92
-rw-r--r--debian/patches/bugfix/powerpc/fbdev-offb-Update-expected-device-name.patch46
-rw-r--r--debian/patches/bugfix/powerpc/powerpc-boot-fix-missing-crc32poly.h-when-building-with-kernel_xz.patch39
-rw-r--r--debian/patches/bugfix/sh/sh-boot-do-not-use-hyphen-in-exported-variable-name.patch95
-rw-r--r--debian/patches/bugfix/x86/perf-tools-fix-unwind-build-on-i386.patch35
-rw-r--r--debian/patches/bugfix/x86/revert-perf-build-fix-libunwind-feature-detection-on.patch22
-rw-r--r--debian/patches/bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch34
-rw-r--r--debian/patches/debian/Revert-docs-kernel_feat.py-fix-potential-command-inj.patch295
-rw-r--r--debian/patches/debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch101
-rw-r--r--debian/patches/debian/af_802154-Disable-auto-loading-as-mitigation-against.patch29
-rw-r--r--debian/patches/debian/android-enable-building-ashmem-and-binder-as-modules.patch62
-rw-r--r--debian/patches/debian/arch-sh4-fix-uimage-build.patch26
-rw-r--r--debian/patches/debian/btrfs-warn-about-raid5-6-being-experimental-at-mount.patch37
-rw-r--r--debian/patches/debian/cdc_ncm-cdc_mbim-use-ncm-by-default.patch27
-rw-r--r--debian/patches/debian/dccp-disable-auto-loading-as-mitigation-against-local-exploits.patch41
-rw-r--r--debian/patches/debian/dfsg/arch-powerpc-platforms-8xx-ucode-disable.patch29
-rw-r--r--debian/patches/debian/dfsg/documentation-fix-broken-link-to-cipso-draft.patch18
-rw-r--r--debian/patches/debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch15
-rw-r--r--debian/patches/debian/dfsg/drivers-net-appletalk-cops.patch55
-rw-r--r--debian/patches/debian/dfsg/video-remove-nvidiafb-and-rivafb.patch130
-rw-r--r--debian/patches/debian/documentation-drop-sphinx-version-check.patch56
-rw-r--r--debian/patches/debian/export-symbols-needed-by-android-drivers.patch116
-rw-r--r--debian/patches/debian/fanotify-taint-on-use-of-fanotify_access_permissions.patch29
-rw-r--r--debian/patches/debian/firmware_class-refer-to-debian-wiki-firmware-page.patch48
-rw-r--r--debian/patches/debian/fixdep-allow-overriding-hostcc-and-hostld.patch23
-rw-r--r--debian/patches/debian/fjes-disable-autoload.patch26
-rw-r--r--debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch22
-rw-r--r--debian/patches/debian/gitignore.patch53
-rw-r--r--debian/patches/debian/hamradio-disable-auto-loading-as-mitigation-against-local-exploits.patch48
-rw-r--r--debian/patches/debian/i386-686-pae-pci-set-pci-nobios-by-default.patch27
-rw-r--r--debian/patches/debian/ia64-hardcode-arch-script-output.patch71
-rw-r--r--debian/patches/debian/iwlwifi-do-not-request-unreleased-firmware.patch26
-rw-r--r--debian/patches/debian/kbuild-abort-build-if-subdirs-used.patch37
-rw-r--r--debian/patches/debian/kbuild-look-for-module.lds-under-arch-directory-too.patch52
-rw-r--r--debian/patches/debian/kernelvariables.patch92
-rw-r--r--debian/patches/debian/makefile-make-compiler-version-comparison-optional.patch31
-rw-r--r--debian/patches/debian/mips-boston-disable-its.patch22
-rw-r--r--debian/patches/debian/mips-disable-werror.patch23
-rw-r--r--debian/patches/debian/mips-ieee754-relaxed.patch32
-rw-r--r--debian/patches/debian/module-avoid-abi-changes-when-debug-info-is-disabled.patch23
-rw-r--r--debian/patches/debian/ntfs-mark-it-as-broken.patch23
-rw-r--r--debian/patches/debian/perf-traceevent-support-asciidoctor-for-documentatio.patch40
-rw-r--r--debian/patches/debian/rds-Disable-auto-loading-as-mitigation-against-local.patch34
-rw-r--r--debian/patches/debian/sched-autogroup-disabled.patch19
-rw-r--r--debian/patches/debian/snd-pcsp-disable-autoload.patch30
-rw-r--r--debian/patches/debian/tools-perf-install-python-bindings.patch26
-rw-r--r--debian/patches/debian/tools-perf-perf-read-vdso-in-libexec.patch32
-rw-r--r--debian/patches/debian/uname-version-timestamp.patch26
-rw-r--r--debian/patches/debian/version.patch174
-rw-r--r--debian/patches/debian/wireless-add-debian-wireless-regdb-certificates.patch1452
-rw-r--r--debian/patches/debian/yama-disable-by-default.patch32
-rw-r--r--debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch130
-rw-r--r--debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch33
-rw-r--r--debian/patches/features/all/db-mok-keyring/trust-machine-keyring-by-default.patch29
-rw-r--r--debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch149
-rw-r--r--debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch153
-rw-r--r--debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch153
-rw-r--r--debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch121
-rw-r--r--debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch75
-rw-r--r--debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch80
-rw-r--r--debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch76
-rw-r--r--debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch90
-rw-r--r--debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch180
-rw-r--r--debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch28
-rw-r--r--debian/patches/series119
277 files changed, 32248 insertions, 0 deletions
diff --git a/debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch b/debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch
new file mode 100644
index 0000000000..03eb551db3
--- /dev/null
+++ b/debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch
@@ -0,0 +1,75 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 19 May 2023 16:57:29 +0200
+Subject: [PATCH 1/4] ARM: vfp: Provide vfp_lock() for VFP locking.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+kernel_neon_begin() uses local_bh_disable() to ensure exclusive access
+to the VFP unit. This is broken on PREEMPT_RT because a BH disabled
+section remains preemptible on PREEMPT_RT.
+
+Introduce vfp_lock() which uses local_bh_disable() and preempt_disable()
+on PREEMPT_RT. Since softirqs are processed always in thread context,
+disabling preemption is enough to ensure that the current context won't
+get interrupted by something that is using the VFP. Use it in
+kernel_neon_begin().
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/arm/vfp/vfpmodule.c | 32 ++++++++++++++++++++++++++++++--
+ 1 file changed, 30 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -56,6 +56,34 @@ extern unsigned int VFP_arch_feroceon __
+ union vfp_state *vfp_current_hw_state[NR_CPUS];
+
+ /*
++ * Claim ownership of the VFP unit.
++ *
++ * The caller may change VFP registers until vfp_unlock() is called.
++ *
++ * local_bh_disable() is used to disable preemption and to disable VFP
++ * processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is
++ * not sufficient because it only serializes soft interrupt related sections
++ * via a local lock, but stays preemptible. Disabling preemption is the right
++ * choice here as bottom half processing is always in thread context on RT
++ * kernels so it implicitly prevents bottom half processing as well.
++ */
++static void vfp_lock(void)
++{
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_bh_disable();
++ else
++ preempt_disable();
++}
++
++static void vfp_unlock(void)
++{
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_bh_enable();
++ else
++ preempt_enable();
++}
++
++/*
+ * Is 'thread's most up to date state stored in this CPUs hardware?
+ * Must be called from non-preemptible context.
+ */
+@@ -819,7 +847,7 @@ void kernel_neon_begin(void)
+ unsigned int cpu;
+ u32 fpexc;
+
+- local_bh_disable();
++ vfp_lock();
+
+ /*
+ * Kernel mode NEON is only allowed outside of hardirq context with
+@@ -850,7 +878,7 @@ void kernel_neon_end(void)
+ {
+ /* Disable the NEON/VFP unit. */
+ fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
+- local_bh_enable();
++ vfp_unlock();
+ }
+ EXPORT_SYMBOL(kernel_neon_end);
+
diff --git a/debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch b/debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch
new file mode 100644
index 0000000000..5c8c179aef
--- /dev/null
+++ b/debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch
@@ -0,0 +1,36 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 8 Jul 2015 17:14:48 +0200
+Subject: [PATCH 1/2] arm: Disable jump-label on PREEMPT_RT.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+jump-labels are used to efficiently switch between two possible code
+paths. To achieve this, stop_machine() is used to keep the CPU in a
+known state while the opcode is modified. The usage of stop_machine()
+here leads to large latency spikes which can be observed on PREEMPT_RT.
+
+Jump labels may change the target during runtime and are not restricted
+to debug or "configuration/ setup" part of a PREEMPT_RT system where
+high latencies could be defined as acceptable.
+
+Disable jump-label support on a PREEMPT_RT system.
+
+[bigeasy: Patch description.]
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lkml.kernel.org/r/20220613182447.112191-2-bigeasy@linutronix.de
+---
+ arch/arm/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -73,7 +73,7 @@ config ARM
+ select HAS_IOPORT
+ select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
+ select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
+- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
++ select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && !PREEMPT_RT
+ select HAVE_ARCH_KFENCE if MMU && !XIP_KERNEL
+ select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
+ select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
diff --git a/debian/patches-rt/0001-drm-amd-display-Remove-migrate_en-dis-from-dc_fpu_be.patch b/debian/patches-rt/0001-drm-amd-display-Remove-migrate_en-dis-from-dc_fpu_be.patch
new file mode 100644
index 0000000000..b78f988da5
--- /dev/null
+++ b/debian/patches-rt/0001-drm-amd-display-Remove-migrate_en-dis-from-dc_fpu_be.patch
@@ -0,0 +1,86 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Sep 2023 16:15:12 +0200
+Subject: [PATCH 1/5] drm/amd/display: Remove migrate_en/dis from
+ dc_fpu_begin().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+This is a revert of the commit mentioned below while it is not wrong, as
+in the kernel will explode, having migrate_disable() here it is
+complete waste of resources.
+
+Additionally commit message is plain wrong the review tag does not make
+it any better. The migrate_disable() interface has a fat comment
+describing it and it includes the word "undesired" in the headline which
+should tickle people to read it before using it.
+Initially I assumed it is worded too harsh but now I beg to differ.
+
+The reviewer of the original commit, even not understanding what
+migrate_disable() does should ask the following:
+
+- migrate_disable() is added only to the CONFIG_X86 block and it claims
+ to protect fpu_recursion_depth. Why are the other the architectures
+ excluded?
+
+- migrate_disable() is added after fpu_recursion_depth was modified.
+ Shouldn't it be added before the modification or referencing takes
+ place?
+
+Moving on.
+Disabling preemption DOES prevent CPU migration. A task, that can not be
+pushed away from the CPU by the scheduler (due to disabled preemption)
+can not be pushed or migrated to another CPU.
+
+Disabling migration DOES NOT ensure consistency of per-CPU variables. It
+only ensures that the task acts always on the same per-CPU variable. The
+task remains preemptible meaning multiple tasks can access the same
+per-CPU variable. This in turn leads to inconsistency for the statement
+
+ *pcpu -= 1;
+
+with two tasks on one CPU and a preemption point during the RMW
+operation:
+
+ Task A Task B
+ read pcpu to reg # 0
+ inc reg # 0 -> 1
+ read pcpu to reg # 0
+ inc reg # 0 -> 1
+ write reg to pcpu # 1
+ write reg to pcpu # 1
+
+At the end pcpu reads 1 but should read 2 instead. Boom.
+
+get_cpu_ptr() already contains a preempt_disable() statement. That means
+that the per-CPU variable can only be referenced by a single task which
+is currently running. The only inconsistency that can occur if the
+variable is additionally accessed from an interrupt.
+
+Remove migrate_disable/enable() from dc_fpu_begin/end().
+
+Cc: Tianci Yin <tianci.yin@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Fixes: 0c316556d1249 ("drm/amd/display: Disable migration to ensure consistency of per-CPU variable")
+Link: https://lore.kernel.org/r/20230921141516.520471-2-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+@@ -91,7 +91,6 @@ void dc_fpu_begin(const char *function_n
+
+ if (*pcpu == 1) {
+ #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
+- migrate_disable();
+ kernel_fpu_begin();
+ #elif defined(CONFIG_PPC64)
+ if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+@@ -132,7 +131,6 @@ void dc_fpu_end(const char *function_nam
+ if (*pcpu <= 0) {
+ #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
+ kernel_fpu_end();
+- migrate_enable();
+ #elif defined(CONFIG_PPC64)
+ if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+ disable_kernel_vsx();
diff --git a/debian/patches-rt/0001-sched-Constrain-locks-in-sched_submit_work.patch b/debian/patches-rt/0001-sched-Constrain-locks-in-sched_submit_work.patch
new file mode 100644
index 0000000000..73828f0efd
--- /dev/null
+++ b/debian/patches-rt/0001-sched-Constrain-locks-in-sched_submit_work.patch
@@ -0,0 +1,49 @@
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Fri, 8 Sep 2023 18:22:48 +0200
+Subject: [PATCH 1/7] sched: Constrain locks in sched_submit_work()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Even though sched_submit_work() is ran from preemptible context,
+it is discouraged to have it use blocking locks due to the recursion
+potential.
+
+Enforce this.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20230908162254.999499-2-bigeasy@linutronix.de
+---
+ kernel/sched/core.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -6721,11 +6721,18 @@ void __noreturn do_task_dead(void)
+
+ static inline void sched_submit_work(struct task_struct *tsk)
+ {
++ static DEFINE_WAIT_OVERRIDE_MAP(sched_map, LD_WAIT_CONFIG);
+ unsigned int task_flags;
+
+ if (task_is_running(tsk))
+ return;
+
++ /*
++ * Establish LD_WAIT_CONFIG context to ensure none of the code called
++ * will use a blocking primitive -- which would lead to recursion.
++ */
++ lock_map_acquire_try(&sched_map);
++
+ task_flags = tsk->flags;
+ /*
+ * If a worker goes to sleep, notify and ask workqueue whether it
+@@ -6750,6 +6757,8 @@ static inline void sched_submit_work(str
+ * make sure to submit it to avoid deadlocks.
+ */
+ blk_flush_plug(tsk->plug, true);
++
++ lock_map_release(&sched_map);
+ }
+
+ static void sched_update_worker(struct task_struct *tsk)
diff --git a/debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch b/debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch
new file mode 100644
index 0000000000..35892558e6
--- /dev/null
+++ b/debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch
@@ -0,0 +1,54 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 4 Aug 2023 13:30:37 +0200
+Subject: [PATCH 1/3] sched/core: Provide a method to check if a task is
+ PI-boosted.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Provide a method to check if a task inherited the priority from another
+task. This happens if a task owns a lock which is requested by a task
+with higher priority. This can be used as a hint to add a preemption
+point to the critical section.
+
+Provide a function which reports true if the task is PI-boosted.
+
+Link: https://lore.kernel.org/r/20230804113039.419794-2-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/sched.h | 1 +
+ kernel/sched/core.c | 15 +++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1905,6 +1905,7 @@ static inline int dl_task_check_affinity
+ }
+ #endif
+
++extern bool task_is_pi_boosted(const struct task_struct *p);
+ extern int yield_to(struct task_struct *p, bool preempt);
+ extern void set_user_nice(struct task_struct *p, long nice);
+ extern int task_prio(const struct task_struct *p);
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -8923,6 +8923,21 @@ static inline void preempt_dynamic_init(
+
+ #endif /* #ifdef CONFIG_PREEMPT_DYNAMIC */
+
++/*
++ * task_is_pi_boosted - Check if task has been PI boosted.
++ * @p: Task to check.
++ *
++ * Return true if task is subject to priority inheritance.
++ */
++bool task_is_pi_boosted(const struct task_struct *p)
++{
++ int prio = p->prio;
++
++ if (!rt_prio(prio))
++ return false;
++ return prio != p->normal_prio;
++}
++
+ /**
+ * yield - yield the current processor to other threads.
+ *
diff --git a/debian/patches-rt/0001-signal-Add-proper-comment-about-the-preempt-disable-.patch b/debian/patches-rt/0001-signal-Add-proper-comment-about-the-preempt-disable-.patch
new file mode 100644
index 0000000000..e00261d790
--- /dev/null
+++ b/debian/patches-rt/0001-signal-Add-proper-comment-about-the-preempt-disable-.patch
@@ -0,0 +1,47 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 3 Aug 2023 12:09:31 +0200
+Subject: [PATCH 1/2] signal: Add proper comment about the preempt-disable in
+ ptrace_stop().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Commit 53da1d9456fe7 ("fix ptrace slowness") added a preempt-disable section
+between read_unlock() and the following schedule() invocation without
+explaining why it is needed.
+
+Replace the comment with an explanation why this is needed. Clarify that
+it is needed for correctness but for performance reasons.
+
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20230803100932.325870-2-bigeasy@linutronix.de
+---
+ kernel/signal.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -2329,10 +2329,21 @@ static int ptrace_stop(int exit_code, in
+ do_notify_parent_cldstop(current, false, why);
+
+ /*
+- * Don't want to allow preemption here, because
+- * sys_ptrace() needs this task to be inactive.
++ * The previous do_notify_parent_cldstop() invocation woke ptracer.
++ * One a PREEMPTION kernel this can result in preemption requirement
++ * which will be fulfilled after read_unlock() and the ptracer will be
++ * put on the CPU.
++ * The ptracer is in wait_task_inactive(, __TASK_TRACED) waiting for
++ * this task wait in schedule(). If this task gets preempted then it
++ * remains enqueued on the runqueue. The ptracer will observe this and
++ * then sleep for a delay of one HZ tick. In the meantime this task
++ * gets scheduled, enters schedule() and will wait for the ptracer.
+ *
+- * XXX: implement read_unlock_no_resched().
++ * This preemption point is not bad from correctness point of view but
++ * extends the runtime by one HZ tick time due to the ptracer's sleep.
++ * The preempt-disable section ensures that there will be no preemption
++ * between unlock and schedule() and so improving the performance since
++ * the ptracer has no reason to sleep.
+ */
+ preempt_disable();
+ read_unlock(&tasklist_lock);
diff --git a/debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch b/debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch
new file mode 100644
index 0000000000..a0d93547cd
--- /dev/null
+++ b/debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch
@@ -0,0 +1,44 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 19 May 2023 16:57:30 +0200
+Subject: [PATCH 2/4] ARM: vfp: Use vfp_lock() in vfp_sync_hwstate().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+vfp_sync_hwstate() uses preempt_disable() followed by local_bh_disable()
+to ensure that it won't get interrupted while checking the VFP state.
+This harms PREEMPT_RT because softirq handling can get preempted and
+local_bh_disable() synchronizes the related section with a sleeping lock
+which does not work with disabled preemption.
+
+Use the vfp_lock() to synchronize the access.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/arm/vfp/vfpmodule.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -540,11 +540,9 @@ static inline void vfp_pm_init(void) { }
+ */
+ void vfp_sync_hwstate(struct thread_info *thread)
+ {
+- unsigned int cpu = get_cpu();
++ vfp_lock();
+
+- local_bh_disable();
+-
+- if (vfp_state_in_hw(cpu, thread)) {
++ if (vfp_state_in_hw(raw_smp_processor_id(), thread)) {
+ u32 fpexc = fmrx(FPEXC);
+
+ /*
+@@ -555,8 +553,7 @@ void vfp_sync_hwstate(struct thread_info
+ fmxr(FPEXC, fpexc);
+ }
+
+- local_bh_enable();
+- put_cpu();
++ vfp_unlock();
+ }
+
+ /* Ensure that the thread reloads the hardware VFP state on the next use. */
diff --git a/debian/patches-rt/0002-drm-amd-display-Simplify-the-per-CPU-usage.patch b/debian/patches-rt/0002-drm-amd-display-Simplify-the-per-CPU-usage.patch
new file mode 100644
index 0000000000..fd18d53e2d
--- /dev/null
+++ b/debian/patches-rt/0002-drm-amd-display-Simplify-the-per-CPU-usage.patch
@@ -0,0 +1,127 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Sep 2023 16:15:13 +0200
+Subject: [PATCH 2/5] drm/amd/display: Simplify the per-CPU usage.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The fpu_recursion_depth counter is used to ensure that dc_fpu_begin()
+can be invoked multiple times while the FPU-disable function itself is
+only invoked once. Also the counter part (dc_fpu_end()) is ballanced
+properly.
+
+Instead of using the get_cpu_ptr() dance around the inc it is simpler to
+increment the per-CPU variable directly. Also the per-CPU variable has
+to be incremented and decremented on the same CPU. This is ensured by
+the inner-part which disables preemption. This is kind of not obvious,
+works and the preempt-counter is touched a few times for no reason.
+
+Disable preemption before incrementing fpu_recursion_depth for the first
+time. Keep preemption disabled until dc_fpu_end() where the counter is
+decremented making it obvious that the preemption has to stay disabled
+while the counter is non-zero.
+Use simple inc/dec functions.
+Remove the nested preempt_disable/enable functions which are now not
+needed.
+
+Link: https://lore.kernel.org/r/20230921141516.520471-3-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 50 ++++++++++---------------
+ 1 file changed, 20 insertions(+), 30 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+@@ -60,11 +60,9 @@ static DEFINE_PER_CPU(int, fpu_recursion
+ */
+ inline void dc_assert_fp_enabled(void)
+ {
+- int *pcpu, depth = 0;
++ int depth;
+
+- pcpu = get_cpu_ptr(&fpu_recursion_depth);
+- depth = *pcpu;
+- put_cpu_ptr(&fpu_recursion_depth);
++ depth = __this_cpu_read(fpu_recursion_depth);
+
+ ASSERT(depth >= 1);
+ }
+@@ -84,32 +82,27 @@ inline void dc_assert_fp_enabled(void)
+ */
+ void dc_fpu_begin(const char *function_name, const int line)
+ {
+- int *pcpu;
++ int depth;
+
+- pcpu = get_cpu_ptr(&fpu_recursion_depth);
+- *pcpu += 1;
++ preempt_disable();
++ depth = __this_cpu_inc_return(fpu_recursion_depth);
+
+- if (*pcpu == 1) {
++ if (depth == 1) {
+ #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
+ kernel_fpu_begin();
+ #elif defined(CONFIG_PPC64)
+- if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
+- preempt_disable();
++ if (cpu_has_feature(CPU_FTR_VSX_COMP))
+ enable_kernel_vsx();
+- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
+- preempt_disable();
++ else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
+ enable_kernel_altivec();
+- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
+- preempt_disable();
++ else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
+ enable_kernel_fp();
+- }
+ #elif defined(CONFIG_ARM64)
+ kernel_neon_begin();
+ #endif
+ }
+
+- TRACE_DCN_FPU(true, function_name, line, *pcpu);
+- put_cpu_ptr(&fpu_recursion_depth);
++ TRACE_DCN_FPU(true, function_name, line, depth);
+ }
+
+ /**
+@@ -124,29 +117,26 @@ void dc_fpu_begin(const char *function_n
+ */
+ void dc_fpu_end(const char *function_name, const int line)
+ {
+- int *pcpu;
++ int depth;
+
+- pcpu = get_cpu_ptr(&fpu_recursion_depth);
+- *pcpu -= 1;
+- if (*pcpu <= 0) {
++ depth = __this_cpu_dec_return(fpu_recursion_depth);
++ if (depth == 0) {
+ #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH)
+ kernel_fpu_end();
+ #elif defined(CONFIG_PPC64)
+- if (cpu_has_feature(CPU_FTR_VSX_COMP)) {
++ if (cpu_has_feature(CPU_FTR_VSX_COMP))
+ disable_kernel_vsx();
+- preempt_enable();
+- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) {
++ else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP))
+ disable_kernel_altivec();
+- preempt_enable();
+- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) {
++ else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE))
+ disable_kernel_fp();
+- preempt_enable();
+- }
+ #elif defined(CONFIG_ARM64)
+ kernel_neon_end();
+ #endif
++ } else {
++ WARN_ON_ONCE(depth < 0);
+ }
+
+- TRACE_DCN_FPU(false, function_name, line, *pcpu);
+- put_cpu_ptr(&fpu_recursion_depth);
++ TRACE_DCN_FPU(false, function_name, line, depth);
++ preempt_enable();
+ }
diff --git a/debian/patches-rt/0002-locking-rtmutex-Avoid-unconditional-slowpath-for-DEB.patch b/debian/patches-rt/0002-locking-rtmutex-Avoid-unconditional-slowpath-for-DEB.patch
new file mode 100644
index 0000000000..561d5891b1
--- /dev/null
+++ b/debian/patches-rt/0002-locking-rtmutex-Avoid-unconditional-slowpath-for-DEB.patch
@@ -0,0 +1,79 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 8 Sep 2023 18:22:49 +0200
+Subject: [PATCH 2/7] locking/rtmutex: Avoid unconditional slowpath for
+ DEBUG_RT_MUTEXES
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+With DEBUG_RT_MUTEXES enabled the fast-path rt_mutex_cmpxchg_acquire()
+always fails and all lock operations take the slow path.
+
+Provide a new helper inline rt_mutex_try_acquire() which maps to
+rt_mutex_cmpxchg_acquire() in the non-debug case. For the debug case
+it invokes rt_mutex_slowtrylock() which can acquire a non-contended
+rtmutex under full debug coverage.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20230908162254.999499-3-bigeasy@linutronix.de
+---
+ kernel/locking/rtmutex.c | 21 ++++++++++++++++++++-
+ kernel/locking/ww_rt_mutex.c | 2 +-
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -218,6 +218,11 @@ static __always_inline bool rt_mutex_cmp
+ return try_cmpxchg_acquire(&lock->owner, &old, new);
+ }
+
++static __always_inline bool rt_mutex_try_acquire(struct rt_mutex_base *lock)
++{
++ return rt_mutex_cmpxchg_acquire(lock, NULL, current);
++}
++
+ static __always_inline bool rt_mutex_cmpxchg_release(struct rt_mutex_base *lock,
+ struct task_struct *old,
+ struct task_struct *new)
+@@ -297,6 +302,20 @@ static __always_inline bool rt_mutex_cmp
+
+ }
+
++static int __sched rt_mutex_slowtrylock(struct rt_mutex_base *lock);
++
++static __always_inline bool rt_mutex_try_acquire(struct rt_mutex_base *lock)
++{
++ /*
++ * With debug enabled rt_mutex_cmpxchg trylock() will always fail.
++ *
++ * Avoid unconditionally taking the slow path by using
++ * rt_mutex_slow_trylock() which is covered by the debug code and can
++ * acquire a non-contended rtmutex.
++ */
++ return rt_mutex_slowtrylock(lock);
++}
++
+ static __always_inline bool rt_mutex_cmpxchg_release(struct rt_mutex_base *lock,
+ struct task_struct *old,
+ struct task_struct *new)
+@@ -1755,7 +1774,7 @@ static int __sched rt_mutex_slowlock(str
+ static __always_inline int __rt_mutex_lock(struct rt_mutex_base *lock,
+ unsigned int state)
+ {
+- if (likely(rt_mutex_cmpxchg_acquire(lock, NULL, current)))
++ if (likely(rt_mutex_try_acquire(lock)))
+ return 0;
+
+ return rt_mutex_slowlock(lock, NULL, state);
+--- a/kernel/locking/ww_rt_mutex.c
++++ b/kernel/locking/ww_rt_mutex.c
+@@ -62,7 +62,7 @@ static int __sched
+ }
+ mutex_acquire_nest(&rtm->dep_map, 0, 0, nest_lock, ip);
+
+- if (likely(rt_mutex_cmpxchg_acquire(&rtm->rtmutex, NULL, current))) {
++ if (likely(rt_mutex_try_acquire(&rtm->rtmutex))) {
+ if (ww_ctx)
+ ww_mutex_set_context_fastpath(lock, ww_ctx);
+ return 0;
diff --git a/debian/patches-rt/0002-serial-core-Use-lock-wrappers.patch b/debian/patches-rt/0002-serial-core-Use-lock-wrappers.patch
new file mode 100644
index 0000000000..ad41a3dc78
--- /dev/null
+++ b/debian/patches-rt/0002-serial-core-Use-lock-wrappers.patch
@@ -0,0 +1,93 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:19 +0206
+Subject: [PATCH 002/134] serial: core: Use lock wrappers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-3-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/serial_core.h | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -1035,14 +1035,14 @@ static inline void uart_unlock_and_check
+ u8 sysrq_ch;
+
+ if (!port->has_sysrq) {
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ return;
+ }
+
+ sysrq_ch = port->sysrq_ch;
+ port->sysrq_ch = 0;
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ if (sysrq_ch)
+ handle_sysrq(sysrq_ch);
+@@ -1054,14 +1054,14 @@ static inline void uart_unlock_and_check
+ u8 sysrq_ch;
+
+ if (!port->has_sysrq) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return;
+ }
+
+ sysrq_ch = port->sysrq_ch;
+ port->sysrq_ch = 0;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (sysrq_ch)
+ handle_sysrq(sysrq_ch);
+@@ -1077,12 +1077,12 @@ static inline int uart_prepare_sysrq_cha
+ }
+ static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
+ {
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ }
+ static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
+ unsigned long flags)
+ {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ #endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
+
diff --git a/debian/patches-rt/0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch b/debian/patches-rt/0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch
new file mode 100644
index 0000000000..01e89d97ab
--- /dev/null
+++ b/debian/patches-rt/0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch
@@ -0,0 +1,48 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 3 Aug 2023 12:09:32 +0200
+Subject: [PATCH 2/2] signal: Don't disable preemption in ptrace_stop() on
+ PREEMPT_RT.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+On PREEMPT_RT keeping preemption disabled during the invocation of
+cgroup_enter_frozen() is a problem because the function acquires css_set_lock
+which is a sleeping lock on PREEMPT_RT and must not be acquired with disabled
+preemption.
+The preempt-disabled section is only for performance optimisation
+reasons and can be avoided.
+
+Extend the comment and don't disable preemption before scheduling on
+PREEMPT_RT.
+
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20230803100932.325870-3-bigeasy@linutronix.de
+---
+ kernel/signal.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -2344,11 +2344,20 @@ static int ptrace_stop(int exit_code, in
+ * The preempt-disable section ensures that there will be no preemption
+ * between unlock and schedule() and so improving the performance since
+ * the ptracer has no reason to sleep.
++ *
++ * On PREEMPT_RT locking tasklist_lock does not disable preemption.
++ * Therefore the task can be preempted (after
++ * do_notify_parent_cldstop()) before unlocking tasklist_lock so there
++ * is no benefit in doing this. The optimisation is harmful on
++ * PEEMPT_RT because the spinlock_t (in cgroup_enter_frozen()) must not
++ * be acquired with disabled preemption.
+ */
+- preempt_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_disable();
+ read_unlock(&tasklist_lock);
+ cgroup_enter_frozen();
+- preempt_enable_no_resched();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_enable_no_resched();
+ schedule();
+ cgroup_leave_frozen(true);
+
diff --git a/debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch b/debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch
new file mode 100644
index 0000000000..f8cddfa446
--- /dev/null
+++ b/debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch
@@ -0,0 +1,60 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 4 Aug 2023 13:30:38 +0200
+Subject: [PATCH 2/3] softirq: Add function to preempt serving softirqs.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add a functionality for the softirq handler to preempt its current work
+if needed. The softirq core has no particular state. It reads and resets
+the pending softirq bits and then processes one after the other.
+It can already be preempted while it invokes a certain softirq handler.
+
+By enabling the BH the softirq core releases the per-CPU bh lock which
+serializes all softirq handler. It is safe to do as long as the code
+does not expect any serialisation in between. A typical scenarion would
+after the invocation of callback where no state needs to be preserved
+before the next callback is invoked.
+
+Add functionaliry to preempt the serving softirqs.
+
+Link: https://lore.kernel.org/r/20230804113039.419794-3-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/bottom_half.h | 2 ++
+ kernel/softirq.c | 13 +++++++++++++
+ 2 files changed, 15 insertions(+)
+
+--- a/include/linux/bottom_half.h
++++ b/include/linux/bottom_half.h
+@@ -35,8 +35,10 @@ static inline void local_bh_enable(void)
+
+ #ifdef CONFIG_PREEMPT_RT
+ extern bool local_bh_blocked(void);
++extern void softirq_preempt(void);
+ #else
+ static inline bool local_bh_blocked(void) { return false; }
++static inline void softirq_preempt(void) { }
+ #endif
+
+ #endif /* _LINUX_BH_H */
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -247,6 +247,19 @@ void __local_bh_enable_ip(unsigned long
+ }
+ EXPORT_SYMBOL(__local_bh_enable_ip);
+
++void softirq_preempt(void)
++{
++ if (WARN_ON_ONCE(!preemptible()))
++ return;
++
++ if (WARN_ON_ONCE(__this_cpu_read(softirq_ctrl.cnt) != SOFTIRQ_OFFSET))
++ return;
++
++ __local_bh_enable(SOFTIRQ_OFFSET, true);
++ /* preemption point */
++ __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
++}
++
+ /*
+ * Invoked from ksoftirqd_run() outside of the interrupt disabled section
+ * to acquire the per CPU local lock for reentrancy protection.
diff --git a/debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch b/debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch
new file mode 100644
index 0000000000..c02278e5a8
--- /dev/null
+++ b/debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch
@@ -0,0 +1,48 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 28 Jun 2023 09:36:10 +0200
+Subject: [PATCH 3/4] ARM: vfp: Use vfp_lock() in vfp_support_entry().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+vfp_entry() is invoked from exception handler and is fully preemptible.
+It uses local_bh_disable() to remain uninterrupted while checking the
+VFP state.
+This is not working on PREEMPT_RT because local_bh_disable()
+synchronizes the relevant section but the context remains fully
+preemptible.
+
+Use vfp_lock() for uninterrupted access.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/arm/vfp/vfpmodule.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -708,7 +708,7 @@ static int vfp_support_entry(struct pt_r
+ if (!user_mode(regs))
+ return vfp_kmode_exception(regs, trigger);
+
+- local_bh_disable();
++ vfp_lock();
+ fpexc = fmrx(FPEXC);
+
+ /*
+@@ -787,7 +787,7 @@ static int vfp_support_entry(struct pt_r
+ if (!(fpscr & FPSCR_IXE)) {
+ if (!(fpscr & FPSCR_LENGTH_MASK)) {
+ pr_debug("not VFP\n");
+- local_bh_enable();
++ vfp_unlock();
+ return -ENOEXEC;
+ }
+ fpexc |= FPEXC_DEX;
+@@ -797,7 +797,7 @@ bounce: regs->ARM_pc += 4;
+ VFP_bounce(trigger, fpexc, regs);
+ }
+
+- local_bh_enable();
++ vfp_unlock();
+ return 0;
+ }
+
diff --git a/debian/patches-rt/0003-drm-amd-display-Add-a-warning-if-the-FPU-is-used-out.patch b/debian/patches-rt/0003-drm-amd-display-Add-a-warning-if-the-FPU-is-used-out.patch
new file mode 100644
index 0000000000..9e160d5a28
--- /dev/null
+++ b/debian/patches-rt/0003-drm-amd-display-Add-a-warning-if-the-FPU-is-used-out.patch
@@ -0,0 +1,26 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Sep 2023 16:15:14 +0200
+Subject: [PATCH 3/5] drm/amd/display: Add a warning if the FPU is used outside
+ from task context.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add a warning if the FPU is used from any context other than task
+context. This is only precaution since the code is not able to be used
+from softirq while the API allows it on x86 for instance.
+
+Link: https://lore.kernel.org/r/20230921141516.520471-4-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+@@ -84,6 +84,7 @@ void dc_fpu_begin(const char *function_n
+ {
+ int depth;
+
++ WARN_ON_ONCE(!in_task());
+ preempt_disable();
+ depth = __this_cpu_inc_return(fpu_recursion_depth);
+
diff --git a/debian/patches-rt/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch b/debian/patches-rt/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
new file mode 100644
index 0000000000..f2752d0901
--- /dev/null
+++ b/debian/patches-rt/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
@@ -0,0 +1,56 @@
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Sat, 27 Feb 2016 08:09:11 +0100
+Subject: [PATCH 03/10] drm/i915: Use preempt_disable/enable_rt() where
+ recommended
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Mario Kleiner suggest in commit
+ ad3543ede630f ("drm/intel: Push get_scanout_position() timestamping into kms driver.")
+
+a spots where preemption should be disabled on PREEMPT_RT. The
+difference is that on PREEMPT_RT the intel_uncore::lock disables neither
+preemption nor interrupts and so region remains preemptible.
+
+The area covers only register reads and writes. The part that worries me
+is:
+- __intel_get_crtc_scanline() the worst case is 100us if no match is
+ found.
+
+- intel_crtc_scanlines_since_frame_timestamp() not sure how long this
+ may take in the worst case.
+
+It was in the RT queue for a while and nobody complained.
+Disable preemption on PREEPMPT_RT during timestamping.
+
+[bigeasy: patch description.]
+
+Cc: Mario Kleiner <mario.kleiner.de@gmail.com>
+Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/display/intel_vblank.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_vblank.c
++++ b/drivers/gpu/drm/i915/display/intel_vblank.c
+@@ -294,7 +294,8 @@ static bool i915_get_crtc_scanoutpos(str
+ */
+ spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+- /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
++ if (IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_disable();
+
+ /* Get optional system timestamp before query. */
+ if (stime)
+@@ -358,7 +359,8 @@ static bool i915_get_crtc_scanoutpos(str
+ if (etime)
+ *etime = ktime_get();
+
+- /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
++ if (IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_enable();
+
+ spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+
diff --git a/debian/patches-rt/0003-sched-Extract-__schedule_loop.patch b/debian/patches-rt/0003-sched-Extract-__schedule_loop.patch
new file mode 100644
index 0000000000..a236df5321
--- /dev/null
+++ b/debian/patches-rt/0003-sched-Extract-__schedule_loop.patch
@@ -0,0 +1,58 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 8 Sep 2023 18:22:50 +0200
+Subject: [PATCH 3/7] sched: Extract __schedule_loop()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+There are currently two implementations of this basic __schedule()
+loop, and there is soon to be a third.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20230908162254.999499-4-bigeasy@linutronix.de
+---
+ kernel/sched/core.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -6771,16 +6771,21 @@ static void sched_update_worker(struct t
+ }
+ }
+
+-asmlinkage __visible void __sched schedule(void)
++static __always_inline void __schedule_loop(unsigned int sched_mode)
+ {
+- struct task_struct *tsk = current;
+-
+- sched_submit_work(tsk);
+ do {
+ preempt_disable();
+- __schedule(SM_NONE);
++ __schedule(sched_mode);
+ sched_preempt_enable_no_resched();
+ } while (need_resched());
++}
++
++asmlinkage __visible void __sched schedule(void)
++{
++ struct task_struct *tsk = current;
++
++ sched_submit_work(tsk);
++ __schedule_loop(SM_NONE);
+ sched_update_worker(tsk);
+ }
+ EXPORT_SYMBOL(schedule);
+@@ -6844,11 +6849,7 @@ void __sched schedule_preempt_disabled(v
+ #ifdef CONFIG_PREEMPT_RT
+ void __sched notrace schedule_rtlock(void)
+ {
+- do {
+- preempt_disable();
+- __schedule(SM_RTLOCK_WAIT);
+- sched_preempt_enable_no_resched();
+- } while (need_resched());
++ __schedule_loop(SM_RTLOCK_WAIT);
+ }
+ NOKPROBE_SYMBOL(schedule_rtlock);
+ #endif
diff --git a/debian/patches-rt/0003-serial-21285-Use-port-lock-wrappers.patch b/debian/patches-rt/0003-serial-21285-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..e025de601c
--- /dev/null
+++ b/debian/patches-rt/0003-serial-21285-Use-port-lock-wrappers.patch
@@ -0,0 +1,75 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:20 +0206
+Subject: [PATCH 003/134] serial: 21285: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-4-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/21285.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/21285.c
++++ b/drivers/tty/serial/21285.c
+@@ -185,14 +185,14 @@ static void serial21285_break_ctl(struct
+ unsigned long flags;
+ unsigned int h_lcr;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ h_lcr = *CSR_H_UBRLCR;
+ if (break_state)
+ h_lcr |= H_UBRLCR_BREAK;
+ else
+ h_lcr &= ~H_UBRLCR_BREAK;
+ *CSR_H_UBRLCR = h_lcr;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int serial21285_startup(struct uart_port *port)
+@@ -272,7 +272,7 @@ serial21285_set_termios(struct uart_port
+ if (port->fifosize)
+ h_lcr |= H_UBRLCR_FIFO;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -309,7 +309,7 @@ serial21285_set_termios(struct uart_port
+ *CSR_H_UBRLCR = h_lcr;
+ *CSR_UARTCON = 1;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *serial21285_type(struct uart_port *port)
diff --git a/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch b/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch
new file mode 100644
index 0000000000..7ede7d6ae5
--- /dev/null
+++ b/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch
@@ -0,0 +1,47 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 4 Aug 2023 13:30:39 +0200
+Subject: [PATCH 3/3] time: Allow to preempt after a callback.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The TIMER_SOFTIRQ handler invokes timer callbacks of the expired timers.
+Before each invocation the timer_base::lock is dropped. The only lock
+that is still held is the timer_base::expiry_lock and the per-CPU
+bh-lock as part of local_bh_disable(). The former is released as part
+of lock up prevention if the timer is preempted by the caller which is
+waiting for its completion.
+
+Both locks are already released as part of timer_sync_wait_running().
+This can be extended by also releasing in bh-lock. The timer core does
+not rely on any state that is serialized by the bh-lock. The timer
+callback expects the bh-state to be serialized by the lock but there is
+no need to keep state synchronized while invoking multiple callbacks.
+
+Preempt handling softirqs and release all locks after a timer invocation
+if the current has inherited priority.
+
+Link: https://lore.kernel.org/r/20230804113039.419794-4-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/time/timer.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1470,9 +1470,16 @@ static inline void timer_base_unlock_exp
+ */
+ static void timer_sync_wait_running(struct timer_base *base)
+ {
+- if (atomic_read(&base->timer_waiters)) {
++ bool need_preempt;
++
++ need_preempt = task_is_pi_boosted(current);
++ if (need_preempt || atomic_read(&base->timer_waiters)) {
+ raw_spin_unlock_irq(&base->lock);
+ spin_unlock(&base->expiry_lock);
++
++ if (need_preempt)
++ softirq_preempt();
++
+ spin_lock(&base->expiry_lock);
+ raw_spin_lock_irq(&base->lock);
+ }
diff --git a/debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch b/debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch
new file mode 100644
index 0000000000..f7e006261e
--- /dev/null
+++ b/debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch
@@ -0,0 +1,121 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 28 Jun 2023 09:39:33 +0200
+Subject: [PATCH 4/4] ARM: vfp: Move sending signals outside of vfp_lock()ed
+ section.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+VFP_bounce() is invoked from within vfp_support_entry() and may send a
+signal. Sending a signal uses spinlock_t which becomes a sleeping lock
+on PREEMPT_RT and must not be acquired within a preempt-disabled
+section.
+
+Move the vfp_raise_sigfpe() block outside of the vfp_lock() section.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/arm/vfp/vfpmodule.c | 29 ++++++++++++++++++-----------
+ 1 file changed, 18 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/vfp/vfpmodule.c
++++ b/arch/arm/vfp/vfpmodule.c
+@@ -268,7 +268,7 @@ static void vfp_panic(char *reason, u32
+ /*
+ * Process bitmask of exception conditions.
+ */
+-static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
++static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr)
+ {
+ int si_code = 0;
+
+@@ -276,8 +276,7 @@ static void vfp_raise_exceptions(u32 exc
+
+ if (exceptions == VFP_EXCEPTION_ERROR) {
+ vfp_panic("unhandled bounce", inst);
+- vfp_raise_sigfpe(FPE_FLTINV, regs);
+- return;
++ return FPE_FLTINV;
+ }
+
+ /*
+@@ -305,8 +304,7 @@ static void vfp_raise_exceptions(u32 exc
+ RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
+ RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
+
+- if (si_code)
+- vfp_raise_sigfpe(si_code, regs);
++ return si_code;
+ }
+
+ /*
+@@ -352,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 i
+ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
+ {
+ u32 fpscr, orig_fpscr, fpsid, exceptions;
++ int si_code2 = 0;
++ int si_code = 0;
+
+ pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
+
+@@ -397,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32
+ * unallocated VFP instruction but with FPSCR.IXE set and not
+ * on VFP subarch 1.
+ */
+- vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
+- return;
++ si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr);
++ goto exit;
+ }
+
+ /*
+@@ -422,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32
+ */
+ exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
+ if (exceptions)
+- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
++ si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
+
+ /*
+ * If there isn't a second FP instruction, exit now. Note that
+ * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
+ */
+ if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
+- return;
++ goto exit;
+
+ /*
+ * The barrier() here prevents fpinst2 being read
+@@ -441,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32
+ emulate:
+ exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
+ if (exceptions)
+- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
++ si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
++exit:
++ vfp_unlock();
++ if (si_code2)
++ vfp_raise_sigfpe(si_code2, regs);
++ if (si_code)
++ vfp_raise_sigfpe(si_code, regs);
+ }
+
+ static void vfp_enable(void *unused)
+@@ -773,6 +779,7 @@ static int vfp_support_entry(struct pt_r
+ * replay the instruction that trapped.
+ */
+ fmxr(FPEXC, fpexc);
++ vfp_unlock();
+ } else {
+ /* Check for synchronous or asynchronous exceptions */
+ if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
+@@ -794,10 +801,10 @@ static int vfp_support_entry(struct pt_r
+ }
+ }
+ bounce: regs->ARM_pc += 4;
++ /* VFP_bounce() will invoke vfp_unlock() */
+ VFP_bounce(trigger, fpexc, regs);
+ }
+
+- vfp_unlock();
+ return 0;
+ }
+
diff --git a/debian/patches-rt/0004-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch b/debian/patches-rt/0004-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch
new file mode 100644
index 0000000000..a1c046b36c
--- /dev/null
+++ b/debian/patches-rt/0004-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch
@@ -0,0 +1,87 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Sep 2023 16:15:15 +0200
+Subject: [PATCH 4/5] drm/amd/display: Move the memory allocation out of
+ dcn21_validate_bandwidth_fp().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+dcn21_validate_bandwidth_fp() is invoked while FPU access has been
+enabled. FPU access requires disabling preemption even on PREEMPT_RT.
+It is not possible to allocate memory with disabled preemption even with
+GFP_ATOMIC on PREEMPT_RT.
+
+Move the memory allocation before FPU access is enabled.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=217928
+Link: https://lore.kernel.org/r/20230921141516.520471-5-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 10 +++++++++-
+ drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 7 ++-----
+ drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h | 5 ++---
+ 3 files changed, 13 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+@@ -953,9 +953,17 @@ static bool dcn21_validate_bandwidth(str
+ bool fast_validate)
+ {
+ bool voltage_supported;
++ display_e2e_pipe_params_st *pipes;
++
++ pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
++ if (!pipes)
++ return false;
++
+ DC_FP_START();
+- voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate);
++ voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes);
+ DC_FP_END();
++
++ kfree(pipes);
+ return voltage_supported;
+ }
+
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+@@ -2203,9 +2203,8 @@ static void dcn21_calculate_wm(struct dc
+ &context->bw_ctx.dml, pipes, pipe_cnt);
+ }
+
+-bool dcn21_validate_bandwidth_fp(struct dc *dc,
+- struct dc_state *context,
+- bool fast_validate)
++bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
++ bool fast_validate, display_e2e_pipe_params_st *pipes)
+ {
+ bool out = false;
+
+@@ -2214,7 +2213,6 @@ bool dcn21_validate_bandwidth_fp(struct
+ int vlevel = 0;
+ int pipe_split_from[MAX_PIPES];
+ int pipe_cnt = 0;
+- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ BW_VAL_TRACE_COUNT();
+@@ -2254,7 +2252,6 @@ bool dcn21_validate_bandwidth_fp(struct
+ out = false;
+
+ validate_out:
+- kfree(pipes);
+
+ BW_VAL_TRACE_FINISH();
+
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+@@ -77,9 +77,8 @@ int dcn21_populate_dml_pipes_from_contex
+ struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ bool fast_validate);
+-bool dcn21_validate_bandwidth_fp(struct dc *dc,
+- struct dc_state *context,
+- bool fast_validate);
++bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, bool
++ fast_validate, display_e2e_pipe_params_st *pipes);
+ void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
+
+ void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params);
diff --git a/debian/patches-rt/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch b/debian/patches-rt/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
new file mode 100644
index 0000000000..9c386e5188
--- /dev/null
+++ b/debian/patches-rt/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
@@ -0,0 +1,85 @@
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Sat, 27 Feb 2016 09:01:42 +0100
+Subject: [PATCH 04/10] drm/i915: Don't disable interrupts on PREEMPT_RT during
+ atomic updates
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Commit
+ 8d7849db3eab7 ("drm/i915: Make sprite updates atomic")
+
+started disabling interrupts across atomic updates. This breaks on PREEMPT_RT
+because within this section the code attempt to acquire spinlock_t locks which
+are sleeping locks on PREEMPT_RT.
+
+According to the comment the interrupts are disabled to avoid random delays and
+not required for protection or synchronisation.
+If this needs to happen with disabled interrupts on PREEMPT_RT, and the
+whole section is restricted to register access then all sleeping locks
+need to be acquired before interrupts are disabled and some function
+maybe moved after enabling interrupts again.
+This includes:
+- prepare_to_wait() + finish_wait() due its wake queue.
+- drm_crtc_vblank_put() -> vblank_disable_fn() drm_device::vbl_lock.
+- skl_pfit_enable(), intel_update_plane(), vlv_atomic_update_fifo() and
+ maybe others due to intel_uncore::lock
+- drm_crtc_arm_vblank_event() due to drm_device::event_lock and
+ drm_device::vblank_time_lock.
+
+Don't disable interrupts on PREEMPT_RT during atomic updates.
+
+[bigeasy: drop local locks, commit message]
+
+Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/display/intel_crtc.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/i915/display/intel_crtc.c
++++ b/drivers/gpu/drm/i915/display/intel_crtc.c
+@@ -534,7 +534,8 @@ void intel_pipe_update_start(struct inte
+ */
+ intel_psr_wait_for_idle_locked(new_crtc_state);
+
+- local_irq_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_disable();
+
+ crtc->debug.min_vbl = min;
+ crtc->debug.max_vbl = max;
+@@ -559,11 +560,13 @@ void intel_pipe_update_start(struct inte
+ break;
+ }
+
+- local_irq_enable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_enable();
+
+ timeout = schedule_timeout(timeout);
+
+- local_irq_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_disable();
+ }
+
+ finish_wait(wq, &wait);
+@@ -596,7 +599,8 @@ void intel_pipe_update_start(struct inte
+ return;
+
+ irq_disable:
+- local_irq_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_disable();
+ }
+
+ #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE)
+@@ -706,7 +710,8 @@ void intel_pipe_update_end(struct intel_
+ intel_crtc_update_active_timings(new_crtc_state,
+ new_crtc_state->vrr.enable);
+
+- local_irq_enable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_enable();
+
+ if (intel_vgpu_active(dev_priv))
+ return;
diff --git a/debian/patches-rt/0004-sched-Provide-rt_mutex-specific-scheduler-helpers.patch b/debian/patches-rt/0004-sched-Provide-rt_mutex-specific-scheduler-helpers.patch
new file mode 100644
index 0000000000..f61a67ea3f
--- /dev/null
+++ b/debian/patches-rt/0004-sched-Provide-rt_mutex-specific-scheduler-helpers.patch
@@ -0,0 +1,128 @@
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Fri, 8 Sep 2023 18:22:51 +0200
+Subject: [PATCH 4/7] sched: Provide rt_mutex specific scheduler helpers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+With PREEMPT_RT there is a rt_mutex recursion problem where
+sched_submit_work() can use an rtlock (aka spinlock_t). More
+specifically what happens is:
+
+ mutex_lock() /* really rt_mutex */
+ ...
+ __rt_mutex_slowlock_locked()
+ task_blocks_on_rt_mutex()
+ // enqueue current task as waiter
+ // do PI chain walk
+ rt_mutex_slowlock_block()
+ schedule()
+ sched_submit_work()
+ ...
+ spin_lock() /* really rtlock */
+ ...
+ __rt_mutex_slowlock_locked()
+ task_blocks_on_rt_mutex()
+ // enqueue current task as waiter *AGAIN*
+ // *CONFUSION*
+
+Fix this by making rt_mutex do the sched_submit_work() early, before
+it enqueues itself as a waiter -- before it even knows *if* it will
+wait.
+
+[[ basically Thomas' patch but with different naming and a few asserts
+ added ]]
+
+Originally-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20230908162254.999499-5-bigeasy@linutronix.de
+---
+ include/linux/sched.h | 3 +++
+ include/linux/sched/rt.h | 4 ++++
+ kernel/sched/core.c | 36 ++++++++++++++++++++++++++++++++----
+ 3 files changed, 39 insertions(+), 4 deletions(-)
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -911,6 +911,9 @@ struct task_struct {
+ * ->sched_remote_wakeup gets used, so it can be in this word.
+ */
+ unsigned sched_remote_wakeup:1;
++#ifdef CONFIG_RT_MUTEXES
++ unsigned sched_rt_mutex:1;
++#endif
+
+ /* Bit to tell LSMs we're in execve(): */
+ unsigned in_execve:1;
+--- a/include/linux/sched/rt.h
++++ b/include/linux/sched/rt.h
+@@ -30,6 +30,10 @@ static inline bool task_is_realtime(stru
+ }
+
+ #ifdef CONFIG_RT_MUTEXES
++extern void rt_mutex_pre_schedule(void);
++extern void rt_mutex_schedule(void);
++extern void rt_mutex_post_schedule(void);
++
+ /*
+ * Must hold either p->pi_lock or task_rq(p)->lock.
+ */
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -6724,9 +6724,6 @@ static inline void sched_submit_work(str
+ static DEFINE_WAIT_OVERRIDE_MAP(sched_map, LD_WAIT_CONFIG);
+ unsigned int task_flags;
+
+- if (task_is_running(tsk))
+- return;
+-
+ /*
+ * Establish LD_WAIT_CONFIG context to ensure none of the code called
+ * will use a blocking primitive -- which would lead to recursion.
+@@ -6784,7 +6781,12 @@ asmlinkage __visible void __sched schedu
+ {
+ struct task_struct *tsk = current;
+
+- sched_submit_work(tsk);
++#ifdef CONFIG_RT_MUTEXES
++ lockdep_assert(!tsk->sched_rt_mutex);
++#endif
++
++ if (!task_is_running(tsk))
++ sched_submit_work(tsk);
+ __schedule_loop(SM_NONE);
+ sched_update_worker(tsk);
+ }
+@@ -7045,6 +7047,32 @@ static void __setscheduler_prio(struct t
+
+ #ifdef CONFIG_RT_MUTEXES
+
++/*
++ * Would be more useful with typeof()/auto_type but they don't mix with
++ * bit-fields. Since it's a local thing, use int. Keep the generic sounding
++ * name such that if someone were to implement this function we get to compare
++ * notes.
++ */
++#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; })
++
++void rt_mutex_pre_schedule(void)
++{
++ lockdep_assert(!fetch_and_set(current->sched_rt_mutex, 1));
++ sched_submit_work(current);
++}
++
++void rt_mutex_schedule(void)
++{
++ lockdep_assert(current->sched_rt_mutex);
++ __schedule_loop(SM_NONE);
++}
++
++void rt_mutex_post_schedule(void)
++{
++ sched_update_worker(current);
++ lockdep_assert(fetch_and_set(current->sched_rt_mutex, 0));
++}
++
+ static inline int __rt_effective_prio(struct task_struct *pi_task, int prio)
+ {
+ if (pi_task)
diff --git a/debian/patches-rt/0004-serial-8250_aspeed_vuart-Use-port-lock-wrappers.patch b/debian/patches-rt/0004-serial-8250_aspeed_vuart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..eb65ac58fc
--- /dev/null
+++ b/debian/patches-rt/0004-serial-8250_aspeed_vuart-Use-port-lock-wrappers.patch
@@ -0,0 +1,61 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:21 +0206
+Subject: [PATCH 004/134] serial: 8250_aspeed_vuart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-5-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_aspeed_vuart.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
++++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
+@@ -288,9 +288,9 @@ static void aspeed_vuart_set_throttle(st
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ __aspeed_vuart_set_throttle(up, throttle);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void aspeed_vuart_throttle(struct uart_port *port)
+@@ -340,7 +340,7 @@ static int aspeed_vuart_handle_irq(struc
+ if (iir & UART_IIR_NO_INT)
+ return 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ lsr = serial_port_in(port, UART_LSR);
+
diff --git a/debian/patches-rt/0005-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch b/debian/patches-rt/0005-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch
new file mode 100644
index 0000000000..1a2babc614
--- /dev/null
+++ b/debian/patches-rt/0005-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch
@@ -0,0 +1,121 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Sep 2023 16:15:16 +0200
+Subject: [PATCH 5/5] drm/amd/display: Move the memory allocation out of
+ dcn20_validate_bandwidth_fp().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+dcn20_validate_bandwidth_fp() is invoked while FPU access has been
+enabled. FPU access requires disabling preemption even on PREEMPT_RT.
+It is not possible to allocate memory with disabled preemption even with
+GFP_ATOMIC on PREEMPT_RT.
+
+Move the memory allocation before FPU access is enabled.
+To preserve previous "clean" state of "pipes" add a memset() before the
+second invocation of dcn20_validate_bandwidth_internal() where the
+variable is used.
+
+Link: https://lore.kernel.org/r/20230921141516.520471-6-bigeasy@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 10 +++++++++-
+ drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 16 +++++++---------
+ drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h | 5 ++---
+ 3 files changed, 18 insertions(+), 13 deletions(-)
+
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+@@ -2141,9 +2141,17 @@ bool dcn20_validate_bandwidth(struct dc
+ bool fast_validate)
+ {
+ bool voltage_supported;
++ display_e2e_pipe_params_st *pipes;
++
++ pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
++ if (!pipes)
++ return false;
++
+ DC_FP_START();
+- voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate);
++ voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes);
+ DC_FP_END();
++
++ kfree(pipes);
+ return voltage_supported;
+ }
+
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+@@ -1910,7 +1910,7 @@ void dcn20_patch_bounding_box(struct dc
+ }
+
+ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context,
+- bool fast_validate)
++ bool fast_validate, display_e2e_pipe_params_st *pipes)
+ {
+ bool out = false;
+
+@@ -1919,7 +1919,6 @@ static bool dcn20_validate_bandwidth_int
+ int vlevel = 0;
+ int pipe_split_from[MAX_PIPES];
+ int pipe_cnt = 0;
+- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ BW_VAL_TRACE_COUNT();
+@@ -1954,16 +1953,14 @@ static bool dcn20_validate_bandwidth_int
+ out = false;
+
+ validate_out:
+- kfree(pipes);
+
+ BW_VAL_TRACE_FINISH();
+
+ return out;
+ }
+
+-bool dcn20_validate_bandwidth_fp(struct dc *dc,
+- struct dc_state *context,
+- bool fast_validate)
++bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
++ bool fast_validate, display_e2e_pipe_params_st *pipes)
+ {
+ bool voltage_supported = false;
+ bool full_pstate_supported = false;
+@@ -1982,11 +1979,11 @@ bool dcn20_validate_bandwidth_fp(struct
+ ASSERT(context != dc->current_state);
+
+ if (fast_validate) {
+- return dcn20_validate_bandwidth_internal(dc, context, true);
++ return dcn20_validate_bandwidth_internal(dc, context, true, pipes);
+ }
+
+ // Best case, we support full UCLK switch latency
+- voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
++ voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes);
+ full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
+
+ if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 ||
+@@ -1998,7 +1995,8 @@ bool dcn20_validate_bandwidth_fp(struct
+ // Fallback: Try to only support G6 temperature read latency
+ context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
+
+- voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
++ memset(pipes, 0, dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st));
++ voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes);
+ dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
+
+ if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) {
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+@@ -61,9 +61,8 @@ void dcn20_update_bounding_box(struct dc
+ unsigned int num_states);
+ void dcn20_patch_bounding_box(struct dc *dc,
+ struct _vcs_dpi_soc_bounding_box_st *bb);
+-bool dcn20_validate_bandwidth_fp(struct dc *dc,
+- struct dc_state *context,
+- bool fast_validate);
++bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
++ bool fast_validate, display_e2e_pipe_params_st *pipes);
+ void dcn20_fpu_set_wm_ranges(int i,
+ struct pp_smu_wm_range_sets *ranges,
+ struct _vcs_dpi_soc_bounding_box_st *loaded_bb);
diff --git a/debian/patches-rt/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch b/debian/patches-rt/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
new file mode 100644
index 0000000000..4af9325678
--- /dev/null
+++ b/debian/patches-rt/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
@@ -0,0 +1,30 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 25 Oct 2021 15:05:18 +0200
+Subject: [PATCH 05/10] drm/i915: Don't check for atomic context on PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The !in_atomic() check in _wait_for_atomic() triggers on PREEMPT_RT
+because the uncore::lock is a spinlock_t and does not disable
+preemption or interrupts.
+
+Changing the uncore:lock to a raw_spinlock_t doubles the worst case
+latency on an otherwise idle testbox during testing. Therefore I'm
+currently unsure about changing this.
+
+Link: https://lore.kernel.org/all/20211006164628.s2mtsdd2jdbfyf7g@linutronix.de/
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/i915_utils.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_utils.h
++++ b/drivers/gpu/drm/i915/i915_utils.h
+@@ -288,7 +288,7 @@ wait_remaining_ms_from_jiffies(unsigned
+ #define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000)
+
+ /* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */
+-#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT)
++#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) && !defined(CONFIG_PREEMPT_RT)
+ # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) WARN_ON_ONCE((ATOMIC) && !in_atomic())
+ #else
+ # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) do { } while (0)
diff --git a/debian/patches-rt/0005-locking-rtmutex-Use-rt_mutex-specific-scheduler-help.patch b/debian/patches-rt/0005-locking-rtmutex-Use-rt_mutex-specific-scheduler-help.patch
new file mode 100644
index 0000000000..d84497e5fd
--- /dev/null
+++ b/debian/patches-rt/0005-locking-rtmutex-Use-rt_mutex-specific-scheduler-help.patch
@@ -0,0 +1,177 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 8 Sep 2023 18:22:52 +0200
+Subject: [PATCH 5/7] locking/rtmutex: Use rt_mutex specific scheduler helpers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Have rt_mutex use the rt_mutex specific scheduler helpers to avoid
+recursion vs rtlock on the PI state.
+
+[[ peterz: adapted to new names ]]
+
+Reported-by: Crystal Wood <swood@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20230908162254.999499-6-bigeasy@linutronix.de
+---
+ kernel/futex/pi.c | 11 +++++++++++
+ kernel/locking/rtmutex.c | 14 ++++++++++++--
+ kernel/locking/rwbase_rt.c | 6 ++++++
+ kernel/locking/rwsem.c | 8 +++++++-
+ kernel/locking/spinlock_rt.c | 4 ++++
+ 5 files changed, 40 insertions(+), 3 deletions(-)
+
+--- a/kernel/futex/pi.c
++++ b/kernel/futex/pi.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-or-later
+
+ #include <linux/slab.h>
++#include <linux/sched/rt.h>
+ #include <linux/sched/task.h>
+
+ #include "futex.h"
+@@ -1002,6 +1003,12 @@ int futex_lock_pi(u32 __user *uaddr, uns
+ goto no_block;
+ }
+
++ /*
++ * Must be done before we enqueue the waiter, here is unfortunately
++ * under the hb lock, but that *should* work because it does nothing.
++ */
++ rt_mutex_pre_schedule();
++
+ rt_mutex_init_waiter(&rt_waiter);
+
+ /*
+@@ -1052,6 +1059,10 @@ int futex_lock_pi(u32 __user *uaddr, uns
+ if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter))
+ ret = 0;
+
++ /*
++ * Waiter is unqueued.
++ */
++ rt_mutex_post_schedule();
+ no_block:
+ /*
+ * Fixup the pi_state owner and possibly acquire the lock if we
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -1632,7 +1632,7 @@ static int __sched rt_mutex_slowlock_blo
+ raw_spin_unlock_irq(&lock->wait_lock);
+
+ if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner))
+- schedule();
++ rt_mutex_schedule();
+
+ raw_spin_lock_irq(&lock->wait_lock);
+ set_current_state(state);
+@@ -1661,7 +1661,7 @@ static void __sched rt_mutex_handle_dead
+ WARN(1, "rtmutex deadlock detected\n");
+ while (1) {
+ set_current_state(TASK_INTERRUPTIBLE);
+- schedule();
++ rt_mutex_schedule();
+ }
+ }
+
+@@ -1757,6 +1757,15 @@ static int __sched rt_mutex_slowlock(str
+ int ret;
+
+ /*
++ * Do all pre-schedule work here, before we queue a waiter and invoke
++ * PI -- any such work that trips on rtlock (PREEMPT_RT spinlock) would
++ * otherwise recurse back into task_blocks_on_rt_mutex() through
++ * rtlock_slowlock() and will then enqueue a second waiter for this
++ * same task and things get really confusing real fast.
++ */
++ rt_mutex_pre_schedule();
++
++ /*
+ * Technically we could use raw_spin_[un]lock_irq() here, but this can
+ * be called in early boot if the cmpxchg() fast path is disabled
+ * (debug, no architecture support). In this case we will acquire the
+@@ -1767,6 +1776,7 @@ static int __sched rt_mutex_slowlock(str
+ raw_spin_lock_irqsave(&lock->wait_lock, flags);
+ ret = __rt_mutex_slowlock_locked(lock, ww_ctx, state);
+ raw_spin_unlock_irqrestore(&lock->wait_lock, flags);
++ rt_mutex_post_schedule();
+
+ return ret;
+ }
+--- a/kernel/locking/rwbase_rt.c
++++ b/kernel/locking/rwbase_rt.c
+@@ -71,6 +71,7 @@ static int __sched __rwbase_read_lock(st
+ struct rt_mutex_base *rtm = &rwb->rtmutex;
+ int ret;
+
++ rwbase_pre_schedule();
+ raw_spin_lock_irq(&rtm->wait_lock);
+
+ /*
+@@ -125,6 +126,7 @@ static int __sched __rwbase_read_lock(st
+ rwbase_rtmutex_unlock(rtm);
+
+ trace_contention_end(rwb, ret);
++ rwbase_post_schedule();
+ return ret;
+ }
+
+@@ -237,6 +239,8 @@ static int __sched rwbase_write_lock(str
+ /* Force readers into slow path */
+ atomic_sub(READER_BIAS, &rwb->readers);
+
++ rwbase_pre_schedule();
++
+ raw_spin_lock_irqsave(&rtm->wait_lock, flags);
+ if (__rwbase_write_trylock(rwb))
+ goto out_unlock;
+@@ -248,6 +252,7 @@ static int __sched rwbase_write_lock(str
+ if (rwbase_signal_pending_state(state, current)) {
+ rwbase_restore_current_state();
+ __rwbase_write_unlock(rwb, 0, flags);
++ rwbase_post_schedule();
+ trace_contention_end(rwb, -EINTR);
+ return -EINTR;
+ }
+@@ -266,6 +271,7 @@ static int __sched rwbase_write_lock(str
+
+ out_unlock:
+ raw_spin_unlock_irqrestore(&rtm->wait_lock, flags);
++ rwbase_post_schedule();
+ return 0;
+ }
+
+--- a/kernel/locking/rwsem.c
++++ b/kernel/locking/rwsem.c
+@@ -1427,8 +1427,14 @@ static inline void __downgrade_write(str
+ #define rwbase_signal_pending_state(state, current) \
+ signal_pending_state(state, current)
+
++#define rwbase_pre_schedule() \
++ rt_mutex_pre_schedule()
++
+ #define rwbase_schedule() \
+- schedule()
++ rt_mutex_schedule()
++
++#define rwbase_post_schedule() \
++ rt_mutex_post_schedule()
+
+ #include "rwbase_rt.c"
+
+--- a/kernel/locking/spinlock_rt.c
++++ b/kernel/locking/spinlock_rt.c
+@@ -184,9 +184,13 @@ static __always_inline int rwbase_rtmut
+
+ #define rwbase_signal_pending_state(state, current) (0)
+
++#define rwbase_pre_schedule()
++
+ #define rwbase_schedule() \
+ schedule_rtlock()
+
++#define rwbase_post_schedule()
++
+ #include "rwbase_rt.c"
+ /*
+ * The common functions which get wrapped into the rwlock API.
diff --git a/debian/patches-rt/0005-serial-8250_bcm7271-Use-port-lock-wrappers.patch b/debian/patches-rt/0005-serial-8250_bcm7271-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..55ae035b80
--- /dev/null
+++ b/debian/patches-rt/0005-serial-8250_bcm7271-Use-port-lock-wrappers.patch
@@ -0,0 +1,151 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:22 +0206
+Subject: [PATCH 005/134] serial: 8250_bcm7271: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-6-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_bcm7271.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_bcm7271.c
++++ b/drivers/tty/serial/8250/8250_bcm7271.c
+@@ -567,7 +567,7 @@ static irqreturn_t brcmuart_isr(int irq,
+ if (interrupts == 0)
+ return IRQ_NONE;
+
+- spin_lock_irqsave(&up->lock, flags);
++ uart_port_lock_irqsave(up, &flags);
+
+ /* Clear all interrupts */
+ udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_CLEAR, interrupts);
+@@ -581,7 +581,7 @@ static irqreturn_t brcmuart_isr(int irq,
+ if ((rval | tval) == 0)
+ dev_warn(dev, "Spurious interrupt: 0x%x\n", interrupts);
+
+- spin_unlock_irqrestore(&up->lock, flags);
++ uart_port_unlock_irqrestore(up, flags);
+ return IRQ_HANDLED;
+ }
+
+@@ -608,10 +608,10 @@ static int brcmuart_startup(struct uart_
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ up->ier &= ~UART_IER_RDI;
+ serial_port_out(port, UART_IER, up->ier);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+
+ priv->tx_running = false;
+ priv->dma.rx_dma = NULL;
+@@ -629,7 +629,7 @@ static void brcmuart_shutdown(struct uar
+ struct brcmuart_priv *priv = up->port.private_data;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ priv->shutdown = true;
+ if (priv->dma_enabled) {
+ stop_rx_dma(up);
+@@ -645,7 +645,7 @@ static void brcmuart_shutdown(struct uar
+ */
+ up->dma = NULL;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ serial8250_do_shutdown(port);
+ }
+
+@@ -788,7 +788,7 @@ static int brcmuart_handle_irq(struct ua
+ * interrupt but there is no data ready.
+ */
+ if (((iir & UART_IIR_ID) == UART_IIR_RX_TIMEOUT) && !(priv->shutdown)) {
+- spin_lock_irqsave(&p->lock, flags);
++ uart_port_lock_irqsave(p, &flags);
+ status = serial_port_in(p, UART_LSR);
+ if ((status & UART_LSR_DR) == 0) {
+
+@@ -813,7 +813,7 @@ static int brcmuart_handle_irq(struct ua
+
+ handled = 1;
+ }
+- spin_unlock_irqrestore(&p->lock, flags);
++ uart_port_unlock_irqrestore(p, flags);
+ if (handled)
+ return 1;
+ }
+@@ -831,7 +831,7 @@ static enum hrtimer_restart brcmuart_hrt
+ if (priv->shutdown)
+ return HRTIMER_NORESTART;
+
+- spin_lock_irqsave(&p->lock, flags);
++ uart_port_lock_irqsave(p, &flags);
+ status = serial_port_in(p, UART_LSR);
+
+ /*
+@@ -855,7 +855,7 @@ static enum hrtimer_restart brcmuart_hrt
+ status |= UART_MCR_RTS;
+ serial_port_out(p, UART_MCR, status);
+ }
+- spin_unlock_irqrestore(&p->lock, flags);
++ uart_port_unlock_irqrestore(p, flags);
+ return HRTIMER_NORESTART;
+ }
+
+@@ -1154,10 +1154,10 @@ static int __maybe_unused brcmuart_suspe
+ * This will prevent resume from enabling RTS before the
+ * baud rate has been restored.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ priv->saved_mctrl = port->mctrl;
+ port->mctrl &= ~TIOCM_RTS;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ serial8250_suspend_port(priv->line);
+ clk_disable_unprepare(priv->baud_mux_clk);
+@@ -1196,10 +1196,10 @@ static int __maybe_unused brcmuart_resum
+
+ if (priv->saved_mctrl & TIOCM_RTS) {
+ /* Restore RTS */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ port->mctrl |= TIOCM_RTS;
+ port->ops->set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ return 0;
diff --git a/debian/patches-rt/0006-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch b/debian/patches-rt/0006-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch
new file mode 100644
index 0000000000..f29f29bdfe
--- /dev/null
+++ b/debian/patches-rt/0006-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch
@@ -0,0 +1,45 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 6 Dec 2018 09:52:20 +0100
+Subject: [PATCH 06/10] drm/i915: Disable tracing points on PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Luca Abeni reported this:
+| BUG: scheduling while atomic: kworker/u8:2/15203/0x00000003
+| CPU: 1 PID: 15203 Comm: kworker/u8:2 Not tainted 4.19.1-rt3 #10
+| Call Trace:
+| rt_spin_lock+0x3f/0x50
+| gen6_read32+0x45/0x1d0 [i915]
+| g4x_get_vblank_counter+0x36/0x40 [i915]
+| trace_event_raw_event_i915_pipe_update_start+0x7d/0xf0 [i915]
+
+The tracing events use trace_i915_pipe_update_start() among other events
+use functions acquire spinlock_t locks which are transformed into
+sleeping locks on PREEMPT_RT. A few trace points use
+intel_get_crtc_scanline(), others use ->get_vblank_counter() wich also
+might acquire a sleeping locks on PREEMPT_RT.
+At the time the arguments are evaluated within trace point, preemption
+is disabled and so the locks must not be acquired on PREEMPT_RT.
+
+Based on this I don't see any other way than disable trace points on
+PREMPT_RT.
+
+Reported-by: Luca Abeni <lucabe72@gmail.com>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/i915_trace.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/i915/i915_trace.h
++++ b/drivers/gpu/drm/i915/i915_trace.h
+@@ -6,6 +6,10 @@
+ #if !defined(_I915_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+ #define _I915_TRACE_H_
+
++#ifdef CONFIG_PREEMPT_RT
++#define NOTRACE
++#endif
++
+ #include <linux/stringify.h>
+ #include <linux/types.h>
+ #include <linux/tracepoint.h>
diff --git a/debian/patches-rt/0006-locking-rtmutex-Add-a-lockdep-assert-to-catch-potent.patch b/debian/patches-rt/0006-locking-rtmutex-Add-a-lockdep-assert-to-catch-potent.patch
new file mode 100644
index 0000000000..7d94cdb9de
--- /dev/null
+++ b/debian/patches-rt/0006-locking-rtmutex-Add-a-lockdep-assert-to-catch-potent.patch
@@ -0,0 +1,57 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 8 Sep 2023 18:22:53 +0200
+Subject: [PATCH 6/7] locking/rtmutex: Add a lockdep assert to catch potential
+ nested blocking
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+There used to be a BUG_ON(current->pi_blocked_on) in the lock acquisition
+functions, but that vanished in one of the rtmutex overhauls.
+
+Bring it back in form of a lockdep assert to catch code paths which take
+rtmutex based locks with current::pi_blocked_on != NULL.
+
+Reported-by: Crystal Wood <swood@redhat.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: "Peter Zijlstra (Intel)" <peterz@infradead.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20230908162254.999499-7-bigeasy@linutronix.de
+---
+ kernel/locking/rtmutex.c | 2 ++
+ kernel/locking/rwbase_rt.c | 2 ++
+ kernel/locking/spinlock_rt.c | 2 ++
+ 3 files changed, 6 insertions(+)
+
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -1784,6 +1784,8 @@ static int __sched rt_mutex_slowlock(str
+ static __always_inline int __rt_mutex_lock(struct rt_mutex_base *lock,
+ unsigned int state)
+ {
++ lockdep_assert(!current->pi_blocked_on);
++
+ if (likely(rt_mutex_try_acquire(lock)))
+ return 0;
+
+--- a/kernel/locking/rwbase_rt.c
++++ b/kernel/locking/rwbase_rt.c
+@@ -133,6 +133,8 @@ static int __sched __rwbase_read_lock(st
+ static __always_inline int rwbase_read_lock(struct rwbase_rt *rwb,
+ unsigned int state)
+ {
++ lockdep_assert(!current->pi_blocked_on);
++
+ if (rwbase_read_trylock(rwb))
+ return 0;
+
+--- a/kernel/locking/spinlock_rt.c
++++ b/kernel/locking/spinlock_rt.c
+@@ -37,6 +37,8 @@
+
+ static __always_inline void rtlock_lock(struct rt_mutex_base *rtm)
+ {
++ lockdep_assert(!current->pi_blocked_on);
++
+ if (unlikely(!rt_mutex_cmpxchg_acquire(rtm, NULL, current)))
+ rtlock_slowlock(rtm);
+ }
diff --git a/debian/patches-rt/0006-serial-8250-Use-port-lock-wrappers.patch b/debian/patches-rt/0006-serial-8250-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..d6ee818bf9
--- /dev/null
+++ b/debian/patches-rt/0006-serial-8250-Use-port-lock-wrappers.patch
@@ -0,0 +1,465 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:23 +0206
+Subject: [PATCH 006/134] serial: 8250: Use port lock wrappers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-7-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_core.c | 12 ++--
+ drivers/tty/serial/8250/8250_port.c | 100 ++++++++++++++++++------------------
+ 2 files changed, 56 insertions(+), 56 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -259,7 +259,7 @@ static void serial8250_backup_timeout(st
+ unsigned int iir, ier = 0, lsr;
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * Must disable interrupts or else we risk racing with the interrupt
+@@ -292,7 +292,7 @@ static void serial8250_backup_timeout(st
+ if (up->port.irq)
+ serial_out(up, UART_IER, ier);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ /* Standard timer interval plus 0.2s to keep the port running */
+ mod_timer(&up->timer,
+@@ -992,11 +992,11 @@ static void serial_8250_overrun_backoff_
+ struct uart_port *port = &up->port;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ up->port.read_status_mask |= UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /**
+@@ -1194,9 +1194,9 @@ void serial8250_unregister_port(int line
+ if (uart->em485) {
+ unsigned long flags;
+
+- spin_lock_irqsave(&uart->port.lock, flags);
++ uart_port_lock_irqsave(&uart->port, &flags);
+ serial8250_em485_destroy(uart);
+- spin_unlock_irqrestore(&uart->port.lock, flags);
++ uart_port_unlock_irqrestore(&uart->port, flags);
+ }
+
+ uart_remove_one_port(&serial8250_reg, &uart->port);
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -689,7 +689,7 @@ static void serial8250_set_sleep(struct
+
+ if (p->capabilities & UART_CAP_SLEEP) {
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&p->port.lock);
++ uart_port_lock_irq(&p->port);
+ if (p->capabilities & UART_CAP_EFR) {
+ lcr = serial_in(p, UART_LCR);
+ efr = serial_in(p, UART_EFR);
+@@ -703,7 +703,7 @@ static void serial8250_set_sleep(struct
+ serial_out(p, UART_EFR, efr);
+ serial_out(p, UART_LCR, lcr);
+ }
+- spin_unlock_irq(&p->port.lock);
++ uart_port_unlock_irq(&p->port);
+ }
+
+ serial8250_rpm_put(p);
+@@ -746,9 +746,9 @@ static void enable_rsa(struct uart_8250_
+ {
+ if (up->port.type == PORT_RSA) {
+ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
+- spin_lock_irq(&up->port.lock);
++ uart_port_lock_irq(&up->port);
+ __enable_rsa(up);
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ }
+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+ serial_out(up, UART_RSA_FRR, 0);
+@@ -768,7 +768,7 @@ static void disable_rsa(struct uart_8250
+
+ if (up->port.type == PORT_RSA &&
+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+- spin_lock_irq(&up->port.lock);
++ uart_port_lock_irq(&up->port);
+
+ mode = serial_in(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+@@ -781,7 +781,7 @@ static void disable_rsa(struct uart_8250
+
+ if (result)
+ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ }
+ }
+ #endif /* CONFIG_SERIAL_8250_RSA */
+@@ -1172,7 +1172,7 @@ static void autoconfig(struct uart_8250_
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ up->capabilities = 0;
+ up->bugs = 0;
+@@ -1211,7 +1211,7 @@ static void autoconfig(struct uart_8250_
+ /*
+ * We failed; there's nothing here
+ */
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
+ scratch2, scratch3);
+ goto out;
+@@ -1235,7 +1235,7 @@ static void autoconfig(struct uart_8250_
+ status1 = serial_in(up, UART_MSR) & UART_MSR_STATUS_BITS;
+ serial8250_out_MCR(up, save_mcr);
+ if (status1 != (UART_MSR_DCD | UART_MSR_CTS)) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+ status1);
+ goto out;
+@@ -1304,7 +1304,7 @@ static void autoconfig(struct uart_8250_
+ serial8250_clear_IER(up);
+
+ out_unlock:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /*
+ * Check if the device is a Fintek F81216A
+@@ -1344,9 +1344,9 @@ static void autoconfig_irq(struct uart_8
+ probe_irq_off(probe_irq_on());
+ save_mcr = serial8250_in_MCR(up);
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ save_ier = serial_in(up, UART_IER);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+ irqs = probe_irq_on();
+@@ -1359,9 +1359,9 @@ static void autoconfig_irq(struct uart_8
+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+ }
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ serial_out(up, UART_IER, UART_IER_ALL_INTR);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ serial_in(up, UART_LSR);
+ serial_in(up, UART_RX);
+ serial_in(up, UART_IIR);
+@@ -1372,9 +1372,9 @@ static void autoconfig_irq(struct uart_8
+
+ serial8250_out_MCR(up, save_mcr);
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ serial_out(up, UART_IER, save_ier);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+
+ if (port->flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+@@ -1442,13 +1442,13 @@ static enum hrtimer_restart serial8250_e
+ unsigned long flags;
+
+ serial8250_rpm_get(p);
+- spin_lock_irqsave(&p->port.lock, flags);
++ uart_port_lock_irqsave(&p->port, &flags);
+ if (em485->active_timer == &em485->stop_tx_timer) {
+ p->rs485_stop_tx(p);
+ em485->active_timer = NULL;
+ em485->tx_stopped = true;
+ }
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+ serial8250_rpm_put(p);
+
+ return HRTIMER_NORESTART;
+@@ -1630,12 +1630,12 @@ static enum hrtimer_restart serial8250_e
+ struct uart_8250_port *p = em485->port;
+ unsigned long flags;
+
+- spin_lock_irqsave(&p->port.lock, flags);
++ uart_port_lock_irqsave(&p->port, &flags);
+ if (em485->active_timer == &em485->start_tx_timer) {
+ __start_tx(&p->port);
+ em485->active_timer = NULL;
+ }
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+
+ return HRTIMER_NORESTART;
+ }
+@@ -1918,7 +1918,7 @@ int serial8250_handle_irq(struct uart_po
+ if (iir & UART_IIR_NO_INT)
+ return 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ status = serial_lsr_in(up);
+
+@@ -1988,9 +1988,9 @@ static int serial8250_tx_threshold_handl
+ if ((iir & UART_IIR_ID) == UART_IIR_THRI) {
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ serial8250_tx_chars(up);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ iir = serial_port_in(port, UART_IIR);
+@@ -2005,10 +2005,10 @@ static unsigned int serial8250_tx_empty(
+
+ serial8250_rpm_get(up);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (!serial8250_tx_dma_running(up) && uart_lsr_tx_empty(serial_lsr_in(up)))
+ result = TIOCSER_TEMT;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ serial8250_rpm_put(up);
+
+@@ -2070,13 +2070,13 @@ static void serial8250_break_ctl(struct
+ unsigned long flags;
+
+ serial8250_rpm_get(up);
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_port_out(port, UART_LCR, up->lcr);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ serial8250_rpm_put(up);
+ }
+
+@@ -2211,7 +2211,7 @@ int serial8250_do_startup(struct uart_po
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ up->acr = 0;
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_port_out(port, UART_EFR, UART_EFR_ECB);
+@@ -2221,7 +2221,7 @@ int serial8250_do_startup(struct uart_po
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_port_out(port, UART_EFR, UART_EFR_ECB);
+ serial_port_out(port, UART_LCR, 0);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ if (port->type == PORT_DA830) {
+@@ -2230,10 +2230,10 @@ int serial8250_do_startup(struct uart_po
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ serial_port_out(port, UART_IER, 0);
+ serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ mdelay(10);
+
+ /* Enable Tx, Rx and free run mode */
+@@ -2347,7 +2347,7 @@ int serial8250_do_startup(struct uart_po
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+@@ -2359,7 +2359,7 @@ int serial8250_do_startup(struct uart_po
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (port->irqflags & IRQF_SHARED)
+ enable_irq(port->irq);
+@@ -2382,7 +2382,7 @@ int serial8250_do_startup(struct uart_po
+ */
+ serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ if (!up->port.irq)
+ up->port.mctrl |= TIOCM_OUT1;
+@@ -2428,7 +2428,7 @@ int serial8250_do_startup(struct uart_po
+ }
+
+ dont_test_tx_en:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /*
+ * Clear the interrupt registers again for luck, and clear the
+@@ -2499,17 +2499,17 @@ void serial8250_do_shutdown(struct uart_
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ up->ier = 0;
+ serial_port_out(port, UART_IER, 0);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ synchronize_irq(port->irq);
+
+ if (up->dma)
+ serial8250_release_dma(up);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (port->flags & UPF_FOURPORT) {
+ /* reset interrupts on the AST Fourport board */
+ inb((port->iobase & 0xfe0) | 0x1f);
+@@ -2518,7 +2518,7 @@ void serial8250_do_shutdown(struct uart_
+ port->mctrl &= ~TIOCM_OUT2;
+
+ serial8250_set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /*
+ * Disable break condition and FIFOs
+@@ -2754,14 +2754,14 @@ void serial8250_update_uartclk(struct ua
+ quot = serial8250_get_divisor(port, baud, &frac);
+
+ serial8250_rpm_get(up);
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ serial8250_set_divisor(port, baud, quot, frac);
+ serial_port_out(port, UART_LCR, up->lcr);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ serial8250_rpm_put(up);
+
+ out_unlock:
+@@ -2798,7 +2798,7 @@ serial8250_do_set_termios(struct uart_po
+ * Synchronize UART_IER access against the console.
+ */
+ serial8250_rpm_get(up);
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ up->lcr = cval; /* Save computed LCR */
+
+@@ -2901,7 +2901,7 @@ serial8250_do_set_termios(struct uart_po
+ serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
+ }
+ serial8250_set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ serial8250_rpm_put(up);
+
+ /* Don't rewrite B0 */
+@@ -2924,15 +2924,15 @@ void serial8250_do_set_ldisc(struct uart
+ {
+ if (termios->c_line == N_PPS) {
+ port->flags |= UPF_HARDPPS_CD;
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ serial8250_enable_ms(port);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ } else {
+ port->flags &= ~UPF_HARDPPS_CD;
+ if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ serial8250_disable_ms(port);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ }
+ }
+ }
+@@ -3406,9 +3406,9 @@ void serial8250_console_write(struct uar
+ touch_nmi_watchdog();
+
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -3478,7 +3478,7 @@ void serial8250_console_write(struct uar
+ serial8250_modem_status(up);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static unsigned int probe_baud(struct uart_port *port)
diff --git a/debian/patches-rt/0007-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch b/debian/patches-rt/0007-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch
new file mode 100644
index 0000000000..d784f90a94
--- /dev/null
+++ b/debian/patches-rt/0007-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch
@@ -0,0 +1,29 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 19 Dec 2018 10:47:02 +0100
+Subject: [PATCH 07/10] drm/i915: skip DRM_I915_LOW_LEVEL_TRACEPOINTS with
+ NOTRACE
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The order of the header files is important. If this header file is
+included after tracepoint.h was included then the NOTRACE here becomes a
+nop. Currently this happens for two .c files which use the tracepoitns
+behind DRM_I915_LOW_LEVEL_TRACEPOINTS.
+
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ drivers/gpu/drm/i915/i915_trace.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_trace.h
++++ b/drivers/gpu/drm/i915/i915_trace.h
+@@ -326,7 +326,7 @@ DEFINE_EVENT(i915_request, i915_request_
+ TP_ARGS(rq)
+ );
+
+-#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS)
++#if defined(CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS) && !defined(NOTRACE)
+ DEFINE_EVENT(i915_request, i915_request_guc_submit,
+ TP_PROTO(struct i915_request *rq),
+ TP_ARGS(rq)
diff --git a/debian/patches-rt/0007-futex-pi-Fix-recursive-rt_mutex-waiter-state.patch b/debian/patches-rt/0007-futex-pi-Fix-recursive-rt_mutex-waiter-state.patch
new file mode 100644
index 0000000000..76a9b60581
--- /dev/null
+++ b/debian/patches-rt/0007-futex-pi-Fix-recursive-rt_mutex-waiter-state.patch
@@ -0,0 +1,198 @@
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Fri, 15 Sep 2023 17:19:44 +0200
+Subject: [PATCH 7/7] futex/pi: Fix recursive rt_mutex waiter state
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Some new assertions pointed out that the existing code has nested rt_mutex wait
+state in the futex code.
+
+Specifically, the futex_lock_pi() cancel case uses spin_lock() while there
+still is a rt_waiter enqueued for this task, resulting in a state where there
+are two waiters for the same task (and task_struct::pi_blocked_on gets
+scrambled).
+
+The reason to take hb->lock at this point is to avoid the wake_futex_pi()
+EAGAIN case.
+
+This happens when futex_top_waiter() and rt_mutex_top_waiter() state becomes
+inconsistent. The current rules are such that this inconsistency will not be
+observed.
+
+Notably the case that needs to be avoided is where futex_lock_pi() and
+futex_unlock_pi() interleave such that unlock will fail to observe a new
+waiter.
+
+*However* the case at hand is where a waiter is leaving, in this case the race
+means a waiter that is going away is not observed -- which is harmless,
+provided this race is explicitly handled.
+
+This is a somewhat dangerous proposition because the converse race is not
+observing a new waiter, which must absolutely not happen. But since the race is
+valid this cannot be asserted.
+
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lkml.kernel.org/r/20230915151943.GD6743@noisy.programming.kicks-ass.net
+---
+ kernel/futex/pi.c | 76 ++++++++++++++++++++++++++++++-------------------
+ kernel/futex/requeue.c | 6 ++-
+ 2 files changed, 52 insertions(+), 30 deletions(-)
+
+--- a/kernel/futex/pi.c
++++ b/kernel/futex/pi.c
+@@ -611,29 +611,16 @@ int futex_lock_pi_atomic(u32 __user *uad
+ /*
+ * Caller must hold a reference on @pi_state.
+ */
+-static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state)
++static int wake_futex_pi(u32 __user *uaddr, u32 uval,
++ struct futex_pi_state *pi_state,
++ struct rt_mutex_waiter *top_waiter)
+ {
+- struct rt_mutex_waiter *top_waiter;
+ struct task_struct *new_owner;
+ bool postunlock = false;
+ DEFINE_RT_WAKE_Q(wqh);
+ u32 curval, newval;
+ int ret = 0;
+
+- top_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex);
+- if (WARN_ON_ONCE(!top_waiter)) {
+- /*
+- * As per the comment in futex_unlock_pi() this should not happen.
+- *
+- * When this happens, give up our locks and try again, giving
+- * the futex_lock_pi() instance time to complete, either by
+- * waiting on the rtmutex or removing itself from the futex
+- * queue.
+- */
+- ret = -EAGAIN;
+- goto out_unlock;
+- }
+-
+ new_owner = top_waiter->task;
+
+ /*
+@@ -1046,20 +1033,34 @@ int futex_lock_pi(u32 __user *uaddr, uns
+ ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
+
+ cleanup:
+- spin_lock(q.lock_ptr);
+ /*
+ * If we failed to acquire the lock (deadlock/signal/timeout), we must
+- * first acquire the hb->lock before removing the lock from the
+- * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
+- * lists consistent.
++ * must unwind the above, however we canont lock hb->lock because
++ * rt_mutex already has a waiter enqueued and hb->lock can itself try
++ * and enqueue an rt_waiter through rtlock.
++ *
++ * Doing the cleanup without holding hb->lock can cause inconsistent
++ * state between hb and pi_state, but only in the direction of not
++ * seeing a waiter that is leaving.
++ *
++ * See futex_unlock_pi(), it deals with this inconsistency.
++ *
++ * There be dragons here, since we must deal with the inconsistency on
++ * the way out (here), it is impossible to detect/warn about the race
++ * the other way around (missing an incoming waiter).
+ *
+- * In particular; it is important that futex_unlock_pi() can not
+- * observe this inconsistency.
++ * What could possibly go wrong...
+ */
+ if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter))
+ ret = 0;
+
+ /*
++ * Now that the rt_waiter has been dequeued, it is safe to use
++ * spinlock/rtlock (which might enqueue its own rt_waiter) and fix up
++ * the
++ */
++ spin_lock(q.lock_ptr);
++ /*
+ * Waiter is unqueued.
+ */
+ rt_mutex_post_schedule();
+@@ -1143,6 +1144,7 @@ int futex_unlock_pi(u32 __user *uaddr, u
+ top_waiter = futex_top_waiter(hb, &key);
+ if (top_waiter) {
+ struct futex_pi_state *pi_state = top_waiter->pi_state;
++ struct rt_mutex_waiter *rt_waiter;
+
+ ret = -EINVAL;
+ if (!pi_state)
+@@ -1155,22 +1157,39 @@ int futex_unlock_pi(u32 __user *uaddr, u
+ if (pi_state->owner != current)
+ goto out_unlock;
+
+- get_pi_state(pi_state);
+ /*
+ * By taking wait_lock while still holding hb->lock, we ensure
+- * there is no point where we hold neither; and therefore
+- * wake_futex_p() must observe a state consistent with what we
+- * observed.
++ * there is no point where we hold neither; and thereby
++ * wake_futex_pi() must observe any new waiters.
++ *
++ * Since the cleanup: case in futex_lock_pi() removes the
++ * rt_waiter without holding hb->lock, it is possible for
++ * wake_futex_pi() to not find a waiter while the above does,
++ * in this case the waiter is on the way out and it can be
++ * ignored.
+ *
+ * In particular; this forces __rt_mutex_start_proxy() to
+ * complete such that we're guaranteed to observe the
+- * rt_waiter. Also see the WARN in wake_futex_pi().
++ * rt_waiter.
+ */
+ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
++
++ /*
++ * Futex vs rt_mutex waiter state -- if there are no rt_mutex
++ * waiters even though futex thinks there are, then the waiter
++ * is leaving and the uncontended path is safe to take.
++ */
++ rt_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex);
++ if (!rt_waiter) {
++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
++ goto do_uncontended;
++ }
++
++ get_pi_state(pi_state);
+ spin_unlock(&hb->lock);
+
+ /* drops pi_state->pi_mutex.wait_lock */
+- ret = wake_futex_pi(uaddr, uval, pi_state);
++ ret = wake_futex_pi(uaddr, uval, pi_state, rt_waiter);
+
+ put_pi_state(pi_state);
+
+@@ -1198,6 +1217,7 @@ int futex_unlock_pi(u32 __user *uaddr, u
+ return ret;
+ }
+
++do_uncontended:
+ /*
+ * We have no kernel internal state, i.e. no waiters in the
+ * kernel. Waiters which are about to queue themselves are stuck
+--- a/kernel/futex/requeue.c
++++ b/kernel/futex/requeue.c
+@@ -850,11 +850,13 @@ int futex_wait_requeue_pi(u32 __user *ua
+ pi_mutex = &q.pi_state->pi_mutex;
+ ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter);
+
+- /* Current is not longer pi_blocked_on */
+- spin_lock(q.lock_ptr);
++ /*
++ * See futex_unlock_pi()'s cleanup: comment.
++ */
+ if (ret && !rt_mutex_cleanup_proxy_lock(pi_mutex, &rt_waiter))
+ ret = 0;
+
++ spin_lock(q.lock_ptr);
+ debug_rt_mutex_free_waiter(&rt_waiter);
+ /*
+ * Fixup the pi_state owner and possibly acquire the lock if we
diff --git a/debian/patches-rt/0007-serial-8250_dma-Use-port-lock-wrappers.patch b/debian/patches-rt/0007-serial-8250_dma-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..bc8686e892
--- /dev/null
+++ b/debian/patches-rt/0007-serial-8250_dma-Use-port-lock-wrappers.patch
@@ -0,0 +1,80 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:24 +0206
+Subject: [PATCH 007/134] serial: 8250_dma: Use port lock wrappers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-8-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_dma.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_dma.c
++++ b/drivers/tty/serial/8250/8250_dma.c
+@@ -22,7 +22,7 @@ static void __dma_tx_complete(void *para
+ dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+- spin_lock_irqsave(&p->port.lock, flags);
++ uart_port_lock_irqsave(&p->port, &flags);
+
+ dma->tx_running = 0;
+
+@@ -35,7 +35,7 @@ static void __dma_tx_complete(void *para
+ if (ret || !dma->tx_running)
+ serial8250_set_THRI(p);
+
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+ }
+
+ static void __dma_rx_complete(struct uart_8250_port *p)
+@@ -70,7 +70,7 @@ static void dma_rx_complete(void *param)
+ struct uart_8250_dma *dma = p->dma;
+ unsigned long flags;
+
+- spin_lock_irqsave(&p->port.lock, flags);
++ uart_port_lock_irqsave(&p->port, &flags);
+ if (dma->rx_running)
+ __dma_rx_complete(p);
+
+@@ -80,7 +80,7 @@ static void dma_rx_complete(void *param)
+ */
+ if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR))
+ p->dma->rx_dma(p);
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+ }
+
+ int serial8250_tx_dma(struct uart_8250_port *p)
diff --git a/debian/patches-rt/0008-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch b/debian/patches-rt/0008-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch
new file mode 100644
index 0000000000..0322ae1544
--- /dev/null
+++ b/debian/patches-rt/0008-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch
@@ -0,0 +1,42 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 8 Sep 2021 17:18:00 +0200
+Subject: [PATCH 08/10] drm/i915/gt: Queue and wait for the irq_work item.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Disabling interrupts and invoking the irq_work function directly breaks
+on PREEMPT_RT.
+PREEMPT_RT does not invoke all irq_work from hardirq context because
+some of the user have spinlock_t locking in the callback function.
+These locks are then turned into a sleeping locks which can not be
+acquired with disabled interrupts.
+
+Using irq_work_queue() has the benefit that the irqwork will be invoked
+in the regular context. In general there is "no" delay between enqueuing
+the callback and its invocation because the interrupt is raised right
+away on architectures which support it (which includes x86).
+
+Use irq_work_queue() + irq_work_sync() instead invoking the callback
+directly.
+
+Reported-by: Clark Williams <williams@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+---
+ drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
++++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+@@ -312,10 +312,9 @@ void __intel_breadcrumbs_park(struct int
+ /* Kick the work once more to drain the signalers, and disarm the irq */
+ irq_work_sync(&b->irq_work);
+ while (READ_ONCE(b->irq_armed) && !atomic_read(&b->active)) {
+- local_irq_disable();
+- signal_irq_work(&b->irq_work);
+- local_irq_enable();
++ irq_work_queue(&b->irq_work);
+ cond_resched();
++ irq_work_sync(&b->irq_work);
+ }
+ }
+
diff --git a/debian/patches-rt/0008-serial-8250_dw-Use-port-lock-wrappers.patch b/debian/patches-rt/0008-serial-8250_dw-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..d5394fc7a3
--- /dev/null
+++ b/debian/patches-rt/0008-serial-8250_dw-Use-port-lock-wrappers.patch
@@ -0,0 +1,69 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:25 +0206
+Subject: [PATCH 008/134] serial: 8250_dw: Use port lock wrappers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-9-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_dw.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -263,20 +263,20 @@ static int dw8250_handle_irq(struct uart
+ * so we limit the workaround only to non-DMA mode.
+ */
+ if (!up->dma && rx_timeout) {
+- spin_lock_irqsave(&p->lock, flags);
++ uart_port_lock_irqsave(p, &flags);
+ status = serial_lsr_in(up);
+
+ if (!(status & (UART_LSR_DR | UART_LSR_BI)))
+ (void) p->serial_in(p, UART_RX);
+
+- spin_unlock_irqrestore(&p->lock, flags);
++ uart_port_unlock_irqrestore(p, flags);
+ }
+
+ /* Manually stop the Rx DMA transfer when acting as flow controller */
+ if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
+- spin_lock_irqsave(&p->lock, flags);
++ uart_port_lock_irqsave(p, &flags);
+ status = serial_lsr_in(up);
+- spin_unlock_irqrestore(&p->lock, flags);
++ uart_port_unlock_irqrestore(p, flags);
+
+ if (status & (UART_LSR_DR | UART_LSR_BI)) {
+ dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
diff --git a/debian/patches-rt/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch b/debian/patches-rt/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
new file mode 100644
index 0000000000..3245e145f0
--- /dev/null
+++ b/debian/patches-rt/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
@@ -0,0 +1,89 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 8 Sep 2021 19:03:41 +0200
+Subject: [PATCH 09/10] drm/i915/gt: Use spin_lock_irq() instead of
+ local_irq_disable() + spin_lock()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+execlists_dequeue() is invoked from a function which uses
+local_irq_disable() to disable interrupts so the spin_lock() behaves
+like spin_lock_irq().
+This breaks PREEMPT_RT because local_irq_disable() + spin_lock() is not
+the same as spin_lock_irq().
+
+execlists_dequeue_irq() and execlists_dequeue() has each one caller
+only. If intel_engine_cs::active::lock is acquired and released with the
+_irq suffix then it behaves almost as if execlists_dequeue() would be
+invoked with disabled interrupts. The difference is the last part of the
+function which is then invoked with enabled interrupts.
+I can't tell if this makes a difference. From looking at it, it might
+work to move the last unlock at the end of the function as I didn't find
+anything that would acquire the lock again.
+
+Reported-by: Clark Williams <williams@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+---
+ drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+@@ -1303,7 +1303,7 @@ static void execlists_dequeue(struct int
+ * and context switches) submission.
+ */
+
+- spin_lock(&sched_engine->lock);
++ spin_lock_irq(&sched_engine->lock);
+
+ /*
+ * If the queue is higher priority than the last
+@@ -1403,7 +1403,7 @@ static void execlists_dequeue(struct int
+ * Even if ELSP[1] is occupied and not worthy
+ * of timeslices, our queue might be.
+ */
+- spin_unlock(&sched_engine->lock);
++ spin_unlock_irq(&sched_engine->lock);
+ return;
+ }
+ }
+@@ -1429,7 +1429,7 @@ static void execlists_dequeue(struct int
+
+ if (last && !can_merge_rq(last, rq)) {
+ spin_unlock(&ve->base.sched_engine->lock);
+- spin_unlock(&engine->sched_engine->lock);
++ spin_unlock_irq(&engine->sched_engine->lock);
+ return; /* leave this for another sibling */
+ }
+
+@@ -1591,7 +1591,7 @@ static void execlists_dequeue(struct int
+ */
+ sched_engine->queue_priority_hint = queue_prio(sched_engine);
+ i915_sched_engine_reset_on_empty(sched_engine);
+- spin_unlock(&sched_engine->lock);
++ spin_unlock_irq(&sched_engine->lock);
+
+ /*
+ * We can skip poking the HW if we ended up with exactly the same set
+@@ -1617,13 +1617,6 @@ static void execlists_dequeue(struct int
+ }
+ }
+
+-static void execlists_dequeue_irq(struct intel_engine_cs *engine)
+-{
+- local_irq_disable(); /* Suspend interrupts across request submission */
+- execlists_dequeue(engine);
+- local_irq_enable(); /* flush irq_work (e.g. breadcrumb enabling) */
+-}
+-
+ static void clear_ports(struct i915_request **ports, int count)
+ {
+ memset_p((void **)ports, NULL, count);
+@@ -2478,7 +2471,7 @@ static void execlists_submission_tasklet
+ }
+
+ if (!engine->execlists.pending[0]) {
+- execlists_dequeue_irq(engine);
++ execlists_dequeue(engine);
+ start_timeslice(engine);
+ }
+
diff --git a/debian/patches-rt/0009-serial-8250_exar-Use-port-lock-wrappers.patch b/debian/patches-rt/0009-serial-8250_exar-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..80c37fba6c
--- /dev/null
+++ b/debian/patches-rt/0009-serial-8250_exar-Use-port-lock-wrappers.patch
@@ -0,0 +1,52 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:26 +0206
+Subject: [PATCH 009/134] serial: 8250_exar: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-10-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_exar.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_exar.c
++++ b/drivers/tty/serial/8250/8250_exar.c
+@@ -201,9 +201,9 @@ static int xr17v35x_startup(struct uart_
+ *
+ * Synchronize UART_IER access against the console.
+ */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ serial_port_out(port, UART_IER, 0);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+
+ return serial8250_do_startup(port);
+ }
diff --git a/debian/patches-rt/0010-drm-i915-Drop-the-irqs_disabled-check.patch b/debian/patches-rt/0010-drm-i915-Drop-the-irqs_disabled-check.patch
new file mode 100644
index 0000000000..83a516ce8b
--- /dev/null
+++ b/debian/patches-rt/0010-drm-i915-Drop-the-irqs_disabled-check.patch
@@ -0,0 +1,39 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 1 Oct 2021 20:01:03 +0200
+Subject: [PATCH 10/10] drm/i915: Drop the irqs_disabled() check
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The !irqs_disabled() check triggers on PREEMPT_RT even with
+i915_sched_engine::lock acquired. The reason is the lock is transformed
+into a sleeping lock on PREEMPT_RT and does not disable interrupts.
+
+There is no need to check for disabled interrupts. The lockdep
+annotation below already check if the lock has been acquired by the
+caller and will yell if the interrupts are not disabled.
+
+Remove the !irqs_disabled() check.
+
+Reported-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/i915_request.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_request.c
++++ b/drivers/gpu/drm/i915/i915_request.c
+@@ -609,7 +609,6 @@ bool __i915_request_submit(struct i915_r
+
+ RQ_TRACE(request, "\n");
+
+- GEM_BUG_ON(!irqs_disabled());
+ lockdep_assert_held(&engine->sched_engine->lock);
+
+ /*
+@@ -718,7 +717,6 @@ void __i915_request_unsubmit(struct i915
+ */
+ RQ_TRACE(request, "\n");
+
+- GEM_BUG_ON(!irqs_disabled());
+ lockdep_assert_held(&engine->sched_engine->lock);
+
+ /*
diff --git a/debian/patches-rt/0010-serial-8250_fsl-Use-port-lock-wrappers.patch b/debian/patches-rt/0010-serial-8250_fsl-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..abe7c81a98
--- /dev/null
+++ b/debian/patches-rt/0010-serial-8250_fsl-Use-port-lock-wrappers.patch
@@ -0,0 +1,63 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:27 +0206
+Subject: [PATCH 010/134] serial: 8250_fsl: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-11-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_fsl.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_fsl.c
++++ b/drivers/tty/serial/8250/8250_fsl.c
+@@ -30,11 +30,11 @@ int fsl8250_handle_irq(struct uart_port
+ unsigned int iir;
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ iir = port->serial_in(port, UART_IIR);
+ if (iir & UART_IIR_NO_INT) {
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ return 0;
+ }
+
+@@ -54,7 +54,7 @@ int fsl8250_handle_irq(struct uart_port
+ if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) {
+ up->lsr_saved_flags &= ~UART_LSR_BI;
+ port->serial_in(port, UART_RX);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ return 1;
+ }
+
diff --git a/debian/patches-rt/0011-serial-8250_mtk-Use-port-lock-wrappers.patch b/debian/patches-rt/0011-serial-8250_mtk-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..a668182042
--- /dev/null
+++ b/debian/patches-rt/0011-serial-8250_mtk-Use-port-lock-wrappers.patch
@@ -0,0 +1,77 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:28 +0206
+Subject: [PATCH 011/134] serial: 8250_mtk: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Chen-Yu Tsai <wenst@chromium.org>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-12-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_mtk.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_mtk.c
++++ b/drivers/tty/serial/8250/8250_mtk.c
+@@ -102,7 +102,7 @@ static void mtk8250_dma_rx_complete(void
+ if (data->rx_status == DMA_RX_SHUTDOWN)
+ return;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
+ total = dma->rx_size - state.residue;
+@@ -128,7 +128,7 @@ static void mtk8250_dma_rx_complete(void
+
+ mtk8250_rx_dma(up);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static void mtk8250_rx_dma(struct uart_8250_port *up)
+@@ -368,7 +368,7 @@ mtk8250_set_termios(struct uart_port *po
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -416,7 +416,7 @@ mtk8250_set_termios(struct uart_port *po
+ if (uart_console(port))
+ up->port.cons->cflag = termios->c_cflag;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
diff --git a/debian/patches-rt/0012-serial-8250_omap-Use-port-lock-wrappers.patch b/debian/patches-rt/0012-serial-8250_omap-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..10ebd70ea0
--- /dev/null
+++ b/debian/patches-rt/0012-serial-8250_omap-Use-port-lock-wrappers.patch
@@ -0,0 +1,236 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:29 +0206
+Subject: [PATCH 012/134] serial: 8250_omap: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-13-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_omap.c | 52 ++++++++++++++++++------------------
+ 1 file changed, 26 insertions(+), 26 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_omap.c
++++ b/drivers/tty/serial/8250/8250_omap.c
+@@ -401,7 +401,7 @@ static void omap_8250_set_termios(struct
+ * interrupts disabled.
+ */
+ pm_runtime_get_sync(port->dev);
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+
+ /*
+ * Update the per-port timeout.
+@@ -504,7 +504,7 @@ static void omap_8250_set_termios(struct
+ }
+ omap8250_restore_regs(up);
+
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+
+@@ -529,7 +529,7 @@ static void omap_8250_pm(struct uart_por
+ pm_runtime_get_sync(port->dev);
+
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ efr = serial_in(up, UART_EFR);
+@@ -541,7 +541,7 @@ static void omap_8250_pm(struct uart_por
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, 0);
+
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+@@ -660,7 +660,7 @@ static irqreturn_t omap8250_irq(int irq,
+ unsigned long delay;
+
+ /* Synchronize UART_IER access against the console. */
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ up->ier = port->serial_in(port, UART_IER);
+ if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
+ port->ops->stop_rx(port);
+@@ -670,7 +670,7 @@ static irqreturn_t omap8250_irq(int irq,
+ */
+ cancel_delayed_work(&up->overrun_backoff);
+ }
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ delay = msecs_to_jiffies(up->overrun_backoff_time_ms);
+ schedule_delayed_work(&up->overrun_backoff, delay);
+@@ -717,10 +717,10 @@ static int omap_8250_startup(struct uart
+ }
+
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+
+ #ifdef CONFIG_PM
+ up->capabilities |= UART_CAP_RPM;
+@@ -733,9 +733,9 @@ static int omap_8250_startup(struct uart
+ serial_out(up, UART_OMAP_WER, priv->wer);
+
+ if (up->dma && !(priv->habit & UART_HAS_EFR2)) {
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ up->dma->rx_dma(up);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ }
+
+ enable_irq(up->port.irq);
+@@ -761,10 +761,10 @@ static void omap_8250_shutdown(struct ua
+ serial_out(up, UART_OMAP_EFR2, 0x0);
+
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ disable_irq_nosync(up->port.irq);
+ dev_pm_clear_wake_irq(port->dev);
+
+@@ -789,10 +789,10 @@ static void omap_8250_throttle(struct ua
+
+ pm_runtime_get_sync(port->dev);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ port->ops->stop_rx(port);
+ priv->throttled = true;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+@@ -807,14 +807,14 @@ static void omap_8250_unthrottle(struct
+ pm_runtime_get_sync(port->dev);
+
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ priv->throttled = false;
+ if (up->dma)
+ up->dma->rx_dma(up);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ port->read_status_mask |= UART_LSR_DR;
+ serial_out(up, UART_IER, up->ier);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ pm_runtime_mark_last_busy(port->dev);
+ pm_runtime_put_autosuspend(port->dev);
+@@ -958,7 +958,7 @@ static void __dma_rx_complete(void *para
+ unsigned long flags;
+
+ /* Synchronize UART_IER access against the console. */
+- spin_lock_irqsave(&p->port.lock, flags);
++ uart_port_lock_irqsave(&p->port, &flags);
+
+ /*
+ * If the tx status is not DMA_COMPLETE, then this is a delayed
+@@ -967,7 +967,7 @@ static void __dma_rx_complete(void *para
+ */
+ if (dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state) !=
+ DMA_COMPLETE) {
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+ return;
+ }
+ __dma_rx_do_complete(p);
+@@ -978,7 +978,7 @@ static void __dma_rx_complete(void *para
+ omap_8250_rx_dma(p);
+ }
+
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+ }
+
+ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)
+@@ -1083,7 +1083,7 @@ static void omap_8250_dma_tx_complete(vo
+ dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
+ UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+- spin_lock_irqsave(&p->port.lock, flags);
++ uart_port_lock_irqsave(&p->port, &flags);
+
+ dma->tx_running = 0;
+
+@@ -1112,7 +1112,7 @@ static void omap_8250_dma_tx_complete(vo
+ serial8250_set_THRI(p);
+ }
+
+- spin_unlock_irqrestore(&p->port.lock, flags);
++ uart_port_unlock_irqrestore(&p->port, flags);
+ }
+
+ static int omap_8250_tx_dma(struct uart_8250_port *p)
+@@ -1278,7 +1278,7 @@ static int omap_8250_dma_handle_irq(stru
+ return IRQ_HANDLED;
+ }
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ status = serial_port_in(port, UART_LSR);
+
+@@ -1756,15 +1756,15 @@ static int omap8250_runtime_resume(struc
+ up = serial8250_get_port(priv->line);
+
+ if (up && omap8250_lost_context(up)) {
+- spin_lock_irq(&up->port.lock);
++ uart_port_lock_irq(&up->port);
+ omap8250_restore_regs(up);
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ }
+
+ if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) {
+- spin_lock_irq(&up->port.lock);
++ uart_port_lock_irq(&up->port);
+ omap_8250_rx_dma(up);
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ }
+
+ priv->latency = priv->calc_latency;
diff --git a/debian/patches-rt/0013-serial-8250_pci1xxxx-Use-port-lock-wrappers.patch b/debian/patches-rt/0013-serial-8250_pci1xxxx-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..2916387692
--- /dev/null
+++ b/debian/patches-rt/0013-serial-8250_pci1xxxx-Use-port-lock-wrappers.patch
@@ -0,0 +1,66 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:30 +0206
+Subject: [PATCH 013/134] serial: 8250_pci1xxxx: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-14-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_pci1xxxx.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_pci1xxxx.c
++++ b/drivers/tty/serial/8250/8250_pci1xxxx.c
+@@ -225,10 +225,10 @@ static bool pci1xxxx_port_suspend(int li
+ if (port->suspended == 0 && port->dev) {
+ wakeup_mask = readb(up->port.membase + UART_WAKE_MASK_REG);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ port->mctrl &= ~TIOCM_OUT2;
+ port->ops->set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ ret = (wakeup_mask & UART_WAKE_SRCS) != UART_WAKE_SRCS;
+ }
+@@ -251,10 +251,10 @@ static void pci1xxxx_port_resume(int lin
+ writeb(UART_WAKE_SRCS, port->membase + UART_WAKE_REG);
+
+ if (port->suspended == 0) {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ port->mctrl |= TIOCM_OUT2;
+ port->ops->set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ mutex_unlock(&tport->mutex);
+ }
diff --git a/debian/patches-rt/0014-serial-altera_jtaguart-Use-port-lock-wrappers.patch b/debian/patches-rt/0014-serial-altera_jtaguart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..46dbf785d0
--- /dev/null
+++ b/debian/patches-rt/0014-serial-altera_jtaguart-Use-port-lock-wrappers.patch
@@ -0,0 +1,133 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:31 +0206
+Subject: [PATCH 014/134] serial: altera_jtaguart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-15-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/altera_jtaguart.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/tty/serial/altera_jtaguart.c
++++ b/drivers/tty/serial/altera_jtaguart.c
+@@ -147,14 +147,14 @@ static irqreturn_t altera_jtaguart_inter
+ isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >>
+ ALTERA_JTAGUART_CONTROL_RI_OFF) & port->read_status_mask;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK)
+ altera_jtaguart_rx_chars(port);
+ if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK)
+ altera_jtaguart_tx_chars(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_RETVAL(isr);
+ }
+@@ -180,14 +180,14 @@ static int altera_jtaguart_startup(struc
+ return ret;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Enable RX interrupts now */
+ port->read_status_mask = ALTERA_JTAGUART_CONTROL_RE_MSK;
+ writel(port->read_status_mask,
+ port->membase + ALTERA_JTAGUART_CONTROL_REG);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -196,14 +196,14 @@ static void altera_jtaguart_shutdown(str
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable all interrupts now */
+ port->read_status_mask = 0;
+ writel(port->read_status_mask,
+ port->membase + ALTERA_JTAGUART_CONTROL_REG);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ free_irq(port->irq, port);
+ }
+@@ -264,33 +264,33 @@ static void altera_jtaguart_console_putc
+ unsigned long flags;
+ u32 status;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ while (!altera_jtaguart_tx_space(port, &status)) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) {
+ return; /* no connection activity */
+ }
+
+ cpu_relax();
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ }
+ writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ #else
+ static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c)
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ while (!altera_jtaguart_tx_space(port, NULL)) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ cpu_relax();
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ }
+ writel(c, port->membase + ALTERA_JTAGUART_DATA_REG);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ #endif
+
diff --git a/debian/patches-rt/0015-serial-altera_uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0015-serial-altera_uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..95e2c031f5
--- /dev/null
+++ b/debian/patches-rt/0015-serial-altera_uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,116 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:32 +0206
+Subject: [PATCH 015/134] serial: altera_uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-16-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/altera_uart.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/altera_uart.c
++++ b/drivers/tty/serial/altera_uart.c
+@@ -164,13 +164,13 @@ static void altera_uart_break_ctl(struct
+ struct altera_uart *pp = container_of(port, struct altera_uart, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (break_state == -1)
+ pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK;
+ else
+ pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK;
+ altera_uart_update_ctrl_reg(pp);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void altera_uart_set_termios(struct uart_port *port,
+@@ -187,10 +187,10 @@ static void altera_uart_set_termios(stru
+ tty_termios_copy_hw(termios, old);
+ tty_termios_encode_baud_rate(termios, baud, baud);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ uart_update_timeout(port, termios->c_cflag, baud);
+ altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /*
+ * FIXME: port->read_status_mask and port->ignore_status_mask
+@@ -264,12 +264,12 @@ static irqreturn_t altera_uart_interrupt
+
+ isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (isr & ALTERA_UART_STATUS_RRDY_MSK)
+ altera_uart_rx_chars(port);
+ if (isr & ALTERA_UART_STATUS_TRDY_MSK)
+ altera_uart_tx_chars(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_RETVAL(isr);
+ }
+@@ -313,13 +313,13 @@ static int altera_uart_startup(struct ua
+ }
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Enable RX interrupts now */
+ pp->imr = ALTERA_UART_CONTROL_RRDY_MSK;
+ altera_uart_update_ctrl_reg(pp);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -329,13 +329,13 @@ static void altera_uart_shutdown(struct
+ struct altera_uart *pp = container_of(port, struct altera_uart, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable all interrupts now */
+ pp->imr = 0;
+ altera_uart_update_ctrl_reg(pp);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (port->irq)
+ free_irq(port->irq, port);
diff --git a/debian/patches-rt/0016-serial-amba-pl010-Use-port-lock-wrappers.patch b/debian/patches-rt/0016-serial-amba-pl010-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..f3ba735bfc
--- /dev/null
+++ b/debian/patches-rt/0016-serial-amba-pl010-Use-port-lock-wrappers.patch
@@ -0,0 +1,112 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:33 +0206
+Subject: [PATCH 016/134] serial: amba-pl010: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-17-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/amba-pl010.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/amba-pl010.c
++++ b/drivers/tty/serial/amba-pl010.c
+@@ -207,7 +207,7 @@ static irqreturn_t pl010_int(int irq, vo
+ unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
+ int handled = 0;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ status = readb(port->membase + UART010_IIR);
+ if (status) {
+@@ -228,7 +228,7 @@ static irqreturn_t pl010_int(int irq, vo
+ handled = 1;
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_RETVAL(handled);
+ }
+@@ -270,14 +270,14 @@ static void pl010_break_ctl(struct uart_
+ unsigned long flags;
+ unsigned int lcr_h;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ lcr_h = readb(port->membase + UART010_LCRH);
+ if (break_state == -1)
+ lcr_h |= UART01x_LCRH_BRK;
+ else
+ lcr_h &= ~UART01x_LCRH_BRK;
+ writel(lcr_h, port->membase + UART010_LCRH);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int pl010_startup(struct uart_port *port)
+@@ -385,7 +385,7 @@ pl010_set_termios(struct uart_port *port
+ if (port->fifosize > 1)
+ lcr_h |= UART01x_LCRH_FEN;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -438,22 +438,22 @@ pl010_set_termios(struct uart_port *port
+ writel(lcr_h, port->membase + UART010_LCRH);
+ writel(old_cr, port->membase + UART010_CR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios)
+ {
+ if (termios->c_line == N_PPS) {
+ port->flags |= UPF_HARDPPS_CD;
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ pl010_enable_ms(port);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ } else {
+ port->flags &= ~UPF_HARDPPS_CD;
+ if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ pl010_disable_ms(port);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ }
+ }
+ }
diff --git a/debian/patches-rt/0017-serial-amba-pl011-Use-port-lock-wrappers.patch b/debian/patches-rt/0017-serial-amba-pl011-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..2a5e3a85ea
--- /dev/null
+++ b/debian/patches-rt/0017-serial-amba-pl011-Use-port-lock-wrappers.patch
@@ -0,0 +1,327 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:34 +0206
+Subject: [PATCH 017/134] serial: amba-pl011: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-18-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/amba-pl011.c | 72 ++++++++++++++++++++--------------------
+ 1 file changed, 36 insertions(+), 36 deletions(-)
+
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -347,9 +347,9 @@ static int pl011_fifo_to_tty(struct uart
+ flag = TTY_FRAME;
+ }
+
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ sysrq = uart_handle_sysrq_char(&uap->port, ch & 255);
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+
+ if (!sysrq)
+ uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
+@@ -544,7 +544,7 @@ static void pl011_dma_tx_callback(void *
+ unsigned long flags;
+ u16 dmacr;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ if (uap->dmatx.queued)
+ dma_unmap_single(dmatx->chan->device->dev, dmatx->dma,
+ dmatx->len, DMA_TO_DEVICE);
+@@ -565,7 +565,7 @@ static void pl011_dma_tx_callback(void *
+ if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) ||
+ uart_circ_empty(&uap->port.state->xmit)) {
+ uap->dmatx.queued = false;
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ return;
+ }
+
+@@ -576,7 +576,7 @@ static void pl011_dma_tx_callback(void *
+ */
+ pl011_start_tx_pio(uap);
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ /*
+@@ -1004,7 +1004,7 @@ static void pl011_dma_rx_callback(void *
+ * routine to flush out the secondary DMA buffer while
+ * we immediately trigger the next DMA job.
+ */
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+ /*
+ * Rx data can be taken by the UART interrupts during
+ * the DMA irq handler. So we check the residue here.
+@@ -1020,7 +1020,7 @@ static void pl011_dma_rx_callback(void *
+ ret = pl011_dma_rx_trigger_dma(uap);
+
+ pl011_dma_rx_chars(uap, pending, lastbuf, false);
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+ /*
+ * Do this check after we picked the DMA chars so we don't
+ * get some IRQ immediately from RX.
+@@ -1086,11 +1086,11 @@ static void pl011_dma_rx_poll(struct tim
+ if (jiffies_to_msecs(jiffies - dmarx->last_jiffies)
+ > uap->dmarx.poll_timeout) {
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ pl011_dma_rx_stop(uap);
+ uap->im |= UART011_RXIM;
+ pl011_write(uap->im, uap, REG_IMSC);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+
+ uap->dmarx.running = false;
+ dmaengine_terminate_all(rxchan);
+@@ -1186,10 +1186,10 @@ static void pl011_dma_shutdown(struct ua
+ while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
+ cpu_relax();
+
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+ uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
+ pl011_write(uap->dmacr, uap, REG_DMACR);
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+
+ if (uap->using_tx_dma) {
+ /* In theory, this should already be done by pl011_dma_flush_buffer */
+@@ -1370,9 +1370,9 @@ static void pl011_throttle_rx(struct uar
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ pl011_stop_rx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void pl011_enable_ms(struct uart_port *port)
+@@ -1390,7 +1390,7 @@ static void pl011_rx_chars(struct uart_a
+ {
+ pl011_fifo_to_tty(uap);
+
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ tty_flip_buffer_push(&uap->port.state->port);
+ /*
+ * If we were temporarily out of DMA mode for a while,
+@@ -1415,7 +1415,7 @@ static void pl011_rx_chars(struct uart_a
+ #endif
+ }
+ }
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+ }
+
+ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
+@@ -1551,7 +1551,7 @@ static irqreturn_t pl011_int(int irq, vo
+ unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
+ int handled = 0;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ status = pl011_read(uap, REG_RIS) & uap->im;
+ if (status) {
+ do {
+@@ -1581,7 +1581,7 @@ static irqreturn_t pl011_int(int irq, vo
+ handled = 1;
+ }
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+
+ return IRQ_RETVAL(handled);
+ }
+@@ -1653,14 +1653,14 @@ static void pl011_break_ctl(struct uart_
+ unsigned long flags;
+ unsigned int lcr_h;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ lcr_h = pl011_read(uap, REG_LCRH_TX);
+ if (break_state == -1)
+ lcr_h |= UART01x_LCRH_BRK;
+ else
+ lcr_h &= ~UART01x_LCRH_BRK;
+ pl011_write(lcr_h, uap, REG_LCRH_TX);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ #ifdef CONFIG_CONSOLE_POLL
+@@ -1799,7 +1799,7 @@ static void pl011_enable_interrupts(stru
+ unsigned long flags;
+ unsigned int i;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+
+ /* Clear out any spuriously appearing RX interrupts */
+ pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR);
+@@ -1821,7 +1821,7 @@ static void pl011_enable_interrupts(stru
+ if (!pl011_dma_rx_running(uap))
+ uap->im |= UART011_RXIM;
+ pl011_write(uap->im, uap, REG_IMSC);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ static void pl011_unthrottle_rx(struct uart_port *port)
+@@ -1829,7 +1829,7 @@ static void pl011_unthrottle_rx(struct u
+ struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+
+ uap->im = UART011_RTIM;
+ if (!pl011_dma_rx_running(uap))
+@@ -1837,7 +1837,7 @@ static void pl011_unthrottle_rx(struct u
+
+ pl011_write(uap->im, uap, REG_IMSC);
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ static int pl011_startup(struct uart_port *port)
+@@ -1857,7 +1857,7 @@ static int pl011_startup(struct uart_por
+
+ pl011_write(uap->vendor->ifls, uap, REG_IFLS);
+
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+
+ cr = pl011_read(uap, REG_CR);
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
+@@ -1868,7 +1868,7 @@ static int pl011_startup(struct uart_por
+
+ pl011_write(cr, uap, REG_CR);
+
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+
+ /*
+ * initialise the old status of the modem signals
+@@ -1929,12 +1929,12 @@ static void pl011_disable_uart(struct ua
+ unsigned int cr;
+
+ uap->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS);
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+ cr = pl011_read(uap, REG_CR);
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
+ cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
+ pl011_write(cr, uap, REG_CR);
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+
+ /*
+ * disable break condition and fifos
+@@ -1946,14 +1946,14 @@ static void pl011_disable_uart(struct ua
+
+ static void pl011_disable_interrupts(struct uart_amba_port *uap)
+ {
+- spin_lock_irq(&uap->port.lock);
++ uart_port_lock_irq(&uap->port);
+
+ /* mask all interrupts and clear all pending ones */
+ uap->im = 0;
+ pl011_write(uap->im, uap, REG_IMSC);
+ pl011_write(0xffff, uap, REG_ICR);
+
+- spin_unlock_irq(&uap->port.lock);
++ uart_port_unlock_irq(&uap->port);
+ }
+
+ static void pl011_shutdown(struct uart_port *port)
+@@ -2098,7 +2098,7 @@ pl011_set_termios(struct uart_port *port
+
+ bits = tty_get_frame_size(termios->c_cflag);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -2172,7 +2172,7 @@ pl011_set_termios(struct uart_port *port
+ old_cr |= UART011_CR_RXE;
+ pl011_write(old_cr, uap, REG_CR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void
+@@ -2190,10 +2190,10 @@ sbsa_uart_set_termios(struct uart_port *
+ termios->c_cflag &= ~(CMSPAR | CRTSCTS);
+ termios->c_cflag |= CS8 | CLOCAL;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ uart_update_timeout(port, CS8, uap->fixed_baud);
+ pl011_setup_status_masks(port, termios);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *pl011_type(struct uart_port *port)
+@@ -2332,9 +2332,9 @@ pl011_console_write(struct console *co,
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&uap->port.lock);
++ locked = uart_port_trylock(&uap->port);
+ else
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+
+ /*
+ * First save the CR then disable the interrupts
+@@ -2360,7 +2360,7 @@ pl011_console_write(struct console *co,
+ pl011_write(old_cr, uap, REG_CR);
+
+ if (locked)
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ local_irq_restore(flags);
+
+ clk_disable(uap->clk);
diff --git a/debian/patches-rt/0018-serial-apb-Use-port-lock-wrappers.patch b/debian/patches-rt/0018-serial-apb-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..4dcf54a895
--- /dev/null
+++ b/debian/patches-rt/0018-serial-apb-Use-port-lock-wrappers.patch
@@ -0,0 +1,76 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:35 +0206
+Subject: [PATCH 018/134] serial: apb: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-19-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/apbuart.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/apbuart.c
++++ b/drivers/tty/serial/apbuart.c
+@@ -133,7 +133,7 @@ static irqreturn_t apbuart_int(int irq,
+ struct uart_port *port = dev_id;
+ unsigned int status;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ status = UART_GET_STATUS(port);
+ if (status & UART_STATUS_DR)
+@@ -141,7 +141,7 @@ static irqreturn_t apbuart_int(int irq,
+ if (status & UART_STATUS_THE)
+ apbuart_tx_chars(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -228,7 +228,7 @@ static void apbuart_set_termios(struct u
+ if (termios->c_cflag & CRTSCTS)
+ cr |= UART_CTRL_FL;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Update the per-port timeout. */
+ uart_update_timeout(port, termios->c_cflag, baud);
+@@ -251,7 +251,7 @@ static void apbuart_set_termios(struct u
+ UART_PUT_SCAL(port, quot);
+ UART_PUT_CTRL(port, cr);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *apbuart_type(struct uart_port *port)
diff --git a/debian/patches-rt/0019-serial-ar933x-Use-port-lock-wrappers.patch b/debian/patches-rt/0019-serial-ar933x-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..61a5d3b1a6
--- /dev/null
+++ b/debian/patches-rt/0019-serial-ar933x-Use-port-lock-wrappers.patch
@@ -0,0 +1,144 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:36 +0206
+Subject: [PATCH 019/134] serial: ar933x: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-20-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/ar933x_uart.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/ar933x_uart.c
++++ b/drivers/tty/serial/ar933x_uart.c
+@@ -133,9 +133,9 @@ static unsigned int ar933x_uart_tx_empty
+ unsigned long flags;
+ unsigned int rdata;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return (rdata & AR933X_UART_DATA_TX_CSR) ? 0 : TIOCSER_TEMT;
+ }
+@@ -220,14 +220,14 @@ static void ar933x_uart_break_ctl(struct
+ container_of(port, struct ar933x_uart_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ if (break_state == -1)
+ ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_TX_BREAK);
+ else
+ ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+ AR933X_UART_CS_TX_BREAK);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ /*
+@@ -318,7 +318,7 @@ static void ar933x_uart_set_termios(stru
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /* disable the UART */
+ ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
+@@ -352,7 +352,7 @@ static void ar933x_uart_set_termios(stru
+ AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
+ AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ if (tty_termios_baud_rate(new))
+ tty_termios_encode_baud_rate(new, baud, baud);
+@@ -450,7 +450,7 @@ static irqreturn_t ar933x_uart_interrupt
+ if ((status & AR933X_UART_CS_HOST_INT) == 0)
+ return IRQ_NONE;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ status = ar933x_uart_read(up, AR933X_UART_INT_REG);
+ status &= ar933x_uart_read(up, AR933X_UART_INT_EN_REG);
+@@ -468,7 +468,7 @@ static irqreturn_t ar933x_uart_interrupt
+ ar933x_uart_tx_chars(up);
+ }
+
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ return IRQ_HANDLED;
+ }
+@@ -485,7 +485,7 @@ static int ar933x_uart_startup(struct ua
+ if (ret)
+ return ret;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /* Enable HOST interrupts */
+ ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+@@ -498,7 +498,7 @@ static int ar933x_uart_startup(struct ua
+ /* Enable RX interrupts */
+ ar933x_uart_start_rx_interrupt(up);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return 0;
+ }
+@@ -632,9 +632,9 @@ static void ar933x_uart_console_write(st
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&up->port.lock);
++ locked = uart_port_trylock(&up->port);
+ else
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -654,7 +654,7 @@ static void ar933x_uart_console_write(st
+ ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS);
+
+ if (locked)
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ local_irq_restore(flags);
+ }
diff --git a/debian/patches-rt/0020-serial-arc_uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0020-serial-arc_uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..bc7be2c4d3
--- /dev/null
+++ b/debian/patches-rt/0020-serial-arc_uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,97 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:37 +0206
+Subject: [PATCH 020/134] serial: arc_uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-21-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/arc_uart.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/tty/serial/arc_uart.c
++++ b/drivers/tty/serial/arc_uart.c
+@@ -279,9 +279,9 @@ static irqreturn_t arc_serial_isr(int ir
+ if (status & RXIENB) {
+
+ /* already in ISR, no need of xx_irqsave */
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ arc_serial_rx_chars(port, status);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ }
+
+ if ((status & TXIENB) && (status & TXEMPTY)) {
+@@ -291,12 +291,12 @@ static irqreturn_t arc_serial_isr(int ir
+ */
+ UART_TX_IRQ_DISABLE(port);
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (!uart_tx_stopped(port))
+ arc_serial_tx_chars(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ }
+
+ return IRQ_HANDLED;
+@@ -366,7 +366,7 @@ arc_serial_set_termios(struct uart_port
+ uartl = hw_val & 0xFF;
+ uarth = (hw_val >> 8) & 0xFF;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ UART_ALL_IRQ_DISABLE(port);
+
+@@ -391,7 +391,7 @@ arc_serial_set_termios(struct uart_port
+
+ uart_update_timeout(port, new->c_cflag, baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *arc_serial_type(struct uart_port *port)
+@@ -521,9 +521,9 @@ static void arc_serial_console_write(str
+ struct uart_port *port = &arc_uart_ports[co->index].port;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ uart_console_write(port, s, count, arc_serial_console_putchar);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static struct console arc_console = {
diff --git a/debian/patches-rt/0021-serial-atmel-Use-port-lock-wrappers.patch b/debian/patches-rt/0021-serial-atmel-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..ab70954a10
--- /dev/null
+++ b/debian/patches-rt/0021-serial-atmel-Use-port-lock-wrappers.patch
@@ -0,0 +1,119 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:38 +0206
+Subject: [PATCH 021/134] serial: atmel: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-22-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/atmel_serial.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -861,7 +861,7 @@ static void atmel_complete_tx_dma(void *
+ struct dma_chan *chan = atmel_port->chan_tx;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (chan)
+ dmaengine_terminate_all(chan);
+@@ -893,7 +893,7 @@ static void atmel_complete_tx_dma(void *
+ atmel_port->tx_done_mask);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void atmel_release_tx_dma(struct uart_port *port)
+@@ -1711,9 +1711,9 @@ static void atmel_tasklet_rx_func(struct
+ struct uart_port *port = &atmel_port->uart;
+
+ /* The interrupt handler does not take the lock */
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ atmel_port->schedule_rx(port);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ }
+
+ static void atmel_tasklet_tx_func(struct tasklet_struct *t)
+@@ -1723,9 +1723,9 @@ static void atmel_tasklet_tx_func(struct
+ struct uart_port *port = &atmel_port->uart;
+
+ /* The interrupt handler does not take the lock */
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ atmel_port->schedule_tx(port);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ }
+
+ static void atmel_init_property(struct atmel_uart_port *atmel_port,
+@@ -2175,7 +2175,7 @@ static void atmel_set_termios(struct uar
+ } else
+ mode |= ATMEL_US_PAR_NONE;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ port->read_status_mask = ATMEL_US_OVRE;
+ if (termios->c_iflag & INPCK)
+@@ -2377,22 +2377,22 @@ static void atmel_set_termios(struct uar
+ else
+ atmel_disable_ms(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void atmel_set_ldisc(struct uart_port *port, struct ktermios *termios)
+ {
+ if (termios->c_line == N_PPS) {
+ port->flags |= UPF_HARDPPS_CD;
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ atmel_enable_ms(port);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ } else {
+ port->flags &= ~UPF_HARDPPS_CD;
+ if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ atmel_disable_ms(port);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ }
+ }
+ }
diff --git a/debian/patches-rt/0022-serial-bcm63xx-uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0022-serial-bcm63xx-uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..90efec4080
--- /dev/null
+++ b/debian/patches-rt/0022-serial-bcm63xx-uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,128 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:39 +0206
+Subject: [PATCH 022/134] serial: bcm63xx-uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-23-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/bcm63xx_uart.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+--- a/drivers/tty/serial/bcm63xx_uart.c
++++ b/drivers/tty/serial/bcm63xx_uart.c
+@@ -201,7 +201,7 @@ static void bcm_uart_break_ctl(struct ua
+ unsigned long flags;
+ unsigned int val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = bcm_uart_readl(port, UART_CTL_REG);
+ if (ctl)
+@@ -210,7 +210,7 @@ static void bcm_uart_break_ctl(struct ua
+ val &= ~UART_CTL_XMITBRK_MASK;
+ bcm_uart_writel(port, val, UART_CTL_REG);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /*
+@@ -332,7 +332,7 @@ static irqreturn_t bcm_uart_interrupt(in
+ unsigned int irqstat;
+
+ port = dev_id;
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ irqstat = bcm_uart_readl(port, UART_IR_REG);
+ if (irqstat & UART_RX_INT_STAT)
+@@ -353,7 +353,7 @@ static irqreturn_t bcm_uart_interrupt(in
+ estat & UART_EXTINP_DCD_MASK);
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ return IRQ_HANDLED;
+ }
+
+@@ -451,9 +451,9 @@ static void bcm_uart_shutdown(struct uar
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ bcm_uart_writel(port, 0, UART_IR_REG);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ bcm_uart_disable(port);
+ bcm_uart_flush(port);
+@@ -470,7 +470,7 @@ static void bcm_uart_set_termios(struct
+ unsigned long flags;
+ int tries;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Drain the hot tub fully before we power it off for the winter. */
+ for (tries = 3; !bcm_uart_tx_empty(port) && tries; tries--)
+@@ -546,7 +546,7 @@ static void bcm_uart_set_termios(struct
+
+ uart_update_timeout(port, new->c_cflag, baud);
+ bcm_uart_enable(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /*
+@@ -712,9 +712,9 @@ static void bcm_console_write(struct con
+ /* bcm_uart_interrupt() already took the lock */
+ locked = 0;
+ } else if (oops_in_progress) {
+- locked = spin_trylock(&port->lock);
++ locked = uart_port_trylock(port);
+ } else {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ locked = 1;
+ }
+
+@@ -725,7 +725,7 @@ static void bcm_console_write(struct con
+ wait_for_xmitr(port);
+
+ if (locked)
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ local_irq_restore(flags);
+ }
+
diff --git a/debian/patches-rt/0023-serial-cpm_uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0023-serial-cpm_uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..c3400eac99
--- /dev/null
+++ b/debian/patches-rt/0023-serial-cpm_uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,70 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:40 +0206
+Subject: [PATCH 023/134] serial: cpm_uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-24-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/cpm_uart.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/cpm_uart.c
++++ b/drivers/tty/serial/cpm_uart.c
+@@ -569,7 +569,7 @@ static void cpm_uart_set_termios(struct
+ if ((termios->c_cflag & CREAD) == 0)
+ port->read_status_mask &= ~BD_SC_EMPTY;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (IS_SMC(pinfo)) {
+ unsigned int bits = tty_get_frame_size(termios->c_cflag);
+@@ -609,7 +609,7 @@ static void cpm_uart_set_termios(struct
+ clk_set_rate(pinfo->clk, baud);
+ else
+ cpm_setbrg(pinfo->brg - 1, baud);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *cpm_uart_type(struct uart_port *port)
+@@ -1386,9 +1386,9 @@ static void cpm_uart_console_write(struc
+ cpm_uart_early_write(pinfo, s, count, true);
+ local_irq_restore(flags);
+ } else {
+- spin_lock_irqsave(&pinfo->port.lock, flags);
++ uart_port_lock_irqsave(&pinfo->port, &flags);
+ cpm_uart_early_write(pinfo, s, count, true);
+- spin_unlock_irqrestore(&pinfo->port.lock, flags);
++ uart_port_unlock_irqrestore(&pinfo->port, flags);
+ }
+ }
+
diff --git a/debian/patches-rt/0024-serial-digicolor-Use-port-lock-wrappers.patch b/debian/patches-rt/0024-serial-digicolor-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..2a3aa5c9a5
--- /dev/null
+++ b/debian/patches-rt/0024-serial-digicolor-Use-port-lock-wrappers.patch
@@ -0,0 +1,113 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:41 +0206
+Subject: [PATCH 024/134] serial: digicolor: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Baruch Siach <baruch@tkos.co.il>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-25-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/digicolor-usart.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/tty/serial/digicolor-usart.c
++++ b/drivers/tty/serial/digicolor-usart.c
+@@ -133,7 +133,7 @@ static void digicolor_uart_rx(struct uar
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ while (1) {
+ u8 status, ch, ch_flag;
+@@ -172,7 +172,7 @@ static void digicolor_uart_rx(struct uar
+ ch_flag);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ tty_flip_buffer_push(&port->state->port);
+ }
+@@ -185,7 +185,7 @@ static void digicolor_uart_tx(struct uar
+ if (digicolor_uart_tx_full(port))
+ return;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (port->x_char) {
+ writeb_relaxed(port->x_char, port->membase + UA_EMI_REC);
+@@ -211,7 +211,7 @@ static void digicolor_uart_tx(struct uar
+ uart_write_wakeup(port);
+
+ out:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static irqreturn_t digicolor_uart_int(int irq, void *dev_id)
+@@ -333,7 +333,7 @@ static void digicolor_uart_set_termios(s
+ port->ignore_status_mask |= UA_STATUS_OVERRUN_ERR
+ | UA_STATUS_PARITY_ERR | UA_STATUS_FRAME_ERR;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+@@ -341,7 +341,7 @@ static void digicolor_uart_set_termios(s
+ writeb_relaxed(divisor & 0xff, port->membase + UA_HBAUD_LO);
+ writeb_relaxed(divisor >> 8, port->membase + UA_HBAUD_HI);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *digicolor_uart_type(struct uart_port *port)
+@@ -398,14 +398,14 @@ static void digicolor_uart_console_write
+ int locked = 1;
+
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_console_write(port, c, n, digicolor_uart_console_putchar);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Wait for transmitter to become empty */
+ do {
diff --git a/debian/patches-rt/0025-serial-dz-Use-port-lock-wrappers.patch b/debian/patches-rt/0025-serial-dz-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..7b3f11604c
--- /dev/null
+++ b/debian/patches-rt/0025-serial-dz-Use-port-lock-wrappers.patch
@@ -0,0 +1,161 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:42 +0206
+Subject: [PATCH 025/134] serial: dz: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-26-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/dz.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/tty/serial/dz.c
++++ b/drivers/tty/serial/dz.c
+@@ -268,9 +268,9 @@ static inline void dz_transmit_chars(str
+ }
+ /* If nothing to do or stopped or hardware stopped. */
+ if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
+- spin_lock(&dport->port.lock);
++ uart_port_lock(&dport->port);
+ dz_stop_tx(&dport->port);
+- spin_unlock(&dport->port.lock);
++ uart_port_unlock(&dport->port);
+ return;
+ }
+
+@@ -287,9 +287,9 @@ static inline void dz_transmit_chars(str
+
+ /* Are we are done. */
+ if (uart_circ_empty(xmit)) {
+- spin_lock(&dport->port.lock);
++ uart_port_lock(&dport->port);
+ dz_stop_tx(&dport->port);
+- spin_unlock(&dport->port.lock);
++ uart_port_unlock(&dport->port);
+ }
+ }
+
+@@ -415,14 +415,14 @@ static int dz_startup(struct uart_port *
+ return ret;
+ }
+
+- spin_lock_irqsave(&dport->port.lock, flags);
++ uart_port_lock_irqsave(&dport->port, &flags);
+
+ /* Enable interrupts. */
+ tmp = dz_in(dport, DZ_CSR);
+ tmp |= DZ_RIE | DZ_TIE;
+ dz_out(dport, DZ_CSR, tmp);
+
+- spin_unlock_irqrestore(&dport->port.lock, flags);
++ uart_port_unlock_irqrestore(&dport->port, flags);
+
+ return 0;
+ }
+@@ -443,9 +443,9 @@ static void dz_shutdown(struct uart_port
+ int irq_guard;
+ u16 tmp;
+
+- spin_lock_irqsave(&dport->port.lock, flags);
++ uart_port_lock_irqsave(&dport->port, &flags);
+ dz_stop_tx(&dport->port);
+- spin_unlock_irqrestore(&dport->port.lock, flags);
++ uart_port_unlock_irqrestore(&dport->port, flags);
+
+ irq_guard = atomic_add_return(-1, &mux->irq_guard);
+ if (!irq_guard) {
+@@ -491,14 +491,14 @@ static void dz_break_ctl(struct uart_por
+ unsigned long flags;
+ unsigned short tmp, mask = 1 << dport->port.line;
+
+- spin_lock_irqsave(&uport->lock, flags);
++ uart_port_lock_irqsave(uport, &flags);
+ tmp = dz_in(dport, DZ_TCR);
+ if (break_state)
+ tmp |= mask;
+ else
+ tmp &= ~mask;
+ dz_out(dport, DZ_TCR, tmp);
+- spin_unlock_irqrestore(&uport->lock, flags);
++ uart_port_unlock_irqrestore(uport, flags);
+ }
+
+ static int dz_encode_baud_rate(unsigned int baud)
+@@ -608,7 +608,7 @@ static void dz_set_termios(struct uart_p
+ if (termios->c_cflag & CREAD)
+ cflag |= DZ_RXENAB;
+
+- spin_lock_irqsave(&dport->port.lock, flags);
++ uart_port_lock_irqsave(&dport->port, &flags);
+
+ uart_update_timeout(uport, termios->c_cflag, baud);
+
+@@ -631,7 +631,7 @@ static void dz_set_termios(struct uart_p
+ if (termios->c_iflag & IGNBRK)
+ dport->port.ignore_status_mask |= DZ_BREAK;
+
+- spin_unlock_irqrestore(&dport->port.lock, flags);
++ uart_port_unlock_irqrestore(&dport->port, flags);
+ }
+
+ /*
+@@ -645,12 +645,12 @@ static void dz_pm(struct uart_port *upor
+ struct dz_port *dport = to_dport(uport);
+ unsigned long flags;
+
+- spin_lock_irqsave(&dport->port.lock, flags);
++ uart_port_lock_irqsave(&dport->port, &flags);
+ if (state < 3)
+ dz_start_tx(&dport->port);
+ else
+ dz_stop_tx(&dport->port);
+- spin_unlock_irqrestore(&dport->port.lock, flags);
++ uart_port_unlock_irqrestore(&dport->port, flags);
+ }
+
+
+@@ -811,7 +811,7 @@ static void dz_console_putchar(struct ua
+ unsigned short csr, tcr, trdy, mask;
+ int loops = 10000;
+
+- spin_lock_irqsave(&dport->port.lock, flags);
++ uart_port_lock_irqsave(&dport->port, &flags);
+ csr = dz_in(dport, DZ_CSR);
+ dz_out(dport, DZ_CSR, csr & ~DZ_TIE);
+ tcr = dz_in(dport, DZ_TCR);
+@@ -819,7 +819,7 @@ static void dz_console_putchar(struct ua
+ mask = tcr;
+ dz_out(dport, DZ_TCR, mask);
+ iob();
+- spin_unlock_irqrestore(&dport->port.lock, flags);
++ uart_port_unlock_irqrestore(&dport->port, flags);
+
+ do {
+ trdy = dz_in(dport, DZ_CSR);
diff --git a/debian/patches-rt/0026-serial-linflexuart-Use-port-lock-wrappers.patch b/debian/patches-rt/0026-serial-linflexuart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..e2a3628ae5
--- /dev/null
+++ b/debian/patches-rt/0026-serial-linflexuart-Use-port-lock-wrappers.patch
@@ -0,0 +1,143 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:43 +0206
+Subject: [PATCH 026/134] serial: linflexuart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-27-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/fsl_linflexuart.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/fsl_linflexuart.c
++++ b/drivers/tty/serial/fsl_linflexuart.c
+@@ -203,7 +203,7 @@ static irqreturn_t linflex_txint(int irq
+ struct circ_buf *xmit = &sport->state->xmit;
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->lock, flags);
++ uart_port_lock_irqsave(sport, &flags);
+
+ if (sport->x_char) {
+ linflex_put_char(sport, sport->x_char);
+@@ -217,7 +217,7 @@ static irqreturn_t linflex_txint(int irq
+
+ linflex_transmit_buffer(sport);
+ out:
+- spin_unlock_irqrestore(&sport->lock, flags);
++ uart_port_unlock_irqrestore(sport, flags);
+ return IRQ_HANDLED;
+ }
+
+@@ -230,7 +230,7 @@ static irqreturn_t linflex_rxint(int irq
+ unsigned char rx;
+ bool brk;
+
+- spin_lock_irqsave(&sport->lock, flags);
++ uart_port_lock_irqsave(sport, &flags);
+
+ status = readl(sport->membase + UARTSR);
+ while (status & LINFLEXD_UARTSR_RMB) {
+@@ -266,7 +266,7 @@ static irqreturn_t linflex_rxint(int irq
+ }
+ }
+
+- spin_unlock_irqrestore(&sport->lock, flags);
++ uart_port_unlock_irqrestore(sport, flags);
+
+ tty_flip_buffer_push(port);
+
+@@ -369,11 +369,11 @@ static int linflex_startup(struct uart_p
+ int ret = 0;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ linflex_setup_watermark(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ ret = devm_request_irq(port->dev, port->irq, linflex_int, 0,
+ DRIVER_NAME, port);
+@@ -386,14 +386,14 @@ static void linflex_shutdown(struct uart
+ unsigned long ier;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* disable interrupts */
+ ier = readl(port->membase + LINIER);
+ ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE);
+ writel(ier, port->membase + LINIER);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ devm_free_irq(port->dev, port->irq, port);
+ }
+@@ -474,7 +474,7 @@ linflex_set_termios(struct uart_port *po
+ cr &= ~LINFLEXD_UARTCR_PCE;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ port->read_status_mask = 0;
+
+@@ -507,7 +507,7 @@ linflex_set_termios(struct uart_port *po
+
+ writel(cr1, port->membase + LINCR1);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *linflex_type(struct uart_port *port)
+@@ -646,14 +646,14 @@ linflex_console_write(struct console *co
+ if (sport->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&sport->lock, flags);
++ locked = uart_port_trylock_irqsave(sport, &flags);
+ else
+- spin_lock_irqsave(&sport->lock, flags);
++ uart_port_lock_irqsave(sport, &flags);
+
+ linflex_string_write(sport, s, count);
+
+ if (locked)
+- spin_unlock_irqrestore(&sport->lock, flags);
++ uart_port_unlock_irqrestore(sport, flags);
+ }
+
+ /*
diff --git a/debian/patches-rt/0027-serial-fsl_lpuart-Use-port-lock-wrappers.patch b/debian/patches-rt/0027-serial-fsl_lpuart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..f1475a5ffd
--- /dev/null
+++ b/debian/patches-rt/0027-serial-fsl_lpuart-Use-port-lock-wrappers.patch
@@ -0,0 +1,389 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:44 +0206
+Subject: [PATCH 027/134] serial: fsl_lpuart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-28-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/fsl_lpuart.c | 88 ++++++++++++++++++++--------------------
+ 1 file changed, 44 insertions(+), 44 deletions(-)
+
+--- a/drivers/tty/serial/fsl_lpuart.c
++++ b/drivers/tty/serial/fsl_lpuart.c
+@@ -532,9 +532,9 @@ static void lpuart_dma_tx_complete(void
+ struct dma_chan *chan = sport->dma_tx_chan;
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (!sport->dma_tx_in_progress) {
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ return;
+ }
+
+@@ -543,7 +543,7 @@ static void lpuart_dma_tx_complete(void
+
+ uart_xmit_advance(&sport->port, sport->dma_tx_bytes);
+ sport->dma_tx_in_progress = false;
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&sport->port);
+@@ -553,12 +553,12 @@ static void lpuart_dma_tx_complete(void
+ return;
+ }
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ if (!lpuart_stopped_or_empty(&sport->port))
+ lpuart_dma_tx(sport);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static dma_addr_t lpuart_dma_datareg_addr(struct lpuart_port *sport)
+@@ -651,7 +651,7 @@ static int lpuart_poll_init(struct uart_
+
+ sport->port.fifosize = 0;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ /* Disable Rx & Tx */
+ writeb(0, sport->port.membase + UARTCR2);
+
+@@ -675,7 +675,7 @@ static int lpuart_poll_init(struct uart_
+
+ /* Enable Rx and Tx */
+ writeb(UARTCR2_RE | UARTCR2_TE, sport->port.membase + UARTCR2);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ return 0;
+ }
+@@ -703,7 +703,7 @@ static int lpuart32_poll_init(struct uar
+
+ sport->port.fifosize = 0;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /* Disable Rx & Tx */
+ lpuart32_write(&sport->port, 0, UARTCTRL);
+@@ -724,7 +724,7 @@ static int lpuart32_poll_init(struct uar
+
+ /* Enable Rx and Tx */
+ lpuart32_write(&sport->port, UARTCTRL_RE | UARTCTRL_TE, UARTCTRL);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ return 0;
+ }
+@@ -879,9 +879,9 @@ static unsigned int lpuart32_tx_empty(st
+
+ static void lpuart_txint(struct lpuart_port *sport)
+ {
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+ lpuart_transmit_buffer(sport);
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+ }
+
+ static void lpuart_rxint(struct lpuart_port *sport)
+@@ -890,7 +890,7 @@ static void lpuart_rxint(struct lpuart_p
+ struct tty_port *port = &sport->port.state->port;
+ unsigned char rx, sr;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+
+ while (!(readb(sport->port.membase + UARTSFIFO) & UARTSFIFO_RXEMPT)) {
+ flg = TTY_NORMAL;
+@@ -956,9 +956,9 @@ static void lpuart_rxint(struct lpuart_p
+
+ static void lpuart32_txint(struct lpuart_port *sport)
+ {
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+ lpuart32_transmit_buffer(sport);
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+ }
+
+ static void lpuart32_rxint(struct lpuart_port *sport)
+@@ -968,7 +968,7 @@ static void lpuart32_rxint(struct lpuart
+ unsigned long rx, sr;
+ bool is_break;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+
+ while (!(lpuart32_read(&sport->port, UARTFIFO) & UARTFIFO_RXEMPT)) {
+ flg = TTY_NORMAL;
+@@ -1170,12 +1170,12 @@ static void lpuart_copy_rx_to_tty(struct
+
+ async_tx_ack(sport->dma_rx_desc);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state);
+ if (dmastat == DMA_ERROR) {
+ dev_err(sport->port.dev, "Rx DMA transfer failed!\n");
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ return;
+ }
+
+@@ -1244,7 +1244,7 @@ static void lpuart_copy_rx_to_tty(struct
+ dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1,
+ DMA_FROM_DEVICE);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ tty_flip_buffer_push(port);
+ if (!sport->dma_idle_int)
+@@ -1335,9 +1335,9 @@ static void lpuart_timer_func(struct tim
+ mod_timer(&sport->lpuart_timer,
+ jiffies + sport->dma_rx_timeout);
+
+- if (spin_trylock_irqsave(&sport->port.lock, flags)) {
++ if (uart_port_trylock_irqsave(&sport->port, &flags)) {
+ sport->last_residue = state.residue;
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+ }
+
+@@ -1802,14 +1802,14 @@ static void lpuart_hw_setup(struct lpuar
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ lpuart_setup_watermark_enable(sport);
+
+ lpuart_rx_dma_startup(sport);
+ lpuart_tx_dma_startup(sport);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static int lpuart_startup(struct uart_port *port)
+@@ -1859,7 +1859,7 @@ static void lpuart32_hw_setup(struct lpu
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ lpuart32_hw_disable(sport);
+
+@@ -1869,7 +1869,7 @@ static void lpuart32_hw_setup(struct lpu
+ lpuart32_setup_watermark_enable(sport);
+ lpuart32_configure(sport);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static int lpuart32_startup(struct uart_port *port)
+@@ -1932,7 +1932,7 @@ static void lpuart_shutdown(struct uart_
+ unsigned char temp;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* disable Rx/Tx and interrupts */
+ temp = readb(port->membase + UARTCR2);
+@@ -1940,7 +1940,7 @@ static void lpuart_shutdown(struct uart_
+ UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE);
+ writeb(temp, port->membase + UARTCR2);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ lpuart_dma_shutdown(sport);
+ }
+@@ -1952,7 +1952,7 @@ static void lpuart32_shutdown(struct uar
+ unsigned long temp;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* clear status */
+ temp = lpuart32_read(&sport->port, UARTSTAT);
+@@ -1969,7 +1969,7 @@ static void lpuart32_shutdown(struct uar
+ UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE | UARTCTRL_SBK);
+ lpuart32_write(port, temp, UARTCTRL);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ lpuart_dma_shutdown(sport);
+ }
+@@ -2069,7 +2069,7 @@ lpuart_set_termios(struct uart_port *por
+ if (old && sport->lpuart_dma_rx_use)
+ lpuart_dma_rx_free(&sport->port);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ sport->port.read_status_mask = 0;
+ if (termios->c_iflag & INPCK)
+@@ -2124,7 +2124,7 @@ lpuart_set_termios(struct uart_port *por
+ sport->lpuart_dma_rx_use = false;
+ }
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static void __lpuart32_serial_setbrg(struct uart_port *port,
+@@ -2304,7 +2304,7 @@ lpuart32_set_termios(struct uart_port *p
+ if (old && sport->lpuart_dma_rx_use)
+ lpuart_dma_rx_free(&sport->port);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ sport->port.read_status_mask = 0;
+ if (termios->c_iflag & INPCK)
+@@ -2359,7 +2359,7 @@ lpuart32_set_termios(struct uart_port *p
+ sport->lpuart_dma_rx_use = false;
+ }
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static const char *lpuart_type(struct uart_port *port)
+@@ -2477,9 +2477,9 @@ lpuart_console_write(struct console *co,
+ int locked = 1;
+
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&sport->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&sport->port, &flags);
+ else
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /* first save CR2 and then disable interrupts */
+ cr2 = old_cr2 = readb(sport->port.membase + UARTCR2);
+@@ -2495,7 +2495,7 @@ lpuart_console_write(struct console *co,
+ writeb(old_cr2, sport->port.membase + UARTCR2);
+
+ if (locked)
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static void
+@@ -2507,9 +2507,9 @@ lpuart32_console_write(struct console *c
+ int locked = 1;
+
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&sport->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&sport->port, &flags);
+ else
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /* first save CR2 and then disable interrupts */
+ cr = old_cr = lpuart32_read(&sport->port, UARTCTRL);
+@@ -2525,7 +2525,7 @@ lpuart32_console_write(struct console *c
+ lpuart32_write(&sport->port, old_cr, UARTCTRL);
+
+ if (locked)
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ /*
+@@ -3089,7 +3089,7 @@ static int lpuart_suspend(struct device
+ uart_suspend_port(&lpuart_reg, &sport->port);
+
+ if (lpuart_uport_is_active(sport)) {
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (lpuart_is_32(sport)) {
+ /* disable Rx/Tx and interrupts */
+ temp = lpuart32_read(&sport->port, UARTCTRL);
+@@ -3101,7 +3101,7 @@ static int lpuart_suspend(struct device
+ temp &= ~(UARTCR2_TE | UARTCR2_TIE | UARTCR2_TCIE);
+ writeb(temp, sport->port.membase + UARTCR2);
+ }
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ if (sport->lpuart_dma_rx_use) {
+ /*
+@@ -3114,7 +3114,7 @@ static int lpuart_suspend(struct device
+ lpuart_dma_rx_free(&sport->port);
+
+ /* Disable Rx DMA to use UART port as wakeup source */
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (lpuart_is_32(sport)) {
+ temp = lpuart32_read(&sport->port, UARTBAUD);
+ lpuart32_write(&sport->port, temp & ~UARTBAUD_RDMAE,
+@@ -3123,11 +3123,11 @@ static int lpuart_suspend(struct device
+ writeb(readb(sport->port.membase + UARTCR5) &
+ ~UARTCR5_RDMAS, sport->port.membase + UARTCR5);
+ }
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ if (sport->lpuart_dma_tx_use) {
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (lpuart_is_32(sport)) {
+ temp = lpuart32_read(&sport->port, UARTBAUD);
+ temp &= ~UARTBAUD_TDMAE;
+@@ -3137,7 +3137,7 @@ static int lpuart_suspend(struct device
+ temp &= ~UARTCR5_TDMAS;
+ writeb(temp, sport->port.membase + UARTCR5);
+ }
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ sport->dma_tx_in_progress = false;
+ dmaengine_terminate_sync(sport->dma_tx_chan);
+ }
diff --git a/debian/patches-rt/0028-serial-icom-Use-port-lock-wrappers.patch b/debian/patches-rt/0028-serial-icom-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..da765879ce
--- /dev/null
+++ b/debian/patches-rt/0028-serial-icom-Use-port-lock-wrappers.patch
@@ -0,0 +1,151 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:45 +0206
+Subject: [PATCH 028/134] serial: icom: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-29-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/icom.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/icom.c
++++ b/drivers/tty/serial/icom.c
+@@ -929,7 +929,7 @@ static inline void check_modem_status(st
+ char delta_status;
+ unsigned char status;
+
+- spin_lock(&icom_port->uart_port.lock);
++ uart_port_lock(&icom_port->uart_port);
+
+ /*modem input register */
+ status = readb(&icom_port->dram->isr);
+@@ -951,7 +951,7 @@ static inline void check_modem_status(st
+ port.delta_msr_wait);
+ old_status = status;
+ }
+- spin_unlock(&icom_port->uart_port.lock);
++ uart_port_unlock(&icom_port->uart_port);
+ }
+
+ static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port)
+@@ -1093,7 +1093,7 @@ static void process_interrupt(u16 port_i
+ struct icom_port *icom_port)
+ {
+
+- spin_lock(&icom_port->uart_port.lock);
++ uart_port_lock(&icom_port->uart_port);
+ trace(icom_port, "INTERRUPT", port_int_reg);
+
+ if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED))
+@@ -1102,7 +1102,7 @@ static void process_interrupt(u16 port_i
+ if (port_int_reg & INT_RCV_COMPLETED)
+ recv_interrupt(port_int_reg, icom_port);
+
+- spin_unlock(&icom_port->uart_port.lock);
++ uart_port_unlock(&icom_port->uart_port);
+ }
+
+ static irqreturn_t icom_interrupt(int irq, void *dev_id)
+@@ -1186,14 +1186,14 @@ static unsigned int icom_tx_empty(struct
+ int ret;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (le16_to_cpu(icom_port->statStg->xmit[0].flags) &
+ SA_FLAGS_READY_TO_XMIT)
+ ret = TIOCSER_TEMT;
+ else
+ ret = 0;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return ret;
+ }
+
+@@ -1276,7 +1276,7 @@ static void icom_send_xchar(struct uart_
+
+ /* wait .1 sec to send char */
+ for (index = 0; index < 10; index++) {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ xdata = readb(&icom_port->dram->xchar);
+ if (xdata == 0x00) {
+ trace(icom_port, "QUICK_WRITE", 0);
+@@ -1284,10 +1284,10 @@ static void icom_send_xchar(struct uart_
+
+ /* flush write operation */
+ xdata = readb(&icom_port->dram->xchar);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ break;
+ }
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ msleep(10);
+ }
+ }
+@@ -1307,7 +1307,7 @@ static void icom_break(struct uart_port
+ unsigned char cmdReg;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ trace(icom_port, "BREAK", 0);
+ cmdReg = readb(&icom_port->dram->CmdReg);
+ if (break_state == -1) {
+@@ -1315,7 +1315,7 @@ static void icom_break(struct uart_port
+ } else {
+ writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg);
+ }
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int icom_open(struct uart_port *port)
+@@ -1365,7 +1365,7 @@ static void icom_set_termios(struct uart
+ unsigned long offset;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ trace(icom_port, "CHANGE_SPEED", 0);
+
+ cflag = termios->c_cflag;
+@@ -1516,7 +1516,7 @@ static void icom_set_termios(struct uart
+ trace(icom_port, "XR_ENAB", 0);
+ writeb(CMD_XMIT_RCV_ENABLE, &icom_port->dram->CmdReg);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *icom_type(struct uart_port *port)
diff --git a/debian/patches-rt/0029-serial-imx-Use-port-lock-wrappers.patch b/debian/patches-rt/0029-serial-imx-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..24f582ae87
--- /dev/null
+++ b/debian/patches-rt/0029-serial-imx-Use-port-lock-wrappers.patch
@@ -0,0 +1,354 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:46 +0206
+Subject: [PATCH 029/134] serial: imx: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-30-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/imx.c | 84 +++++++++++++++++++++++------------------------
+ 1 file changed, 42 insertions(+), 42 deletions(-)
+
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -575,7 +575,7 @@ static void imx_uart_dma_tx_callback(voi
+ unsigned long flags;
+ u32 ucr1;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
+
+@@ -600,7 +600,7 @@ static void imx_uart_dma_tx_callback(voi
+ imx_uart_writel(sport, ucr4, UCR4);
+ }
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ /* called with port.lock taken and irqs off */
+@@ -766,11 +766,11 @@ static irqreturn_t imx_uart_rtsint(int i
+ struct imx_port *sport = dev_id;
+ irqreturn_t ret;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+
+ ret = __imx_uart_rtsint(irq, dev_id);
+
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+
+ return ret;
+ }
+@@ -779,9 +779,9 @@ static irqreturn_t imx_uart_txint(int ir
+ {
+ struct imx_port *sport = dev_id;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+ imx_uart_transmit_buffer(sport);
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+ return IRQ_HANDLED;
+ }
+
+@@ -895,11 +895,11 @@ static irqreturn_t imx_uart_rxint(int ir
+ struct imx_port *sport = dev_id;
+ irqreturn_t ret;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+
+ ret = __imx_uart_rxint(irq, dev_id);
+
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+
+ return ret;
+ }
+@@ -962,7 +962,7 @@ static irqreturn_t imx_uart_int(int irq,
+ unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4;
+ irqreturn_t ret = IRQ_NONE;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+
+ usr1 = imx_uart_readl(sport, USR1);
+ usr2 = imx_uart_readl(sport, USR2);
+@@ -1032,7 +1032,7 @@ static irqreturn_t imx_uart_int(int irq,
+ ret = IRQ_HANDLED;
+ }
+
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+
+ return ret;
+ }
+@@ -1115,7 +1115,7 @@ static void imx_uart_break_ctl(struct ua
+ unsigned long flags;
+ u32 ucr1;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ ucr1 = imx_uart_readl(sport, UCR1) & ~UCR1_SNDBRK;
+
+@@ -1124,7 +1124,7 @@ static void imx_uart_break_ctl(struct ua
+
+ imx_uart_writel(sport, ucr1, UCR1);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ /*
+@@ -1137,9 +1137,9 @@ static void imx_uart_timeout(struct time
+ unsigned long flags;
+
+ if (sport->port.state) {
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ imx_uart_mctrl_check(sport);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
+ }
+@@ -1169,9 +1169,9 @@ static void imx_uart_dma_rx_callback(voi
+ status = dmaengine_tx_status(chan, sport->rx_cookie, &state);
+
+ if (status == DMA_ERROR) {
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+ imx_uart_clear_rx_errors(sport);
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+ return;
+ }
+
+@@ -1200,9 +1200,9 @@ static void imx_uart_dma_rx_callback(voi
+ r_bytes = rx_ring->head - rx_ring->tail;
+
+ /* If we received something, check for 0xff flood */
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+ imx_uart_check_flood(sport, imx_uart_readl(sport, USR2));
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+
+ if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
+
+@@ -1460,7 +1460,7 @@ static int imx_uart_startup(struct uart_
+ if (!uart_console(port) && imx_uart_dma_init(sport) == 0)
+ dma_is_inited = 1;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /* Reset fifo's and state machines */
+ imx_uart_soft_reset(sport);
+@@ -1533,7 +1533,7 @@ static int imx_uart_startup(struct uart_
+
+ imx_uart_disable_loopback_rs485(sport);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ return 0;
+ }
+@@ -1558,21 +1558,21 @@ static void imx_uart_shutdown(struct uar
+ sport->dma_is_rxing = 0;
+ }
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ imx_uart_stop_tx(port);
+ imx_uart_stop_rx(port);
+ imx_uart_disable_dma(sport);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ imx_uart_dma_exit(sport);
+ }
+
+ mctrl_gpio_disable_ms(sport->gpios);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ ucr2 = imx_uart_readl(sport, UCR2);
+ ucr2 &= ~(UCR2_TXEN | UCR2_ATEN);
+ imx_uart_writel(sport, ucr2, UCR2);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ /*
+ * Stop our timer.
+@@ -1583,7 +1583,7 @@ static void imx_uart_shutdown(struct uar
+ * Disable all interrupts, port and break condition.
+ */
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ ucr1 = imx_uart_readl(sport, UCR1);
+ ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_RXDMAEN |
+@@ -1605,7 +1605,7 @@ static void imx_uart_shutdown(struct uar
+ ucr4 &= ~UCR4_TCEN;
+ imx_uart_writel(sport, ucr4, UCR4);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ clk_disable_unprepare(sport->clk_per);
+ clk_disable_unprepare(sport->clk_ipg);
+@@ -1668,7 +1668,7 @@ imx_uart_set_termios(struct uart_port *p
+ baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+ quot = uart_get_divisor(port, baud);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /*
+ * Read current UCR2 and save it for future use, then clear all the bits
+@@ -1796,7 +1796,7 @@ imx_uart_set_termios(struct uart_port *p
+ if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
+ imx_uart_enable_ms(&sport->port);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static const char *imx_uart_type(struct uart_port *port)
+@@ -1858,7 +1858,7 @@ static int imx_uart_poll_init(struct uar
+
+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /*
+ * Be careful about the order of enabling bits here. First enable the
+@@ -1886,7 +1886,7 @@ static int imx_uart_poll_init(struct uar
+ imx_uart_writel(sport, ucr1 | UCR1_RRDYEN, UCR1);
+ imx_uart_writel(sport, ucr2 | UCR2_ATEN, UCR2);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ return 0;
+ }
+@@ -2005,9 +2005,9 @@ imx_uart_console_write(struct console *c
+ if (sport->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&sport->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&sport->port, &flags);
+ else
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ /*
+ * First, save UCR1/2/3 and then disable interrupts
+@@ -2035,7 +2035,7 @@ imx_uart_console_write(struct console *c
+ imx_uart_ucrs_restore(sport, &old_ucr);
+
+ if (locked)
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ /*
+@@ -2193,10 +2193,10 @@ static enum hrtimer_restart imx_trigger_
+ struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx);
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (sport->tx_state == WAIT_AFTER_RTS)
+ imx_uart_start_tx(&sport->port);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ return HRTIMER_NORESTART;
+ }
+@@ -2206,10 +2206,10 @@ static enum hrtimer_restart imx_trigger_
+ struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx);
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (sport->tx_state == WAIT_AFTER_SEND)
+ imx_uart_stop_tx(&sport->port);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ return HRTIMER_NORESTART;
+ }
+@@ -2482,9 +2482,9 @@ static void imx_uart_restore_context(str
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ if (!sport->context_saved) {
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ return;
+ }
+
+@@ -2499,7 +2499,7 @@ static void imx_uart_restore_context(str
+ imx_uart_writel(sport, sport->saved_reg[2], UCR3);
+ imx_uart_writel(sport, sport->saved_reg[3], UCR4);
+ sport->context_saved = false;
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static void imx_uart_save_context(struct imx_port *sport)
+@@ -2507,7 +2507,7 @@ static void imx_uart_save_context(struct
+ unsigned long flags;
+
+ /* Save necessary regs */
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ sport->saved_reg[0] = imx_uart_readl(sport, UCR1);
+ sport->saved_reg[1] = imx_uart_readl(sport, UCR2);
+ sport->saved_reg[2] = imx_uart_readl(sport, UCR3);
+@@ -2519,7 +2519,7 @@ static void imx_uart_save_context(struct
+ sport->saved_reg[8] = imx_uart_readl(sport, UBMR);
+ sport->saved_reg[9] = imx_uart_readl(sport, IMX21_UTS);
+ sport->context_saved = true;
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
diff --git a/debian/patches-rt/0030-serial-ip22zilog-Use-port-lock-wrappers.patch b/debian/patches-rt/0030-serial-ip22zilog-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..c1307a246b
--- /dev/null
+++ b/debian/patches-rt/0030-serial-ip22zilog-Use-port-lock-wrappers.patch
@@ -0,0 +1,185 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:47 +0206
+Subject: [PATCH 030/134] serial: ip22zilog: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-31-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/ip22zilog.c | 36 ++++++++++++++++++------------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+--- a/drivers/tty/serial/ip22zilog.c
++++ b/drivers/tty/serial/ip22zilog.c
+@@ -432,7 +432,7 @@ static irqreturn_t ip22zilog_interrupt(i
+ unsigned char r3;
+ bool push = false;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ r3 = read_zsreg(channel, R3);
+
+ /* Channel A */
+@@ -448,7 +448,7 @@ static irqreturn_t ip22zilog_interrupt(i
+ if (r3 & CHATxIP)
+ ip22zilog_transmit_chars(up, channel);
+ }
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ if (push)
+ tty_flip_buffer_push(&up->port.state->port);
+@@ -458,7 +458,7 @@ static irqreturn_t ip22zilog_interrupt(i
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+ push = false;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
+ writeb(RES_H_IUS, &channel->control);
+ ZSDELAY();
+@@ -471,7 +471,7 @@ static irqreturn_t ip22zilog_interrupt(i
+ if (r3 & CHBTxIP)
+ ip22zilog_transmit_chars(up, channel);
+ }
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ if (push)
+ tty_flip_buffer_push(&up->port.state->port);
+@@ -504,11 +504,11 @@ static unsigned int ip22zilog_tx_empty(s
+ unsigned char status;
+ unsigned int ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ status = ip22zilog_read_channel_status(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (status & Tx_BUF_EMP)
+ ret = TIOCSER_TEMT;
+@@ -664,7 +664,7 @@ static void ip22zilog_break_ctl(struct u
+ else
+ clear_bits |= SND_BRK;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;
+ if (new_reg != up->curregs[R5]) {
+@@ -674,7 +674,7 @@ static void ip22zilog_break_ctl(struct u
+ write_zsreg(channel, R5, up->curregs[R5]);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void __ip22zilog_reset(struct uart_ip22zilog_port *up)
+@@ -735,9 +735,9 @@ static int ip22zilog_startup(struct uart
+ if (ZS_IS_CONS(up))
+ return 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ __ip22zilog_startup(up);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return 0;
+ }
+
+@@ -775,7 +775,7 @@ static void ip22zilog_shutdown(struct ua
+ if (ZS_IS_CONS(up))
+ return;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ channel = ZILOG_CHANNEL_FROM_PORT(port);
+
+@@ -788,7 +788,7 @@ static void ip22zilog_shutdown(struct ua
+ up->curregs[R5] &= ~SND_BRK;
+ ip22zilog_maybe_update_regs(up, channel);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* Shared by TTY driver and serial console setup. The port lock is held
+@@ -880,7 +880,7 @@ ip22zilog_set_termios(struct uart_port *
+
+ baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+
+@@ -894,7 +894,7 @@ ip22zilog_set_termios(struct uart_port *
+ ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static const char *ip22zilog_type(struct uart_port *port)
+@@ -1016,10 +1016,10 @@ ip22zilog_console_write(struct console *
+ struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index];
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ uart_console_write(&up->port, s, count, ip22zilog_put_char);
+ udelay(2);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int __init ip22zilog_console_setup(struct console *con, char *options)
+@@ -1034,13 +1034,13 @@ static int __init ip22zilog_console_setu
+
+ printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ up->curregs[R15] |= BRKIE;
+
+ __ip22zilog_startup(up);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
diff --git a/debian/patches-rt/0031-serial-jsm-Use-port-lock-wrappers.patch b/debian/patches-rt/0031-serial-jsm-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..4326b333a7
--- /dev/null
+++ b/debian/patches-rt/0031-serial-jsm-Use-port-lock-wrappers.patch
@@ -0,0 +1,124 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:48 +0206
+Subject: [PATCH 031/134] serial: jsm: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-32-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/jsm/jsm_neo.c | 4 ++--
+ drivers/tty/serial/jsm/jsm_tty.c | 16 ++++++++--------
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/jsm/jsm_neo.c
++++ b/drivers/tty/serial/jsm/jsm_neo.c
+@@ -816,9 +816,9 @@ static void neo_parse_isr(struct jsm_boa
+ /* Parse any modem signal changes */
+ jsm_dbg(INTR, &ch->ch_bd->pci_dev,
+ "MOD_STAT: sending to parse_modem_sigs\n");
+- spin_lock_irqsave(&ch->uart_port.lock, lock_flags);
++ uart_port_lock_irqsave(&ch->uart_port, &lock_flags);
+ neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr));
+- spin_unlock_irqrestore(&ch->uart_port.lock, lock_flags);
++ uart_port_unlock_irqrestore(&ch->uart_port, lock_flags);
+ }
+ }
+
+--- a/drivers/tty/serial/jsm/jsm_tty.c
++++ b/drivers/tty/serial/jsm/jsm_tty.c
+@@ -152,14 +152,14 @@ static void jsm_tty_send_xchar(struct ua
+ container_of(port, struct jsm_channel, uart_port);
+ struct ktermios *termios;
+
+- spin_lock_irqsave(&port->lock, lock_flags);
++ uart_port_lock_irqsave(port, &lock_flags);
+ termios = &port->state->port.tty->termios;
+ if (ch == termios->c_cc[VSTART])
+ channel->ch_bd->bd_ops->send_start_character(channel);
+
+ if (ch == termios->c_cc[VSTOP])
+ channel->ch_bd->bd_ops->send_stop_character(channel);
+- spin_unlock_irqrestore(&port->lock, lock_flags);
++ uart_port_unlock_irqrestore(port, lock_flags);
+ }
+
+ static void jsm_tty_stop_rx(struct uart_port *port)
+@@ -176,13 +176,13 @@ static void jsm_tty_break(struct uart_po
+ struct jsm_channel *channel =
+ container_of(port, struct jsm_channel, uart_port);
+
+- spin_lock_irqsave(&port->lock, lock_flags);
++ uart_port_lock_irqsave(port, &lock_flags);
+ if (break_state == -1)
+ channel->ch_bd->bd_ops->send_break(channel);
+ else
+ channel->ch_bd->bd_ops->clear_break(channel);
+
+- spin_unlock_irqrestore(&port->lock, lock_flags);
++ uart_port_unlock_irqrestore(port, lock_flags);
+ }
+
+ static int jsm_tty_open(struct uart_port *port)
+@@ -241,7 +241,7 @@ static int jsm_tty_open(struct uart_port
+ channel->ch_cached_lsr = 0;
+ channel->ch_stops_sent = 0;
+
+- spin_lock_irqsave(&port->lock, lock_flags);
++ uart_port_lock_irqsave(port, &lock_flags);
+ termios = &port->state->port.tty->termios;
+ channel->ch_c_cflag = termios->c_cflag;
+ channel->ch_c_iflag = termios->c_iflag;
+@@ -261,7 +261,7 @@ static int jsm_tty_open(struct uart_port
+ jsm_carrier(channel);
+
+ channel->ch_open_count++;
+- spin_unlock_irqrestore(&port->lock, lock_flags);
++ uart_port_unlock_irqrestore(port, lock_flags);
+
+ jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n");
+ return 0;
+@@ -307,7 +307,7 @@ static void jsm_tty_set_termios(struct u
+ struct jsm_channel *channel =
+ container_of(port, struct jsm_channel, uart_port);
+
+- spin_lock_irqsave(&port->lock, lock_flags);
++ uart_port_lock_irqsave(port, &lock_flags);
+ channel->ch_c_cflag = termios->c_cflag;
+ channel->ch_c_iflag = termios->c_iflag;
+ channel->ch_c_oflag = termios->c_oflag;
+@@ -317,7 +317,7 @@ static void jsm_tty_set_termios(struct u
+
+ channel->ch_bd->bd_ops->param(channel);
+ jsm_carrier(channel);
+- spin_unlock_irqrestore(&port->lock, lock_flags);
++ uart_port_unlock_irqrestore(port, lock_flags);
+ }
+
+ static const char *jsm_tty_type(struct uart_port *port)
diff --git a/debian/patches-rt/0032-serial-liteuart-Use-port-lock-wrappers.patch b/debian/patches-rt/0032-serial-liteuart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..ae679c098c
--- /dev/null
+++ b/debian/patches-rt/0032-serial-liteuart-Use-port-lock-wrappers.patch
@@ -0,0 +1,110 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:49 +0206
+Subject: [PATCH 032/134] serial: liteuart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Gabriel Somlo <gsomlo@gmail.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-33-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/liteuart.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/liteuart.c
++++ b/drivers/tty/serial/liteuart.c
+@@ -139,13 +139,13 @@ static irqreturn_t liteuart_interrupt(in
+ * if polling, the context would be "in_serving_softirq", so use
+ * irq[save|restore] spin_lock variants to cover all possibilities
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ isr = litex_read8(port->membase + OFF_EV_PENDING) & uart->irq_reg;
+ if (isr & EV_RX)
+ liteuart_rx_chars(port);
+ if (isr & EV_TX)
+ liteuart_tx_chars(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_RETVAL(isr);
+ }
+@@ -195,10 +195,10 @@ static int liteuart_startup(struct uart_
+ }
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ /* only enabling rx irqs during startup */
+ liteuart_update_irq_reg(port, true, EV_RX);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (!port->irq) {
+ timer_setup(&uart->timer, liteuart_timer, 0);
+@@ -213,9 +213,9 @@ static void liteuart_shutdown(struct uar
+ struct liteuart_port *uart = to_liteuart_port(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ liteuart_update_irq_reg(port, false, EV_RX | EV_TX);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (port->irq)
+ free_irq(port->irq, port);
+@@ -229,13 +229,13 @@ static void liteuart_set_termios(struct
+ unsigned int baud;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* update baudrate */
+ baud = uart_get_baud_rate(port, new, old, 0, 460800);
+ uart_update_timeout(port, new->c_cflag, baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *liteuart_type(struct uart_port *port)
+@@ -382,9 +382,9 @@ static void liteuart_console_write(struc
+ uart = (struct liteuart_port *)xa_load(&liteuart_array, co->index);
+ port = &uart->port;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ uart_console_write(port, s, count, liteuart_putchar);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int liteuart_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0033-serial-lpc32xx_hs-Use-port-lock-wrappers.patch b/debian/patches-rt/0033-serial-lpc32xx_hs-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..06518e8460
--- /dev/null
+++ b/debian/patches-rt/0033-serial-lpc32xx_hs-Use-port-lock-wrappers.patch
@@ -0,0 +1,148 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:50 +0206
+Subject: [PATCH 033/134] serial: lpc32xx_hs: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-34-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/lpc32xx_hs.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/lpc32xx_hs.c
++++ b/drivers/tty/serial/lpc32xx_hs.c
+@@ -140,15 +140,15 @@ static void lpc32xx_hsuart_console_write
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&up->port.lock);
++ locked = uart_port_trylock(&up->port);
+ else
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar);
+ wait_for_xmit_empty(&up->port);
+
+ if (locked)
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+ local_irq_restore(flags);
+ }
+
+@@ -298,7 +298,7 @@ static irqreturn_t serial_lpc32xx_interr
+ struct tty_port *tport = &port->state->port;
+ u32 status;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ /* Read UART status and clear latched interrupts */
+ status = readl(LPC32XX_HSUART_IIR(port->membase));
+@@ -333,7 +333,7 @@ static irqreturn_t serial_lpc32xx_interr
+ __serial_lpc32xx_tx(port);
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -404,14 +404,14 @@ static void serial_lpc32xx_break_ctl(str
+ unsigned long flags;
+ u32 tmp;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+ if (break_state != 0)
+ tmp |= LPC32XX_HSU_BREAK;
+ else
+ tmp &= ~LPC32XX_HSU_BREAK;
+ writel(tmp, LPC32XX_HSUART_CTRL(port->membase));
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* port->lock is not held. */
+@@ -421,7 +421,7 @@ static int serial_lpc32xx_startup(struct
+ unsigned long flags;
+ u32 tmp;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ __serial_uart_flush(port);
+
+@@ -441,7 +441,7 @@ static int serial_lpc32xx_startup(struct
+
+ lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ retval = request_irq(port->irq, serial_lpc32xx_interrupt,
+ 0, MODNAME, port);
+@@ -458,7 +458,7 @@ static void serial_lpc32xx_shutdown(stru
+ u32 tmp;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B |
+ LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B;
+@@ -466,7 +466,7 @@ static void serial_lpc32xx_shutdown(stru
+
+ lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ free_irq(port->irq, port);
+ }
+@@ -491,7 +491,7 @@ static void serial_lpc32xx_set_termios(s
+
+ quot = __serial_get_clock_div(port->uartclk, baud);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Ignore characters? */
+ tmp = readl(LPC32XX_HSUART_CTRL(port->membase));
+@@ -505,7 +505,7 @@ static void serial_lpc32xx_set_termios(s
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
diff --git a/debian/patches-rt/0034-serial-ma35d1-Use-port-lock-wrappers.patch b/debian/patches-rt/0034-serial-ma35d1-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..995bad9aad
--- /dev/null
+++ b/debian/patches-rt/0034-serial-ma35d1-Use-port-lock-wrappers.patch
@@ -0,0 +1,117 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:51 +0206
+Subject: [PATCH 034/134] serial: ma35d1: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-35-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/ma35d1_serial.c | 22 +++++++++++-----------
+ 1 file changed, 11 insertions(+), 11 deletions(-)
+
+--- a/drivers/tty/serial/ma35d1_serial.c
++++ b/drivers/tty/serial/ma35d1_serial.c
+@@ -269,16 +269,16 @@ static void receive_chars(struct uart_ma
+ if (uart_handle_sysrq_char(&up->port, ch))
+ continue;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ uart_insert_char(&up->port, fsr, MA35_FSR_RX_OVER_IF, ch, flag);
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ fsr = serial_in(up, MA35_FSR_REG);
+ } while (!(fsr & MA35_FSR_RX_EMPTY) && (max_count-- > 0));
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ tty_flip_buffer_push(&up->port.state->port);
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+ }
+
+ static irqreturn_t ma35d1serial_interrupt(int irq, void *dev_id)
+@@ -364,14 +364,14 @@ static void ma35d1serial_break_ctl(struc
+ unsigned long flags;
+ u32 lcr;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ lcr = serial_in(up, MA35_LCR_REG);
+ if (break_state != 0)
+ lcr |= MA35_LCR_BREAK;
+ else
+ lcr &= ~MA35_LCR_BREAK;
+ serial_out(up, MA35_LCR_REG, lcr);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int ma35d1serial_startup(struct uart_port *port)
+@@ -441,7 +441,7 @@ static void ma35d1serial_set_termios(str
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ up->port.read_status_mask = MA35_FSR_RX_OVER_IF;
+ if (termios->c_iflag & INPCK)
+@@ -475,7 +475,7 @@ static void ma35d1serial_set_termios(str
+
+ serial_out(up, MA35_LCR_REG, lcr);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static const char *ma35d1serial_type(struct uart_port *port)
+@@ -560,9 +560,9 @@ static void ma35d1serial_console_write(s
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&up->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&up->port, &flags);
+ else
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -576,7 +576,7 @@ static void ma35d1serial_console_write(s
+ serial_out(up, MA35_IER_REG, ier);
+
+ if (locked)
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int __init ma35d1serial_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0035-serial-mcf-Use-port-lock-wrappers.patch b/debian/patches-rt/0035-serial-mcf-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..966618a3e4
--- /dev/null
+++ b/debian/patches-rt/0035-serial-mcf-Use-port-lock-wrappers.patch
@@ -0,0 +1,127 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:52 +0206
+Subject: [PATCH 035/134] serial: mcf: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-36-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/mcf.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/mcf.c
++++ b/drivers/tty/serial/mcf.c
+@@ -135,12 +135,12 @@ static void mcf_break_ctl(struct uart_po
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (break_state == -1)
+ writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR);
+ else
+ writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /****************************************************************************/
+@@ -150,7 +150,7 @@ static int mcf_startup(struct uart_port
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Reset UART, get it into known state... */
+ writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
+@@ -164,7 +164,7 @@ static int mcf_startup(struct uart_port
+ pp->imr = MCFUART_UIR_RXREADY;
+ writeb(pp->imr, port->membase + MCFUART_UIMR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -176,7 +176,7 @@ static void mcf_shutdown(struct uart_por
+ struct mcf_uart *pp = container_of(port, struct mcf_uart, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable all interrupts now */
+ pp->imr = 0;
+@@ -186,7 +186,7 @@ static void mcf_shutdown(struct uart_por
+ writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR);
+ writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /****************************************************************************/
+@@ -252,7 +252,7 @@ static void mcf_set_termios(struct uart_
+ mr2 |= MCFUART_MR2_TXCTS;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (port->rs485.flags & SER_RS485_ENABLED) {
+ dev_dbg(port->dev, "Setting UART to RS485\n");
+ mr2 |= MCFUART_MR2_TXRTS;
+@@ -273,7 +273,7 @@ static void mcf_set_termios(struct uart_
+ port->membase + MCFUART_UCSR);
+ writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE,
+ port->membase + MCFUART_UCR);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /****************************************************************************/
+@@ -350,7 +350,7 @@ static irqreturn_t mcf_interrupt(int irq
+
+ isr = readb(port->membase + MCFUART_UISR) & pp->imr;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ if (isr & MCFUART_UIR_RXREADY) {
+ mcf_rx_chars(pp);
+ ret = IRQ_HANDLED;
+@@ -359,7 +359,7 @@ static irqreturn_t mcf_interrupt(int irq
+ mcf_tx_chars(pp);
+ ret = IRQ_HANDLED;
+ }
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return ret;
+ }
diff --git a/debian/patches-rt/0036-serial-men_z135_uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0036-serial-men_z135_uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..11019689b6
--- /dev/null
+++ b/debian/patches-rt/0036-serial-men_z135_uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,76 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:53 +0206
+Subject: [PATCH 036/134] serial: men_z135_uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-37-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/men_z135_uart.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/men_z135_uart.c
++++ b/drivers/tty/serial/men_z135_uart.c
+@@ -392,7 +392,7 @@ static irqreturn_t men_z135_intr(int irq
+ if (!irq_id)
+ goto out;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ /* It's save to write to IIR[7:6] RXC[9:8] */
+ iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
+
+@@ -418,7 +418,7 @@ static irqreturn_t men_z135_intr(int irq
+ handled = true;
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ out:
+ return IRQ_RETVAL(handled);
+ }
+@@ -708,7 +708,7 @@ static void men_z135_set_termios(struct
+
+ baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
+
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+
+@@ -716,7 +716,7 @@ static void men_z135_set_termios(struct
+ iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ }
+
+ static const char *men_z135_type(struct uart_port *port)
diff --git a/debian/patches-rt/0037-serial-meson-Use-port-lock-wrappers.patch b/debian/patches-rt/0037-serial-meson-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..d2efb460bc
--- /dev/null
+++ b/debian/patches-rt/0037-serial-meson-Use-port-lock-wrappers.patch
@@ -0,0 +1,168 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:54 +0206
+Subject: [PATCH 037/134] serial: meson: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-38-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/meson_uart.c | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+--- a/drivers/tty/serial/meson_uart.c
++++ b/drivers/tty/serial/meson_uart.c
+@@ -129,14 +129,14 @@ static void meson_uart_shutdown(struct u
+
+ free_irq(port->irq, port);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = readl(port->membase + AML_UART_CONTROL);
+ val &= ~AML_UART_RX_EN;
+ val &= ~(AML_UART_RX_INT_EN | AML_UART_TX_INT_EN);
+ writel(val, port->membase + AML_UART_CONTROL);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void meson_uart_start_tx(struct uart_port *port)
+@@ -238,7 +238,7 @@ static irqreturn_t meson_uart_interrupt(
+ {
+ struct uart_port *port = (struct uart_port *)dev_id;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY))
+ meson_receive_chars(port);
+@@ -248,7 +248,7 @@ static irqreturn_t meson_uart_interrupt(
+ meson_uart_start_tx(port);
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -284,7 +284,7 @@ static int meson_uart_startup(struct uar
+ u32 val;
+ int ret = 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = readl(port->membase + AML_UART_CONTROL);
+ val |= AML_UART_CLEAR_ERR;
+@@ -301,7 +301,7 @@ static int meson_uart_startup(struct uar
+ val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2));
+ writel(val, port->membase + AML_UART_MISC);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ ret = request_irq(port->irq, meson_uart_interrupt, 0,
+ port->name, port);
+@@ -341,7 +341,7 @@ static void meson_uart_set_termios(struc
+ unsigned long flags;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ cflags = termios->c_cflag;
+ iflags = termios->c_iflag;
+@@ -405,7 +405,7 @@ static void meson_uart_set_termios(struc
+ AML_UART_FRAME_ERR;
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int meson_uart_verify_port(struct uart_port *port,
+@@ -464,14 +464,14 @@ static int meson_uart_poll_get_char(stru
+ u32 c;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)
+ c = NO_POLL_CHAR;
+ else
+ c = readl(port->membase + AML_UART_RFIFO);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return c;
+ }
+@@ -482,7 +482,7 @@ static void meson_uart_poll_put_char(str
+ u32 reg;
+ int ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Wait until FIFO is empty or timeout */
+ ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg,
+@@ -506,7 +506,7 @@ static void meson_uart_poll_put_char(str
+ dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n");
+
+ out:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ #endif /* CONFIG_CONSOLE_POLL */
+@@ -563,9 +563,9 @@ static void meson_serial_port_write(stru
+ if (port->sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+- locked = spin_trylock(&port->lock);
++ locked = uart_port_trylock(port);
+ } else {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ locked = 1;
+ }
+
+@@ -577,7 +577,7 @@ static void meson_serial_port_write(stru
+ writel(val, port->membase + AML_UART_CONTROL);
+
+ if (locked)
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ local_irq_restore(flags);
+ }
+
diff --git a/debian/patches-rt/0038-serial-milbeaut_usio-Use-port-lock-wrappers.patch b/debian/patches-rt/0038-serial-milbeaut_usio-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..47b1b7f3cc
--- /dev/null
+++ b/debian/patches-rt/0038-serial-milbeaut_usio-Use-port-lock-wrappers.patch
@@ -0,0 +1,101 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:55 +0206
+Subject: [PATCH 038/134] serial: milbeaut_usio: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-39-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/milbeaut_usio.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/tty/serial/milbeaut_usio.c
++++ b/drivers/tty/serial/milbeaut_usio.c
+@@ -207,9 +207,9 @@ static irqreturn_t mlb_usio_rx_irq(int i
+ {
+ struct uart_port *port = dev_id;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ mlb_usio_rx_chars(port);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -218,10 +218,10 @@ static irqreturn_t mlb_usio_tx_irq(int i
+ {
+ struct uart_port *port = dev_id;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ if (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI)
+ mlb_usio_tx_chars(port);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -267,7 +267,7 @@ static int mlb_usio_startup(struct uart_
+ escr = readb(port->membase + MLB_USIO_REG_ESCR);
+ if (of_property_read_bool(port->dev->of_node, "auto-flow-control"))
+ escr |= MLB_USIO_ESCR_FLWEN;
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ writeb(0, port->membase + MLB_USIO_REG_SCR);
+ writeb(escr, port->membase + MLB_USIO_REG_ESCR);
+ writeb(MLB_USIO_SCR_UPCL, port->membase + MLB_USIO_REG_SCR);
+@@ -282,7 +282,7 @@ static int mlb_usio_startup(struct uart_
+
+ writeb(MLB_USIO_SCR_TXE | MLB_USIO_SCR_RIE | MLB_USIO_SCR_TBIE |
+ MLB_USIO_SCR_RXE, port->membase + MLB_USIO_REG_SCR);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -337,7 +337,7 @@ static void mlb_usio_set_termios(struct
+ else
+ quot = 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ uart_update_timeout(port, termios->c_cflag, baud);
+ port->read_status_mask = MLB_USIO_SSR_ORE | MLB_USIO_SSR_RDRF |
+ MLB_USIO_SSR_TDRE;
+@@ -367,7 +367,7 @@ static void mlb_usio_set_termios(struct
+ writew(BIT(12), port->membase + MLB_USIO_REG_FBYTE);
+ writeb(MLB_USIO_SCR_RIE | MLB_USIO_SCR_RXE | MLB_USIO_SCR_TBIE |
+ MLB_USIO_SCR_TXE, port->membase + MLB_USIO_REG_SCR);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *mlb_usio_type(struct uart_port *port)
diff --git a/debian/patches-rt/0039-serial-mpc52xx-Use-port-lock-wrappers.patch b/debian/patches-rt/0039-serial-mpc52xx-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..ee7014a925
--- /dev/null
+++ b/debian/patches-rt/0039-serial-mpc52xx-Use-port-lock-wrappers.patch
@@ -0,0 +1,89 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:56 +0206
+Subject: [PATCH 039/134] serial: mpc52xx: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-40-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/mpc52xx_uart.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/serial/mpc52xx_uart.c
++++ b/drivers/tty/serial/mpc52xx_uart.c
+@@ -1096,14 +1096,14 @@ static void
+ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
+ {
+ unsigned long flags;
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (ctl == -1)
+ psc_ops->command(port, MPC52xx_PSC_START_BRK);
+ else
+ psc_ops->command(port, MPC52xx_PSC_STOP_BRK);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int
+@@ -1214,7 +1214,7 @@ mpc52xx_uart_set_termios(struct uart_por
+ }
+
+ /* Get the lock */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Do our best to flush TX & RX, so we don't lose anything */
+ /* But we don't wait indefinitely ! */
+@@ -1250,7 +1250,7 @@ mpc52xx_uart_set_termios(struct uart_por
+ psc_ops->command(port, MPC52xx_PSC_RX_ENABLE);
+
+ /* We're all set, release the lock */
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *
+@@ -1477,11 +1477,11 @@ mpc52xx_uart_int(int irq, void *dev_id)
+ struct uart_port *port = dev_id;
+ irqreturn_t ret;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ ret = psc_ops->handle_irq(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return ret;
+ }
diff --git a/debian/patches-rt/0040-serial-mps2-uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0040-serial-mps2-uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..a626bdb031
--- /dev/null
+++ b/debian/patches-rt/0040-serial-mps2-uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,103 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:57 +0206
+Subject: [PATCH 040/134] serial: mps2-uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-41-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/mps2-uart.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/tty/serial/mps2-uart.c
++++ b/drivers/tty/serial/mps2-uart.c
+@@ -188,12 +188,12 @@ static irqreturn_t mps2_uart_rxirq(int i
+ if (unlikely(!(irqflag & UARTn_INT_RX)))
+ return IRQ_NONE;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ mps2_uart_write8(port, UARTn_INT_RX, UARTn_INT);
+ mps2_uart_rx_chars(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -206,12 +206,12 @@ static irqreturn_t mps2_uart_txirq(int i
+ if (unlikely(!(irqflag & UARTn_INT_TX)))
+ return IRQ_NONE;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ mps2_uart_write8(port, UARTn_INT_TX, UARTn_INT);
+ mps2_uart_tx_chars(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -222,7 +222,7 @@ static irqreturn_t mps2_uart_oerrirq(int
+ struct uart_port *port = data;
+ u8 irqflag = mps2_uart_read8(port, UARTn_INT);
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (irqflag & UARTn_INT_RX_OVERRUN) {
+ struct tty_port *tport = &port->state->port;
+@@ -244,7 +244,7 @@ static irqreturn_t mps2_uart_oerrirq(int
+ handled = IRQ_HANDLED;
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return handled;
+ }
+@@ -356,12 +356,12 @@ mps2_uart_set_termios(struct uart_port *
+
+ bauddiv = DIV_ROUND_CLOSEST(port->uartclk, baud);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+ mps2_uart_write32(port, bauddiv, UARTn_BAUDDIV);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
diff --git a/debian/patches-rt/0041-serial-msm-Use-port-lock-wrappers.patch b/debian/patches-rt/0041-serial-msm-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..89b8453303
--- /dev/null
+++ b/debian/patches-rt/0041-serial-msm-Use-port-lock-wrappers.patch
@@ -0,0 +1,185 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:58 +0206
+Subject: [PATCH 041/134] serial: msm: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Bjorn Andersson <quic_bjorande@quicinc.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-42-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/msm_serial.c | 38 +++++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+--- a/drivers/tty/serial/msm_serial.c
++++ b/drivers/tty/serial/msm_serial.c
+@@ -444,7 +444,7 @@ static void msm_complete_tx_dma(void *ar
+ unsigned int count;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Already stopped */
+ if (!dma->count)
+@@ -476,7 +476,7 @@ static void msm_complete_tx_dma(void *ar
+
+ msm_handle_tx(port);
+ done:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count)
+@@ -549,7 +549,7 @@ static void msm_complete_rx_dma(void *ar
+ unsigned long flags;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Already stopped */
+ if (!dma->count)
+@@ -587,16 +587,16 @@ static void msm_complete_rx_dma(void *ar
+ if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK))
+ flag = TTY_NORMAL;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ sysrq = uart_handle_sysrq_char(port, dma->virt[i]);
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (!sysrq)
+ tty_insert_flip_char(tport, dma->virt[i], flag);
+ }
+
+ msm_start_rx_dma(msm_port);
+ done:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (count)
+ tty_flip_buffer_push(tport);
+@@ -762,9 +762,9 @@ static void msm_handle_rx_dm(struct uart
+ if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK))
+ flag = TTY_NORMAL;
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ sysrq = uart_handle_sysrq_char(port, buf[i]);
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ if (!sysrq)
+ tty_insert_flip_char(tport, buf[i], flag);
+ }
+@@ -824,9 +824,9 @@ static void msm_handle_rx(struct uart_po
+ else if (sr & MSM_UART_SR_PAR_FRAME_ERR)
+ flag = TTY_FRAME;
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ sysrq = uart_handle_sysrq_char(port, c);
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ if (!sysrq)
+ tty_insert_flip_char(tport, c, flag);
+ }
+@@ -951,7 +951,7 @@ static irqreturn_t msm_uart_irq(int irq,
+ unsigned int misr;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ misr = msm_read(port, MSM_UART_MISR);
+ msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */
+
+@@ -983,7 +983,7 @@ static irqreturn_t msm_uart_irq(int irq,
+ msm_handle_delta_cts(port);
+
+ msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -1128,13 +1128,13 @@ static int msm_set_baud_rate(struct uart
+ unsigned long flags, rate;
+
+ flags = *saved_flags;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ entry = msm_find_best_baud(port, baud, &rate);
+ clk_set_rate(msm_port->clk, rate);
+ baud = rate / 16 / entry->divisor;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ *saved_flags = flags;
+ port->uartclk = rate;
+
+@@ -1266,7 +1266,7 @@ static void msm_set_termios(struct uart_
+ unsigned long flags;
+ unsigned int baud, mr;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (dma->chan) /* Terminate if any */
+ msm_stop_dma(port, dma);
+@@ -1338,7 +1338,7 @@ static void msm_set_termios(struct uart_
+ /* Try to use DMA */
+ msm_start_rx_dma(msm_port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *msm_type(struct uart_port *port)
+@@ -1620,9 +1620,9 @@ static void __msm_console_write(struct u
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&port->lock);
++ locked = uart_port_trylock(port);
+ else
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (is_uartdm)
+ msm_reset_dm_count(port, count);
+@@ -1661,7 +1661,7 @@ static void __msm_console_write(struct u
+ }
+
+ if (locked)
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ local_irq_restore(flags);
+ }
diff --git a/debian/patches-rt/0042-serial-mvebu-uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0042-serial-mvebu-uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..28b2c3b46e
--- /dev/null
+++ b/debian/patches-rt/0042-serial-mvebu-uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,108 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:43:59 +0206
+Subject: [PATCH 042/134] serial: mvebu-uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-43-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/mvebu-uart.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/tty/serial/mvebu-uart.c
++++ b/drivers/tty/serial/mvebu-uart.c
+@@ -187,9 +187,9 @@ static unsigned int mvebu_uart_tx_empty(
+ unsigned long flags;
+ unsigned int st;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ st = readl(port->membase + UART_STAT);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return (st & STAT_TX_EMP) ? TIOCSER_TEMT : 0;
+ }
+@@ -249,14 +249,14 @@ static void mvebu_uart_break_ctl(struct
+ unsigned int ctl;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ctl = readl(port->membase + UART_CTRL(port));
+ if (brk == -1)
+ ctl |= CTRL_SND_BRK_SEQ;
+ else
+ ctl &= ~CTRL_SND_BRK_SEQ;
+ writel(ctl, port->membase + UART_CTRL(port));
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status)
+@@ -540,7 +540,7 @@ static void mvebu_uart_set_termios(struc
+ unsigned long flags;
+ unsigned int baud, min_baud, max_baud;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ port->read_status_mask = STAT_RX_RDY(port) | STAT_OVR_ERR |
+ STAT_TX_RDY(port) | STAT_TX_FIFO_FUL;
+@@ -589,7 +589,7 @@ static void mvebu_uart_set_termios(struc
+ uart_update_timeout(port, termios->c_cflag, baud);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *mvebu_uart_type(struct uart_port *port)
+@@ -735,9 +735,9 @@ static void mvebu_uart_console_write(str
+ int locked = 1;
+
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ier = readl(port->membase + UART_CTRL(port)) & CTRL_BRK_INT;
+ intr = readl(port->membase + UART_INTR(port)) &
+@@ -758,7 +758,7 @@ static void mvebu_uart_console_write(str
+ }
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int mvebu_uart_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0043-serial-omap-Use-port-lock-wrappers.patch b/debian/patches-rt/0043-serial-omap-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..a79d6253c4
--- /dev/null
+++ b/debian/patches-rt/0043-serial-omap-Use-port-lock-wrappers.patch
@@ -0,0 +1,180 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:00 +0206
+Subject: [PATCH 043/134] serial: omap: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-44-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/omap-serial.c | 38 +++++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -390,10 +390,10 @@ static void serial_omap_throttle(struct
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ serial_out(up, UART_IER, up->ier);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static void serial_omap_unthrottle(struct uart_port *port)
+@@ -401,10 +401,10 @@ static void serial_omap_unthrottle(struc
+ struct uart_omap_port *up = to_uart_omap_port(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ serial_out(up, UART_IER, up->ier);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static unsigned int check_modem_status(struct uart_omap_port *up)
+@@ -527,7 +527,7 @@ static irqreturn_t serial_omap_irq(int i
+ irqreturn_t ret = IRQ_NONE;
+ int max_count = 256;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ do {
+ iir = serial_in(up, UART_IIR);
+@@ -563,7 +563,7 @@ static irqreturn_t serial_omap_irq(int i
+ }
+ } while (max_count--);
+
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ tty_flip_buffer_push(&up->port.state->port);
+
+@@ -579,9 +579,9 @@ static unsigned int serial_omap_tx_empty
+ unsigned int ret = 0;
+
+ dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return ret;
+ }
+@@ -647,13 +647,13 @@ static void serial_omap_break_ctl(struct
+ unsigned long flags;
+
+ dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(up, UART_LCR, up->lcr);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int serial_omap_startup(struct uart_port *port)
+@@ -701,13 +701,13 @@ static int serial_omap_startup(struct ua
+ * Now, initialize the UART
+ */
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ /*
+ * Most PC uarts need OUT2 raised to enable interrupts.
+ */
+ up->port.mctrl |= TIOCM_OUT2;
+ serial_omap_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ up->msr_saved_flags = 0;
+ /*
+@@ -742,10 +742,10 @@ static void serial_omap_shutdown(struct
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ up->port.mctrl &= ~TIOCM_OUT2;
+ serial_omap_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ /*
+ * Disable break condition and FIFOs
+@@ -815,7 +815,7 @@ serial_omap_set_termios(struct uart_port
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -1013,7 +1013,7 @@ serial_omap_set_termios(struct uart_port
+
+ serial_omap_set_mctrl(&up->port, up->port.mctrl);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
+ }
+
+@@ -1216,9 +1216,9 @@ serial_omap_console_write(struct console
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&up->port.lock);
++ locked = uart_port_trylock(&up->port);
+ else
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -1245,7 +1245,7 @@ serial_omap_console_write(struct console
+ check_modem_status(up);
+
+ if (locked)
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+ local_irq_restore(flags);
+ }
+
diff --git a/debian/patches-rt/0044-serial-owl-Use-port-lock-wrappers.patch b/debian/patches-rt/0044-serial-owl-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..fd8dc75013
--- /dev/null
+++ b/debian/patches-rt/0044-serial-owl-Use-port-lock-wrappers.patch
@@ -0,0 +1,147 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:01 +0206
+Subject: [PATCH 044/134] serial: owl: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-45-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/owl-uart.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/owl-uart.c
++++ b/drivers/tty/serial/owl-uart.c
+@@ -125,12 +125,12 @@ static unsigned int owl_uart_tx_empty(st
+ u32 val;
+ unsigned int ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ ret = (val & OWL_UART_STAT_TFES) ? TIOCSER_TEMT : 0;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return ret;
+ }
+@@ -232,7 +232,7 @@ static irqreturn_t owl_uart_irq(int irq,
+ unsigned long flags;
+ u32 stat;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ stat = owl_uart_read(port, OWL_UART_STAT);
+
+@@ -246,7 +246,7 @@ static irqreturn_t owl_uart_irq(int irq,
+ stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP;
+ owl_uart_write(port, stat, OWL_UART_STAT);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -256,14 +256,14 @@ static void owl_uart_shutdown(struct uar
+ u32 val;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = owl_uart_read(port, OWL_UART_CTL);
+ val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_RXIE
+ | OWL_UART_CTL_TXDE | OWL_UART_CTL_RXDE | OWL_UART_CTL_EN);
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ free_irq(port->irq, port);
+ }
+@@ -279,7 +279,7 @@ static int owl_uart_startup(struct uart_
+ if (ret)
+ return ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = owl_uart_read(port, OWL_UART_STAT);
+ val |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP
+@@ -291,7 +291,7 @@ static int owl_uart_startup(struct uart_
+ val |= OWL_UART_CTL_EN;
+ owl_uart_write(port, val, OWL_UART_CTL);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -311,7 +311,7 @@ static void owl_uart_set_termios(struct
+ u32 ctl;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ctl = owl_uart_read(port, OWL_UART_CTL);
+
+@@ -371,7 +371,7 @@ static void owl_uart_set_termios(struct
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void owl_uart_release_port(struct uart_port *port)
+@@ -515,9 +515,9 @@ static void owl_uart_port_write(struct u
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&port->lock);
++ locked = uart_port_trylock(port);
+ else {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ locked = 1;
+ }
+
+@@ -541,7 +541,7 @@ static void owl_uart_port_write(struct u
+ owl_uart_write(port, old_ctl, OWL_UART_CTL);
+
+ if (locked)
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ local_irq_restore(flags);
+ }
diff --git a/debian/patches-rt/0045-serial-pch-Use-port-lock-wrappers.patch b/debian/patches-rt/0045-serial-pch-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..6c4781cd09
--- /dev/null
+++ b/debian/patches-rt/0045-serial-pch-Use-port-lock-wrappers.patch
@@ -0,0 +1,80 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:02 +0206
+Subject: [PATCH 045/134] serial: pch: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-46-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/pch_uart.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/tty/serial/pch_uart.c
++++ b/drivers/tty/serial/pch_uart.c
+@@ -1347,7 +1347,7 @@ static void pch_uart_set_termios(struct
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+
+ spin_lock_irqsave(&priv->lock, flags);
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+ rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb);
+@@ -1360,7 +1360,7 @@ static void pch_uart_set_termios(struct
+ tty_termios_encode_baud_rate(termios, baud, baud);
+
+ out:
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+@@ -1581,10 +1581,10 @@ pch_console_write(struct console *co, co
+ port_locked = 0;
+ } else if (oops_in_progress) {
+ priv_locked = spin_trylock(&priv->lock);
+- port_locked = spin_trylock(&priv->port.lock);
++ port_locked = uart_port_trylock(&priv->port);
+ } else {
+ spin_lock(&priv->lock);
+- spin_lock(&priv->port.lock);
++ uart_port_lock(&priv->port);
+ }
+
+ /*
+@@ -1604,7 +1604,7 @@ pch_console_write(struct console *co, co
+ iowrite8(ier, priv->membase + UART_IER);
+
+ if (port_locked)
+- spin_unlock(&priv->port.lock);
++ uart_port_unlock(&priv->port);
+ if (priv_locked)
+ spin_unlock(&priv->lock);
+ local_irq_restore(flags);
diff --git a/debian/patches-rt/0046-serial-pic32-Use-port-lock-wrappers.patch b/debian/patches-rt/0046-serial-pic32-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..7cb8da7d86
--- /dev/null
+++ b/debian/patches-rt/0046-serial-pic32-Use-port-lock-wrappers.patch
@@ -0,0 +1,118 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:03 +0206
+Subject: [PATCH 046/134] serial: pic32: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-47-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/pic32_uart.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/pic32_uart.c
++++ b/drivers/tty/serial/pic32_uart.c
+@@ -243,7 +243,7 @@ static void pic32_uart_break_ctl(struct
+ struct pic32_sport *sport = to_pic32_sport(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (ctl)
+ pic32_uart_writel(sport, PIC32_SET(PIC32_UART_STA),
+@@ -252,7 +252,7 @@ static void pic32_uart_break_ctl(struct
+ pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA),
+ PIC32_UART_STA_UTXBRK);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* get port type in string format */
+@@ -274,7 +274,7 @@ static void pic32_uart_do_rx(struct uart
+ */
+ max_count = PIC32_UART_RX_FIFO_DEPTH;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ tty = &port->state->port;
+
+@@ -331,7 +331,7 @@ static void pic32_uart_do_rx(struct uart
+
+ } while (--max_count);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ tty_flip_buffer_push(tty);
+ }
+@@ -410,9 +410,9 @@ static irqreturn_t pic32_uart_tx_interru
+ struct uart_port *port = dev_id;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ pic32_uart_do_tx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -580,9 +580,9 @@ static void pic32_uart_shutdown(struct u
+ unsigned long flags;
+
+ /* disable uart */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ pic32_uart_dsbl_and_mask(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ clk_disable_unprepare(sport->clk);
+
+ /* free all 3 interrupts for this UART */
+@@ -604,7 +604,7 @@ static void pic32_uart_set_termios(struc
+ unsigned int quot;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* disable uart and mask all interrupts while changing speed */
+ pic32_uart_dsbl_and_mask(port);
+@@ -672,7 +672,7 @@ static void pic32_uart_set_termios(struc
+ /* enable uart */
+ pic32_uart_en_and_unmask(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* serial core request to claim uart iomem */
diff --git a/debian/patches-rt/0047-serial-pmac_zilog-Use-port-lock-wrappers.patch b/debian/patches-rt/0047-serial-pmac_zilog-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..e4a81157e1
--- /dev/null
+++ b/debian/patches-rt/0047-serial-pmac_zilog-Use-port-lock-wrappers.patch
@@ -0,0 +1,232 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:04 +0206
+Subject: [PATCH 047/134] serial: pmac_zilog: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-48-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/pmac_zilog.c | 52 ++++++++++++++++++++--------------------
+ 1 file changed, 26 insertions(+), 26 deletions(-)
+
+--- a/drivers/tty/serial/pmac_zilog.c
++++ b/drivers/tty/serial/pmac_zilog.c
+@@ -246,9 +246,9 @@ static bool pmz_receive_chars(struct uar
+ #endif /* USE_CTRL_O_SYSRQ */
+ if (uap->port.sysrq) {
+ int swallow;
+- spin_unlock(&uap->port.lock);
++ uart_port_unlock(&uap->port);
+ swallow = uart_handle_sysrq_char(&uap->port, ch);
+- spin_lock(&uap->port.lock);
++ uart_port_lock(&uap->port);
+ if (swallow)
+ goto next_char;
+ }
+@@ -435,7 +435,7 @@ static irqreturn_t pmz_interrupt(int irq
+ uap_a = pmz_get_port_A(uap);
+ uap_b = uap_a->mate;
+
+- spin_lock(&uap_a->port.lock);
++ uart_port_lock(&uap_a->port);
+ r3 = read_zsreg(uap_a, R3);
+
+ /* Channel A */
+@@ -456,14 +456,14 @@ static irqreturn_t pmz_interrupt(int irq
+ rc = IRQ_HANDLED;
+ }
+ skip_a:
+- spin_unlock(&uap_a->port.lock);
++ uart_port_unlock(&uap_a->port);
+ if (push)
+ tty_flip_buffer_push(&uap->port.state->port);
+
+ if (!uap_b)
+ goto out;
+
+- spin_lock(&uap_b->port.lock);
++ uart_port_lock(&uap_b->port);
+ push = false;
+ if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
+ if (!ZS_IS_OPEN(uap_b)) {
+@@ -481,7 +481,7 @@ static irqreturn_t pmz_interrupt(int irq
+ rc = IRQ_HANDLED;
+ }
+ skip_b:
+- spin_unlock(&uap_b->port.lock);
++ uart_port_unlock(&uap_b->port);
+ if (push)
+ tty_flip_buffer_push(&uap->port.state->port);
+
+@@ -497,9 +497,9 @@ static inline u8 pmz_peek_status(struct
+ unsigned long flags;
+ u8 status;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ status = read_zsreg(uap, R0);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+
+ return status;
+ }
+@@ -685,7 +685,7 @@ static void pmz_break_ctl(struct uart_po
+ else
+ clear_bits |= SND_BRK;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits;
+ if (new_reg != uap->curregs[R5]) {
+@@ -693,7 +693,7 @@ static void pmz_break_ctl(struct uart_po
+ write_zsreg(uap, R5, uap->curregs[R5]);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ #ifdef CONFIG_PPC_PMAC
+@@ -865,18 +865,18 @@ static void pmz_irda_reset(struct uart_p
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ uap->curregs[R5] |= DTR;
+ write_zsreg(uap, R5, uap->curregs[R5]);
+ zssync(uap);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ msleep(110);
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+ uap->curregs[R5] &= ~DTR;
+ write_zsreg(uap, R5, uap->curregs[R5]);
+ zssync(uap);
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ msleep(10);
+ }
+
+@@ -896,9 +896,9 @@ static int pmz_startup(struct uart_port
+ * initialize the chip
+ */
+ if (!ZS_IS_CONS(uap)) {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ pwr_delay = __pmz_startup(uap);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ sprintf(uap->irq_name, PMACZILOG_NAME"%d", uap->port.line);
+ if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED,
+@@ -921,9 +921,9 @@ static int pmz_startup(struct uart_port
+ pmz_irda_reset(uap);
+
+ /* Enable interrupt requests for the channel */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ pmz_interrupt_control(uap, 1);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -933,7 +933,7 @@ static void pmz_shutdown(struct uart_por
+ struct uart_pmac_port *uap = to_pmz(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable interrupt requests for the channel */
+ pmz_interrupt_control(uap, 0);
+@@ -948,19 +948,19 @@ static void pmz_shutdown(struct uart_por
+ pmz_maybe_update_regs(uap);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Release interrupt handler */
+ free_irq(uap->port.irq, uap);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uap->flags &= ~PMACZILOG_FLAG_IS_OPEN;
+
+ if (!ZS_IS_CONS(uap))
+ pmz_set_scc_power(uap, 0); /* Shut the chip down */
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* Shared by TTY driver and serial console setup. The port lock is held
+@@ -1247,7 +1247,7 @@ static void pmz_set_termios(struct uart_
+ struct uart_pmac_port *uap = to_pmz(port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable IRQs on the port */
+ pmz_interrupt_control(uap, 0);
+@@ -1259,7 +1259,7 @@ static void pmz_set_termios(struct uart_
+ if (ZS_IS_OPEN(uap))
+ pmz_interrupt_control(uap, 1);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *pmz_type(struct uart_port *port)
+@@ -1896,7 +1896,7 @@ static void pmz_console_write(struct con
+ struct uart_pmac_port *uap = &pmz_ports[con->index];
+ unsigned long flags;
+
+- spin_lock_irqsave(&uap->port.lock, flags);
++ uart_port_lock_irqsave(&uap->port, &flags);
+
+ /* Turn of interrupts and enable the transmitter. */
+ write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB);
+@@ -1908,7 +1908,7 @@ static void pmz_console_write(struct con
+ write_zsreg(uap, R1, uap->curregs[1]);
+ /* Don't disable the transmitter. */
+
+- spin_unlock_irqrestore(&uap->port.lock, flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+ }
+
+ /*
diff --git a/debian/patches-rt/0048-serial-pxa-Use-port-lock-wrappers.patch b/debian/patches-rt/0048-serial-pxa-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..b0df211b6f
--- /dev/null
+++ b/debian/patches-rt/0048-serial-pxa-Use-port-lock-wrappers.patch
@@ -0,0 +1,150 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:05 +0206
+Subject: [PATCH 048/134] serial: pxa: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-49-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/pxa.c | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+--- a/drivers/tty/serial/pxa.c
++++ b/drivers/tty/serial/pxa.c
+@@ -225,14 +225,14 @@ static inline irqreturn_t serial_pxa_irq
+ iir = serial_in(up, UART_IIR);
+ if (iir & UART_IIR_NO_INT)
+ return IRQ_NONE;
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ lsr = serial_in(up, UART_LSR);
+ if (lsr & UART_LSR_DR)
+ receive_chars(up, &lsr);
+ check_modem_status(up);
+ if (lsr & UART_LSR_THRE)
+ transmit_chars(up);
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+ return IRQ_HANDLED;
+ }
+
+@@ -242,9 +242,9 @@ static unsigned int serial_pxa_tx_empty(
+ unsigned long flags;
+ unsigned int ret;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return ret;
+ }
+@@ -295,13 +295,13 @@ static void serial_pxa_break_ctl(struct
+ struct uart_pxa_port *up = (struct uart_pxa_port *)port;
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(up, UART_LCR, up->lcr);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int serial_pxa_startup(struct uart_port *port)
+@@ -346,10 +346,10 @@ static int serial_pxa_startup(struct uar
+ */
+ serial_out(up, UART_LCR, UART_LCR_WLEN8);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ up->port.mctrl |= TIOCM_OUT2;
+ serial_pxa_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ /*
+ * Finally, enable interrupts. Note: Modem status interrupts
+@@ -383,10 +383,10 @@ static void serial_pxa_shutdown(struct u
+ up->ier = 0;
+ serial_out(up, UART_IER, 0);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ up->port.mctrl &= ~TIOCM_OUT2;
+ serial_pxa_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ /*
+ * Disable break condition and FIFOs
+@@ -434,7 +434,7 @@ serial_pxa_set_termios(struct uart_port
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * Ensure the port will be enabled.
+@@ -504,7 +504,7 @@ serial_pxa_set_termios(struct uart_port
+ up->lcr = cval; /* Save LCR */
+ serial_pxa_set_mctrl(&up->port, up->port.mctrl);
+ serial_out(up, UART_FCR, fcr);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static void
+@@ -608,9 +608,9 @@ serial_pxa_console_write(struct console
+ if (up->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&up->port.lock);
++ locked = uart_port_trylock(&up->port);
+ else
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -628,7 +628,7 @@ serial_pxa_console_write(struct console
+ serial_out(up, UART_IER, ier);
+
+ if (locked)
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+ local_irq_restore(flags);
+ clk_disable(up->clk);
+
diff --git a/debian/patches-rt/0049-serial-qcom-geni-Use-port-lock-wrappers.patch b/debian/patches-rt/0049-serial-qcom-geni-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..4f1bc6a1cb
--- /dev/null
+++ b/debian/patches-rt/0049-serial-qcom-geni-Use-port-lock-wrappers.patch
@@ -0,0 +1,71 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:06 +0206
+Subject: [PATCH 049/134] serial: qcom-geni: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Bjorn Andersson <quic_bjorande@quicinc.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-50-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/qcom_geni_serial.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/qcom_geni_serial.c
++++ b/drivers/tty/serial/qcom_geni_serial.c
+@@ -482,9 +482,9 @@ static void qcom_geni_serial_console_wri
+
+ uport = &port->uport;
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&uport->lock, flags);
++ locked = uart_port_trylock_irqsave(uport, &flags);
+ else
+- spin_lock_irqsave(&uport->lock, flags);
++ uart_port_lock_irqsave(uport, &flags);
+
+ geni_status = readl(uport->membase + SE_GENI_STATUS);
+
+@@ -520,7 +520,7 @@ static void qcom_geni_serial_console_wri
+ qcom_geni_serial_setup_tx(uport, port->tx_remaining);
+
+ if (locked)
+- spin_unlock_irqrestore(&uport->lock, flags);
++ uart_port_unlock_irqrestore(uport, flags);
+ }
+
+ static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
+@@ -970,7 +970,7 @@ static irqreturn_t qcom_geni_serial_isr(
+ if (uport->suspended)
+ return IRQ_NONE;
+
+- spin_lock(&uport->lock);
++ uart_port_lock(uport);
+
+ m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS);
+ s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
diff --git a/debian/patches-rt/0050-serial-rda-Use-port-lock-wrappers.patch b/debian/patches-rt/0050-serial-rda-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..6d51972bcd
--- /dev/null
+++ b/debian/patches-rt/0050-serial-rda-Use-port-lock-wrappers.patch
@@ -0,0 +1,177 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:07 +0206
+Subject: [PATCH 050/134] serial: rda: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-51-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/rda-uart.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+--- a/drivers/tty/serial/rda-uart.c
++++ b/drivers/tty/serial/rda-uart.c
+@@ -139,12 +139,12 @@ static unsigned int rda_uart_tx_empty(st
+ unsigned int ret;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = rda_uart_read(port, RDA_UART_STATUS);
+ ret = (val & RDA_UART_TX_FIFO_MASK) ? TIOCSER_TEMT : 0;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return ret;
+ }
+@@ -246,7 +246,7 @@ static void rda_uart_set_termios(struct
+ unsigned int baud;
+ u32 irq_mask;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ baud = uart_get_baud_rate(port, termios, old, 9600, port->uartclk / 4);
+ rda_uart_change_baudrate(rda_port, baud);
+@@ -325,7 +325,7 @@ static void rda_uart_set_termios(struct
+ /* update the per-port timeout */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void rda_uart_send_chars(struct uart_port *port)
+@@ -408,7 +408,7 @@ static irqreturn_t rda_interrupt(int irq
+ unsigned long flags;
+ u32 val, irq_mask;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Clear IRQ cause */
+ val = rda_uart_read(port, RDA_UART_IRQ_CAUSE);
+@@ -425,7 +425,7 @@ static irqreturn_t rda_interrupt(int irq
+ rda_uart_send_chars(port);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -436,16 +436,16 @@ static int rda_uart_startup(struct uart_
+ int ret;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ rda_uart_write(port, 0, RDA_UART_IRQ_MASK);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ ret = request_irq(port->irq, rda_interrupt, IRQF_NO_SUSPEND,
+ "rda-uart", port);
+ if (ret)
+ return ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ val = rda_uart_read(port, RDA_UART_CTRL);
+ val |= RDA_UART_ENABLE;
+@@ -456,7 +456,7 @@ static int rda_uart_startup(struct uart_
+ val |= (RDA_UART_RX_DATA_AVAILABLE | RDA_UART_RX_TIMEOUT);
+ rda_uart_write(port, val, RDA_UART_IRQ_MASK);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -466,7 +466,7 @@ static void rda_uart_shutdown(struct uar
+ unsigned long flags;
+ u32 val;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ rda_uart_stop_tx(port);
+ rda_uart_stop_rx(port);
+@@ -475,7 +475,7 @@ static void rda_uart_shutdown(struct uar
+ val &= ~RDA_UART_ENABLE;
+ rda_uart_write(port, val, RDA_UART_CTRL);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *rda_uart_type(struct uart_port *port)
+@@ -515,7 +515,7 @@ static void rda_uart_config_port(struct
+ rda_uart_request_port(port);
+ }
+
+- spin_lock_irqsave(&port->lock, irq_flags);
++ uart_port_lock_irqsave(port, &irq_flags);
+
+ /* Clear mask, so no surprise interrupts. */
+ rda_uart_write(port, 0, RDA_UART_IRQ_MASK);
+@@ -523,7 +523,7 @@ static void rda_uart_config_port(struct
+ /* Clear status register */
+ rda_uart_write(port, 0, RDA_UART_STATUS);
+
+- spin_unlock_irqrestore(&port->lock, irq_flags);
++ uart_port_unlock_irqrestore(port, irq_flags);
+ }
+
+ static void rda_uart_release_port(struct uart_port *port)
+@@ -597,9 +597,9 @@ static void rda_uart_port_write(struct u
+ if (port->sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+- locked = spin_trylock(&port->lock);
++ locked = uart_port_trylock(port);
+ } else {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ locked = 1;
+ }
+
+@@ -615,7 +615,7 @@ static void rda_uart_port_write(struct u
+ rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK);
+
+ if (locked)
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ local_irq_restore(flags);
+ }
diff --git a/debian/patches-rt/0051-serial-rp2-Use-port-lock-wrappers.patch b/debian/patches-rt/0051-serial-rp2-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..e2009ff4c6
--- /dev/null
+++ b/debian/patches-rt/0051-serial-rp2-Use-port-lock-wrappers.patch
@@ -0,0 +1,114 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:08 +0206
+Subject: [PATCH 051/134] serial: rp2: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-52-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/rp2.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/rp2.c
++++ b/drivers/tty/serial/rp2.c
+@@ -276,9 +276,9 @@ static unsigned int rp2_uart_tx_empty(st
+ * But the TXEMPTY bit doesn't seem to work unless the TX IRQ is
+ * enabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ tx_fifo_bytes = readw(up->base + RP2_TX_FIFO_COUNT);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return tx_fifo_bytes ? 0 : TIOCSER_TEMT;
+ }
+@@ -323,10 +323,10 @@ static void rp2_uart_break_ctl(struct ua
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ rp2_rmw(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_BREAK_m,
+ break_state ? RP2_TXRX_CTL_BREAK_m : 0);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void rp2_uart_enable_ms(struct uart_port *port)
+@@ -383,7 +383,7 @@ static void rp2_uart_set_termios(struct
+ if (tty_termios_baud_rate(new))
+ tty_termios_encode_baud_rate(new, baud, baud);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* ignore all characters if CREAD is not set */
+ port->ignore_status_mask = (new->c_cflag & CREAD) ? 0 : RP2_DUMMY_READ;
+@@ -391,7 +391,7 @@ static void rp2_uart_set_termios(struct
+ __rp2_uart_set_termios(up, new->c_cflag, new->c_iflag, baud_div);
+ uart_update_timeout(port, new->c_cflag, baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void rp2_rx_chars(struct rp2_uart_port *up)
+@@ -440,7 +440,7 @@ static void rp2_ch_interrupt(struct rp2_
+ {
+ u32 status;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+
+ /*
+ * The IRQ status bits are clear-on-write. Other status bits in
+@@ -456,7 +456,7 @@ static void rp2_ch_interrupt(struct rp2_
+ if (status & RP2_CHAN_STAT_MS_CHANGED_MASK)
+ wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+ }
+
+ static int rp2_asic_interrupt(struct rp2_card *card, unsigned int asic_id)
+@@ -516,10 +516,10 @@ static void rp2_uart_shutdown(struct uar
+
+ rp2_uart_break_ctl(port, 0);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ rp2_mask_ch_irq(up, up->idx, 0);
+ rp2_rmw(up, RP2_CHAN_STAT, 0, 0);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *rp2_uart_type(struct uart_port *port)
diff --git a/debian/patches-rt/0052-serial-sa1100-Use-port-lock-wrappers.patch b/debian/patches-rt/0052-serial-sa1100-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..2f8073a485
--- /dev/null
+++ b/debian/patches-rt/0052-serial-sa1100-Use-port-lock-wrappers.patch
@@ -0,0 +1,117 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:09 +0206
+Subject: [PATCH 052/134] serial: sa1100: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-53-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sa1100.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/tty/serial/sa1100.c
++++ b/drivers/tty/serial/sa1100.c
+@@ -115,9 +115,9 @@ static void sa1100_timeout(struct timer_
+ unsigned long flags;
+
+ if (sport->port.state) {
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ sa1100_mctrl_check(sport);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+
+ mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT);
+ }
+@@ -247,7 +247,7 @@ static irqreturn_t sa1100_int(int irq, v
+ struct sa1100_port *sport = dev_id;
+ unsigned int status, pass_counter = 0;
+
+- spin_lock(&sport->port.lock);
++ uart_port_lock(&sport->port);
+ status = UART_GET_UTSR0(sport);
+ status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS;
+ do {
+@@ -276,7 +276,7 @@ static irqreturn_t sa1100_int(int irq, v
+ status &= SM_TO_UTSR0(sport->port.read_status_mask) |
+ ~UTSR0_TFS;
+ } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID));
+- spin_unlock(&sport->port.lock);
++ uart_port_unlock(&sport->port);
+
+ return IRQ_HANDLED;
+ }
+@@ -321,14 +321,14 @@ static void sa1100_break_ctl(struct uart
+ unsigned long flags;
+ unsigned int utcr3;
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+ utcr3 = UART_GET_UTCR3(sport);
+ if (break_state == -1)
+ utcr3 |= UTCR3_BRK;
+ else
+ utcr3 &= ~UTCR3_BRK;
+ UART_PUT_UTCR3(sport, utcr3);
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static int sa1100_startup(struct uart_port *port)
+@@ -354,9 +354,9 @@ static int sa1100_startup(struct uart_po
+ /*
+ * Enable modem status interrupts
+ */
+- spin_lock_irq(&sport->port.lock);
++ uart_port_lock_irq(&sport->port);
+ sa1100_enable_ms(&sport->port);
+- spin_unlock_irq(&sport->port.lock);
++ uart_port_unlock_irq(&sport->port);
+
+ return 0;
+ }
+@@ -423,7 +423,7 @@ sa1100_set_termios(struct uart_port *por
+
+ del_timer_sync(&sport->timer);
+
+- spin_lock_irqsave(&sport->port.lock, flags);
++ uart_port_lock_irqsave(&sport->port, &flags);
+
+ sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS);
+ sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR);
+@@ -485,7 +485,7 @@ sa1100_set_termios(struct uart_port *por
+ if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
+ sa1100_enable_ms(&sport->port);
+
+- spin_unlock_irqrestore(&sport->port.lock, flags);
++ uart_port_unlock_irqrestore(&sport->port, flags);
+ }
+
+ static const char *sa1100_type(struct uart_port *port)
diff --git a/debian/patches-rt/0053-serial-samsung_tty-Use-port-lock-wrappers.patch b/debian/patches-rt/0053-serial-samsung_tty-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..74dc3c0145
--- /dev/null
+++ b/debian/patches-rt/0053-serial-samsung_tty-Use-port-lock-wrappers.patch
@@ -0,0 +1,245 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:10 +0206
+Subject: [PATCH 053/134] serial: samsung_tty: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-54-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/samsung_tty.c | 50 +++++++++++++++++++--------------------
+ 1 file changed, 25 insertions(+), 25 deletions(-)
+
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -248,7 +248,7 @@ static void s3c24xx_serial_rx_enable(str
+ unsigned int ucon, ufcon;
+ int count = 10000;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ while (--count && !s3c24xx_serial_txempty_nofifo(port))
+ udelay(100);
+@@ -262,7 +262,7 @@ static void s3c24xx_serial_rx_enable(str
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ ourport->rx_enabled = 1;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c24xx_serial_rx_disable(struct uart_port *port)
+@@ -271,14 +271,14 @@ static void s3c24xx_serial_rx_disable(st
+ unsigned long flags;
+ unsigned int ucon;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ucon = rd_regl(port, S3C2410_UCON);
+ ucon &= ~S3C2410_UCON_RXIRQMODE;
+ wr_regl(port, S3C2410_UCON, ucon);
+
+ ourport->rx_enabled = 0;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c24xx_serial_stop_tx(struct uart_port *port)
+@@ -344,7 +344,7 @@ static void s3c24xx_serial_tx_dma_comple
+ dma->tx_transfer_addr, dma->tx_size,
+ DMA_TO_DEVICE);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_xmit_advance(port, count);
+ ourport->tx_in_progress = 0;
+@@ -353,7 +353,7 @@ static void s3c24xx_serial_tx_dma_comple
+ uart_write_wakeup(port);
+
+ s3c24xx_serial_start_next_tx(ourport);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void enable_tx_dma(struct s3c24xx_uart_port *ourport)
+@@ -619,7 +619,7 @@ static void s3c24xx_serial_rx_dma_comple
+ received = dma->rx_bytes_requested - state.residue;
+ async_tx_ack(dma->rx_desc);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ if (received)
+ s3c24xx_uart_copy_rx_to_tty(ourport, t, received);
+@@ -631,7 +631,7 @@ static void s3c24xx_serial_rx_dma_comple
+
+ s3c64xx_start_rx_dma(ourport);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport)
+@@ -722,7 +722,7 @@ static irqreturn_t s3c24xx_serial_rx_cha
+ utrstat = rd_regl(port, S3C2410_UTRSTAT);
+ rd_regl(port, S3C2410_UFSTAT);
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) {
+ s3c64xx_start_rx_dma(ourport);
+@@ -751,7 +751,7 @@ static irqreturn_t s3c24xx_serial_rx_cha
+ wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT);
+
+ finish:
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -849,9 +849,9 @@ static irqreturn_t s3c24xx_serial_rx_cha
+ struct s3c24xx_uart_port *ourport = dev_id;
+ struct uart_port *port = &ourport->port;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ s3c24xx_serial_rx_drain_fifo(ourport);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -932,11 +932,11 @@ static irqreturn_t s3c24xx_serial_tx_irq
+ struct s3c24xx_uart_port *ourport = id;
+ struct uart_port *port = &ourport->port;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ s3c24xx_serial_tx_chars(ourport);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ return IRQ_HANDLED;
+ }
+
+@@ -1033,7 +1033,7 @@ static void s3c24xx_serial_break_ctl(str
+ unsigned long flags;
+ unsigned int ucon;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ucon = rd_regl(port, S3C2410_UCON);
+
+@@ -1044,7 +1044,7 @@ static void s3c24xx_serial_break_ctl(str
+
+ wr_regl(port, S3C2410_UCON, ucon);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
+@@ -1303,7 +1303,7 @@ static int s3c64xx_serial_startup(struct
+ ourport->rx_enabled = 1;
+ ourport->tx_enabled = 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ufcon = rd_regl(port, S3C2410_UFCON);
+ ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+@@ -1313,7 +1313,7 @@ static int s3c64xx_serial_startup(struct
+
+ enable_rx_pio(ourport);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Enable Rx Interrupt */
+ s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM);
+@@ -1341,7 +1341,7 @@ static int apple_s5l_serial_startup(stru
+ ourport->rx_enabled = 1;
+ ourport->tx_enabled = 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ufcon = rd_regl(port, S3C2410_UFCON);
+ ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
+@@ -1351,7 +1351,7 @@ static int apple_s5l_serial_startup(stru
+
+ enable_rx_pio(ourport);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Enable Rx Interrupt */
+ s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
+@@ -1626,7 +1626,7 @@ static void s3c24xx_serial_set_termios(s
+ ulcon |= S3C2410_LCON_PNONE;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ dev_dbg(port->dev,
+ "setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
+@@ -1684,7 +1684,7 @@ static void s3c24xx_serial_set_termios(s
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= RXSTAT_DUMMY_READ;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *s3c24xx_serial_type(struct uart_port *port)
+@@ -2376,14 +2376,14 @@ s3c24xx_serial_console_write(struct cons
+ if (cons_uart->sysrq)
+ locked = false;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&cons_uart->lock, flags);
++ locked = uart_port_trylock_irqsave(cons_uart, &flags);
+ else
+- spin_lock_irqsave(&cons_uart->lock, flags);
++ uart_port_lock_irqsave(cons_uart, &flags);
+
+ uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);
+
+ if (locked)
+- spin_unlock_irqrestore(&cons_uart->lock, flags);
++ uart_port_unlock_irqrestore(cons_uart, flags);
+ }
+
+ /* Shouldn't be __init, as it can be instantiated from other module */
diff --git a/debian/patches-rt/0054-serial-sb1250-duart-Use-port-lock-wrappers.patch b/debian/patches-rt/0054-serial-sb1250-duart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..e5aeb528fe
--- /dev/null
+++ b/debian/patches-rt/0054-serial-sb1250-duart-Use-port-lock-wrappers.patch
@@ -0,0 +1,85 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:11 +0206
+Subject: [PATCH 054/134] serial: sb1250-duart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-55-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sb1250-duart.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/serial/sb1250-duart.c
++++ b/drivers/tty/serial/sb1250-duart.c
+@@ -610,7 +610,7 @@ static void sbd_set_termios(struct uart_
+ else
+ aux &= ~M_DUART_CTS_CHNG_ENA;
+
+- spin_lock(&uport->lock);
++ uart_port_lock(uport);
+
+ if (sport->tx_stopped)
+ command |= M_DUART_TX_DIS;
+@@ -632,7 +632,7 @@ static void sbd_set_termios(struct uart_
+
+ write_sbdchn(sport, R_DUART_CMD, command);
+
+- spin_unlock(&uport->lock);
++ uart_port_unlock(uport);
+ }
+
+
+@@ -839,22 +839,22 @@ static void sbd_console_write(struct con
+ unsigned int mask;
+
+ /* Disable transmit interrupts and enable the transmitter. */
+- spin_lock_irqsave(&uport->lock, flags);
++ uart_port_lock_irqsave(uport, &flags);
+ mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
+ mask & ~M_DUART_IMR_TX);
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
+- spin_unlock_irqrestore(&uport->lock, flags);
++ uart_port_unlock_irqrestore(uport, flags);
+
+ uart_console_write(&sport->port, s, count, sbd_console_putchar);
+
+ /* Restore transmit interrupts and the transmitter enable. */
+- spin_lock_irqsave(&uport->lock, flags);
++ uart_port_lock_irqsave(uport, &flags);
+ sbd_line_drain(sport);
+ if (sport->tx_stopped)
+ write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
+ write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
+- spin_unlock_irqrestore(&uport->lock, flags);
++ uart_port_unlock_irqrestore(uport, flags);
+ }
+
+ static int __init sbd_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0056-serial-tegra-Use-port-lock-wrappers.patch b/debian/patches-rt/0056-serial-tegra-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..f53b521dc0
--- /dev/null
+++ b/debian/patches-rt/0056-serial-tegra-Use-port-lock-wrappers.patch
@@ -0,0 +1,176 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:13 +0206
+Subject: [PATCH 056/134] serial: tegra: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-57-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/serial-tegra.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/tty/serial/serial-tegra.c
++++ b/drivers/tty/serial/serial-tegra.c
+@@ -411,7 +411,7 @@ static int tegra_set_baudrate(struct teg
+ divisor = DIV_ROUND_CLOSEST(rate, baud * 16);
+ }
+
+- spin_lock_irqsave(&tup->uport.lock, flags);
++ uart_port_lock_irqsave(&tup->uport, &flags);
+ lcr = tup->lcr_shadow;
+ lcr |= UART_LCR_DLAB;
+ tegra_uart_write(tup, lcr, UART_LCR);
+@@ -424,7 +424,7 @@ static int tegra_set_baudrate(struct teg
+
+ /* Dummy read to ensure the write is posted */
+ tegra_uart_read(tup, UART_SCR);
+- spin_unlock_irqrestore(&tup->uport.lock, flags);
++ uart_port_unlock_irqrestore(&tup->uport, flags);
+
+ tup->current_baud = baud;
+
+@@ -522,13 +522,13 @@ static void tegra_uart_tx_dma_complete(v
+ dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state);
+ count = tup->tx_bytes_requested - state.residue;
+ async_tx_ack(tup->tx_dma_desc);
+- spin_lock_irqsave(&tup->uport.lock, flags);
++ uart_port_lock_irqsave(&tup->uport, &flags);
+ uart_xmit_advance(&tup->uport, count);
+ tup->tx_in_progress = 0;
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(&tup->uport);
+ tegra_uart_start_next_tx(tup);
+- spin_unlock_irqrestore(&tup->uport.lock, flags);
++ uart_port_unlock_irqrestore(&tup->uport, flags);
+ }
+
+ static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup,
+@@ -598,13 +598,13 @@ static unsigned int tegra_uart_tx_empty(
+ unsigned int ret = 0;
+ unsigned long flags;
+
+- spin_lock_irqsave(&u->lock, flags);
++ uart_port_lock_irqsave(u, &flags);
+ if (!tup->tx_in_progress) {
+ unsigned long lsr = tegra_uart_read(tup, UART_LSR);
+ if ((lsr & TX_EMPTY_STATUS) == TX_EMPTY_STATUS)
+ ret = TIOCSER_TEMT;
+ }
+- spin_unlock_irqrestore(&u->lock, flags);
++ uart_port_unlock_irqrestore(u, flags);
+ return ret;
+ }
+
+@@ -727,7 +727,7 @@ static void tegra_uart_rx_dma_complete(v
+ struct dma_tx_state state;
+ enum dma_status status;
+
+- spin_lock_irqsave(&u->lock, flags);
++ uart_port_lock_irqsave(u, &flags);
+
+ status = dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
+
+@@ -749,7 +749,7 @@ static void tegra_uart_rx_dma_complete(v
+ set_rts(tup, true);
+
+ done:
+- spin_unlock_irqrestore(&u->lock, flags);
++ uart_port_unlock_irqrestore(u, flags);
+ }
+
+ static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup)
+@@ -836,7 +836,7 @@ static irqreturn_t tegra_uart_isr(int ir
+ bool is_rx_int = false;
+ unsigned long flags;
+
+- spin_lock_irqsave(&u->lock, flags);
++ uart_port_lock_irqsave(u, &flags);
+ while (1) {
+ iir = tegra_uart_read(tup, UART_IIR);
+ if (iir & UART_IIR_NO_INT) {
+@@ -852,7 +852,7 @@ static irqreturn_t tegra_uart_isr(int ir
+ } else if (is_rx_start) {
+ tegra_uart_start_rx_dma(tup);
+ }
+- spin_unlock_irqrestore(&u->lock, flags);
++ uart_port_unlock_irqrestore(u, flags);
+ return IRQ_HANDLED;
+ }
+
+@@ -969,11 +969,11 @@ static void tegra_uart_hw_deinit(struct
+ }
+ }
+
+- spin_lock_irqsave(&tup->uport.lock, flags);
++ uart_port_lock_irqsave(&tup->uport, &flags);
+ /* Reset the Rx and Tx FIFOs */
+ tegra_uart_fifo_reset(tup, UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR);
+ tup->current_baud = 0;
+- spin_unlock_irqrestore(&tup->uport.lock, flags);
++ uart_port_unlock_irqrestore(&tup->uport, flags);
+
+ tup->rx_in_progress = 0;
+ tup->tx_in_progress = 0;
+@@ -1292,7 +1292,7 @@ static void tegra_uart_set_termios(struc
+ int ret;
+
+ max_divider *= 16;
+- spin_lock_irqsave(&u->lock, flags);
++ uart_port_lock_irqsave(u, &flags);
+
+ /* Changing configuration, it is safe to stop any rx now */
+ if (tup->rts_active)
+@@ -1341,7 +1341,7 @@ static void tegra_uart_set_termios(struc
+ baud = uart_get_baud_rate(u, termios, oldtermios,
+ parent_clk_rate/max_divider,
+ parent_clk_rate/16);
+- spin_unlock_irqrestore(&u->lock, flags);
++ uart_port_unlock_irqrestore(u, flags);
+ ret = tegra_set_baudrate(tup, baud);
+ if (ret < 0) {
+ dev_err(tup->uport.dev, "Failed to set baud rate\n");
+@@ -1349,7 +1349,7 @@ static void tegra_uart_set_termios(struc
+ }
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+- spin_lock_irqsave(&u->lock, flags);
++ uart_port_lock_irqsave(u, &flags);
+
+ /* Flow control */
+ if (termios->c_cflag & CRTSCTS) {
+@@ -1382,7 +1382,7 @@ static void tegra_uart_set_termios(struc
+ if (termios->c_iflag & IGNBRK)
+ tup->uport.ignore_status_mask |= UART_LSR_BI;
+
+- spin_unlock_irqrestore(&u->lock, flags);
++ uart_port_unlock_irqrestore(u, flags);
+ }
+
+ static const char *tegra_uart_type(struct uart_port *u)
diff --git a/debian/patches-rt/0057-serial-core-Use-port-lock-wrappers.patch b/debian/patches-rt/0057-serial-core-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..33c2703827
--- /dev/null
+++ b/debian/patches-rt/0057-serial-core-Use-port-lock-wrappers.patch
@@ -0,0 +1,365 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:14 +0206
+Subject: [PATCH 057/134] serial: core: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-58-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/serial_core.c | 92 +++++++++++++++++++--------------------
+ drivers/tty/serial/serial_port.c | 4 -
+ 2 files changed, 48 insertions(+), 48 deletions(-)
+
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -79,7 +79,7 @@
+ ({ \
+ struct uart_port *__uport = uart_port_ref(state); \
+ if (__uport) \
+- spin_lock_irqsave(&__uport->lock, flags); \
++ uart_port_lock_irqsave(__uport, &flags); \
+ __uport; \
+ })
+
+@@ -87,7 +87,7 @@
+ ({ \
+ struct uart_port *__uport = uport; \
+ if (__uport) { \
+- spin_unlock_irqrestore(&__uport->lock, flags); \
++ uart_port_unlock_irqrestore(__uport, flags); \
+ uart_port_deref(__uport); \
+ } \
+ })
+@@ -179,12 +179,12 @@
+ unsigned long flags;
+ unsigned int old;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ old = port->mctrl;
+ port->mctrl = (old & ~clear) | set;
+ if (old != port->mctrl && !(port->rs485.flags & SER_RS485_ENABLED))
+ port->ops->set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ #define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0)
+@@ -219,7 +219,7 @@
+ /*
+ * Set modem status enables based on termios cflag
+ */
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ if (termios->c_cflag & CRTSCTS)
+ uport->status |= UPSTAT_CTS_ENABLE;
+ else
+@@ -240,7 +240,7 @@
+ else
+ __uart_start(state);
+ }
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ }
+
+ /*
+@@ -702,11 +702,11 @@
+ if (port->ops->send_xchar)
+ port->ops->send_xchar(port, ch);
+ else {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ port->x_char = ch;
+ if (ch)
+ port->ops->start_tx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ uart_port_deref(port);
+ }
+@@ -1085,9 +1085,9 @@
+
+ if (!tty_io_error(tty)) {
+ result = uport->mctrl;
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ result |= uport->ops->get_mctrl(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ }
+ out:
+ mutex_unlock(&port->mutex);
+@@ -1223,16 +1223,16 @@
+ uport = uart_port_ref(state);
+ if (!uport)
+ return -EIO;
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ memcpy(&cprev, &uport->icount, sizeof(struct uart_icount));
+ uart_enable_ms(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+
+ add_wait_queue(&port->delta_msr_wait, &wait);
+ for (;;) {
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+
+@@ -1277,9 +1277,9 @@
+ uport = uart_port_ref(state);
+ if (!uport)
+ return -EIO;
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ uart_port_deref(uport);
+
+ icount->cts = cnow.cts;
+@@ -1432,9 +1432,9 @@
+ uart_set_rs485_termination(port, rs485);
+ uart_set_rs485_rx_during_tx(port, rs485);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ret = port->rs485_config(port, NULL, rs485);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ if (ret) {
+ memset(rs485, 0, sizeof(*rs485));
+ /* unset GPIOs */
+@@ -1451,9 +1451,9 @@
+ unsigned long flags;
+ struct serial_rs485 aux;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ aux = port->rs485;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (copy_to_user(rs485, &aux, sizeof(aux)))
+ return -EFAULT;
+@@ -1481,7 +1481,7 @@
+ uart_set_rs485_termination(port, &rs485);
+ uart_set_rs485_rx_during_tx(port, &rs485);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ret = port->rs485_config(port, &tty->termios, &rs485);
+ if (!ret) {
+ port->rs485 = rs485;
+@@ -1490,7 +1490,7 @@
+ if (!(rs485.flags & SER_RS485_ENABLED))
+ port->ops->set_mctrl(port, port->mctrl);
+ }
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ if (ret) {
+ /* restore old GPIO settings */
+ gpiod_set_value_cansleep(port->rs485_term_gpio,
+@@ -1515,9 +1515,9 @@
+ if (!port->iso7816_config)
+ return -ENOTTY;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ aux = port->iso7816;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (copy_to_user(iso7816, &aux, sizeof(aux)))
+ return -EFAULT;
+@@ -1546,9 +1546,9 @@
+ if (iso7816.reserved[i])
+ return -EINVAL;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ret = port->iso7816_config(port, &iso7816);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ if (ret)
+ return ret;
+
+@@ -1765,9 +1765,9 @@
+ if (WARN(!uport, "detached port still initialized!\n"))
+ return;
+
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ uport->ops->stop_rx(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+
+ uart_port_shutdown(port);
+
+@@ -1781,10 +1781,10 @@
+ /*
+ * Free the transmit buffer.
+ */
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ buf = state->xmit.buf;
+ state->xmit.buf = NULL;
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+
+ free_page((unsigned long)buf);
+
+@@ -1927,10 +1927,10 @@
+ */
+ if (WARN_ON(!uport))
+ return true;
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ uart_enable_ms(uport);
+ mctrl = uport->ops->get_mctrl(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ uart_port_deref(uport);
+
+ return mctrl & TIOCM_CAR;
+@@ -2047,9 +2047,9 @@
+ pm_state = state->pm_state;
+ if (pm_state != UART_PM_STATE_ON)
+ uart_change_pm(state, UART_PM_STATE_ON);
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ status = uport->ops->get_mctrl(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ if (pm_state != UART_PM_STATE_ON)
+ uart_change_pm(state, pm_state);
+
+@@ -2388,9 +2388,9 @@
+ */
+ if (!console_suspend_enabled && uart_console(uport)) {
+ if (uport->ops->start_rx) {
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ uport->ops->stop_rx(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ }
+ goto unlock;
+ }
+@@ -2405,7 +2405,7 @@
+ tty_port_set_suspended(port, true);
+ tty_port_set_initialized(port, false);
+
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ ops->stop_tx(uport);
+ if (!(uport->rs485.flags & SER_RS485_ENABLED))
+ ops->set_mctrl(uport, 0);
+@@ -2413,7 +2413,7 @@
+ mctrl = uport->mctrl;
+ uport->mctrl = 0;
+ ops->stop_rx(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+
+ /*
+ * Wait for the transmitter to empty.
+@@ -2485,9 +2485,9 @@
+ uart_change_pm(state, UART_PM_STATE_ON);
+ uport->ops->set_termios(uport, &termios, NULL);
+ if (!console_suspend_enabled && uport->ops->start_rx) {
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ uport->ops->start_rx(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ }
+ if (console_suspend_enabled)
+ console_start(uport->cons);
+@@ -2498,10 +2498,10 @@
+ int ret;
+
+ uart_change_pm(state, UART_PM_STATE_ON);
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ if (!(uport->rs485.flags & SER_RS485_ENABLED))
+ ops->set_mctrl(uport, 0);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ if (console_suspend_enabled || !uart_console(uport)) {
+ /* Protected by port mutex for now */
+ struct tty_struct *tty = port->tty;
+@@ -2511,11 +2511,11 @@
+ if (tty)
+ uart_change_line_settings(tty, state, NULL);
+ uart_rs485_config(uport);
+- spin_lock_irq(&uport->lock);
++ uart_port_lock_irq(uport);
+ if (!(uport->rs485.flags & SER_RS485_ENABLED))
+ ops->set_mctrl(uport, uport->mctrl);
+ ops->start_tx(uport);
+- spin_unlock_irq(&uport->lock);
++ uart_port_unlock_irq(uport);
+ tty_port_set_initialized(port, true);
+ } else {
+ /*
+@@ -2618,11 +2618,11 @@
+ * keep the DTR setting that is set in uart_set_options()
+ * We probably don't need a spinlock around this, but
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ port->mctrl &= TIOCM_DTR;
+ if (!(port->rs485.flags & SER_RS485_ENABLED))
+ port->ops->set_mctrl(port, port->mctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ uart_rs485_config(port);
+
+--- a/drivers/tty/serial/serial_port.c
++++ b/drivers/tty/serial/serial_port.c
+@@ -35,10 +35,10 @@
+ goto out;
+
+ /* Flush any pending TX for the port */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (__serial_port_busy(port))
+ port->ops->start_tx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ out:
+ pm_runtime_mark_last_busy(dev);
diff --git a/debian/patches-rt/0058-serial-mctrl_gpio-Use-port-lock-wrappers.patch b/debian/patches-rt/0058-serial-mctrl_gpio-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..46719cb077
--- /dev/null
+++ b/debian/patches-rt/0058-serial-mctrl_gpio-Use-port-lock-wrappers.patch
@@ -0,0 +1,58 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:15 +0206
+Subject: [PATCH 058/134] serial: mctrl_gpio: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-59-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/serial_mctrl_gpio.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/serial/serial_mctrl_gpio.c
++++ b/drivers/tty/serial/serial_mctrl_gpio.c
+@@ -184,7 +184,7 @@ static irqreturn_t mctrl_gpio_irq_handle
+
+ mctrl_gpio_get(gpios, &mctrl);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ mctrl_diff = mctrl ^ gpios->mctrl_prev;
+ gpios->mctrl_prev = mctrl;
+@@ -205,7 +205,7 @@ static irqreturn_t mctrl_gpio_irq_handle
+ wake_up_interruptible(&port->state->port.delta_msr_wait);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
diff --git a/debian/patches-rt/0059-serial-txx9-Use-port-lock-wrappers.patch b/debian/patches-rt/0059-serial-txx9-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..bbe48684ba
--- /dev/null
+++ b/debian/patches-rt/0059-serial-txx9-Use-port-lock-wrappers.patch
@@ -0,0 +1,134 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:16 +0206
+Subject: [PATCH 059/134] serial: txx9: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-60-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/serial_txx9.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/serial_txx9.c
++++ b/drivers/tty/serial/serial_txx9.c
+@@ -335,13 +335,13 @@ static irqreturn_t serial_txx9_interrupt
+ unsigned int status;
+
+ while (1) {
+- spin_lock(&up->lock);
++ uart_port_lock(up);
+ status = sio_in(up, TXX9_SIDISR);
+ if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE))
+ status &= ~TXX9_SIDISR_TDIS;
+ if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
+ TXX9_SIDISR_TOUT))) {
+- spin_unlock(&up->lock);
++ uart_port_unlock(up);
+ break;
+ }
+
+@@ -353,7 +353,7 @@ static irqreturn_t serial_txx9_interrupt
+ sio_mask(up, TXX9_SIDISR,
+ TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS |
+ TXX9_SIDISR_TOUT);
+- spin_unlock(&up->lock);
++ uart_port_unlock(up);
+
+ if (pass_counter++ > PASS_LIMIT)
+ break;
+@@ -367,9 +367,9 @@ static unsigned int serial_txx9_tx_empty
+ unsigned long flags;
+ unsigned int ret;
+
+- spin_lock_irqsave(&up->lock, flags);
++ uart_port_lock_irqsave(up, &flags);
+ ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0;
+- spin_unlock_irqrestore(&up->lock, flags);
++ uart_port_unlock_irqrestore(up, flags);
+
+ return ret;
+ }
+@@ -399,12 +399,12 @@ static void serial_txx9_break_ctl(struct
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->lock, flags);
++ uart_port_lock_irqsave(up, &flags);
+ if (break_state == -1)
+ sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
+ else
+ sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK);
+- spin_unlock_irqrestore(&up->lock, flags);
++ uart_port_unlock_irqrestore(up, flags);
+ }
+
+ #if defined(CONFIG_SERIAL_TXX9_CONSOLE) || defined(CONFIG_CONSOLE_POLL)
+@@ -517,9 +517,9 @@ static int serial_txx9_startup(struct ua
+ /*
+ * Now, initialize the UART
+ */
+- spin_lock_irqsave(&up->lock, flags);
++ uart_port_lock_irqsave(up, &flags);
+ serial_txx9_set_mctrl(up, up->mctrl);
+- spin_unlock_irqrestore(&up->lock, flags);
++ uart_port_unlock_irqrestore(up, flags);
+
+ /* Enable RX/TX */
+ sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE);
+@@ -541,9 +541,9 @@ static void serial_txx9_shutdown(struct
+ */
+ sio_out(up, TXX9_SIDICR, 0); /* disable all intrs */
+
+- spin_lock_irqsave(&up->lock, flags);
++ uart_port_lock_irqsave(up, &flags);
+ serial_txx9_set_mctrl(up, up->mctrl);
+- spin_unlock_irqrestore(&up->lock, flags);
++ uart_port_unlock_irqrestore(up, flags);
+
+ /*
+ * Disable break condition
+@@ -625,7 +625,7 @@ serial_txx9_set_termios(struct uart_port
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->lock, flags);
++ uart_port_lock_irqsave(up, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -676,7 +676,7 @@ serial_txx9_set_termios(struct uart_port
+ sio_out(up, TXX9_SIFCR, fcr);
+
+ serial_txx9_set_mctrl(up, up->mctrl);
+- spin_unlock_irqrestore(&up->lock, flags);
++ uart_port_unlock_irqrestore(up, flags);
+ }
+
+ static void
diff --git a/debian/patches-rt/0060-serial-sh-sci-Use-port-lock-wrappers.patch b/debian/patches-rt/0060-serial-sh-sci-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..6d039c6658
--- /dev/null
+++ b/debian/patches-rt/0060-serial-sh-sci-Use-port-lock-wrappers.patch
@@ -0,0 +1,302 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:17 +0206
+Subject: [PATCH 060/134] serial: sh-sci: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-61-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sh-sci.c | 68 ++++++++++++++++++++++----------------------
+ 1 file changed, 34 insertions(+), 34 deletions(-)
+
+--- a/drivers/tty/serial/sh-sci.c
++++ b/drivers/tty/serial/sh-sci.c
+@@ -1205,7 +1205,7 @@ static void sci_dma_tx_complete(void *ar
+
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_xmit_advance(port, s->tx_dma_len);
+
+@@ -1229,7 +1229,7 @@ static void sci_dma_tx_complete(void *ar
+ }
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* Locking: called with port lock held */
+@@ -1320,7 +1320,7 @@ static void sci_dma_rx_complete(void *ar
+ dev_dbg(port->dev, "%s(%d) active cookie %d\n", __func__, port->line,
+ s->active_rx);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ active = sci_dma_rx_find_active(s);
+ if (active >= 0)
+@@ -1347,20 +1347,20 @@ static void sci_dma_rx_complete(void *ar
+
+ dma_async_issue_pending(chan);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ dev_dbg(port->dev, "%s: cookie %d #%d, new active cookie %d\n",
+ __func__, s->cookie_rx[active], active, s->active_rx);
+ return;
+
+ fail:
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
+ /* Switch to PIO */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ dmaengine_terminate_async(chan);
+ sci_dma_rx_chan_invalidate(s);
+ sci_dma_rx_reenable_irq(s);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void sci_dma_tx_release(struct sci_port *s)
+@@ -1409,13 +1409,13 @@ static int sci_dma_rx_submit(struct sci_
+ fail:
+ /* Switch to PIO */
+ if (!port_lock_held)
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ if (i)
+ dmaengine_terminate_async(chan);
+ sci_dma_rx_chan_invalidate(s);
+ sci_start_rx(port);
+ if (!port_lock_held)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return -EAGAIN;
+ }
+
+@@ -1437,14 +1437,14 @@ static void sci_dma_tx_work_fn(struct wo
+ * transmit till the end, and then the rest. Take the port lock to get a
+ * consistent xmit buffer state.
+ */
+- spin_lock_irq(&port->lock);
++ uart_port_lock_irq(port);
+ head = xmit->head;
+ tail = xmit->tail;
+ buf = s->tx_dma_addr + tail;
+ s->tx_dma_len = CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE);
+ if (!s->tx_dma_len) {
+ /* Transmit buffer has been flushed */
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ return;
+ }
+
+@@ -1452,7 +1452,7 @@ static void sci_dma_tx_work_fn(struct wo
+ DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ dev_warn(port->dev, "Failed preparing Tx DMA descriptor\n");
+ goto switch_to_pio;
+ }
+@@ -1464,12 +1464,12 @@ static void sci_dma_tx_work_fn(struct wo
+ desc->callback_param = s;
+ s->cookie_tx = dmaengine_submit(desc);
+ if (dma_submit_error(s->cookie_tx)) {
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
+ goto switch_to_pio;
+ }
+
+- spin_unlock_irq(&port->lock);
++ uart_port_unlock_irq(port);
+ dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n",
+ __func__, xmit->buf, tail, head, s->cookie_tx);
+
+@@ -1477,10 +1477,10 @@ static void sci_dma_tx_work_fn(struct wo
+ return;
+
+ switch_to_pio:
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ s->chan_tx = NULL;
+ sci_start_tx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return;
+ }
+
+@@ -1497,17 +1497,17 @@ static enum hrtimer_restart sci_dma_rx_t
+
+ dev_dbg(port->dev, "DMA Rx timed out\n");
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ active = sci_dma_rx_find_active(s);
+ if (active < 0) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return HRTIMER_NORESTART;
+ }
+
+ status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
+ if (status == DMA_COMPLETE) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ dev_dbg(port->dev, "Cookie %d #%d has already completed\n",
+ s->active_rx, active);
+
+@@ -1525,7 +1525,7 @@ static enum hrtimer_restart sci_dma_rx_t
+ */
+ status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state);
+ if (status == DMA_COMPLETE) {
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ dev_dbg(port->dev, "Transaction complete after DMA engine was stopped");
+ return HRTIMER_NORESTART;
+ }
+@@ -1546,7 +1546,7 @@ static enum hrtimer_restart sci_dma_rx_t
+
+ sci_dma_rx_reenable_irq(s);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return HRTIMER_NORESTART;
+ }
+@@ -1770,9 +1770,9 @@ static irqreturn_t sci_tx_interrupt(int
+ struct uart_port *port = ptr;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ sci_transmit_chars(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -1786,11 +1786,11 @@ static irqreturn_t sci_tx_end_interrupt(
+ if (port->type != PORT_SCI)
+ return sci_tx_interrupt(irq, ptr);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ctrl = serial_port_in(port, SCSCR);
+ ctrl &= ~(SCSCR_TE | SCSCR_TEIE);
+ serial_port_out(port, SCSCR, ctrl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -2187,7 +2187,7 @@ static void sci_break_ctl(struct uart_po
+ return;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ scsptr = serial_port_in(port, SCSPTR);
+ scscr = serial_port_in(port, SCSCR);
+
+@@ -2201,7 +2201,7 @@ static void sci_break_ctl(struct uart_po
+
+ serial_port_out(port, SCSPTR, scsptr);
+ serial_port_out(port, SCSCR, scscr);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int sci_startup(struct uart_port *port)
+@@ -2233,7 +2233,7 @@ static void sci_shutdown(struct uart_por
+ s->autorts = false;
+ mctrl_gpio_disable_ms(to_sci_port(port)->gpios);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ sci_stop_rx(port);
+ sci_stop_tx(port);
+ /*
+@@ -2243,7 +2243,7 @@ static void sci_shutdown(struct uart_por
+ scr = serial_port_in(port, SCSCR);
+ serial_port_out(port, SCSCR, scr &
+ (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot));
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ #ifdef CONFIG_SERIAL_SH_SCI_DMA
+ if (s->chan_rx_saved) {
+@@ -2545,7 +2545,7 @@ static void sci_set_termios(struct uart_
+ serial_port_out(port, SCCKS, sccks);
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ sci_reset(port);
+
+@@ -2667,7 +2667,7 @@ static void sci_set_termios(struct uart_
+ if ((termios->c_cflag & CREAD) != 0)
+ sci_start_rx(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ sci_port_disable(s);
+
+@@ -3052,9 +3052,9 @@ static void serial_console_write(struct
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* first save SCSCR then disable interrupts, keep clock source */
+ ctrl = serial_port_in(port, SCSCR);
+@@ -3074,7 +3074,7 @@ static void serial_console_write(struct
+ serial_port_out(port, SCSCR, ctrl);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int serial_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0061-serial-sifive-Use-port-lock-wrappers.patch b/debian/patches-rt/0061-serial-sifive-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..a2babdbea9
--- /dev/null
+++ b/debian/patches-rt/0061-serial-sifive-Use-port-lock-wrappers.patch
@@ -0,0 +1,102 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:18 +0206
+Subject: [PATCH 061/134] serial: sifive: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-62-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sifive.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+--- a/drivers/tty/serial/sifive.c
++++ b/drivers/tty/serial/sifive.c
+@@ -521,11 +521,11 @@ static irqreturn_t sifive_serial_irq(int
+ struct sifive_serial_port *ssp = dev_id;
+ u32 ip;
+
+- spin_lock(&ssp->port.lock);
++ uart_port_lock(&ssp->port);
+
+ ip = __ssp_readl(ssp, SIFIVE_SERIAL_IP_OFFS);
+ if (!ip) {
+- spin_unlock(&ssp->port.lock);
++ uart_port_unlock(&ssp->port);
+ return IRQ_NONE;
+ }
+
+@@ -534,7 +534,7 @@ static irqreturn_t sifive_serial_irq(int
+ if (ip & SIFIVE_SERIAL_IP_TXWM_MASK)
+ __ssp_transmit_chars(ssp);
+
+- spin_unlock(&ssp->port.lock);
++ uart_port_unlock(&ssp->port);
+
+ return IRQ_HANDLED;
+ }
+@@ -653,7 +653,7 @@ static void sifive_serial_set_termios(st
+ ssp->port.uartclk / 16);
+ __ssp_update_baud_rate(ssp, rate);
+
+- spin_lock_irqsave(&ssp->port.lock, flags);
++ uart_port_lock_irqsave(&ssp->port, &flags);
+
+ /* Update the per-port timeout */
+ uart_update_timeout(port, termios->c_cflag, rate);
+@@ -670,7 +670,7 @@ static void sifive_serial_set_termios(st
+ if (v != old_v)
+ __ssp_writel(v, SIFIVE_SERIAL_RXCTRL_OFFS, ssp);
+
+- spin_unlock_irqrestore(&ssp->port.lock, flags);
++ uart_port_unlock_irqrestore(&ssp->port, flags);
+ }
+
+ static void sifive_serial_release_port(struct uart_port *port)
+@@ -795,9 +795,9 @@ static void sifive_serial_console_write(
+ if (ssp->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&ssp->port.lock);
++ locked = uart_port_trylock(&ssp->port);
+ else
+- spin_lock(&ssp->port.lock);
++ uart_port_lock(&ssp->port);
+
+ ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS);
+ __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp);
+@@ -807,7 +807,7 @@ static void sifive_serial_console_write(
+ __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp);
+
+ if (locked)
+- spin_unlock(&ssp->port.lock);
++ uart_port_unlock(&ssp->port);
+ local_irq_restore(flags);
+ }
+
diff --git a/debian/patches-rt/0062-serial-sprd-Use-port-lock-wrappers.patch b/debian/patches-rt/0062-serial-sprd-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..5be78db092
--- /dev/null
+++ b/debian/patches-rt/0062-serial-sprd-Use-port-lock-wrappers.patch
@@ -0,0 +1,162 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:19 +0206
+Subject: [PATCH 062/134] serial: sprd: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-63-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sprd_serial.c | 30 +++++++++++++++---------------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+--- a/drivers/tty/serial/sprd_serial.c
++++ b/drivers/tty/serial/sprd_serial.c
+@@ -247,7 +247,7 @@ static void sprd_complete_tx_dma(void *d
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ dma_unmap_single(port->dev, sp->tx_dma.phys_addr,
+ sp->tx_dma.trans_len, DMA_TO_DEVICE);
+
+@@ -260,7 +260,7 @@ static void sprd_complete_tx_dma(void *d
+ sprd_tx_dma_config(port))
+ sp->tx_dma.trans_len = 0;
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int sprd_uart_dma_submit(struct uart_port *port,
+@@ -429,13 +429,13 @@ static void sprd_complete_rx_dma(void *d
+ enum dma_status status;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ status = dmaengine_tx_status(sp->rx_dma.chn,
+ sp->rx_dma.cookie, &state);
+ if (status != DMA_COMPLETE) {
+ sprd_stop_rx(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return;
+ }
+
+@@ -449,7 +449,7 @@ static void sprd_complete_rx_dma(void *d
+ if (sprd_start_dma_rx(port))
+ sprd_stop_rx(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int sprd_start_dma_rx(struct uart_port *port)
+@@ -638,12 +638,12 @@ static irqreturn_t sprd_handle_irq(int i
+ struct uart_port *port = dev_id;
+ unsigned int ims;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ ims = serial_in(port, SPRD_IMSR);
+
+ if (!ims) {
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ return IRQ_NONE;
+ }
+
+@@ -660,7 +660,7 @@ static irqreturn_t sprd_handle_irq(int i
+ if (ims & SPRD_IMSR_TX_FIFO_EMPTY)
+ sprd_tx(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -727,13 +727,13 @@ static int sprd_startup(struct uart_port
+ serial_out(port, SPRD_CTL1, fc);
+
+ /* enable interrupt */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ien = serial_in(port, SPRD_IEN);
+ ien |= SPRD_IEN_BREAK_DETECT | SPRD_IEN_TIMEOUT;
+ if (!sp->rx_dma.enable)
+ ien |= SPRD_IEN_RX_FULL;
+ serial_out(port, SPRD_IEN, ien);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -793,7 +793,7 @@ static void sprd_set_termios(struct uart
+ lcr |= SPRD_LCR_EVEN_PAR;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* update the per-port timeout */
+ uart_update_timeout(port, termios->c_cflag, baud);
+@@ -837,7 +837,7 @@ static void sprd_set_termios(struct uart
+ fc |= RX_TOUT_THLD_DEF | RX_HFC_THLD_DEF;
+ serial_out(port, SPRD_CTL1, fc);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+@@ -974,9 +974,9 @@ static void sprd_console_write(struct co
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_console_write(port, s, count, sprd_console_putchar);
+
+@@ -984,7 +984,7 @@ static void sprd_console_write(struct co
+ wait_for_xmitr(port);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int sprd_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0063-serial-st-asc-Use-port-lock-wrappers.patch b/debian/patches-rt/0063-serial-st-asc-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..99f4358e61
--- /dev/null
+++ b/debian/patches-rt/0063-serial-st-asc-Use-port-lock-wrappers.patch
@@ -0,0 +1,110 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:20 +0206
+Subject: [PATCH 063/134] serial: st-asc: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-64-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/st-asc.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/tty/serial/st-asc.c
++++ b/drivers/tty/serial/st-asc.c
+@@ -319,7 +319,7 @@ static irqreturn_t asc_interrupt(int irq
+ struct uart_port *port = ptr;
+ u32 status;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ status = asc_in(port, ASC_STA);
+
+@@ -334,7 +334,7 @@ static irqreturn_t asc_interrupt(int irq
+ asc_transmit_chars(port);
+ }
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -452,10 +452,10 @@ static void asc_pm(struct uart_port *por
+ * we can come to turning it off. Note this is not called with
+ * the port spinlock held.
+ */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN;
+ asc_out(port, ASC_CTL, ctl);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ clk_disable_unprepare(ascport->clk);
+ break;
+ }
+@@ -480,7 +480,7 @@ static void asc_set_termios(struct uart_
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ cflag = termios->c_cflag;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* read control register */
+ ctrl_val = asc_in(port, ASC_CTL);
+@@ -594,7 +594,7 @@ static void asc_set_termios(struct uart_
+ /* write final value and enable port */
+ asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *asc_type(struct uart_port *port)
+@@ -849,9 +849,9 @@ static void asc_console_write(struct con
+ if (port->sysrq)
+ locked = 0; /* asc_interrupt has already claimed the lock */
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Disable interrupts so we don't get the IRQ line bouncing
+@@ -869,7 +869,7 @@ static void asc_console_write(struct con
+ asc_out(port, ASC_INTEN, intenable);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int asc_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0064-serial-stm32-Use-port-lock-wrappers.patch b/debian/patches-rt/0064-serial-stm32-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..cc261d43ee
--- /dev/null
+++ b/debian/patches-rt/0064-serial-stm32-Use-port-lock-wrappers.patch
@@ -0,0 +1,184 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:21 +0206
+Subject: [PATCH 064/134] serial: stm32: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-65-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/stm32-usart.c | 38 +++++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+--- a/drivers/tty/serial/stm32-usart.c
++++ b/drivers/tty/serial/stm32-usart.c
+@@ -537,7 +537,7 @@ static void stm32_usart_rx_dma_complete(
+ unsigned int size;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ size = stm32_usart_receive_chars(port, false);
+ uart_unlock_and_check_sysrq_irqrestore(port, flags);
+ if (size)
+@@ -643,9 +643,9 @@ static void stm32_usart_tx_dma_complete(
+ stm32_usart_tx_dma_terminate(stm32port);
+
+ /* Let's see if we have pending data to send */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ stm32_usart_transmit_chars(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void stm32_usart_tx_interrupt_enable(struct uart_port *port)
+@@ -889,7 +889,7 @@ static irqreturn_t stm32_usart_interrupt
+ if (!stm32_port->throttled) {
+ if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_started(stm32_port)) ||
+ ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_started(stm32_port))) {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ size = stm32_usart_receive_chars(port, false);
+ uart_unlock_and_check_sysrq(port);
+ if (size)
+@@ -898,14 +898,14 @@ static irqreturn_t stm32_usart_interrupt
+ }
+
+ if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ stm32_usart_transmit_chars(port);
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ }
+
+ /* Receiver timeout irq for DMA RX */
+ if (stm32_usart_rx_dma_started(stm32_port) && !stm32_port->throttled) {
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ size = stm32_usart_receive_chars(port, false);
+ uart_unlock_and_check_sysrq(port);
+ if (size)
+@@ -993,7 +993,7 @@ static void stm32_usart_throttle(struct
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /*
+ * Pause DMA transfer, so the RX data gets queued into the FIFO.
+@@ -1006,7 +1006,7 @@ static void stm32_usart_throttle(struct
+ stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq);
+
+ stm32_port->throttled = true;
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* Unthrottle the remote, the input buffer can now accept data. */
+@@ -1016,7 +1016,7 @@ static void stm32_usart_unthrottle(struc
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ stm32_usart_set_bits(port, ofs->cr1, stm32_port->cr1_irq);
+ if (stm32_port->cr3_irq)
+ stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq);
+@@ -1030,7 +1030,7 @@ static void stm32_usart_unthrottle(struc
+ if (stm32_port->rx_ch)
+ stm32_usart_rx_dma_start_or_resume(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* Receive stop */
+@@ -1158,7 +1158,7 @@ static void stm32_usart_set_termios(stru
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 8);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr,
+ isr,
+@@ -1349,7 +1349,7 @@ static void stm32_usart_set_termios(stru
+ writel_relaxed(cr1, port->membase + ofs->cr1);
+
+ stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ /* Handle modem control interrupts */
+ if (UART_ENABLE_MS(port, termios->c_cflag))
+@@ -1399,9 +1399,9 @@ static void stm32_usart_pm(struct uart_p
+ pm_runtime_get_sync(port->dev);
+ break;
+ case UART_PM_STATE_OFF:
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ pm_runtime_put_sync(port->dev);
+ break;
+ }
+@@ -1884,9 +1884,9 @@ static void stm32_usart_console_write(st
+ int locked = 1;
+
+ if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Save and disable interrupts, enable the transmitter */
+ old_cr1 = readl_relaxed(port->membase + ofs->cr1);
+@@ -1900,7 +1900,7 @@ static void stm32_usart_console_write(st
+ writel_relaxed(old_cr1, port->membase + ofs->cr1);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int stm32_usart_console_setup(struct console *co, char *options)
+@@ -2035,7 +2035,7 @@ static int __maybe_unused stm32_usart_se
+ * low-power mode.
+ */
+ if (stm32_port->rx_ch) {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ /* Poll data from DMA RX buffer if any */
+ if (!stm32_usart_rx_dma_pause(stm32_port))
+ size += stm32_usart_receive_chars(port, true);
diff --git a/debian/patches-rt/0065-serial-sunhv-Use-port-lock-wrappers.patch b/debian/patches-rt/0065-serial-sunhv-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..beacd2be79
--- /dev/null
+++ b/debian/patches-rt/0065-serial-sunhv-Use-port-lock-wrappers.patch
@@ -0,0 +1,149 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:22 +0206
+Subject: [PATCH 065/134] serial: sunhv: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-66-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sunhv.c | 28 ++++++++++++++--------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+--- a/drivers/tty/serial/sunhv.c
++++ b/drivers/tty/serial/sunhv.c
+@@ -217,10 +217,10 @@ static irqreturn_t sunhv_interrupt(int i
+ struct tty_port *tport;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ tport = receive_chars(port);
+ transmit_chars(port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (tport)
+ tty_flip_buffer_push(tport);
+@@ -271,7 +271,7 @@ static void sunhv_send_xchar(struct uart
+ if (ch == __DISABLED_CHAR)
+ return;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ while (limit-- > 0) {
+ long status = sun4v_con_putchar(ch);
+@@ -280,7 +280,7 @@ static void sunhv_send_xchar(struct uart
+ udelay(1);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* port->lock held by caller. */
+@@ -295,7 +295,7 @@ static void sunhv_break_ctl(struct uart_
+ unsigned long flags;
+ int limit = 10000;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ while (limit-- > 0) {
+ long status = sun4v_con_putchar(CON_BREAK);
+@@ -304,7 +304,7 @@ static void sunhv_break_ctl(struct uart_
+ udelay(1);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ }
+
+@@ -328,7 +328,7 @@ static void sunhv_set_termios(struct uar
+ unsigned int iflag, cflag;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ iflag = termios->c_iflag;
+ cflag = termios->c_cflag;
+@@ -343,7 +343,7 @@ static void sunhv_set_termios(struct uar
+ uart_update_timeout(port, cflag,
+ (port->uartclk / (16 * quot)));
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *sunhv_type(struct uart_port *port)
+@@ -437,9 +437,9 @@ static void sunhv_console_write_paged(st
+ int locked = 1;
+
+ if (port->sysrq || oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ while (n > 0) {
+ unsigned long ra = __pa(con_write_page);
+@@ -470,7 +470,7 @@ static void sunhv_console_write_paged(st
+ }
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static inline void sunhv_console_putchar(struct uart_port *port, char c)
+@@ -492,9 +492,9 @@ static void sunhv_console_write_bychar(s
+ int i, locked = 1;
+
+ if (port->sysrq || oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ for (i = 0; i < n; i++) {
+ if (*s == '\n')
+@@ -503,7 +503,7 @@ static void sunhv_console_write_bychar(s
+ }
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static struct console sunhv_console = {
diff --git a/debian/patches-rt/0066-serial-sunplus-uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0066-serial-sunplus-uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..10ae6c477c
--- /dev/null
+++ b/debian/patches-rt/0066-serial-sunplus-uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,146 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:23 +0206
+Subject: [PATCH 066/134] serial: sunplus-uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-67-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sunplus-uart.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/drivers/tty/serial/sunplus-uart.c
++++ b/drivers/tty/serial/sunplus-uart.c
+@@ -184,7 +184,7 @@ static void sunplus_break_ctl(struct uar
+ unsigned long flags;
+ unsigned int lcr;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ lcr = readl(port->membase + SUP_UART_LCR);
+
+@@ -195,7 +195,7 @@ static void sunplus_break_ctl(struct uar
+
+ writel(lcr, port->membase + SUP_UART_LCR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void transmit_chars(struct uart_port *port)
+@@ -277,7 +277,7 @@ static irqreturn_t sunplus_uart_irq(int
+ struct uart_port *port = args;
+ unsigned int isc;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ isc = readl(port->membase + SUP_UART_ISC);
+
+@@ -287,7 +287,7 @@ static irqreturn_t sunplus_uart_irq(int
+ if (isc & SUP_UART_ISC_TX)
+ transmit_chars(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -302,14 +302,14 @@ static int sunplus_startup(struct uart_p
+ if (ret)
+ return ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ /* isc define Bit[7:4] int setting, Bit[3:0] int status
+ * isc register will clean Bit[3:0] int status after read
+ * only do a write to Bit[7:4] int setting
+ */
+ isc |= SUP_UART_ISC_RXM;
+ writel(isc, port->membase + SUP_UART_ISC);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return 0;
+ }
+@@ -318,13 +318,13 @@ static void sunplus_shutdown(struct uart
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ /* isc define Bit[7:4] int setting, Bit[3:0] int status
+ * isc register will clean Bit[3:0] int status after read
+ * only do a write to Bit[7:4] int setting
+ */
+ writel(0, port->membase + SUP_UART_ISC); /* disable all interrupt */
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ free_irq(port->irq, port);
+ }
+@@ -372,7 +372,7 @@ static void sunplus_set_termios(struct u
+ lcr |= UART_LCR_EPAR;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+@@ -407,7 +407,7 @@ static void sunplus_set_termios(struct u
+ writel(div_l, port->membase + SUP_UART_DIV_L);
+ writel(lcr, port->membase + SUP_UART_LCR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void sunplus_set_ldisc(struct uart_port *port, struct ktermios *termios)
+@@ -517,15 +517,15 @@ static void sunplus_console_write(struct
+ if (sunplus_console_ports[co->index]->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&sunplus_console_ports[co->index]->port.lock);
++ locked = uart_port_trylock(&sunplus_console_ports[co->index]->port);
+ else
+- spin_lock(&sunplus_console_ports[co->index]->port.lock);
++ uart_port_lock(&sunplus_console_ports[co->index]->port);
+
+ uart_console_write(&sunplus_console_ports[co->index]->port, s, count,
+ sunplus_uart_console_putchar);
+
+ if (locked)
+- spin_unlock(&sunplus_console_ports[co->index]->port.lock);
++ uart_port_unlock(&sunplus_console_ports[co->index]->port);
+
+ local_irq_restore(flags);
+ }
diff --git a/debian/patches-rt/0067-serial-sunsab-Use-port-lock-wrappers.patch b/debian/patches-rt/0067-serial-sunsab-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..b96d5080cd
--- /dev/null
+++ b/debian/patches-rt/0067-serial-sunsab-Use-port-lock-wrappers.patch
@@ -0,0 +1,176 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:24 +0206
+Subject: [PATCH 067/134] serial: sunsab: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-68-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sunsab.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+--- a/drivers/tty/serial/sunsab.c
++++ b/drivers/tty/serial/sunsab.c
+@@ -310,7 +310,7 @@ static irqreturn_t sunsab_interrupt(int
+ unsigned long flags;
+ unsigned char gis;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ status.stat = 0;
+ gis = readb(&up->regs->r.gis) >> up->gis_shift;
+@@ -331,7 +331,7 @@ static irqreturn_t sunsab_interrupt(int
+ transmit_chars(up, &status);
+ }
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ if (port)
+ tty_flip_buffer_push(port);
+@@ -473,12 +473,12 @@ static void sunsab_send_xchar(struct uar
+ if (ch == __DISABLED_CHAR)
+ return;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ sunsab_tec_wait(up);
+ writeb(ch, &up->regs->w.tic);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ /* port->lock held by caller. */
+@@ -499,7 +499,7 @@ static void sunsab_break_ctl(struct uart
+ unsigned long flags;
+ unsigned char val;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ val = up->cached_dafo;
+ if (break_state)
+@@ -512,7 +512,7 @@ static void sunsab_break_ctl(struct uart
+ if (test_bit(SAB82532_XPR, &up->irqflags))
+ sunsab_tx_idle(up);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ /* port->lock is not held. */
+@@ -527,7 +527,7 @@ static int sunsab_startup(struct uart_po
+ if (err)
+ return err;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * Wait for any commands or immediate characters
+@@ -582,7 +582,7 @@ static int sunsab_startup(struct uart_po
+ set_bit(SAB82532_ALLS, &up->irqflags);
+ set_bit(SAB82532_XPR, &up->irqflags);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return 0;
+ }
+@@ -594,7 +594,7 @@ static void sunsab_shutdown(struct uart_
+ container_of(port, struct uart_sunsab_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /* Disable Interrupts */
+ up->interrupt_mask0 = 0xff;
+@@ -628,7 +628,7 @@ static void sunsab_shutdown(struct uart_
+ writeb(tmp, &up->regs->rw.ccr0);
+ #endif
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ free_irq(up->port.irq, up);
+ }
+
+@@ -779,9 +779,9 @@ static void sunsab_set_termios(struct ua
+ unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
+ unsigned int quot = uart_get_divisor(port, baud);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud, quot);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static const char *sunsab_type(struct uart_port *port)
+@@ -857,15 +857,15 @@ static void sunsab_console_write(struct
+ int locked = 1;
+
+ if (up->port.sysrq || oops_in_progress)
+- locked = spin_trylock_irqsave(&up->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&up->port, &flags);
+ else
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ uart_console_write(&up->port, s, n, sunsab_console_putchar);
+ sunsab_tec_wait(up);
+
+ if (locked)
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int sunsab_console_setup(struct console *con, char *options)
+@@ -914,7 +914,7 @@ static int sunsab_console_setup(struct c
+ */
+ sunsab_startup(&up->port);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * Finally, enable interrupts
+@@ -932,7 +932,7 @@ static int sunsab_console_setup(struct c
+ sunsab_convert_to_sab(up, con->cflag, 0, baud, quot);
+ sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return 0;
+ }
diff --git a/debian/patches-rt/0068-serial-sunsu-Use-port-lock-wrappers.patch b/debian/patches-rt/0068-serial-sunsu-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..77945a1edb
--- /dev/null
+++ b/debian/patches-rt/0068-serial-sunsu-Use-port-lock-wrappers.patch
@@ -0,0 +1,219 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:25 +0206
+Subject: [PATCH 068/134] serial: sunsu: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-69-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sunsu.c | 46 ++++++++++++++++++++++-----------------------
+ 1 file changed, 23 insertions(+), 23 deletions(-)
+
+--- a/drivers/tty/serial/sunsu.c
++++ b/drivers/tty/serial/sunsu.c
+@@ -212,9 +212,9 @@ static void enable_rsa(struct uart_sunsu
+ {
+ if (up->port.type == PORT_RSA) {
+ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
+- spin_lock_irq(&up->port.lock);
++ uart_port_lock_irq(&up->port);
+ __enable_rsa(up);
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ }
+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+ serial_outp(up, UART_RSA_FRR, 0);
+@@ -234,7 +234,7 @@ static void disable_rsa(struct uart_suns
+
+ if (up->port.type == PORT_RSA &&
+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+- spin_lock_irq(&up->port.lock);
++ uart_port_lock_irq(&up->port);
+
+ mode = serial_inp(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+@@ -247,7 +247,7 @@ static void disable_rsa(struct uart_suns
+
+ if (result)
+ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
+- spin_unlock_irq(&up->port.lock);
++ uart_port_unlock_irq(&up->port);
+ }
+ }
+ #endif /* CONFIG_SERIAL_8250_RSA */
+@@ -311,10 +311,10 @@ static void sunsu_enable_ms(struct uart_
+ container_of(port, struct uart_sunsu_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ up->ier |= UART_IER_MSI;
+ serial_out(up, UART_IER, up->ier);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static void
+@@ -456,7 +456,7 @@ static irqreturn_t sunsu_serial_interrup
+ unsigned long flags;
+ unsigned char status;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ do {
+ status = serial_inp(up, UART_LSR);
+@@ -470,7 +470,7 @@ static irqreturn_t sunsu_serial_interrup
+
+ } while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT));
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return IRQ_HANDLED;
+ }
+@@ -545,9 +545,9 @@ static unsigned int sunsu_tx_empty(struc
+ unsigned long flags;
+ unsigned int ret;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return ret;
+ }
+@@ -599,13 +599,13 @@ static void sunsu_break_ctl(struct uart_
+ container_of(port, struct uart_sunsu_port, port);
+ unsigned long flags;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(up, UART_LCR, up->lcr);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int sunsu_startup(struct uart_port *port)
+@@ -683,12 +683,12 @@ static int sunsu_startup(struct uart_por
+ */
+ serial_outp(up, UART_LCR, UART_LCR_WLEN8);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ up->port.mctrl |= TIOCM_OUT2;
+
+ sunsu_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ /*
+ * Finally, enable interrupts. Note: Modem status interrupts
+@@ -731,7 +731,7 @@ static void sunsu_shutdown(struct uart_p
+ up->ier = 0;
+ serial_outp(up, UART_IER, 0);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ /* reset interrupts on the AST Fourport board */
+ inb((up->port.iobase & 0xfe0) | 0x1f);
+@@ -740,7 +740,7 @@ static void sunsu_shutdown(struct uart_p
+ up->port.mctrl &= ~TIOCM_OUT2;
+
+ sunsu_set_mctrl(&up->port, up->port.mctrl);
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ /*
+ * Disable break condition and FIFOs
+@@ -826,7 +826,7 @@ sunsu_change_speed(struct uart_port *por
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * Update the per-port timeout.
+@@ -891,7 +891,7 @@ sunsu_change_speed(struct uart_port *por
+
+ up->cflag = cflag;
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static void
+@@ -1038,7 +1038,7 @@ static void sunsu_autoconfig(struct uart
+ up->type_probed = PORT_UNKNOWN;
+ up->port.iotype = UPIO_MEM;
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ if (!(up->port.flags & UPF_BUGGY_UART)) {
+ /*
+@@ -1173,7 +1173,7 @@ static void sunsu_autoconfig(struct uart
+ serial_outp(up, UART_IER, 0);
+
+ out:
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static struct uart_driver sunsu_reg = {
+@@ -1298,9 +1298,9 @@ static void sunsu_console_write(struct c
+ int locked = 1;
+
+ if (up->port.sysrq || oops_in_progress)
+- locked = spin_trylock_irqsave(&up->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&up->port, &flags);
+ else
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * First save the UER then disable the interrupts
+@@ -1318,7 +1318,7 @@ static void sunsu_console_write(struct c
+ serial_out(up, UART_IER, ier);
+
+ if (locked)
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ /*
diff --git a/debian/patches-rt/0069-serial-sunzilog-Use-port-lock-wrappers.patch b/debian/patches-rt/0069-serial-sunzilog-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..dca4327a46
--- /dev/null
+++ b/debian/patches-rt/0069-serial-sunzilog-Use-port-lock-wrappers.patch
@@ -0,0 +1,211 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:26 +0206
+Subject: [PATCH 069/134] serial: sunzilog: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-70-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/sunzilog.c | 42 +++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+--- a/drivers/tty/serial/sunzilog.c
++++ b/drivers/tty/serial/sunzilog.c
+@@ -531,7 +531,7 @@ static irqreturn_t sunzilog_interrupt(in
+ struct tty_port *port;
+ unsigned char r3;
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ r3 = read_zsreg(channel, R3);
+
+ /* Channel A */
+@@ -548,7 +548,7 @@ static irqreturn_t sunzilog_interrupt(in
+ if (r3 & CHATxIP)
+ sunzilog_transmit_chars(up, channel);
+ }
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ if (port)
+ tty_flip_buffer_push(port);
+@@ -557,7 +557,7 @@ static irqreturn_t sunzilog_interrupt(in
+ up = up->next;
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+
+- spin_lock(&up->port.lock);
++ uart_port_lock(&up->port);
+ port = NULL;
+ if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
+ writeb(RES_H_IUS, &channel->control);
+@@ -571,7 +571,7 @@ static irqreturn_t sunzilog_interrupt(in
+ if (r3 & CHBTxIP)
+ sunzilog_transmit_chars(up, channel);
+ }
+- spin_unlock(&up->port.lock);
++ uart_port_unlock(&up->port);
+
+ if (port)
+ tty_flip_buffer_push(port);
+@@ -604,11 +604,11 @@ static unsigned int sunzilog_tx_empty(st
+ unsigned char status;
+ unsigned int ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ status = sunzilog_read_channel_status(port);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ if (status & Tx_BUF_EMP)
+ ret = TIOCSER_TEMT;
+@@ -764,7 +764,7 @@ static void sunzilog_break_ctl(struct ua
+ else
+ clear_bits |= SND_BRK;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ new_reg = (up->curregs[R5] | set_bits) & ~clear_bits;
+ if (new_reg != up->curregs[R5]) {
+@@ -774,7 +774,7 @@ static void sunzilog_break_ctl(struct ua
+ write_zsreg(channel, R5, up->curregs[R5]);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static void __sunzilog_startup(struct uart_sunzilog_port *up)
+@@ -800,9 +800,9 @@ static int sunzilog_startup(struct uart_
+ if (ZS_IS_CONS(up))
+ return 0;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ __sunzilog_startup(up);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ return 0;
+ }
+
+@@ -840,7 +840,7 @@ static void sunzilog_shutdown(struct uar
+ if (ZS_IS_CONS(up))
+ return;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ channel = ZILOG_CHANNEL_FROM_PORT(port);
+
+@@ -853,7 +853,7 @@ static void sunzilog_shutdown(struct uar
+ up->curregs[R5] &= ~SND_BRK;
+ sunzilog_maybe_update_regs(up, channel);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /* Shared by TTY driver and serial console setup. The port lock is held
+@@ -945,7 +945,7 @@ sunzilog_set_termios(struct uart_port *p
+
+ baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+
+@@ -962,7 +962,7 @@ sunzilog_set_termios(struct uart_port *p
+
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static const char *sunzilog_type(struct uart_port *port)
+@@ -1201,15 +1201,15 @@ sunzilog_console_write(struct console *c
+ int locked = 1;
+
+ if (up->port.sysrq || oops_in_progress)
+- locked = spin_trylock_irqsave(&up->port.lock, flags);
++ locked = uart_port_trylock_irqsave(&up->port, &flags);
+ else
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ uart_console_write(&up->port, s, count, sunzilog_putchar);
+ udelay(2);
+
+ if (locked)
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int __init sunzilog_console_setup(struct console *con, char *options)
+@@ -1244,7 +1244,7 @@ static int __init sunzilog_console_setup
+
+ brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ up->curregs[R15] |= BRKIE;
+ sunzilog_convert_to_zs(up, con->cflag, 0, brg);
+@@ -1252,7 +1252,7 @@ static int __init sunzilog_console_setup
+ sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
+ __sunzilog_startup(up);
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ return 0;
+ }
+@@ -1333,7 +1333,7 @@ static void sunzilog_init_hw(struct uart
+
+ channel = ZILOG_CHANNEL_FROM_PORT(&up->port);
+
+- spin_lock_irqsave(&up->port.lock, flags);
++ uart_port_lock_irqsave(&up->port, &flags);
+ if (ZS_IS_CHANNEL_A(up)) {
+ write_zsreg(channel, R9, FHWRES);
+ ZSDELAY_LONG();
+@@ -1383,7 +1383,7 @@ static void sunzilog_init_hw(struct uart
+ write_zsreg(channel, R9, up->curregs[R9]);
+ }
+
+- spin_unlock_irqrestore(&up->port.lock, flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+
+ #ifdef CONFIG_SERIO
+ if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
diff --git a/debian/patches-rt/0070-serial-timbuart-Use-port-lock-wrappers.patch b/debian/patches-rt/0070-serial-timbuart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..2d5a3d95e3
--- /dev/null
+++ b/debian/patches-rt/0070-serial-timbuart-Use-port-lock-wrappers.patch
@@ -0,0 +1,71 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:27 +0206
+Subject: [PATCH 070/134] serial: timbuart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-71-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/timbuart.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/timbuart.c
++++ b/drivers/tty/serial/timbuart.c
+@@ -174,7 +174,7 @@ static void timbuart_tasklet(struct task
+ struct timbuart_port *uart = from_tasklet(uart, t, tasklet);
+ u32 isr, ier = 0;
+
+- spin_lock(&uart->port.lock);
++ uart_port_lock(&uart->port);
+
+ isr = ioread32(uart->port.membase + TIMBUART_ISR);
+ dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr);
+@@ -189,7 +189,7 @@ static void timbuart_tasklet(struct task
+
+ iowrite32(ier, uart->port.membase + TIMBUART_IER);
+
+- spin_unlock(&uart->port.lock);
++ uart_port_unlock(&uart->port);
+ dev_dbg(uart->port.dev, "%s leaving\n", __func__);
+ }
+
+@@ -295,10 +295,10 @@ static void timbuart_set_termios(struct
+ tty_termios_copy_hw(termios, old);
+ tty_termios_encode_baud_rate(termios, baud, baud);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE);
+ uart_update_timeout(port, termios->c_cflag, baud);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *timbuart_type(struct uart_port *port)
diff --git a/debian/patches-rt/0071-serial-uartlite-Use-port-lock-wrappers.patch b/debian/patches-rt/0071-serial-uartlite-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..13c64d7eed
--- /dev/null
+++ b/debian/patches-rt/0071-serial-uartlite-Use-port-lock-wrappers.patch
@@ -0,0 +1,105 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:28 +0206
+Subject: [PATCH 071/134] serial: uartlite: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-72-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/uartlite.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/tty/serial/uartlite.c
++++ b/drivers/tty/serial/uartlite.c
+@@ -216,11 +216,11 @@ static irqreturn_t ulite_isr(int irq, vo
+ unsigned long flags;
+
+ do {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ stat = uart_in32(ULITE_STATUS, port);
+ busy = ulite_receive(port, stat);
+ busy |= ulite_transmit(port, stat);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ n++;
+ } while (busy);
+
+@@ -238,9 +238,9 @@ static unsigned int ulite_tx_empty(struc
+ unsigned long flags;
+ unsigned int ret;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ ret = uart_in32(ULITE_STATUS, port);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0;
+ }
+@@ -323,7 +323,7 @@ static void ulite_set_termios(struct uar
+ termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE);
+ tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud);
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN
+ | ULITE_STATUS_TXFULL;
+@@ -346,7 +346,7 @@ static void ulite_set_termios(struct uar
+ /* update timeout */
+ uart_update_timeout(port, termios->c_cflag, pdata->baud);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *ulite_type(struct uart_port *port)
+@@ -495,9 +495,9 @@ static void ulite_console_write(struct c
+ int locked = 1;
+
+ if (oops_in_progress) {
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ } else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* save and disable interrupt */
+ ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE;
+@@ -512,7 +512,7 @@ static void ulite_console_write(struct c
+ uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static int ulite_console_setup(struct console *co, char *options)
diff --git a/debian/patches-rt/0072-serial-ucc_uart-Use-port-lock-wrappers.patch b/debian/patches-rt/0072-serial-ucc_uart-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..30681434a7
--- /dev/null
+++ b/debian/patches-rt/0072-serial-ucc_uart-Use-port-lock-wrappers.patch
@@ -0,0 +1,59 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:29 +0206
+Subject: [PATCH 072/134] serial: ucc_uart: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Timur Tabi <timur@kernel.org>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-73-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/ucc_uart.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/serial/ucc_uart.c
++++ b/drivers/tty/serial/ucc_uart.c
+@@ -931,7 +931,7 @@ static void qe_uart_set_termios(struct u
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+
+ /* Do we really need a spinlock here? */
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Update the per-port timeout. */
+ uart_update_timeout(port, termios->c_cflag, baud);
+@@ -949,7 +949,7 @@ static void qe_uart_set_termios(struct u
+ qe_setbrg(qe_port->us_info.tx_clock, baud, 16);
+ }
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /*
diff --git a/debian/patches-rt/0073-serial-vt8500-Use-port-lock-wrappers.patch b/debian/patches-rt/0073-serial-vt8500-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..7209ed0661
--- /dev/null
+++ b/debian/patches-rt/0073-serial-vt8500-Use-port-lock-wrappers.patch
@@ -0,0 +1,76 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:30 +0206
+Subject: [PATCH 073/134] serial: vt8500: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-74-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/vt8500_serial.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/serial/vt8500_serial.c
++++ b/drivers/tty/serial/vt8500_serial.c
+@@ -227,7 +227,7 @@ static irqreturn_t vt8500_irq(int irq, v
+ struct uart_port *port = dev_id;
+ unsigned long isr;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+ isr = vt8500_read(port, VT8500_URISR);
+
+ /* Acknowledge active status bits */
+@@ -240,7 +240,7 @@ static irqreturn_t vt8500_irq(int irq, v
+ if (isr & TCTS)
+ handle_delta_cts(port);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+
+ return IRQ_HANDLED;
+ }
+@@ -342,7 +342,7 @@ static void vt8500_set_termios(struct ua
+ unsigned int baud, lcr;
+ unsigned int loops = 1000;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* calculate and set baud rate */
+ baud = uart_get_baud_rate(port, termios, old, 900, 921600);
+@@ -410,7 +410,7 @@ static void vt8500_set_termios(struct ua
+ vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR);
+ vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ static const char *vt8500_type(struct uart_port *port)
diff --git a/debian/patches-rt/0074-serial-xilinx_uartps-Use-port-lock-wrappers.patch b/debian/patches-rt/0074-serial-xilinx_uartps-Use-port-lock-wrappers.patch
new file mode 100644
index 0000000000..307ee6df75
--- /dev/null
+++ b/debian/patches-rt/0074-serial-xilinx_uartps-Use-port-lock-wrappers.patch
@@ -0,0 +1,276 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Sep 2023 20:44:31 +0206
+Subject: [PATCH 074/134] serial: xilinx_uartps: Use port lock wrappers
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When a serial port is used for kernel console output, then all
+modifications to the UART registers which are done from other contexts,
+e.g. getty, termios, are interference points for the kernel console.
+
+So far this has been ignored and the printk output is based on the
+principle of hope. The rework of the console infrastructure which aims to
+support threaded and atomic consoles, requires to mark sections which
+modify the UART registers as unsafe. This allows the atomic write function
+to make informed decisions and eventually to restore operational state. It
+also allows to prevent the regular UART code from modifying UART registers
+while printk output is in progress.
+
+All modifications of UART registers are guarded by the UART port lock,
+which provides an obvious synchronization point with the console
+infrastructure.
+
+To avoid adding this functionality to all UART drivers, wrap the
+spin_[un]lock*() invocations for uart_port::lock into helper functions
+which just contain the spin_[un]lock*() invocations for now. In a
+subsequent step these helpers will gain the console synchronization
+mechanisms.
+
+Converted with coccinelle. No functional change.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20230914183831.587273-75-john.ogness@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/xilinx_uartps.c | 56 ++++++++++++++++++-------------------
+ 1 file changed, 28 insertions(+), 28 deletions(-)
+
+--- a/drivers/tty/serial/xilinx_uartps.c
++++ b/drivers/tty/serial/xilinx_uartps.c
+@@ -346,7 +346,7 @@ static irqreturn_t cdns_uart_isr(int irq
+ struct uart_port *port = (struct uart_port *)dev_id;
+ unsigned int isrstatus;
+
+- spin_lock(&port->lock);
++ uart_port_lock(port);
+
+ /* Read the interrupt status register to determine which
+ * interrupt(s) is/are active and clear them.
+@@ -369,7 +369,7 @@ static irqreturn_t cdns_uart_isr(int irq
+ !(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_RX_DIS))
+ cdns_uart_handle_rx(dev_id, isrstatus);
+
+- spin_unlock(&port->lock);
++ uart_port_unlock(port);
+ return IRQ_HANDLED;
+ }
+
+@@ -506,14 +506,14 @@ static int cdns_uart_clk_notifier_cb(str
+ return NOTIFY_BAD;
+ }
+
+- spin_lock_irqsave(&cdns_uart->port->lock, flags);
++ uart_port_lock_irqsave(cdns_uart->port, &flags);
+
+ /* Disable the TX and RX to set baud rate */
+ ctrl_reg = readl(port->membase + CDNS_UART_CR);
+ ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS;
+ writel(ctrl_reg, port->membase + CDNS_UART_CR);
+
+- spin_unlock_irqrestore(&cdns_uart->port->lock, flags);
++ uart_port_unlock_irqrestore(cdns_uart->port, flags);
+
+ return NOTIFY_OK;
+ }
+@@ -523,7 +523,7 @@ static int cdns_uart_clk_notifier_cb(str
+ * frequency.
+ */
+
+- spin_lock_irqsave(&cdns_uart->port->lock, flags);
++ uart_port_lock_irqsave(cdns_uart->port, &flags);
+
+ locked = 1;
+ port->uartclk = ndata->new_rate;
+@@ -533,7 +533,7 @@ static int cdns_uart_clk_notifier_cb(str
+ fallthrough;
+ case ABORT_RATE_CHANGE:
+ if (!locked)
+- spin_lock_irqsave(&cdns_uart->port->lock, flags);
++ uart_port_lock_irqsave(cdns_uart->port, &flags);
+
+ /* Set TX/RX Reset */
+ ctrl_reg = readl(port->membase + CDNS_UART_CR);
+@@ -555,7 +555,7 @@ static int cdns_uart_clk_notifier_cb(str
+ ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN;
+ writel(ctrl_reg, port->membase + CDNS_UART_CR);
+
+- spin_unlock_irqrestore(&cdns_uart->port->lock, flags);
++ uart_port_unlock_irqrestore(cdns_uart->port, flags);
+
+ return NOTIFY_OK;
+ default:
+@@ -652,7 +652,7 @@ static void cdns_uart_break_ctl(struct u
+ unsigned int status;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ status = readl(port->membase + CDNS_UART_CR);
+
+@@ -664,7 +664,7 @@ static void cdns_uart_break_ctl(struct u
+ writel(CDNS_UART_CR_STOPBRK | status,
+ port->membase + CDNS_UART_CR);
+ }
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /**
+@@ -683,7 +683,7 @@ static void cdns_uart_set_termios(struct
+ unsigned long flags;
+ unsigned int ctrl_reg, mode_reg;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable the TX and RX to set baud rate */
+ ctrl_reg = readl(port->membase + CDNS_UART_CR);
+@@ -794,7 +794,7 @@ static void cdns_uart_set_termios(struct
+ cval &= ~CDNS_UART_MODEMCR_FCM;
+ writel(cval, port->membase + CDNS_UART_MODEMCR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /**
+@@ -813,7 +813,7 @@ static int cdns_uart_startup(struct uart
+
+ is_brk_support = cdns_uart->quirks & CDNS_UART_RXBS_SUPPORT;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable the TX and RX */
+ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
+@@ -861,7 +861,7 @@ static int cdns_uart_startup(struct uart
+ writel(readl(port->membase + CDNS_UART_ISR),
+ port->membase + CDNS_UART_ISR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ ret = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, port);
+ if (ret) {
+@@ -889,7 +889,7 @@ static void cdns_uart_shutdown(struct ua
+ int status;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Disable interrupts */
+ status = readl(port->membase + CDNS_UART_IMR);
+@@ -900,7 +900,7 @@ static void cdns_uart_shutdown(struct ua
+ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS,
+ port->membase + CDNS_UART_CR);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ free_irq(port->irq, port);
+ }
+@@ -1050,7 +1050,7 @@ static int cdns_uart_poll_get_char(struc
+ int c;
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Check if FIFO is empty */
+ if (readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)
+@@ -1058,7 +1058,7 @@ static int cdns_uart_poll_get_char(struc
+ else /* Read a character */
+ c = (unsigned char) readl(port->membase + CDNS_UART_FIFO);
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+
+ return c;
+ }
+@@ -1067,7 +1067,7 @@ static void cdns_uart_poll_put_char(stru
+ {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Wait until FIFO is empty */
+ while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY))
+@@ -1080,7 +1080,7 @@ static void cdns_uart_poll_put_char(stru
+ while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY))
+ cpu_relax();
+
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+ #endif
+
+@@ -1232,9 +1232,9 @@ static void cdns_uart_console_write(stru
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
++ locked = uart_port_trylock_irqsave(port, &flags);
+ else
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* save and disable interrupt */
+ imr = readl(port->membase + CDNS_UART_IMR);
+@@ -1257,7 +1257,7 @@ static void cdns_uart_console_write(stru
+ writel(imr, port->membase + CDNS_UART_IER);
+
+ if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /**
+@@ -1325,7 +1325,7 @@ static int cdns_uart_suspend(struct devi
+ if (console_suspend_enabled && uart_console(port) && may_wake) {
+ unsigned long flags;
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ /* Empty the receive FIFO 1st before making changes */
+ while (!(readl(port->membase + CDNS_UART_SR) &
+ CDNS_UART_SR_RXEMPTY))
+@@ -1334,7 +1334,7 @@ static int cdns_uart_suspend(struct devi
+ writel(1, port->membase + CDNS_UART_RXWM);
+ /* disable RX timeout interrups */
+ writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IDR);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ /*
+@@ -1372,7 +1372,7 @@ static int cdns_uart_resume(struct devic
+ return ret;
+ }
+
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+
+ /* Set TX/RX Reset */
+ ctrl_reg = readl(port->membase + CDNS_UART_CR);
+@@ -1392,14 +1392,14 @@ static int cdns_uart_resume(struct devic
+
+ clk_disable(cdns_uart->uartclk);
+ clk_disable(cdns_uart->pclk);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ } else {
+- spin_lock_irqsave(&port->lock, flags);
++ uart_port_lock_irqsave(port, &flags);
+ /* restore original rx trigger level */
+ writel(rx_trigger_level, port->membase + CDNS_UART_RXWM);
+ /* enable RX timeout interrupt */
+ writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER);
+- spin_unlock_irqrestore(&port->lock, flags);
++ uart_port_unlock_irqrestore(port, flags);
+ }
+
+ return uart_resume_port(cdns_uart->cdns_uart_driver, port);
diff --git a/debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch b/debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch
new file mode 100644
index 0000000000..00f7850c36
--- /dev/null
+++ b/debian/patches-rt/0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch
@@ -0,0 +1,261 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:00 +0206
+Subject: [PATCH 075/134] printk: Add non-BKL (nbcon) console basic
+ infrastructure
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The current console/printk subsystem is protected by a Big Kernel Lock,
+(aka console_lock) which has ill defined semantics and is more or less
+stateless. This puts severe limitations on the console subsystem and
+makes forced takeover and output in emergency and panic situations a
+fragile endeavour that is based on try and pray.
+
+The goal of non-BKL (nbcon) consoles is to break out of the console lock
+jail and to provide a new infrastructure that avoids the pitfalls and
+also allows console drivers to be gradually converted over.
+
+The proposed infrastructure aims for the following properties:
+
+ - Per console locking instead of global locking
+ - Per console state that allows to make informed decisions
+ - Stateful handover and takeover
+
+As a first step, state is added to struct console. The per console state
+is an atomic_t using a 32bit bit field.
+
+Reserve state bits, which will be populated later in the series. Wire
+it up into the console register/unregister functionality.
+
+It was decided to use a bitfield because using a plain u32 with
+mask/shift operations resulted in uncomprehensible code.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-2-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 31 ++++++++++++++++++++
+ kernel/printk/Makefile | 2 -
+ kernel/printk/internal.h | 8 +++++
+ kernel/printk/nbcon.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 13 ++++++--
+ 5 files changed, 120 insertions(+), 4 deletions(-)
+ create mode 100644 kernel/printk/nbcon.c
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -156,6 +156,8 @@ static inline int con_debug_leave(void)
+ * /dev/kmesg which requires a larger output buffer.
+ * @CON_SUSPENDED: Indicates if a console is suspended. If true, the
+ * printing callbacks must not be called.
++ * @CON_NBCON: Console can operate outside of the legacy style console_lock
++ * constraints.
+ */
+ enum cons_flags {
+ CON_PRINTBUFFER = BIT(0),
+@@ -166,9 +168,33 @@ enum cons_flags {
+ CON_BRL = BIT(5),
+ CON_EXTENDED = BIT(6),
+ CON_SUSPENDED = BIT(7),
++ CON_NBCON = BIT(8),
+ };
+
+ /**
++ * struct nbcon_state - console state for nbcon consoles
++ * @atom: Compound of the state fields for atomic operations
++ *
++ * To be used for reading and preparing of the value stored in the nbcon
++ * state variable @console::nbcon_state.
++ */
++struct nbcon_state {
++ union {
++ unsigned int atom;
++ struct {
++ };
++ };
++};
++
++/*
++ * The nbcon_state struct is used to easily create and interpret values that
++ * are stored in the @console::nbcon_state variable. Ensure this struct stays
++ * within the size boundaries of the atomic variable's underlying type in
++ * order to avoid any accidental truncation.
++ */
++static_assert(sizeof(struct nbcon_state) <= sizeof(int));
++
++/**
+ * struct console - The console descriptor structure
+ * @name: The name of the console driver
+ * @write: Write callback to output messages (Optional)
+@@ -187,6 +213,8 @@ enum cons_flags {
+ * @dropped: Number of unreported dropped ringbuffer records
+ * @data: Driver private data
+ * @node: hlist node for the console list
++ *
++ * @nbcon_state: State for nbcon consoles
+ */
+ struct console {
+ char name[16];
+@@ -206,6 +234,9 @@ struct console {
+ unsigned long dropped;
+ void *data;
+ struct hlist_node node;
++
++ /* nbcon console specific members */
++ atomic_t __private nbcon_state;
+ };
+
+ #ifdef CONFIG_LOCKDEP
+--- a/kernel/printk/Makefile
++++ b/kernel/printk/Makefile
+@@ -1,6 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-y = printk.o
+-obj-$(CONFIG_PRINTK) += printk_safe.o
++obj-$(CONFIG_PRINTK) += printk_safe.o nbcon.o
+ obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o
+ obj-$(CONFIG_PRINTK_INDEX) += index.o
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -3,6 +3,7 @@
+ * internal.h - printk internal definitions
+ */
+ #include <linux/percpu.h>
++#include <linux/console.h>
+
+ #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL)
+ void __init printk_sysctl_init(void);
+@@ -61,6 +62,10 @@ void defer_console_output(void);
+
+ u16 printk_parse_prefix(const char *text, int *level,
+ enum printk_info_flags *flags);
++
++void nbcon_init(struct console *con);
++void nbcon_cleanup(struct console *con);
++
+ #else
+
+ #define PRINTK_PREFIX_MAX 0
+@@ -76,6 +81,9 @@ u16 printk_parse_prefix(const char *text
+ #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
+
+ static inline bool printk_percpu_data_ready(void) { return false; }
++static inline void nbcon_init(struct console *con) { }
++static inline void nbcon_cleanup(struct console *con) { }
++
+ #endif /* CONFIG_PRINTK */
+
+ /**
+--- /dev/null
++++ b/kernel/printk/nbcon.c
+@@ -0,0 +1,70 @@
++// SPDX-License-Identifier: GPL-2.0-only
++// Copyright (C) 2022 Linutronix GmbH, John Ogness
++// Copyright (C) 2022 Intel, Thomas Gleixner
++
++#include <linux/kernel.h>
++#include <linux/console.h>
++#include "internal.h"
++/*
++ * Printk console printing implementation for consoles which does not depend
++ * on the legacy style console_lock mechanism.
++ */
++
++/**
++ * nbcon_state_set - Helper function to set the console state
++ * @con: Console to update
++ * @new: The new state to write
++ *
++ * Only to be used when the console is not yet or no longer visible in the
++ * system. Otherwise use nbcon_state_try_cmpxchg().
++ */
++static inline void nbcon_state_set(struct console *con, struct nbcon_state *new)
++{
++ atomic_set(&ACCESS_PRIVATE(con, nbcon_state), new->atom);
++}
++
++/**
++ * nbcon_state_read - Helper function to read the console state
++ * @con: Console to read
++ * @state: The state to store the result
++ */
++static inline void nbcon_state_read(struct console *con, struct nbcon_state *state)
++{
++ state->atom = atomic_read(&ACCESS_PRIVATE(con, nbcon_state));
++}
++
++/**
++ * nbcon_state_try_cmpxchg() - Helper function for atomic_try_cmpxchg() on console state
++ * @con: Console to update
++ * @cur: Old/expected state
++ * @new: New state
++ *
++ * Return: True on success. False on fail and @cur is updated.
++ */
++static inline bool nbcon_state_try_cmpxchg(struct console *con, struct nbcon_state *cur,
++ struct nbcon_state *new)
++{
++ return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom);
++}
++
++/**
++ * nbcon_init - Initialize the nbcon console specific data
++ * @con: Console to initialize
++ */
++void nbcon_init(struct console *con)
++{
++ struct nbcon_state state = { };
++
++ nbcon_state_set(con, &state);
++}
++
++/**
++ * nbcon_cleanup - Cleanup the nbcon console specific data
++ * @con: Console to cleanup
++ */
++void nbcon_cleanup(struct console *con)
++{
++ struct nbcon_state state = { };
++
++ nbcon_state_set(con, &state);
++}
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3326,9 +3326,10 @@ static void try_enable_default_console(s
+ newcon->flags |= CON_CONSDEV;
+ }
+
+-#define con_printk(lvl, con, fmt, ...) \
+- printk(lvl pr_fmt("%sconsole [%s%d] " fmt), \
+- (con->flags & CON_BOOT) ? "boot" : "", \
++#define con_printk(lvl, con, fmt, ...) \
++ printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \
++ (con->flags & CON_NBCON) ? "" : "legacy ", \
++ (con->flags & CON_BOOT) ? "boot" : "", \
+ con->name, con->index, ##__VA_ARGS__)
+
+ static void console_init_seq(struct console *newcon, bool bootcon_registered)
+@@ -3488,6 +3489,9 @@ void register_console(struct console *ne
+ newcon->dropped = 0;
+ console_init_seq(newcon, bootcon_registered);
+
++ if (newcon->flags & CON_NBCON)
++ nbcon_init(newcon);
++
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+@@ -3579,6 +3583,9 @@ static int unregister_console_locked(str
+ */
+ synchronize_srcu(&console_srcu);
+
++ if (console->flags & CON_NBCON)
++ nbcon_cleanup(console);
++
+ console_sysfs_notify();
+
+ if (console->exit)
diff --git a/debian/patches-rt/0076-printk-nbcon-Add-acquire-release-logic.patch b/debian/patches-rt/0076-printk-nbcon-Add-acquire-release-logic.patch
new file mode 100644
index 0000000000..2718379038
--- /dev/null
+++ b/debian/patches-rt/0076-printk-nbcon-Add-acquire-release-logic.patch
@@ -0,0 +1,705 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:01 +0206
+Subject: [PATCH 076/134] printk: nbcon: Add acquire/release logic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add per console acquire/release functionality.
+
+The state of the console is maintained in the "nbcon_state" atomic
+variable.
+
+The console is locked when:
+
+ - The 'prio' field contains the priority of the context that owns the
+ console. Only higher priority contexts are allowed to take over the
+ lock. A value of 0 (NBCON_PRIO_NONE) means the console is not locked.
+
+ - The 'cpu' field denotes on which CPU the console is locked. It is used
+ to prevent busy waiting on the same CPU. Also it informs the lock owner
+ that it has lost the lock in a more complex scenario when the lock was
+ taken over by a higher priority context, released, and taken on another
+ CPU with the same priority as the interrupted owner.
+
+The acquire mechanism uses a few more fields:
+
+ - The 'req_prio' field is used by the handover approach to make the
+ current owner aware that there is a context with a higher priority
+ waiting for the friendly handover.
+
+ - The 'unsafe' field allows to take over the console in a safe way in the
+ middle of emitting a message. The field is set only when accessing some
+ shared resources or when the console device is manipulated. It can be
+ cleared, for example, after emitting one character when the console
+ device is in a consistent state.
+
+ - The 'unsafe_takeover' field is set when a hostile takeover took the
+ console in an unsafe state. The console will stay in the unsafe state
+ until re-initialized.
+
+The acquire mechanism uses three approaches:
+
+ 1) Direct acquire when the console is not owned or is owned by a lower
+ priority context and is in a safe state.
+
+ 2) Friendly handover mechanism uses a request/grant handshake. It is used
+ when the current owner has lower priority and the console is in an
+ unsafe state.
+
+ The requesting context:
+
+ a) Sets its priority into the 'req_prio' field.
+
+ b) Waits (with a timeout) for the owning context to unlock the
+ console.
+
+ c) Takes the lock and clears the 'req_prio' field.
+
+ The owning context:
+
+ a) Observes the 'req_prio' field set on exit from the unsafe
+ console state.
+
+ b) Gives up console ownership by clearing the 'prio' field.
+
+ 3) Unsafe hostile takeover allows to take over the lock even when the
+ console is an unsafe state. It is used only in panic() by the final
+ attempt to flush consoles in a try and hope mode.
+
+ Note that separate record buffers are used in panic(). As a result,
+ the messages can be read and formatted without any risk even after
+ using the hostile takeover in unsafe state.
+
+The release function simply clears the 'prio' field.
+
+All operations on @console::nbcon_state are atomic cmpxchg based to
+handle concurrency.
+
+The acquire/release functions implement only minimal policies:
+
+ - Preference for higher priority contexts.
+ - Protection of the panic CPU.
+
+All other policy decisions must be made at the call sites:
+
+ - What is marked as an unsafe section.
+ - Whether to spin-wait if there is already an owner and the console is
+ in an unsafe state.
+ - Whether to attempt an unsafe hostile takeover.
+
+The design allows to implement the well known:
+
+ acquire()
+ output_one_printk_record()
+ release()
+
+The output of one printk record might be interrupted with a higher priority
+context. The new owner is supposed to reprint the entire interrupted record
+from scratch.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-3-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 56 +++++
+ kernel/printk/nbcon.c | 497 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 553 insertions(+)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -175,13 +175,29 @@ enum cons_flags {
+ * struct nbcon_state - console state for nbcon consoles
+ * @atom: Compound of the state fields for atomic operations
+ *
++ * @req_prio: The priority of a handover request
++ * @prio: The priority of the current owner
++ * @unsafe: Console is busy in a non takeover region
++ * @unsafe_takeover: A hostile takeover in an unsafe state happened in the
++ * past. The console cannot be safe until re-initialized.
++ * @cpu: The CPU on which the owner runs
++ *
+ * To be used for reading and preparing of the value stored in the nbcon
+ * state variable @console::nbcon_state.
++ *
++ * The @prio and @req_prio fields are particularly important to allow
++ * spin-waiting to timeout and give up without the risk of a waiter being
++ * assigned the lock after giving up.
+ */
+ struct nbcon_state {
+ union {
+ unsigned int atom;
+ struct {
++ unsigned int prio : 2;
++ unsigned int req_prio : 2;
++ unsigned int unsafe : 1;
++ unsigned int unsafe_takeover : 1;
++ unsigned int cpu : 24;
+ };
+ };
+ };
+@@ -195,6 +211,46 @@ struct nbcon_state {
+ static_assert(sizeof(struct nbcon_state) <= sizeof(int));
+
+ /**
++ * nbcon_prio - console owner priority for nbcon consoles
++ * @NBCON_PRIO_NONE: Unused
++ * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage
++ * @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...)
++ * @NBCON_PRIO_PANIC: Panic output
++ * @NBCON_PRIO_MAX: The number of priority levels
++ *
++ * A higher priority context can takeover the console when it is
++ * in the safe state. The final attempt to flush consoles in panic()
++ * can be allowed to do so even in an unsafe state (Hope and pray).
++ */
++enum nbcon_prio {
++ NBCON_PRIO_NONE = 0,
++ NBCON_PRIO_NORMAL,
++ NBCON_PRIO_EMERGENCY,
++ NBCON_PRIO_PANIC,
++ NBCON_PRIO_MAX,
++};
++
++struct console;
++
++/**
++ * struct nbcon_context - Context for console acquire/release
++ * @console: The associated console
++ * @spinwait_max_us: Limit for spin-wait acquire
++ * @prio: Priority of the context
++ * @allow_unsafe_takeover: Allow performing takeover even if unsafe. Can
++ * be used only with NBCON_PRIO_PANIC @prio. It
++ * might cause a system freeze when the console
++ * is used later.
++ */
++struct nbcon_context {
++ /* members set by caller */
++ struct console *console;
++ unsigned int spinwait_max_us;
++ enum nbcon_prio prio;
++ unsigned int allow_unsafe_takeover : 1;
++};
++
++/**
+ * struct console - The console descriptor structure
+ * @name: The name of the console driver
+ * @write: Write callback to output messages (Optional)
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -4,10 +4,98 @@
+
+ #include <linux/kernel.h>
+ #include <linux/console.h>
++#include <linux/delay.h>
+ #include "internal.h"
+ /*
+ * Printk console printing implementation for consoles which does not depend
+ * on the legacy style console_lock mechanism.
++ *
++ * The state of the console is maintained in the "nbcon_state" atomic
++ * variable.
++ *
++ * The console is locked when:
++ *
++ * - The 'prio' field contains the priority of the context that owns the
++ * console. Only higher priority contexts are allowed to take over the
++ * lock. A value of 0 (NBCON_PRIO_NONE) means the console is not locked.
++ *
++ * - The 'cpu' field denotes on which CPU the console is locked. It is used
++ * to prevent busy waiting on the same CPU. Also it informs the lock owner
++ * that it has lost the lock in a more complex scenario when the lock was
++ * taken over by a higher priority context, released, and taken on another
++ * CPU with the same priority as the interrupted owner.
++ *
++ * The acquire mechanism uses a few more fields:
++ *
++ * - The 'req_prio' field is used by the handover approach to make the
++ * current owner aware that there is a context with a higher priority
++ * waiting for the friendly handover.
++ *
++ * - The 'unsafe' field allows to take over the console in a safe way in the
++ * middle of emitting a message. The field is set only when accessing some
++ * shared resources or when the console device is manipulated. It can be
++ * cleared, for example, after emitting one character when the console
++ * device is in a consistent state.
++ *
++ * - The 'unsafe_takeover' field is set when a hostile takeover took the
++ * console in an unsafe state. The console will stay in the unsafe state
++ * until re-initialized.
++ *
++ * The acquire mechanism uses three approaches:
++ *
++ * 1) Direct acquire when the console is not owned or is owned by a lower
++ * priority context and is in a safe state.
++ *
++ * 2) Friendly handover mechanism uses a request/grant handshake. It is used
++ * when the current owner has lower priority and the console is in an
++ * unsafe state.
++ *
++ * The requesting context:
++ *
++ * a) Sets its priority into the 'req_prio' field.
++ *
++ * b) Waits (with a timeout) for the owning context to unlock the
++ * console.
++ *
++ * c) Takes the lock and clears the 'req_prio' field.
++ *
++ * The owning context:
++ *
++ * a) Observes the 'req_prio' field set on exit from the unsafe
++ * console state.
++ *
++ * b) Gives up console ownership by clearing the 'prio' field.
++ *
++ * 3) Unsafe hostile takeover allows to take over the lock even when the
++ * console is an unsafe state. It is used only in panic() by the final
++ * attempt to flush consoles in a try and hope mode.
++ *
++ * The release function simply clears the 'prio' field.
++ *
++ * All operations on @console::nbcon_state are atomic cmpxchg based to
++ * handle concurrency.
++ *
++ * The acquire/release functions implement only minimal policies:
++ *
++ * - Preference for higher priority contexts.
++ * - Protection of the panic CPU.
++ *
++ * All other policy decisions must be made at the call sites:
++ *
++ * - What is marked as an unsafe section.
++ * - Whether to spin-wait if there is already an owner and the console is
++ * in an unsafe state.
++ * - Whether to attempt an unsafe hostile takeover.
++ *
++ * The design allows to implement the well known:
++ *
++ * acquire()
++ * output_one_printk_record()
++ * release()
++ *
++ * The output of one printk record might be interrupted with a higher priority
++ * context. The new owner is supposed to reprint the entire interrupted record
++ * from scratch.
+ */
+
+ /**
+@@ -48,6 +136,415 @@ static inline bool nbcon_state_try_cmpxc
+ }
+
+ /**
++ * nbcon_context_try_acquire_direct - Try to acquire directly
++ * @ctxt: The context of the caller
++ * @cur: The current console state
++ *
++ * Acquire the console when it is released. Also acquire the console when
++ * the current owner has a lower priority and the console is in a safe state.
++ *
++ * Return: 0 on success. Otherwise, an error code on failure. Also @cur
++ * is updated to the latest state when failed to modify it.
++ *
++ * Errors:
++ *
++ * -EPERM: A panic is in progress and this is not the panic CPU.
++ * Or the current owner or waiter has the same or higher
++ * priority. No acquire method can be successful in
++ * this case.
++ *
++ * -EBUSY: The current owner has a lower priority but the console
++ * in an unsafe state. The caller should try using
++ * the handover acquire method.
++ */
++static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt,
++ struct nbcon_state *cur)
++{
++ unsigned int cpu = smp_processor_id();
++ struct console *con = ctxt->console;
++ struct nbcon_state new;
++
++ do {
++ if (other_cpu_in_panic())
++ return -EPERM;
++
++ if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio)
++ return -EPERM;
++
++ if (cur->unsafe)
++ return -EBUSY;
++
++ /*
++ * The console should never be safe for a direct acquire
++ * if an unsafe hostile takeover has ever happened.
++ */
++ WARN_ON_ONCE(cur->unsafe_takeover);
++
++ new.atom = cur->atom;
++ new.prio = ctxt->prio;
++ new.req_prio = NBCON_PRIO_NONE;
++ new.unsafe = cur->unsafe_takeover;
++ new.cpu = cpu;
++
++ } while (!nbcon_state_try_cmpxchg(con, cur, &new));
++
++ return 0;
++}
++
++static bool nbcon_waiter_matches(struct nbcon_state *cur, int expected_prio)
++{
++ /*
++ * The request context is well defined by the @req_prio because:
++ *
++ * - Only a context with a higher priority can take over the request.
++ * - There are only three priorities.
++ * - Only one CPU is allowed to request PANIC priority.
++ * - Lower priorities are ignored during panic() until reboot.
++ *
++ * As a result, the following scenario is *not* possible:
++ *
++ * 1. Another context with a higher priority directly takes ownership.
++ * 2. The higher priority context releases the ownership.
++ * 3. A lower priority context takes the ownership.
++ * 4. Another context with the same priority as this context
++ * creates a request and starts waiting.
++ */
++
++ return (cur->req_prio == expected_prio);
++}
++
++/**
++ * nbcon_context_try_acquire_requested - Try to acquire after having
++ * requested a handover
++ * @ctxt: The context of the caller
++ * @cur: The current console state
++ *
++ * This is a helper function for nbcon_context_try_acquire_handover().
++ * It is called when the console is in an unsafe state. The current
++ * owner will release the console on exit from the unsafe region.
++ *
++ * Return: 0 on success and @cur is updated to the new console state.
++ * Otherwise an error code on failure.
++ *
++ * Errors:
++ *
++ * -EPERM: A panic is in progress and this is not the panic CPU
++ * or this context is no longer the waiter.
++ *
++ * -EBUSY: The console is still locked. The caller should
++ * continue waiting.
++ *
++ * Note: The caller must still remove the request when an error has occurred
++ * except when this context is no longer the waiter.
++ */
++static int nbcon_context_try_acquire_requested(struct nbcon_context *ctxt,
++ struct nbcon_state *cur)
++{
++ unsigned int cpu = smp_processor_id();
++ struct console *con = ctxt->console;
++ struct nbcon_state new;
++
++ /* Note that the caller must still remove the request! */
++ if (other_cpu_in_panic())
++ return -EPERM;
++
++ /*
++ * Note that the waiter will also change if there was an unsafe
++ * hostile takeover.
++ */
++ if (!nbcon_waiter_matches(cur, ctxt->prio))
++ return -EPERM;
++
++ /* If still locked, caller should continue waiting. */
++ if (cur->prio != NBCON_PRIO_NONE)
++ return -EBUSY;
++
++ /*
++ * The previous owner should have never released ownership
++ * in an unsafe region.
++ */
++ WARN_ON_ONCE(cur->unsafe);
++
++ new.atom = cur->atom;
++ new.prio = ctxt->prio;
++ new.req_prio = NBCON_PRIO_NONE;
++ new.unsafe = cur->unsafe_takeover;
++ new.cpu = cpu;
++
++ if (!nbcon_state_try_cmpxchg(con, cur, &new)) {
++ /*
++ * The acquire could fail only when it has been taken
++ * over by a higher priority context.
++ */
++ WARN_ON_ONCE(nbcon_waiter_matches(cur, ctxt->prio));
++ return -EPERM;
++ }
++
++ /* Handover success. This context now owns the console. */
++ return 0;
++}
++
++/**
++ * nbcon_context_try_acquire_handover - Try to acquire via handover
++ * @ctxt: The context of the caller
++ * @cur: The current console state
++ *
++ * The function must be called only when the context has higher priority
++ * than the current owner and the console is in an unsafe state.
++ * It is the case when nbcon_context_try_acquire_direct() returns -EBUSY.
++ *
++ * The function sets "req_prio" field to make the current owner aware of
++ * the request. Then it waits until the current owner releases the console,
++ * or an even higher context takes over the request, or timeout expires.
++ *
++ * The current owner checks the "req_prio" field on exit from the unsafe
++ * region and releases the console. It does not touch the "req_prio" field
++ * so that the console stays reserved for the waiter.
++ *
++ * Return: 0 on success. Otherwise, an error code on failure. Also @cur
++ * is updated to the latest state when failed to modify it.
++ *
++ * Errors:
++ *
++ * -EPERM: A panic is in progress and this is not the panic CPU.
++ * Or a higher priority context has taken over the
++ * console or the handover request.
++ *
++ * -EBUSY: The current owner is on the same CPU so that the hand
++ * shake could not work. Or the current owner is not
++ * willing to wait (zero timeout). Or the console does
++ * not enter the safe state before timeout passed. The
++ * caller might still use the unsafe hostile takeover
++ * when allowed.
++ *
++ * -EAGAIN: @cur has changed when creating the handover request.
++ * The caller should retry with direct acquire.
++ */
++static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt,
++ struct nbcon_state *cur)
++{
++ unsigned int cpu = smp_processor_id();
++ struct console *con = ctxt->console;
++ struct nbcon_state new;
++ int timeout;
++ int request_err = -EBUSY;
++
++ /*
++ * Check that the handover is called when the direct acquire failed
++ * with -EBUSY.
++ */
++ WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);
++ WARN_ON_ONCE(!cur->unsafe);
++
++ /* Handover is not possible on the same CPU. */
++ if (cur->cpu == cpu)
++ return -EBUSY;
++
++ /*
++ * Console stays unsafe after an unsafe takeover until re-initialized.
++ * Waiting is not going to help in this case.
++ */
++ if (cur->unsafe_takeover)
++ return -EBUSY;
++
++ /* Is the caller willing to wait? */
++ if (ctxt->spinwait_max_us == 0)
++ return -EBUSY;
++
++ /*
++ * Setup a request for the handover. The caller should try to acquire
++ * the console directly when the current state has been modified.
++ */
++ new.atom = cur->atom;
++ new.req_prio = ctxt->prio;
++ if (!nbcon_state_try_cmpxchg(con, cur, &new))
++ return -EAGAIN;
++
++ cur->atom = new.atom;
++
++ /* Wait until there is no owner and then acquire the console. */
++ for (timeout = ctxt->spinwait_max_us; timeout >= 0; timeout--) {
++ /* On successful acquire, this request is cleared. */
++ request_err = nbcon_context_try_acquire_requested(ctxt, cur);
++ if (!request_err)
++ return 0;
++
++ /*
++ * If the acquire should be aborted, it must be ensured
++ * that the request is removed before returning to caller.
++ */
++ if (request_err == -EPERM)
++ break;
++
++ udelay(1);
++
++ /* Re-read the state because some time has passed. */
++ nbcon_state_read(con, cur);
++ }
++
++ /* Timed out or aborted. Carefully remove handover request. */
++ do {
++ /*
++ * No need to remove request if there is a new waiter. This
++ * can only happen if a higher priority context has taken over
++ * the console or the handover request.
++ */
++ if (!nbcon_waiter_matches(cur, ctxt->prio))
++ return -EPERM;
++
++ /* Unset request for handover. */
++ new.atom = cur->atom;
++ new.req_prio = NBCON_PRIO_NONE;
++ if (nbcon_state_try_cmpxchg(con, cur, &new)) {
++ /*
++ * Request successfully unset. Report failure of
++ * acquiring via handover.
++ */
++ cur->atom = new.atom;
++ return request_err;
++ }
++
++ /*
++ * Unable to remove request. Try to acquire in case
++ * the owner has released the lock.
++ */
++ } while (nbcon_context_try_acquire_requested(ctxt, cur));
++
++ /* Lucky timing. The acquire succeeded while removing the request. */
++ return 0;
++}
++
++/**
++ * nbcon_context_try_acquire_hostile - Acquire via unsafe hostile takeover
++ * @ctxt: The context of the caller
++ * @cur: The current console state
++ *
++ * Acquire the console even in the unsafe state.
++ *
++ * It can be permitted by setting the 'allow_unsafe_takeover' field only
++ * by the final attempt to flush messages in panic().
++ *
++ * Return: 0 on success. -EPERM when not allowed by the context.
++ */
++static int nbcon_context_try_acquire_hostile(struct nbcon_context *ctxt,
++ struct nbcon_state *cur)
++{
++ unsigned int cpu = smp_processor_id();
++ struct console *con = ctxt->console;
++ struct nbcon_state new;
++
++ if (!ctxt->allow_unsafe_takeover)
++ return -EPERM;
++
++ /* Ensure caller is allowed to perform unsafe hostile takeovers. */
++ if (WARN_ON_ONCE(ctxt->prio != NBCON_PRIO_PANIC))
++ return -EPERM;
++
++ /*
++ * Check that try_acquire_direct() and try_acquire_handover() returned
++ * -EBUSY in the right situation.
++ */
++ WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio);
++ WARN_ON_ONCE(cur->unsafe != true);
++
++ do {
++ new.atom = cur->atom;
++ new.cpu = cpu;
++ new.prio = ctxt->prio;
++ new.unsafe |= cur->unsafe_takeover;
++ new.unsafe_takeover |= cur->unsafe;
++
++ } while (!nbcon_state_try_cmpxchg(con, cur, &new));
++
++ return 0;
++}
++
++/**
++ * nbcon_context_try_acquire - Try to acquire nbcon console
++ * @ctxt: The context of the caller
++ *
++ * Return: True if the console was acquired. False otherwise.
++ *
++ * If the caller allowed an unsafe hostile takeover, on success the
++ * caller should check the current console state to see if it is
++ * in an unsafe state. Otherwise, on success the caller may assume
++ * the console is not in an unsafe state.
++ */
++__maybe_unused
++static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)
++{
++ struct console *con = ctxt->console;
++ struct nbcon_state cur;
++ int err;
++
++ nbcon_state_read(con, &cur);
++try_again:
++ err = nbcon_context_try_acquire_direct(ctxt, &cur);
++ if (err != -EBUSY)
++ goto out;
++
++ err = nbcon_context_try_acquire_handover(ctxt, &cur);
++ if (err == -EAGAIN)
++ goto try_again;
++ if (err != -EBUSY)
++ goto out;
++
++ err = nbcon_context_try_acquire_hostile(ctxt, &cur);
++out:
++ return !err;
++}
++
++static bool nbcon_owner_matches(struct nbcon_state *cur, int expected_cpu,
++ int expected_prio)
++{
++ /*
++ * Since consoles can only be acquired by higher priorities,
++ * owning contexts are uniquely identified by @prio. However,
++ * since contexts can unexpectedly lose ownership, it is
++ * possible that later another owner appears with the same
++ * priority. For this reason @cpu is also needed.
++ */
++
++ if (cur->prio != expected_prio)
++ return false;
++
++ if (cur->cpu != expected_cpu)
++ return false;
++
++ return true;
++}
++
++/**
++ * nbcon_context_release - Release the console
++ * @ctxt: The nbcon context from nbcon_context_try_acquire()
++ */
++__maybe_unused
++static void nbcon_context_release(struct nbcon_context *ctxt)
++{
++ unsigned int cpu = smp_processor_id();
++ struct console *con = ctxt->console;
++ struct nbcon_state cur;
++ struct nbcon_state new;
++
++ nbcon_state_read(con, &cur);
++
++ do {
++ if (!nbcon_owner_matches(&cur, cpu, ctxt->prio))
++ return;
++
++ new.atom = cur.atom;
++ new.prio = NBCON_PRIO_NONE;
++
++ /*
++ * If @unsafe_takeover is set, it is kept set so that
++ * the state remains permanently unsafe.
++ */
++ new.unsafe |= cur.unsafe_takeover;
++
++ } while (!nbcon_state_try_cmpxchg(con, &cur, &new));
++}
++
++/**
+ * nbcon_init - Initialize the nbcon console specific data
+ * @con: Console to initialize
+ */
diff --git a/debian/patches-rt/0077-printk-Make-static-printk-buffers-available-to-nbcon.patch b/debian/patches-rt/0077-printk-Make-static-printk-buffers-available-to-nbcon.patch
new file mode 100644
index 0000000000..f3fbb6a822
--- /dev/null
+++ b/debian/patches-rt/0077-printk-Make-static-printk-buffers-available-to-nbcon.patch
@@ -0,0 +1,65 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:02 +0206
+Subject: [PATCH 077/134] printk: Make static printk buffers available to nbcon
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The nbcon boot consoles also need printk buffers that are available
+very early. Since the nbcon boot consoles will also be serialized
+by the console_lock, they can use the same static printk buffers
+that the legacy consoles are using.
+
+Make the legacy static printk buffers available outside of printk.c
+so they can be used by nbcon.c.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-4-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 2 ++
+ kernel/printk/printk.c | 13 +++++++++----
+ 2 files changed, 11 insertions(+), 4 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -86,6 +86,8 @@ static inline void nbcon_cleanup(struct
+
+ #endif /* CONFIG_PRINTK */
+
++extern struct printk_buffers printk_shared_pbufs;
++
+ /**
+ * struct printk_buffers - Buffers to read/format/output printk messages.
+ * @outbuf: After formatting, contains text to output.
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2847,6 +2847,13 @@ static bool printk_get_next_message(stru
+ }
+
+ /*
++ * Used as the printk buffers for non-panic, serialized console printing.
++ * This is for legacy (!CON_NBCON) as well as all boot (CON_BOOT) consoles.
++ * Its usage requires the console_lock held.
++ */
++struct printk_buffers printk_shared_pbufs;
++
++/*
+ * Print one record for the given console. The record printed is whatever
+ * record is the next available record for the given console.
+ *
+@@ -2863,12 +2870,10 @@ static bool printk_get_next_message(stru
+ */
+ static bool console_emit_next_record(struct console *con, bool *handover, int cookie)
+ {
+- static struct printk_buffers pbufs;
+-
+ bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED;
+- char *outbuf = &pbufs.outbuf[0];
++ char *outbuf = &printk_shared_pbufs.outbuf[0];
+ struct printk_message pmsg = {
+- .pbufs = &pbufs,
++ .pbufs = &printk_shared_pbufs,
+ };
+ unsigned long flags;
+
diff --git a/debian/patches-rt/0078-printk-nbcon-Add-buffer-management.patch b/debian/patches-rt/0078-printk-nbcon-Add-buffer-management.patch
new file mode 100644
index 0000000000..ea96abd7ed
--- /dev/null
+++ b/debian/patches-rt/0078-printk-nbcon-Add-buffer-management.patch
@@ -0,0 +1,311 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:03 +0206
+Subject: [PATCH 078/134] printk: nbcon: Add buffer management
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+In case of hostile takeovers it must be ensured that the previous
+owner cannot scribble over the output buffer of the emergency/panic
+context. This is achieved by:
+
+ - Adding a global output buffer instance for the panic context.
+ This is the only situation where hostile takeovers can occur and
+ there is always at most 1 panic context.
+
+ - Allocating an output buffer per non-boot console upon console
+ registration. This buffer is used by the console owner when not
+ in panic context. (For boot consoles, the existing shared global
+ legacy output buffer is used instead. Boot console printing will
+ be synchronized with legacy console printing.)
+
+ - Choosing the appropriate buffer is handled in the acquire/release
+ functions.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-5-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 7 ++++
+ kernel/printk/internal.h | 12 ++++++-
+ kernel/printk/nbcon.c | 73 +++++++++++++++++++++++++++++++++++++++++++----
+ kernel/printk/printk.c | 22 +++++++++-----
+ 4 files changed, 99 insertions(+), 15 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -231,6 +231,7 @@ enum nbcon_prio {
+ };
+
+ struct console;
++struct printk_buffers;
+
+ /**
+ * struct nbcon_context - Context for console acquire/release
+@@ -241,6 +242,7 @@ struct console;
+ * be used only with NBCON_PRIO_PANIC @prio. It
+ * might cause a system freeze when the console
+ * is used later.
++ * @pbufs: Pointer to the text buffer for this context
+ */
+ struct nbcon_context {
+ /* members set by caller */
+@@ -248,6 +250,9 @@ struct nbcon_context {
+ unsigned int spinwait_max_us;
+ enum nbcon_prio prio;
+ unsigned int allow_unsafe_takeover : 1;
++
++ /* members set by acquire */
++ struct printk_buffers *pbufs;
+ };
+
+ /**
+@@ -271,6 +276,7 @@ struct nbcon_context {
+ * @node: hlist node for the console list
+ *
+ * @nbcon_state: State for nbcon consoles
++ * @pbufs: Pointer to nbcon private buffer
+ */
+ struct console {
+ char name[16];
+@@ -293,6 +299,7 @@ struct console {
+
+ /* nbcon console specific members */
+ atomic_t __private nbcon_state;
++ struct printk_buffers *pbufs;
+ };
+
+ #ifdef CONFIG_LOCKDEP
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -13,6 +13,12 @@ int devkmsg_sysctl_set_loglvl(struct ctl
+ #define printk_sysctl_init() do { } while (0)
+ #endif
+
++#define con_printk(lvl, con, fmt, ...) \
++ printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \
++ (con->flags & CON_NBCON) ? "" : "legacy ", \
++ (con->flags & CON_BOOT) ? "boot" : "", \
++ con->name, con->index, ##__VA_ARGS__)
++
+ #ifdef CONFIG_PRINTK
+
+ #ifdef CONFIG_PRINTK_CALLER
+@@ -63,8 +69,9 @@ void defer_console_output(void);
+ u16 printk_parse_prefix(const char *text, int *level,
+ enum printk_info_flags *flags);
+
++bool nbcon_alloc(struct console *con);
+ void nbcon_init(struct console *con);
+-void nbcon_cleanup(struct console *con);
++void nbcon_free(struct console *con);
+
+ #else
+
+@@ -81,8 +88,9 @@ void nbcon_cleanup(struct console *con);
+ #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
+
+ static inline bool printk_percpu_data_ready(void) { return false; }
++static inline bool nbcon_alloc(struct console *con) { return false; }
+ static inline void nbcon_init(struct console *con) { }
+-static inline void nbcon_cleanup(struct console *con) { }
++static inline void nbcon_free(struct console *con) { }
+
+ #endif /* CONFIG_PRINTK */
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -5,6 +5,7 @@
+ #include <linux/kernel.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
++#include <linux/slab.h>
+ #include "internal.h"
+ /*
+ * Printk console printing implementation for consoles which does not depend
+@@ -70,6 +71,10 @@
+ * console is an unsafe state. It is used only in panic() by the final
+ * attempt to flush consoles in a try and hope mode.
+ *
++ * Note that separate record buffers are used in panic(). As a result,
++ * the messages can be read and formatted without any risk even after
++ * using the hostile takeover in unsafe state.
++ *
+ * The release function simply clears the 'prio' field.
+ *
+ * All operations on @console::nbcon_state are atomic cmpxchg based to
+@@ -459,6 +464,8 @@ static int nbcon_context_try_acquire_hos
+ return 0;
+ }
+
++static struct printk_buffers panic_nbcon_pbufs;
++
+ /**
+ * nbcon_context_try_acquire - Try to acquire nbcon console
+ * @ctxt: The context of the caller
+@@ -473,6 +480,7 @@ static int nbcon_context_try_acquire_hos
+ __maybe_unused
+ static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)
+ {
++ unsigned int cpu = smp_processor_id();
+ struct console *con = ctxt->console;
+ struct nbcon_state cur;
+ int err;
+@@ -491,7 +499,18 @@ static bool nbcon_context_try_acquire(st
+
+ err = nbcon_context_try_acquire_hostile(ctxt, &cur);
+ out:
+- return !err;
++ if (err)
++ return false;
++
++ /* Acquire succeeded. */
++
++ /* Assign the appropriate buffer for this context. */
++ if (atomic_read(&panic_cpu) == cpu)
++ ctxt->pbufs = &panic_nbcon_pbufs;
++ else
++ ctxt->pbufs = con->pbufs;
++
++ return true;
+ }
+
+ static bool nbcon_owner_matches(struct nbcon_state *cur, int expected_cpu,
+@@ -530,7 +549,7 @@ static void nbcon_context_release(struct
+
+ do {
+ if (!nbcon_owner_matches(&cur, cpu, ctxt->prio))
+- return;
++ break;
+
+ new.atom = cur.atom;
+ new.prio = NBCON_PRIO_NONE;
+@@ -542,26 +561,70 @@ static void nbcon_context_release(struct
+ new.unsafe |= cur.unsafe_takeover;
+
+ } while (!nbcon_state_try_cmpxchg(con, &cur, &new));
++
++ ctxt->pbufs = NULL;
++}
++
++/**
++ * nbcon_alloc - Allocate buffers needed by the nbcon console
++ * @con: Console to allocate buffers for
++ *
++ * Return: True on success. False otherwise and the console cannot
++ * be used.
++ *
++ * This is not part of nbcon_init() because buffer allocation must
++ * be performed earlier in the console registration process.
++ */
++bool nbcon_alloc(struct console *con)
++{
++ if (con->flags & CON_BOOT) {
++ /*
++ * Boot console printing is synchronized with legacy console
++ * printing, so boot consoles can share the same global printk
++ * buffers.
++ */
++ con->pbufs = &printk_shared_pbufs;
++ } else {
++ con->pbufs = kmalloc(sizeof(*con->pbufs), GFP_KERNEL);
++ if (!con->pbufs) {
++ con_printk(KERN_ERR, con, "failed to allocate printing buffer\n");
++ return false;
++ }
++ }
++
++ return true;
+ }
+
+ /**
+ * nbcon_init - Initialize the nbcon console specific data
+ * @con: Console to initialize
++ *
++ * nbcon_alloc() *must* be called and succeed before this function
++ * is called.
+ */
+ void nbcon_init(struct console *con)
+ {
+ struct nbcon_state state = { };
+
++ /* nbcon_alloc() must have been called and successful! */
++ BUG_ON(!con->pbufs);
++
+ nbcon_state_set(con, &state);
+ }
+
+ /**
+- * nbcon_cleanup - Cleanup the nbcon console specific data
+- * @con: Console to cleanup
++ * nbcon_free - Free and cleanup the nbcon console specific data
++ * @con: Console to free/cleanup nbcon data
+ */
+-void nbcon_cleanup(struct console *con)
++void nbcon_free(struct console *con)
+ {
+ struct nbcon_state state = { };
+
+ nbcon_state_set(con, &state);
++
++ /* Boot consoles share global printk buffers. */
++ if (!(con->flags & CON_BOOT))
++ kfree(con->pbufs);
++
++ con->pbufs = NULL;
+ }
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3331,12 +3331,6 @@ static void try_enable_default_console(s
+ newcon->flags |= CON_CONSDEV;
+ }
+
+-#define con_printk(lvl, con, fmt, ...) \
+- printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \
+- (con->flags & CON_NBCON) ? "" : "legacy ", \
+- (con->flags & CON_BOOT) ? "boot" : "", \
+- con->name, con->index, ##__VA_ARGS__)
+-
+ static void console_init_seq(struct console *newcon, bool bootcon_registered)
+ {
+ struct console *con;
+@@ -3450,6 +3444,15 @@ void register_console(struct console *ne
+ goto unlock;
+ }
+
++ if (newcon->flags & CON_NBCON) {
++ /*
++ * Ensure the nbcon console buffers can be allocated
++ * before modifying any global data.
++ */
++ if (!nbcon_alloc(newcon))
++ goto unlock;
++ }
++
+ /*
+ * See if we want to enable this console driver by default.
+ *
+@@ -3477,8 +3480,11 @@ void register_console(struct console *ne
+ err = try_enable_preferred_console(newcon, false);
+
+ /* printk() messages are not printed to the Braille console. */
+- if (err || newcon->flags & CON_BRL)
++ if (err || newcon->flags & CON_BRL) {
++ if (newcon->flags & CON_NBCON)
++ nbcon_free(newcon);
+ goto unlock;
++ }
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+@@ -3589,7 +3595,7 @@ static int unregister_console_locked(str
+ synchronize_srcu(&console_srcu);
+
+ if (console->flags & CON_NBCON)
+- nbcon_cleanup(console);
++ nbcon_free(console);
+
+ console_sysfs_notify();
+
diff --git a/debian/patches-rt/0079-printk-nbcon-Add-ownership-state-functions.patch b/debian/patches-rt/0079-printk-nbcon-Add-ownership-state-functions.patch
new file mode 100644
index 0000000000..e26a5f332d
--- /dev/null
+++ b/debian/patches-rt/0079-printk-nbcon-Add-ownership-state-functions.patch
@@ -0,0 +1,179 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:04 +0206
+Subject: [PATCH 079/134] printk: nbcon: Add ownership state functions
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Provide functions that are related to the safe handover mechanism
+and allow console drivers to dynamically specify unsafe regions:
+
+ - nbcon_context_can_proceed()
+
+ Invoked by a console owner to check whether a handover request
+ is pending or whether the console has been taken over by another
+ context. If a handover request is pending, this function will
+ also perform the handover, thus cancelling its own ownership.
+
+ - nbcon_context_enter_unsafe()/nbcon_context_exit_unsafe()
+
+ Invoked by a console owner to denote that the driver is about
+ to enter or leave a critical region where a take over is unsafe.
+ The exit variant is the point where the current owner releases
+ the lock for a higher priority context which asked for the
+ friendly handover.
+
+ The unsafe state is stored in the console state and allows a
+ new context to make informed decisions whether to attempt a
+ takeover of such a console. The unsafe state is also available
+ to the driver so that it can make informed decisions about the
+ required actions and possibly take a special emergency path.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-6-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/nbcon.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 122 insertions(+), 1 deletion(-)
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -537,7 +537,6 @@ static bool nbcon_owner_matches(struct n
+ * nbcon_context_release - Release the console
+ * @ctxt: The nbcon context from nbcon_context_try_acquire()
+ */
+-__maybe_unused
+ static void nbcon_context_release(struct nbcon_context *ctxt)
+ {
+ unsigned int cpu = smp_processor_id();
+@@ -566,6 +565,128 @@ static void nbcon_context_release(struct
+ }
+
+ /**
++ * nbcon_context_can_proceed - Check whether ownership can proceed
++ * @ctxt: The nbcon context from nbcon_context_try_acquire()
++ * @cur: The current console state
++ *
++ * Return: True if this context still owns the console. False if
++ * ownership was handed over or taken.
++ *
++ * Must be invoked when entering the unsafe state to make sure that it still
++ * owns the lock. Also must be invoked when exiting the unsafe context
++ * to eventually free the lock for a higher priority context which asked
++ * for the friendly handover.
++ *
++ * It can be called inside an unsafe section when the console is just
++ * temporary in safe state instead of exiting and entering the unsafe
++ * state.
++ *
++ * Also it can be called in the safe context before doing an expensive
++ * safe operation. It does not make sense to do the operation when
++ * a higher priority context took the lock.
++ *
++ * When this function returns false then the calling context no longer owns
++ * the console and is no longer allowed to go forward. In this case it must
++ * back out immediately and carefully. The buffer content is also no longer
++ * trusted since it no longer belongs to the calling context.
++ */
++static bool nbcon_context_can_proceed(struct nbcon_context *ctxt, struct nbcon_state *cur)
++{
++ unsigned int cpu = smp_processor_id();
++
++ /* Make sure this context still owns the console. */
++ if (!nbcon_owner_matches(cur, cpu, ctxt->prio))
++ return false;
++
++ /* The console owner can proceed if there is no waiter. */
++ if (cur->req_prio == NBCON_PRIO_NONE)
++ return true;
++
++ /*
++ * A console owner within an unsafe region is always allowed to
++ * proceed, even if there are waiters. It can perform a handover
++ * when exiting the unsafe region. Otherwise the waiter will
++ * need to perform an unsafe hostile takeover.
++ */
++ if (cur->unsafe)
++ return true;
++
++ /* Waiters always have higher priorities than owners. */
++ WARN_ON_ONCE(cur->req_prio <= cur->prio);
++
++ /*
++ * Having a safe point for take over and eventually a few
++ * duplicated characters or a full line is way better than a
++ * hostile takeover. Post processing can take care of the garbage.
++ * Release and hand over.
++ */
++ nbcon_context_release(ctxt);
++
++ /*
++ * It is not clear whether the waiter really took over ownership. The
++ * outermost callsite must make the final decision whether console
++ * ownership is needed for it to proceed. If yes, it must reacquire
++ * ownership (possibly hostile) before carefully proceeding.
++ *
++ * The calling context no longer owns the console so go back all the
++ * way instead of trying to implement reacquire heuristics in tons of
++ * places.
++ */
++ return false;
++}
++
++#define nbcon_context_enter_unsafe(c) __nbcon_context_update_unsafe(c, true)
++#define nbcon_context_exit_unsafe(c) __nbcon_context_update_unsafe(c, false)
++
++/**
++ * __nbcon_context_update_unsafe - Update the unsafe bit in @con->nbcon_state
++ * @ctxt: The nbcon context from nbcon_context_try_acquire()
++ * @unsafe: The new value for the unsafe bit
++ *
++ * Return: True if the unsafe state was updated and this context still
++ * owns the console. Otherwise false if ownership was handed
++ * over or taken.
++ *
++ * This function allows console owners to modify the unsafe status of the
++ * console.
++ *
++ * When this function returns false then the calling context no longer owns
++ * the console and is no longer allowed to go forward. In this case it must
++ * back out immediately and carefully. The buffer content is also no longer
++ * trusted since it no longer belongs to the calling context.
++ *
++ * Internal helper to avoid duplicated code.
++ */
++__maybe_unused
++static bool __nbcon_context_update_unsafe(struct nbcon_context *ctxt, bool unsafe)
++{
++ struct console *con = ctxt->console;
++ struct nbcon_state cur;
++ struct nbcon_state new;
++
++ nbcon_state_read(con, &cur);
++
++ do {
++ /*
++ * The unsafe bit must not be cleared if an
++ * unsafe hostile takeover has occurred.
++ */
++ if (!unsafe && cur.unsafe_takeover)
++ goto out;
++
++ if (!nbcon_context_can_proceed(ctxt, &cur))
++ return false;
++
++ new.atom = cur.atom;
++ new.unsafe = unsafe;
++ } while (!nbcon_state_try_cmpxchg(con, &cur, &new));
++
++ cur.atom = new.atom;
++out:
++ return nbcon_context_can_proceed(ctxt, &cur);
++}
++
++/**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+ *
diff --git a/debian/patches-rt/0080-printk-nbcon-Add-sequence-handling.patch b/debian/patches-rt/0080-printk-nbcon-Add-sequence-handling.patch
new file mode 100644
index 0000000000..3988d6124a
--- /dev/null
+++ b/debian/patches-rt/0080-printk-nbcon-Add-sequence-handling.patch
@@ -0,0 +1,311 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:05 +0206
+Subject: [PATCH 080/134] printk: nbcon: Add sequence handling
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add an atomic_long_t field @nbcon_seq to the console struct to
+store the sequence number for nbcon consoles. For nbcon consoles
+this will be used instead of the non-atomic @seq field. The new
+field allows for safe atomic sequence number updates without
+requiring any locking.
+
+On 64bit systems the new field stores the full sequence number.
+On 32bit systems the new field stores the lower 32 bits of the
+sequence number, which are expanded to 64bit as needed by
+folding the values based on the sequence numbers available in
+the ringbuffer.
+
+For 32bit systems, having a 32bit representation in the console
+is sufficient. If a console ever gets more than 2^31 records
+behind the ringbuffer then this is the least of the problems.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-7-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 4 +
+ kernel/printk/internal.h | 7 +++
+ kernel/printk/nbcon.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 31 +++++++++++---
+ 4 files changed, 136 insertions(+), 7 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -243,6 +243,7 @@ struct printk_buffers;
+ * might cause a system freeze when the console
+ * is used later.
+ * @pbufs: Pointer to the text buffer for this context
++ * @seq: The sequence number to print for this context
+ */
+ struct nbcon_context {
+ /* members set by caller */
+@@ -253,6 +254,7 @@ struct nbcon_context {
+
+ /* members set by acquire */
+ struct printk_buffers *pbufs;
++ u64 seq;
+ };
+
+ /**
+@@ -276,6 +278,7 @@ struct nbcon_context {
+ * @node: hlist node for the console list
+ *
+ * @nbcon_state: State for nbcon consoles
++ * @nbcon_seq: Sequence number of the next record for nbcon to print
+ * @pbufs: Pointer to nbcon private buffer
+ */
+ struct console {
+@@ -299,6 +302,7 @@ struct console {
+
+ /* nbcon console specific members */
+ atomic_t __private nbcon_state;
++ atomic_long_t __private nbcon_seq;
+ struct printk_buffers *pbufs;
+ };
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -4,6 +4,7 @@
+ */
+ #include <linux/percpu.h>
+ #include <linux/console.h>
++#include "printk_ringbuffer.h"
+
+ #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL)
+ void __init printk_sysctl_init(void);
+@@ -42,6 +43,8 @@ enum printk_info_flags {
+ LOG_CONT = 8, /* text is a fragment of a continuation line */
+ };
+
++extern struct printk_ringbuffer *prb;
++
+ __printf(4, 0)
+ int vprintk_store(int facility, int level,
+ const struct dev_printk_info *dev_info,
+@@ -69,6 +72,8 @@ void defer_console_output(void);
+ u16 printk_parse_prefix(const char *text, int *level,
+ enum printk_info_flags *flags);
+
++u64 nbcon_seq_read(struct console *con);
++void nbcon_seq_force(struct console *con, u64 seq);
+ bool nbcon_alloc(struct console *con);
+ void nbcon_init(struct console *con);
+ void nbcon_free(struct console *con);
+@@ -88,6 +93,8 @@ void nbcon_free(struct console *con);
+ #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
+
+ static inline bool printk_percpu_data_ready(void) { return false; }
++static inline u64 nbcon_seq_read(struct console *con) { return 0; }
++static inline void nbcon_seq_force(struct console *con, u64 seq) { }
+ static inline bool nbcon_alloc(struct console *con) { return false; }
+ static inline void nbcon_init(struct console *con) { }
+ static inline void nbcon_free(struct console *con) { }
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -140,6 +140,101 @@ static inline bool nbcon_state_try_cmpxc
+ return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom);
+ }
+
++#ifdef CONFIG_64BIT
++
++#define __seq_to_nbcon_seq(seq) (seq)
++#define __nbcon_seq_to_seq(seq) (seq)
++
++#else /* CONFIG_64BIT */
++
++#define __seq_to_nbcon_seq(seq) ((u32)seq)
++
++static inline u64 __nbcon_seq_to_seq(u32 nbcon_seq)
++{
++ u64 seq;
++ u64 rb_next_seq;
++
++ /*
++ * The provided sequence is only the lower 32 bits of the ringbuffer
++ * sequence. It needs to be expanded to 64bit. Get the next sequence
++ * number from the ringbuffer and fold it.
++ *
++ * Having a 32bit representation in the console is sufficient.
++ * If a console ever gets more than 2^31 records behind
++ * the ringbuffer then this is the least of the problems.
++ *
++ * Also the access to the ring buffer is always safe.
++ */
++ rb_next_seq = prb_next_seq(prb);
++ seq = rb_next_seq - ((u32)rb_next_seq - nbcon_seq);
++
++ return seq;
++}
++
++#endif /* CONFIG_64BIT */
++
++/**
++ * nbcon_seq_read - Read the current console sequence
++ * @con: Console to read the sequence of
++ *
++ * Return: Sequence number of the next record to print on @con.
++ */
++u64 nbcon_seq_read(struct console *con)
++{
++ unsigned long nbcon_seq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_seq));
++
++ return __nbcon_seq_to_seq(nbcon_seq);
++}
++
++/**
++ * nbcon_seq_force - Force console sequence to a specific value
++ * @con: Console to work on
++ * @seq: Sequence number value to set
++ *
++ * Only to be used during init (before registration) or in extreme situations
++ * (such as panic with CONSOLE_REPLAY_ALL).
++ */
++void nbcon_seq_force(struct console *con, u64 seq)
++{
++ /*
++ * If the specified record no longer exists, the oldest available record
++ * is chosen. This is especially important on 32bit systems because only
++ * the lower 32 bits of the sequence number are stored. The upper 32 bits
++ * are derived from the sequence numbers available in the ringbuffer.
++ */
++ u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb));
++
++ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __seq_to_nbcon_seq(valid_seq));
++
++ /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */
++ con->seq = 0;
++}
++
++/**
++ * nbcon_seq_try_update - Try to update the console sequence number
++ * @ctxt: Pointer to an acquire context that contains
++ * all information about the acquire mode
++ * @new_seq: The new sequence number to set
++ *
++ * @ctxt->seq is updated to the new value of @con::nbcon_seq (expanded to
++ * the 64bit value). This could be a different value than @new_seq if
++ * nbcon_seq_force() was used or the current context no longer owns the
++ * console. In the later case, it will stop printing anyway.
++ */
++__maybe_unused
++static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
++{
++ unsigned long nbcon_seq = __seq_to_nbcon_seq(ctxt->seq);
++ struct console *con = ctxt->console;
++
++ if (atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_seq), &nbcon_seq,
++ __seq_to_nbcon_seq(new_seq))) {
++ ctxt->seq = new_seq;
++ } else {
++ ctxt->seq = nbcon_seq_read(con);
++ }
++}
++
+ /**
+ * nbcon_context_try_acquire_direct - Try to acquire directly
+ * @ctxt: The context of the caller
+@@ -510,6 +605,9 @@ static bool nbcon_context_try_acquire(st
+ else
+ ctxt->pbufs = con->pbufs;
+
++ /* Set the record sequence for this context to print. */
++ ctxt->seq = nbcon_seq_read(ctxt->console);
++
+ return true;
+ }
+
+@@ -722,6 +820,8 @@ bool nbcon_alloc(struct console *con)
+ *
+ * nbcon_alloc() *must* be called and succeed before this function
+ * is called.
++ *
++ * This function expects that the legacy @con->seq has been set.
+ */
+ void nbcon_init(struct console *con)
+ {
+@@ -730,6 +830,7 @@ void nbcon_init(struct console *con)
+ /* nbcon_alloc() must have been called and successful! */
+ BUG_ON(!con->pbufs);
+
++ nbcon_seq_force(con, con->seq);
+ nbcon_state_set(con, &state);
+ }
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -494,7 +494,7 @@ static u32 log_buf_len = __LOG_BUF_LEN;
+
+ static struct printk_ringbuffer printk_rb_dynamic;
+
+-static struct printk_ringbuffer *prb = &printk_rb_static;
++struct printk_ringbuffer *prb = &printk_rb_static;
+
+ /*
+ * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before
+@@ -3168,6 +3168,7 @@ void console_flush_on_panic(enum con_flu
+
+ if (mode == CONSOLE_REPLAY_ALL) {
+ struct console *c;
++ short flags;
+ int cookie;
+ u64 seq;
+
+@@ -3175,11 +3176,17 @@ void console_flush_on_panic(enum con_flu
+
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(c) {
+- /*
+- * This is an unsynchronized assignment, but the
+- * kernel is in "hope and pray" mode anyway.
+- */
+- c->seq = seq;
++ flags = console_srcu_read_flags(c);
++
++ if (flags & CON_NBCON) {
++ nbcon_seq_force(c, seq);
++ } else {
++ /*
++ * This is an unsynchronized assignment. On
++ * panic legacy consoles are only best effort.
++ */
++ c->seq = seq;
++ }
+ }
+ console_srcu_read_unlock(cookie);
+ }
+@@ -3750,6 +3757,7 @@ static bool __pr_flush(struct console *c
+ struct console *c;
+ u64 last_diff = 0;
+ u64 printk_seq;
++ short flags;
+ int cookie;
+ u64 diff;
+ u64 seq;
+@@ -3777,6 +3785,9 @@ static bool __pr_flush(struct console *c
+ for_each_console_srcu(c) {
+ if (con && con != c)
+ continue;
++
++ flags = console_srcu_read_flags(c);
++
+ /*
+ * If consoles are not usable, it cannot be expected
+ * that they make forward progress, so only increment
+@@ -3784,7 +3795,13 @@ static bool __pr_flush(struct console *c
+ */
+ if (!console_is_usable(c))
+ continue;
+- printk_seq = c->seq;
++
++ if (flags & CON_NBCON) {
++ printk_seq = nbcon_seq_read(c);
++ } else {
++ printk_seq = c->seq;
++ }
++
+ if (printk_seq < seq)
+ diff += seq - printk_seq;
+ }
diff --git a/debian/patches-rt/0081-printk-nbcon-Add-emit-function-and-callback-function.patch b/debian/patches-rt/0081-printk-nbcon-Add-emit-function-and-callback-function.patch
new file mode 100644
index 0000000000..ab32a05b19
--- /dev/null
+++ b/debian/patches-rt/0081-printk-nbcon-Add-emit-function-and-callback-function.patch
@@ -0,0 +1,262 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:06 +0206
+Subject: [PATCH 081/134] printk: nbcon: Add emit function and callback
+ function for atomic printing
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Implement an emit function for nbcon consoles to output printk
+messages. It utilizes the lockless printk_get_next_message() and
+console_prepend_dropped() functions to retrieve/build the output
+message. The emit function includes the required safety points to
+check for handover/takeover and calls a new write_atomic callback
+of the console driver to output the message. It also includes
+proper handling for updating the nbcon console sequence number.
+
+A new nbcon_write_context struct is introduced. This is provided
+to the write_atomic callback and includes only the information
+necessary for performing atomic writes.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-8-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 21 +++++++++
+ kernel/printk/internal.h | 6 ++
+ kernel/printk/nbcon.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++-
+ kernel/printk/printk.c | 9 +--
+ 4 files changed, 134 insertions(+), 8 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -242,6 +242,7 @@ struct printk_buffers;
+ * be used only with NBCON_PRIO_PANIC @prio. It
+ * might cause a system freeze when the console
+ * is used later.
++ * @backlog: Ringbuffer has pending records
+ * @pbufs: Pointer to the text buffer for this context
+ * @seq: The sequence number to print for this context
+ */
+@@ -252,12 +253,29 @@ struct nbcon_context {
+ enum nbcon_prio prio;
+ unsigned int allow_unsafe_takeover : 1;
+
++ /* members set by emit */
++ unsigned int backlog : 1;
++
+ /* members set by acquire */
+ struct printk_buffers *pbufs;
+ u64 seq;
+ };
+
+ /**
++ * struct nbcon_write_context - Context handed to the nbcon write callbacks
++ * @ctxt: The core console context
++ * @outbuf: Pointer to the text buffer for output
++ * @len: Length to write
++ * @unsafe_takeover: If a hostile takeover in an unsafe state has occurred
++ */
++struct nbcon_write_context {
++ struct nbcon_context __private ctxt;
++ char *outbuf;
++ unsigned int len;
++ bool unsafe_takeover;
++};
++
++/**
+ * struct console - The console descriptor structure
+ * @name: The name of the console driver
+ * @write: Write callback to output messages (Optional)
+@@ -277,6 +295,7 @@ struct nbcon_context {
+ * @data: Driver private data
+ * @node: hlist node for the console list
+ *
++ * @write_atomic: Write callback for atomic context
+ * @nbcon_state: State for nbcon consoles
+ * @nbcon_seq: Sequence number of the next record for nbcon to print
+ * @pbufs: Pointer to nbcon private buffer
+@@ -301,6 +320,8 @@ struct console {
+ struct hlist_node node;
+
+ /* nbcon console specific members */
++ bool (*write_atomic)(struct console *con,
++ struct nbcon_write_context *wctxt);
+ atomic_t __private nbcon_state;
+ atomic_long_t __private nbcon_seq;
+ struct printk_buffers *pbufs;
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -130,3 +130,9 @@ struct printk_message {
+ };
+
+ bool other_cpu_in_panic(void);
++bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
++ bool is_extended, bool may_supress);
++
++#ifdef CONFIG_PRINTK
++void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped);
++#endif
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -221,7 +221,6 @@ void nbcon_seq_force(struct console *con
+ * nbcon_seq_force() was used or the current context no longer owns the
+ * console. In the later case, it will stop printing anyway.
+ */
+-__maybe_unused
+ static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
+ {
+ unsigned long nbcon_seq = __seq_to_nbcon_seq(ctxt->seq);
+@@ -755,7 +754,6 @@ static bool nbcon_context_can_proceed(st
+ *
+ * Internal helper to avoid duplicated code.
+ */
+-__maybe_unused
+ static bool __nbcon_context_update_unsafe(struct nbcon_context *ctxt, bool unsafe)
+ {
+ struct console *con = ctxt->console;
+@@ -785,6 +783,110 @@ static bool __nbcon_context_update_unsaf
+ }
+
+ /**
++ * nbcon_emit_next_record - Emit a record in the acquired context
++ * @wctxt: The write context that will be handed to the write function
++ *
++ * Return: True if this context still owns the console. False if
++ * ownership was handed over or taken.
++ *
++ * When this function returns false then the calling context no longer owns
++ * the console and is no longer allowed to go forward. In this case it must
++ * back out immediately and carefully. The buffer content is also no longer
++ * trusted since it no longer belongs to the calling context. If the caller
++ * wants to do more it must reacquire the console first.
++ *
++ * When true is returned, @wctxt->ctxt.backlog indicates whether there are
++ * still records pending in the ringbuffer,
++ */
++__maybe_unused
++static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt)
++{
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
++ struct console *con = ctxt->console;
++ bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED;
++ struct printk_message pmsg = {
++ .pbufs = ctxt->pbufs,
++ };
++ unsigned long con_dropped;
++ struct nbcon_state cur;
++ unsigned long dropped;
++ bool done;
++
++ /*
++ * The printk buffers are filled within an unsafe section. This
++ * prevents NBCON_PRIO_NORMAL and NBCON_PRIO_EMERGENCY from
++ * clobbering each other.
++ */
++
++ if (!nbcon_context_enter_unsafe(ctxt))
++ return false;
++
++ ctxt->backlog = printk_get_next_message(&pmsg, ctxt->seq, is_extended, true);
++ if (!ctxt->backlog)
++ return nbcon_context_exit_unsafe(ctxt);
++
++ /*
++ * @con->dropped is not protected in case of an unsafe hostile
++ * takeover. In that situation the update can be racy so
++ * annotate it accordingly.
++ */
++ con_dropped = data_race(READ_ONCE(con->dropped));
++
++ dropped = con_dropped + pmsg.dropped;
++ if (dropped && !is_extended)
++ console_prepend_dropped(&pmsg, dropped);
++
++ if (!nbcon_context_exit_unsafe(ctxt))
++ return false;
++
++ /* For skipped records just update seq/dropped in @con. */
++ if (pmsg.outbuf_len == 0)
++ goto update_con;
++
++ /* Initialize the write context for driver callbacks. */
++ wctxt->outbuf = &pmsg.pbufs->outbuf[0];
++ wctxt->len = pmsg.outbuf_len;
++ nbcon_state_read(con, &cur);
++ wctxt->unsafe_takeover = cur.unsafe_takeover;
++
++ if (con->write_atomic) {
++ done = con->write_atomic(con, wctxt);
++ } else {
++ nbcon_context_release(ctxt);
++ WARN_ON_ONCE(1);
++ done = false;
++ }
++
++ /* If not done, the emit was aborted. */
++ if (!done)
++ return false;
++
++ /*
++ * Since any dropped message was successfully output, reset the
++ * dropped count for the console.
++ */
++ dropped = 0;
++update_con:
++ /*
++ * The dropped count and the sequence number are updated within an
++ * unsafe section. This limits update races to the panic context and
++ * allows the panic context to win.
++ */
++
++ if (!nbcon_context_enter_unsafe(ctxt))
++ return false;
++
++ if (dropped != con_dropped) {
++ /* Counterpart to the READ_ONCE() above. */
++ WRITE_ONCE(con->dropped, dropped);
++ }
++
++ nbcon_seq_try_update(ctxt, pmsg.seq + 1);
++
++ return nbcon_context_exit_unsafe(ctxt);
++}
++
++/**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+ *
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -698,9 +698,6 @@ static ssize_t msg_print_ext_body(char *
+ return len;
+ }
+
+-static bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+- bool is_extended, bool may_supress);
+-
+ /* /dev/kmsg - userspace message inject/listen interface */
+ struct devkmsg_user {
+ atomic64_t seq;
+@@ -2733,7 +2730,7 @@ static void __console_unlock(void)
+ * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated.
+ */
+ #ifdef CONFIG_PRINTK
+-static void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped)
++void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped)
+ {
+ struct printk_buffers *pbufs = pmsg->pbufs;
+ const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf);
+@@ -2787,8 +2784,8 @@ static void console_prepend_dropped(stru
+ * of @pmsg are valid. (See the documentation of struct printk_message
+ * for information about the @pmsg fields.)
+ */
+-static bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+- bool is_extended, bool may_suppress)
++bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
++ bool is_extended, bool may_suppress)
+ {
+ static int panic_console_dropped;
+
diff --git a/debian/patches-rt/0082-printk-nbcon-Allow-drivers-to-mark-unsafe-regions-an.patch b/debian/patches-rt/0082-printk-nbcon-Allow-drivers-to-mark-unsafe-regions-an.patch
new file mode 100644
index 0000000000..16a07a839e
--- /dev/null
+++ b/debian/patches-rt/0082-printk-nbcon-Allow-drivers-to-mark-unsafe-regions-an.patch
@@ -0,0 +1,136 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 16 Sep 2023 21:26:07 +0206
+Subject: [PATCH 082/134] printk: nbcon: Allow drivers to mark unsafe regions
+ and check state
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+For the write_atomic callback, the console driver may have unsafe
+regions that need to be appropriately marked. Provide functions
+that accept the nbcon_write_context struct to allow for the driver
+to enter and exit unsafe regions.
+
+Also provide a function for drivers to check if they are still the
+owner of the console.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230916192007.608398-9-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 10 ++++++
+ kernel/printk/nbcon.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 85 insertions(+)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -451,6 +451,16 @@ static inline bool console_is_registered
+ lockdep_assert_console_list_lock_held(); \
+ hlist_for_each_entry(con, &console_list, node)
+
++#ifdef CONFIG_PRINTK
++extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt);
++extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt);
++extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt);
++#else
++static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; }
++static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; }
++static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; }
++#endif
++
+ extern int console_set_on_cmdline;
+ extern struct console *early_console;
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -732,6 +732,41 @@ static bool nbcon_context_can_proceed(st
+ return false;
+ }
+
++/**
++ * nbcon_can_proceed - Check whether ownership can proceed
++ * @wctxt: The write context that was handed to the write function
++ *
++ * Return: True if this context still owns the console. False if
++ * ownership was handed over or taken.
++ *
++ * It is used in nbcon_enter_unsafe() to make sure that it still owns the
++ * lock. Also it is used in nbcon_exit_unsafe() to eventually free the lock
++ * for a higher priority context which asked for the friendly handover.
++ *
++ * It can be called inside an unsafe section when the console is just
++ * temporary in safe state instead of exiting and entering the unsafe state.
++ *
++ * Also it can be called in the safe context before doing an expensive safe
++ * operation. It does not make sense to do the operation when a higher
++ * priority context took the lock.
++ *
++ * When this function returns false then the calling context no longer owns
++ * the console and is no longer allowed to go forward. In this case it must
++ * back out immediately and carefully. The buffer content is also no longer
++ * trusted since it no longer belongs to the calling context.
++ */
++bool nbcon_can_proceed(struct nbcon_write_context *wctxt)
++{
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
++ struct console *con = ctxt->console;
++ struct nbcon_state cur;
++
++ nbcon_state_read(con, &cur);
++
++ return nbcon_context_can_proceed(ctxt, &cur);
++}
++EXPORT_SYMBOL_GPL(nbcon_can_proceed);
++
+ #define nbcon_context_enter_unsafe(c) __nbcon_context_update_unsafe(c, true)
+ #define nbcon_context_exit_unsafe(c) __nbcon_context_update_unsafe(c, false)
+
+@@ -783,6 +818,46 @@ static bool __nbcon_context_update_unsaf
+ }
+
+ /**
++ * nbcon_enter_unsafe - Enter an unsafe region in the driver
++ * @wctxt: The write context that was handed to the write function
++ *
++ * Return: True if this context still owns the console. False if
++ * ownership was handed over or taken.
++ *
++ * When this function returns false then the calling context no longer owns
++ * the console and is no longer allowed to go forward. In this case it must
++ * back out immediately and carefully. The buffer content is also no longer
++ * trusted since it no longer belongs to the calling context.
++ */
++bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt)
++{
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
++
++ return nbcon_context_enter_unsafe(ctxt);
++}
++EXPORT_SYMBOL_GPL(nbcon_enter_unsafe);
++
++/**
++ * nbcon_exit_unsafe - Exit an unsafe region in the driver
++ * @wctxt: The write context that was handed to the write function
++ *
++ * Return: True if this context still owns the console. False if
++ * ownership was handed over or taken.
++ *
++ * When this function returns false then the calling context no longer owns
++ * the console and is no longer allowed to go forward. In this case it must
++ * back out immediately and carefully. The buffer content is also no longer
++ * trusted since it no longer belongs to the calling context.
++ */
++bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt)
++{
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
++
++ return nbcon_context_exit_unsafe(ctxt);
++}
++EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
++
++/**
+ * nbcon_emit_next_record - Emit a record in the acquired context
+ * @wctxt: The write context that will be handed to the write function
+ *
diff --git a/debian/patches-rt/0083-printk-fix-illegal-pbufs-access-for-CONFIG_PRINTK.patch b/debian/patches-rt/0083-printk-fix-illegal-pbufs-access-for-CONFIG_PRINTK.patch
new file mode 100644
index 0000000000..80de1c716d
--- /dev/null
+++ b/debian/patches-rt/0083-printk-fix-illegal-pbufs-access-for-CONFIG_PRINTK.patch
@@ -0,0 +1,134 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Sep 2023 17:58:38 +0206
+Subject: [PATCH 083/134] printk: fix illegal pbufs access for !CONFIG_PRINTK
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+When CONFIG_PRINTK is not set, PRINTK_MESSAGE_MAX is 0. This
+leads to a zero-sized array @outbuf in @printk_shared_pbufs. In
+console_flush_all() a pointer to the first element of the array
+is assigned with:
+
+ char *outbuf = &printk_shared_pbufs.outbuf[0];
+
+For !CONFIG_PRINTK this leads to a compiler warning:
+
+ warning: array subscript 0 is outside array bounds of
+ 'char[0]' [-Warray-bounds]
+
+This is not really dangerous because printk_get_next_message()
+always returns false for !CONFIG_PRINTK, which leads to @outbuf
+never being used. However, it makes no sense to even compile
+these functions for !CONFIG_PRINTK.
+
+Extend the existing '#ifdef CONFIG_PRINTK' block to contain
+the formatting and emitting functions since these have no
+purpose in !CONFIG_PRINTK. This also allows removing several
+more !CONFIG_PRINTK dummies as well as moving
+@suppress_panic_printk into a CONFIG_PRINTK block.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202309201724.M9BMAQIh-lkp@intel.com/
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230920155238.670439-1-john.ogness@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 44 ++++++++++++++++++--------------------------
+ 1 file changed, 18 insertions(+), 26 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -102,12 +102,6 @@ DEFINE_STATIC_SRCU(console_srcu);
+ */
+ int __read_mostly suppress_printk;
+
+-/*
+- * During panic, heavy printk by other CPUs can delay the
+- * panic and risk deadlock on console resources.
+- */
+-static int __read_mostly suppress_panic_printk;
+-
+ #ifdef CONFIG_LOCKDEP
+ static struct lockdep_map console_lock_dep_map = {
+ .name = "console_lock"
+@@ -445,6 +439,12 @@ static int console_msg_format = MSG_FORM
+ static DEFINE_MUTEX(syslog_lock);
+
+ #ifdef CONFIG_PRINTK
++/*
++ * During panic, heavy printk by other CPUs can delay the
++ * panic and risk deadlock on console resources.
++ */
++static int __read_mostly suppress_panic_printk;
++
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+ /* All 3 protected by @syslog_lock. */
+ /* the next printk record to read by syslog(READ) or /proc/kmsg */
+@@ -2346,22 +2346,6 @@ static bool __pr_flush(struct console *c
+
+ static u64 syslog_seq;
+
+-static size_t record_print_text(const struct printk_record *r,
+- bool syslog, bool time)
+-{
+- return 0;
+-}
+-static ssize_t info_print_ext_header(char *buf, size_t size,
+- struct printk_info *info)
+-{
+- return 0;
+-}
+-static ssize_t msg_print_ext_body(char *buf, size_t size,
+- char *text, size_t text_len,
+- struct dev_printk_info *dev_info) { return 0; }
+-static void console_lock_spinning_enable(void) { }
+-static int console_lock_spinning_disable_and_check(int cookie) { return 0; }
+-static bool suppress_message_printing(int level) { return false; }
+ static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; }
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
+
+@@ -2715,6 +2699,8 @@ static void __console_unlock(void)
+ up_console_sem();
+ }
+
++#ifdef CONFIG_PRINTK
++
+ /*
+ * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". This
+ * is achieved by shifting the existing message over and inserting the dropped
+@@ -2729,7 +2715,6 @@ static void __console_unlock(void)
+ *
+ * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated.
+ */
+-#ifdef CONFIG_PRINTK
+ void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped)
+ {
+ struct printk_buffers *pbufs = pmsg->pbufs;
+@@ -2761,9 +2746,6 @@ void console_prepend_dropped(struct prin
+ memcpy(outbuf, scratchbuf, len);
+ pmsg->outbuf_len += len;
+ }
+-#else
+-#define console_prepend_dropped(pmsg, dropped)
+-#endif /* CONFIG_PRINTK */
+
+ /*
+ * Read and format the specified record (or a later record if the specified
+@@ -2921,6 +2903,16 @@ static bool console_emit_next_record(str
+ return true;
+ }
+
++#else
++
++static bool console_emit_next_record(struct console *con, bool *handover, int cookie)
++{
++ *handover = false;
++ return false;
++}
++
++#endif /* CONFIG_PRINTK */
++
+ /*
+ * Print out all remaining records to all consoles.
+ *
diff --git a/debian/patches-rt/0084-printk-Reduce-pr_flush-pooling-time.patch b/debian/patches-rt/0084-printk-Reduce-pr_flush-pooling-time.patch
new file mode 100644
index 0000000000..09d1d343f4
--- /dev/null
+++ b/debian/patches-rt/0084-printk-Reduce-pr_flush-pooling-time.patch
@@ -0,0 +1,102 @@
+From: Petr Mladek <pmladek@suse.com>
+Date: Fri, 6 Oct 2023 10:21:51 +0200
+Subject: [PATCH 084/134] printk: Reduce pr_flush() pooling time
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+pr_flush() does not guarantee that all messages would really get flushed
+to the console. The best it could do is to wait with a given timeout.[*]
+
+The current interval 100ms for checking the progress might seem too
+long in some situations. For example, such delays are not appreciated
+during suspend and resume especially when the consoles have been flushed
+"long" time before the check.
+
+On the other hand, the sleeping wait might be useful in other situations.
+Especially, it would allow flushing the messages using printk kthreads
+on the same CPU[*].
+
+Use msleep(1) as a compromise.
+
+Also measure the time using jiffies. msleep() does not guarantee
+precise wakeup after the given delay. It might be much longer,
+especially for times < 20s. See Documentation/timers/timers-howto.rst
+for more details.
+
+Note that msecs_to_jiffies() already translates a negative value into
+an infinite timeout.
+
+[*] console_unlock() does not guarantee flushing the consoles since
+ the commit dbdda842fe96f893 ("printk: Add console owner and waiter
+ logic to load balance console writes").
+
+ It would be possible to guarantee it another way. For example,
+ the spinning might be enabled only when the console_lock has been
+ taken via console_trylock().
+
+ But the load balancing is helpful. And more importantly, the flush
+ with a timeout has been added as a preparation step for introducing
+ printk kthreads.
+
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Reviewed-by: John Ogness <john.ogness@linutronix.de>
+Link: https://lore.kernel.org/r/20231006082151.6969-3-pmladek@suse.com
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3742,7 +3742,8 @@ late_initcall(printk_late_init);
+ /* If @con is specified, only wait for that console. Otherwise wait for all. */
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress)
+ {
+- int remaining = timeout_ms;
++ unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms);
++ unsigned long remaining_jiffies = timeout_jiffies;
+ struct console *c;
+ u64 last_diff = 0;
+ u64 printk_seq;
+@@ -3760,6 +3761,9 @@ static bool __pr_flush(struct console *c
+ console_unlock();
+
+ for (;;) {
++ unsigned long begin_jiffies;
++ unsigned long slept_jiffies;
++
+ diff = 0;
+
+ /*
+@@ -3797,24 +3801,20 @@ static bool __pr_flush(struct console *c
+ console_srcu_read_unlock(cookie);
+
+ if (diff != last_diff && reset_on_progress)
+- remaining = timeout_ms;
++ remaining_jiffies = timeout_jiffies;
+
+ console_unlock();
+
+ /* Note: @diff is 0 if there are no usable consoles. */
+- if (diff == 0 || remaining == 0)
++ if (diff == 0 || remaining_jiffies == 0)
+ break;
+
+- if (remaining < 0) {
+- /* no timeout limit */
+- msleep(100);
+- } else if (remaining < 100) {
+- msleep(remaining);
+- remaining = 0;
+- } else {
+- msleep(100);
+- remaining -= 100;
+- }
++ /* msleep(1) might sleep much longer. Check time by jiffies. */
++ begin_jiffies = jiffies;
++ msleep(1);
++ slept_jiffies = jiffies - begin_jiffies;
++
++ remaining_jiffies -= min(slept_jiffies, remaining_jiffies);
+
+ last_diff = diff;
+ }
diff --git a/debian/patches-rt/0085-printk-nbcon-Relocate-32bit-seq-macros.patch b/debian/patches-rt/0085-printk-nbcon-Relocate-32bit-seq-macros.patch
new file mode 100644
index 0000000000..6d1cf3686b
--- /dev/null
+++ b/debian/patches-rt/0085-printk-nbcon-Relocate-32bit-seq-macros.patch
@@ -0,0 +1,141 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 6 Dec 2023 12:01:56 +0000
+Subject: [PATCH 085/134] printk: nbcon: Relocate 32bit seq macros
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The macros __seq_to_nbcon_seq() and __nbcon_seq_to_seq() are
+used to provide support for atomic handling of sequence numbers
+on 32bit systems. Until now this was only used by nbcon.c,
+which is why they were located in nbcon.c and include nbcon in
+the name.
+
+In a follow-up commit this functionality is also needed by
+printk_ringbuffer. Rather than duplicating the functionality,
+relocate the macros to printk_ringbuffer.h.
+
+Also, since the macros will be no longer nbcon-specific, rename
+them to __u64seq_to_ulseq() and __ulseq_to_u64seq().
+
+This does not result in any functional change.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/nbcon.c | 41 +++-----------------------------------
+ kernel/printk/printk_ringbuffer.h | 33 ++++++++++++++++++++++++++++++
+ 2 files changed, 37 insertions(+), 37 deletions(-)
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -140,39 +140,6 @@ static inline bool nbcon_state_try_cmpxc
+ return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom);
+ }
+
+-#ifdef CONFIG_64BIT
+-
+-#define __seq_to_nbcon_seq(seq) (seq)
+-#define __nbcon_seq_to_seq(seq) (seq)
+-
+-#else /* CONFIG_64BIT */
+-
+-#define __seq_to_nbcon_seq(seq) ((u32)seq)
+-
+-static inline u64 __nbcon_seq_to_seq(u32 nbcon_seq)
+-{
+- u64 seq;
+- u64 rb_next_seq;
+-
+- /*
+- * The provided sequence is only the lower 32 bits of the ringbuffer
+- * sequence. It needs to be expanded to 64bit. Get the next sequence
+- * number from the ringbuffer and fold it.
+- *
+- * Having a 32bit representation in the console is sufficient.
+- * If a console ever gets more than 2^31 records behind
+- * the ringbuffer then this is the least of the problems.
+- *
+- * Also the access to the ring buffer is always safe.
+- */
+- rb_next_seq = prb_next_seq(prb);
+- seq = rb_next_seq - ((u32)rb_next_seq - nbcon_seq);
+-
+- return seq;
+-}
+-
+-#endif /* CONFIG_64BIT */
+-
+ /**
+ * nbcon_seq_read - Read the current console sequence
+ * @con: Console to read the sequence of
+@@ -183,7 +150,7 @@ u64 nbcon_seq_read(struct console *con)
+ {
+ unsigned long nbcon_seq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_seq));
+
+- return __nbcon_seq_to_seq(nbcon_seq);
++ return __ulseq_to_u64seq(prb, nbcon_seq);
+ }
+
+ /**
+@@ -204,7 +171,7 @@ void nbcon_seq_force(struct console *con
+ */
+ u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb));
+
+- atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __seq_to_nbcon_seq(valid_seq));
++ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __u64seq_to_ulseq(valid_seq));
+
+ /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */
+ con->seq = 0;
+@@ -223,11 +190,11 @@ void nbcon_seq_force(struct console *con
+ */
+ static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
+ {
+- unsigned long nbcon_seq = __seq_to_nbcon_seq(ctxt->seq);
++ unsigned long nbcon_seq = __u64seq_to_ulseq(ctxt->seq);
+ struct console *con = ctxt->console;
+
+ if (atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_seq), &nbcon_seq,
+- __seq_to_nbcon_seq(new_seq))) {
++ __u64seq_to_ulseq(new_seq))) {
+ ctxt->seq = new_seq;
+ } else {
+ ctxt->seq = nbcon_seq_read(con);
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -381,4 +381,37 @@ bool prb_read_valid_info(struct printk_r
+ u64 prb_first_valid_seq(struct printk_ringbuffer *rb);
+ u64 prb_next_seq(struct printk_ringbuffer *rb);
+
++#ifdef CONFIG_64BIT
++
++#define __u64seq_to_ulseq(u64seq) (u64seq)
++#define __ulseq_to_u64seq(rb, ulseq) (ulseq)
++
++#else /* CONFIG_64BIT */
++
++#define __u64seq_to_ulseq(u64seq) ((u32)u64seq)
++
++static inline u64 __ulseq_to_u64seq(struct printk_ringbuffer *rb, u32 ulseq)
++{
++ u64 seq;
++ u64 rb_next_seq;
++
++ /*
++ * The provided sequence is only the lower 32 bits of the ringbuffer
++ * sequence. It needs to be expanded to 64bit. Get the next sequence
++ * number from the ringbuffer and fold it.
++ *
++ * Having a 32bit representation in the console is sufficient.
++ * If a console ever gets more than 2^31 records behind
++ * the ringbuffer then this is the least of the problems.
++ *
++ * Also the access to the ring buffer is always safe.
++ */
++ rb_next_seq = prb_next_seq(rb);
++ seq = rb_next_seq - ((u32)rb_next_seq - ulseq);
++
++ return seq;
++}
++
++#endif /* CONFIG_64BIT */
++
+ #endif /* _KERNEL_PRINTK_RINGBUFFER_H */
diff --git a/debian/patches-rt/0086-printk-Adjust-mapping-for-32bit-seq-macros.patch b/debian/patches-rt/0086-printk-Adjust-mapping-for-32bit-seq-macros.patch
new file mode 100644
index 0000000000..d6ff341f46
--- /dev/null
+++ b/debian/patches-rt/0086-printk-Adjust-mapping-for-32bit-seq-macros.patch
@@ -0,0 +1,71 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 7 Dec 2023 14:15:15 +0000
+Subject: [PATCH 086/134] printk: Adjust mapping for 32bit seq macros
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Note: This change only applies to 32bit architectures. On 64bit
+ architectures the macros are NOPs.
+
+__ulseq_to_u64seq() computes the upper 32 bits of the passed
+argument value (@ulseq). The upper bits are derived from a base
+value (@rb_next_seq) in a way that assumes @ulseq represents a
+64bit number that is less than or equal to @rb_next_seq.
+
+Until now this mapping has been correct for all call sites. However,
+in a follow-up commit, values of @ulseq will be passed in that are
+higher than the base value. This requires a change to how the 32bit
+value is mapped to a 64bit sequence number.
+
+Rather than mapping @ulseq such that the base value is the end of a
+32bit block, map @ulseq such that the base value is in the middle of
+a 32bit block. This allows supporting 31 bits before and after the
+base value, which is deemed acceptable for the console sequence
+number during runtime.
+
+Here is an example to illustrate the previous and new mappings.
+
+For a base value (@rb_next_seq) of 2 2000 0000...
+
+Before this change the range of possible return values was:
+
+1 2000 0001 to 2 2000 0000
+
+__ulseq_to_u64seq(1fff ffff) => 2 1fff ffff
+__ulseq_to_u64seq(2000 0000) => 2 2000 0000
+__ulseq_to_u64seq(2000 0001) => 1 2000 0001
+__ulseq_to_u64seq(9fff ffff) => 1 9fff ffff
+__ulseq_to_u64seq(a000 0000) => 1 a000 0000
+__ulseq_to_u64seq(a000 0001) => 1 a000 0001
+
+After this change the range of possible return values are:
+1 a000 0001 to 2 a000 0000
+
+__ulseq_to_u64seq(1fff ffff) => 2 1fff ffff
+__ulseq_to_u64seq(2000 0000) => 2 2000 0000
+__ulseq_to_u64seq(2000 0001) => 2 2000 0001
+__ulseq_to_u64seq(9fff ffff) => 2 9fff ffff
+__ulseq_to_u64seq(a000 0000) => 2 a000 0000
+__ulseq_to_u64seq(a000 0001) => 1 a000 0001
+
+[ john.ogness: Rewrite commit message. ]
+
+Reported-by: Francesco Dolcini <francesco@dolcini.it>
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -407,7 +407,7 @@ static inline u64 __ulseq_to_u64seq(stru
+ * Also the access to the ring buffer is always safe.
+ */
+ rb_next_seq = prb_next_seq(rb);
+- seq = rb_next_seq - ((u32)rb_next_seq - ulseq);
++ seq = rb_next_seq - (s32)((u32)rb_next_seq - ulseq);
+
+ return seq;
+ }
diff --git a/debian/patches-rt/0087-printk-Use-prb_first_seq-as-base-for-32bit-seq-macro.patch b/debian/patches-rt/0087-printk-Use-prb_first_seq-as-base-for-32bit-seq-macro.patch
new file mode 100644
index 0000000000..2ed6d52b51
--- /dev/null
+++ b/debian/patches-rt/0087-printk-Use-prb_first_seq-as-base-for-32bit-seq-macro.patch
@@ -0,0 +1,71 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 22 Nov 2023 16:13:37 +0000
+Subject: [PATCH 087/134] printk: Use prb_first_seq() as base for 32bit seq
+ macros
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Note: This change only applies to 32bit architectures. On 64bit
+ architectures the macros are NOPs.
+
+Currently prb_next_seq() is used as the base for the 32bit seq
+macros __u64seq_to_ulseq() and __ulseq_to_u64seq(). However, in
+a follow-up commit, prb_next_seq() will need to make use of the
+32bit seq macros.
+
+Use prb_first_seq() as the base for the 32bit seq macros instead
+because it is guaranteed to return 64bit sequence numbers without
+relying on any 32bit seq macros.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.c | 2 +-
+ kernel/printk/printk_ringbuffer.h | 8 ++++----
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -1832,7 +1832,7 @@ static int prb_read(struct printk_ringbu
+ }
+
+ /* Get the sequence number of the tail descriptor. */
+-static u64 prb_first_seq(struct printk_ringbuffer *rb)
++u64 prb_first_seq(struct printk_ringbuffer *rb)
+ {
+ struct prb_desc_ring *desc_ring = &rb->desc_ring;
+ enum desc_state d_state;
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -378,6 +378,7 @@ bool prb_read_valid(struct printk_ringbu
+ bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq,
+ struct printk_info *info, unsigned int *line_count);
+
++u64 prb_first_seq(struct printk_ringbuffer *rb);
+ u64 prb_first_valid_seq(struct printk_ringbuffer *rb);
+ u64 prb_next_seq(struct printk_ringbuffer *rb);
+
+@@ -392,12 +393,12 @@ u64 prb_next_seq(struct printk_ringbuffe
+
+ static inline u64 __ulseq_to_u64seq(struct printk_ringbuffer *rb, u32 ulseq)
+ {
++ u64 rb_first_seq = prb_first_seq(rb);
+ u64 seq;
+- u64 rb_next_seq;
+
+ /*
+ * The provided sequence is only the lower 32 bits of the ringbuffer
+- * sequence. It needs to be expanded to 64bit. Get the next sequence
++ * sequence. It needs to be expanded to 64bit. Get the first sequence
+ * number from the ringbuffer and fold it.
+ *
+ * Having a 32bit representation in the console is sufficient.
+@@ -406,8 +407,7 @@ static inline u64 __ulseq_to_u64seq(stru
+ *
+ * Also the access to the ring buffer is always safe.
+ */
+- rb_next_seq = prb_next_seq(rb);
+- seq = rb_next_seq - (s32)((u32)rb_next_seq - ulseq);
++ seq = rb_first_seq - (s32)((u32)rb_first_seq - ulseq);
+
+ return seq;
+ }
diff --git a/debian/patches-rt/0088-printk-ringbuffer-Do-not-skip-non-finalized-records-.patch b/debian/patches-rt/0088-printk-ringbuffer-Do-not-skip-non-finalized-records-.patch
new file mode 100644
index 0000000000..917f777f1c
--- /dev/null
+++ b/debian/patches-rt/0088-printk-ringbuffer-Do-not-skip-non-finalized-records-.patch
@@ -0,0 +1,304 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Thu, 19 Oct 2023 10:32:05 +0000
+Subject: [PATCH 088/134] printk: ringbuffer: Do not skip non-finalized records
+ with prb_next_seq()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Commit f244b4dc53e5 ("printk: ringbuffer: Improve
+prb_next_seq() performance") introduced an optimization for
+prb_next_seq() by using best-effort to track recently finalized
+records. However, the order of finalization does not
+necessarily match the order of the records. The optimization
+changed prb_next_seq() to return inconsistent results, possibly
+yielding sequence numbers that are not available to readers
+because they are preceded by non-finalized records or they are
+not yet visible to the reader CPU.
+
+Rather than simply best-effort tracking recently finalized
+records, force the committing writer to read records and
+increment the last "contiguous block" of finalized records. In
+order to do this, the sequence number instead of ID must be
+stored because ID's cannot be directly compared.
+
+A new memory barrier pair is introduced to guarantee that a
+reader can always read the records up until the sequence number
+returned by prb_next_seq() (unless the records have since
+been overwritten in the ringbuffer).
+
+This restores the original functionality of prb_next_seq()
+while also keeping the optimization.
+
+For 32bit systems, only the lower 32 bits of the sequence
+number are stored. When reading the value, it is expanded to
+the full 64bit sequence number using the 32bit seq macros,
+which fold in the value returned by prb_first_seq().
+
+Fixes: f244b4dc53e5 ("printk: ringbuffer: Improve prb_next_seq() performance")
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.c | 164 ++++++++++++++++++++++++++++----------
+ kernel/printk/printk_ringbuffer.h | 4
+ 2 files changed, 127 insertions(+), 41 deletions(-)
+
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -6,6 +6,7 @@
+ #include <linux/errno.h>
+ #include <linux/bug.h>
+ #include "printk_ringbuffer.h"
++#include "internal.h"
+
+ /**
+ * DOC: printk_ringbuffer overview
+@@ -303,6 +304,9 @@
+ *
+ * desc_push_tail:B / desc_reserve:D
+ * set descriptor reusable (state), then push descriptor tail (id)
++ *
++ * desc_update_last_finalized:A / desc_last_finalized_seq:A
++ * store finalized record, then set new highest finalized sequence number
+ */
+
+ #define DATA_SIZE(data_ring) _DATA_SIZE((data_ring)->size_bits)
+@@ -1442,19 +1446,117 @@ bool prb_reserve_in_last(struct prb_rese
+ }
+
+ /*
++ * @last_finalized_seq value guarantees that all records up to and including
++ * this sequence number are finalized and can be read. The only exception are
++ * too old records which have already been overwritten.
++ *
++ * It is also guaranteed that @last_finalized_seq only increases.
++ *
++ * Be aware that finalized records following non-finalized records are not
++ * reported because they are not yet available to the reader. For example,
++ * a new record stored via printk() will not be available to a printer if
++ * it follows a record that has not been finalized yet. However, once that
++ * non-finalized record becomes finalized, @last_finalized_seq will be
++ * appropriately updated and the full set of finalized records will be
++ * available to the printer. And since each printk() caller will either
++ * directly print or trigger deferred printing of all available unprinted
++ * records, all printk() messages will get printed.
++ */
++static u64 desc_last_finalized_seq(struct printk_ringbuffer *rb)
++{
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
++ unsigned long ulseq;
++
++ /*
++ * Guarantee the sequence number is loaded before loading the
++ * associated record in order to guarantee that the record can be
++ * seen by this CPU. This pairs with desc_update_last_finalized:A.
++ */
++ ulseq = atomic_long_read_acquire(&desc_ring->last_finalized_seq
++ ); /* LMM(desc_last_finalized_seq:A) */
++
++ return __ulseq_to_u64seq(rb, ulseq);
++}
++
++static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
++ struct printk_record *r, unsigned int *line_count);
++
++/*
++ * Check if there are records directly following @last_finalized_seq that are
++ * finalized. If so, update @last_finalized_seq to the latest of these
++ * records. It is not allowed to skip over records that are not yet finalized.
++ */
++static void desc_update_last_finalized(struct printk_ringbuffer *rb)
++{
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
++ u64 old_seq = desc_last_finalized_seq(rb);
++ unsigned long oldval;
++ unsigned long newval;
++ u64 finalized_seq;
++ u64 try_seq;
++
++try_again:
++ finalized_seq = old_seq;
++ try_seq = finalized_seq + 1;
++
++ /* Try to find later finalized records. */
++ while (_prb_read_valid(rb, &try_seq, NULL, NULL)) {
++ finalized_seq = try_seq;
++ try_seq++;
++ }
++
++ /* No update needed if no later finalized record was found. */
++ if (finalized_seq == old_seq)
++ return;
++
++ oldval = __u64seq_to_ulseq(old_seq);
++ newval = __u64seq_to_ulseq(finalized_seq);
++
++ /*
++ * Set the sequence number of a later finalized record that has been
++ * seen.
++ *
++ * Guarantee the record data is visible to other CPUs before storing
++ * its sequence number. This pairs with desc_last_finalized_seq:A.
++ *
++ * Memory barrier involvement:
++ *
++ * If desc_last_finalized_seq:A reads from
++ * desc_update_last_finalized:A, then desc_read:A reads from
++ * _prb_commit:B.
++ *
++ * Relies on:
++ *
++ * RELEASE from _prb_commit:B to desc_update_last_finalized:A
++ * matching
++ * ACQUIRE from desc_last_finalized_seq:A to desc_read:A
++ *
++ * Note: _prb_commit:B and desc_update_last_finalized:A can be
++ * different CPUs. However, the desc_update_last_finalized:A
++ * CPU (which performs the release) must have previously seen
++ * _prb_commit:B.
++ */
++ if (!atomic_long_try_cmpxchg_release(&desc_ring->last_finalized_seq,
++ &oldval, newval)) { /* LMM(desc_update_last_finalized:A) */
++ old_seq = __ulseq_to_u64seq(rb, oldval);
++ goto try_again;
++ }
++}
++
++/*
+ * Attempt to finalize a specified descriptor. If this fails, the descriptor
+ * is either already final or it will finalize itself when the writer commits.
+ */
+-static void desc_make_final(struct prb_desc_ring *desc_ring, unsigned long id)
++static void desc_make_final(struct printk_ringbuffer *rb, unsigned long id)
+ {
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
+ unsigned long prev_state_val = DESC_SV(id, desc_committed);
+ struct prb_desc *d = to_desc(desc_ring, id);
+
+- atomic_long_cmpxchg_relaxed(&d->state_var, prev_state_val,
+- DESC_SV(id, desc_finalized)); /* LMM(desc_make_final:A) */
+-
+- /* Best effort to remember the last finalized @id. */
+- atomic_long_set(&desc_ring->last_finalized_id, id);
++ if (atomic_long_try_cmpxchg_relaxed(&d->state_var, &prev_state_val,
++ DESC_SV(id, desc_finalized))) { /* LMM(desc_make_final:A) */
++ desc_update_last_finalized(rb);
++ }
+ }
+
+ /**
+@@ -1550,7 +1652,7 @@ bool prb_reserve(struct prb_reserved_ent
+ * readers. (For seq==0 there is no previous descriptor.)
+ */
+ if (info->seq > 0)
+- desc_make_final(desc_ring, DESC_ID(id - 1));
++ desc_make_final(rb, DESC_ID(id - 1));
+
+ r->text_buf = data_alloc(rb, r->text_buf_size, &d->text_blk_lpos, id);
+ /* If text data allocation fails, a data-less record is committed. */
+@@ -1643,7 +1745,7 @@ void prb_commit(struct prb_reserved_entr
+ */
+ head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_commit:A) */
+ if (head_id != e->id)
+- desc_make_final(desc_ring, e->id);
++ desc_make_final(e->rb, e->id);
+ }
+
+ /**
+@@ -1663,12 +1765,9 @@ void prb_commit(struct prb_reserved_entr
+ */
+ void prb_final_commit(struct prb_reserved_entry *e)
+ {
+- struct prb_desc_ring *desc_ring = &e->rb->desc_ring;
+-
+ _prb_commit(e, desc_finalized);
+
+- /* Best effort to remember the last finalized @id. */
+- atomic_long_set(&desc_ring->last_finalized_id, e->id);
++ desc_update_last_finalized(e->rb);
+ }
+
+ /*
+@@ -2008,7 +2107,9 @@ u64 prb_first_valid_seq(struct printk_ri
+ * newest sequence number available to readers will be.
+ *
+ * This provides readers a sequence number to jump to if all currently
+- * available records should be skipped.
++ * available records should be skipped. It is guaranteed that all records
++ * previous to the returned value have been finalized and are (or were)
++ * available to the reader.
+ *
+ * Context: Any context.
+ * Return: The sequence number of the next newest (not yet available) record
+@@ -2016,34 +2117,19 @@ u64 prb_first_valid_seq(struct printk_ri
+ */
+ u64 prb_next_seq(struct printk_ringbuffer *rb)
+ {
+- struct prb_desc_ring *desc_ring = &rb->desc_ring;
+- enum desc_state d_state;
+- unsigned long id;
+ u64 seq;
+
+- /* Check if the cached @id still points to a valid @seq. */
+- id = atomic_long_read(&desc_ring->last_finalized_id);
+- d_state = desc_read(desc_ring, id, NULL, &seq, NULL);
++ seq = desc_last_finalized_seq(rb);
+
+- if (d_state == desc_finalized || d_state == desc_reusable) {
+- /*
+- * Begin searching after the last finalized record.
+- *
+- * On 0, the search must begin at 0 because of hack#2
+- * of the bootstrapping phase it is not known if a
+- * record at index 0 exists.
+- */
+- if (seq != 0)
+- seq++;
+- } else {
+- /*
+- * The information about the last finalized sequence number
+- * has gone. It should happen only when there is a flood of
+- * new messages and the ringbuffer is rapidly recycled.
+- * Give up and start from the beginning.
+- */
+- seq = 0;
+- }
++ /*
++ * Begin searching after the last finalized record.
++ *
++ * On 0, the search must begin at 0 because of hack#2
++ * of the bootstrapping phase it is not known if a
++ * record at index 0 exists.
++ */
++ if (seq != 0)
++ seq++;
+
+ /*
+ * The information about the last finalized @seq might be inaccurate.
+@@ -2085,7 +2171,7 @@ void prb_init(struct printk_ringbuffer *
+ rb->desc_ring.infos = infos;
+ atomic_long_set(&rb->desc_ring.head_id, DESC0_ID(descbits));
+ atomic_long_set(&rb->desc_ring.tail_id, DESC0_ID(descbits));
+- atomic_long_set(&rb->desc_ring.last_finalized_id, DESC0_ID(descbits));
++ atomic_long_set(&rb->desc_ring.last_finalized_seq, 0);
+
+ rb->text_data_ring.size_bits = textbits;
+ rb->text_data_ring.data = text_buf;
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -75,7 +75,7 @@ struct prb_desc_ring {
+ struct printk_info *infos;
+ atomic_long_t head_id;
+ atomic_long_t tail_id;
+- atomic_long_t last_finalized_id;
++ atomic_long_t last_finalized_seq;
+ };
+
+ /*
+@@ -259,7 +259,7 @@ static struct printk_ringbuffer name = {
+ .infos = &_##name##_infos[0], \
+ .head_id = ATOMIC_INIT(DESC0_ID(descbits)), \
+ .tail_id = ATOMIC_INIT(DESC0_ID(descbits)), \
+- .last_finalized_id = ATOMIC_INIT(DESC0_ID(descbits)), \
++ .last_finalized_seq = ATOMIC_INIT(0), \
+ }, \
+ .text_data_ring = { \
+ .size_bits = (avgtextbits) + (descbits), \
diff --git a/debian/patches-rt/0089-printk-ringbuffer-Clarify-special-lpos-values.patch b/debian/patches-rt/0089-printk-ringbuffer-Clarify-special-lpos-values.patch
new file mode 100644
index 0000000000..397f61984c
--- /dev/null
+++ b/debian/patches-rt/0089-printk-ringbuffer-Clarify-special-lpos-values.patch
@@ -0,0 +1,92 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 23 Oct 2023 11:11:05 +0000
+Subject: [PATCH 089/134] printk: ringbuffer: Clarify special lpos values
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+For empty line records, no data blocks are created. Instead,
+these valid records are identified by special logical position
+values (in fields of @prb_desc.text_blk_lpos).
+
+Currently the macro NO_LPOS is used for empty line records.
+This name is confusing because it does not imply _why_ there is
+no data block.
+
+Rename NO_LPOS to EMPTY_LINE_LPOS so that it is clear why there
+is no data block.
+
+Also add comments explaining the use of EMPTY_LINE_LPOS as well
+as clarification to the values used to represent data-less
+blocks.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.c | 20 ++++++++++++++++----
+ kernel/printk/printk_ringbuffer.h | 16 +++++++++++++++-
+ 2 files changed, 31 insertions(+), 5 deletions(-)
+
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -1034,9 +1034,13 @@ static char *data_alloc(struct printk_ri
+ unsigned long next_lpos;
+
+ if (size == 0) {
+- /* Specify a data-less block. */
+- blk_lpos->begin = NO_LPOS;
+- blk_lpos->next = NO_LPOS;
++ /*
++ * Data blocks are not created for empty lines. Instead, the
++ * reader will recognize these special lpos values and handle
++ * it appropriately.
++ */
++ blk_lpos->begin = EMPTY_LINE_LPOS;
++ blk_lpos->next = EMPTY_LINE_LPOS;
+ return NULL;
+ }
+
+@@ -1214,10 +1218,18 @@ static const char *get_data(struct prb_d
+
+ /* Data-less data block description. */
+ if (BLK_DATALESS(blk_lpos)) {
+- if (blk_lpos->begin == NO_LPOS && blk_lpos->next == NO_LPOS) {
++ /*
++ * Records that are just empty lines are also valid, even
++ * though they do not have a data block. For such records
++ * explicitly return empty string data to signify success.
++ */
++ if (blk_lpos->begin == EMPTY_LINE_LPOS &&
++ blk_lpos->next == EMPTY_LINE_LPOS) {
+ *data_size = 0;
+ return "";
+ }
++
++ /* Data lost, invalid, or otherwise unavailable. */
+ return NULL;
+ }
+
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -127,8 +127,22 @@ enum desc_state {
+ #define DESC_SV(id, state) (((unsigned long)state << DESC_FLAGS_SHIFT) | id)
+ #define DESC_ID_MASK (~DESC_FLAGS_MASK)
+ #define DESC_ID(sv) ((sv) & DESC_ID_MASK)
++
++/*
++ * Special data block logical position values (for fields of
++ * @prb_desc.text_blk_lpos).
++ *
++ * - Bit0 is used to identify if the record has no data block. (Implemented in
++ * the LPOS_DATALESS() macro.)
++ *
++ * - Bit1 specifies the reason for not having a data block.
++ *
++ * These special values could never be real lpos values because of the
++ * meta data and alignment padding of data blocks. (See to_blk_size() for
++ * details.)
++ */
+ #define FAILED_LPOS 0x1
+-#define NO_LPOS 0x3
++#define EMPTY_LINE_LPOS 0x3
+
+ #define FAILED_BLK_LPOS \
+ { \
diff --git a/debian/patches-rt/0090-printk-For-suppress_panic_printk-check-for-other-CPU.patch b/debian/patches-rt/0090-printk-For-suppress_panic_printk-check-for-other-CPU.patch
new file mode 100644
index 0000000000..1fb32b1ace
--- /dev/null
+++ b/debian/patches-rt/0090-printk-For-suppress_panic_printk-check-for-other-CPU.patch
@@ -0,0 +1,34 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 13 Oct 2023 20:13:02 +0000
+Subject: [PATCH 090/134] printk: For @suppress_panic_printk check for other
+ CPU in panic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Currently @suppress_panic_printk is checked along with
+non-matching @panic_cpu and current CPU. This works
+because @suppress_panic_printk is only set when
+panic_in_progress() is true.
+
+Rather than relying on the @suppress_panic_printk semantics,
+use the concise helper function other_cpu_in_progress(). The
+helper function exists to avoid open coding such tests.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2271,8 +2271,7 @@ asmlinkage int vprintk_emit(int facility
+ if (unlikely(suppress_printk))
+ return 0;
+
+- if (unlikely(suppress_panic_printk) &&
+- atomic_read(&panic_cpu) != raw_smp_processor_id())
++ if (unlikely(suppress_panic_printk) && other_cpu_in_panic())
+ return 0;
+
+ if (level == LOGLEVEL_SCHED) {
diff --git a/debian/patches-rt/0091-printk-Add-this_cpu_in_panic.patch b/debian/patches-rt/0091-printk-Add-this_cpu_in_panic.patch
new file mode 100644
index 0000000000..0925911259
--- /dev/null
+++ b/debian/patches-rt/0091-printk-Add-this_cpu_in_panic.patch
@@ -0,0 +1,88 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 13 Oct 2023 14:30:49 +0000
+Subject: [PATCH 091/134] printk: Add this_cpu_in_panic()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+There is already panic_in_progress() and other_cpu_in_panic(),
+but checking if the current CPU is the panic CPU must still be
+open coded.
+
+Add this_cpu_in_panic() to complete the set.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 1 +
+ kernel/printk/printk.c | 43 +++++++++++++++++++++++--------------------
+ 2 files changed, 24 insertions(+), 20 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -130,6 +130,7 @@ struct printk_message {
+ };
+
+ bool other_cpu_in_panic(void);
++bool this_cpu_in_panic(void);
+ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+ bool is_extended, bool may_supress);
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -347,6 +347,29 @@ static bool panic_in_progress(void)
+ return unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID);
+ }
+
++/* Return true if a panic is in progress on the current CPU. */
++bool this_cpu_in_panic(void)
++{
++ /*
++ * We can use raw_smp_processor_id() here because it is impossible for
++ * the task to be migrated to the panic_cpu, or away from it. If
++ * panic_cpu has already been set, and we're not currently executing on
++ * that CPU, then we never will be.
++ */
++ return unlikely(atomic_read(&panic_cpu) == raw_smp_processor_id());
++}
++
++/*
++ * Return true if a panic is in progress on a remote CPU.
++ *
++ * On true, the local CPU should immediately release any printing resources
++ * that may be needed by the panic CPU.
++ */
++bool other_cpu_in_panic(void)
++{
++ return (panic_in_progress() && !this_cpu_in_panic());
++}
++
+ /*
+ * This is used for debugging the mess that is the VT code by
+ * keeping track if we have the console semaphore held. It's
+@@ -2593,26 +2616,6 @@ static int console_cpu_notify(unsigned i
+ return 0;
+ }
+
+-/*
+- * Return true if a panic is in progress on a remote CPU.
+- *
+- * On true, the local CPU should immediately release any printing resources
+- * that may be needed by the panic CPU.
+- */
+-bool other_cpu_in_panic(void)
+-{
+- if (!panic_in_progress())
+- return false;
+-
+- /*
+- * We can use raw_smp_processor_id() here because it is impossible for
+- * the task to be migrated to the panic_cpu, or away from it. If
+- * panic_cpu has already been set, and we're not currently executing on
+- * that CPU, then we never will be.
+- */
+- return atomic_read(&panic_cpu) != raw_smp_processor_id();
+-}
+-
+ /**
+ * console_lock - block the console subsystem from printing
+ *
diff --git a/debian/patches-rt/0092-printk-ringbuffer-Cleanup-reader-terminology.patch b/debian/patches-rt/0092-printk-ringbuffer-Cleanup-reader-terminology.patch
new file mode 100644
index 0000000000..31c6312c46
--- /dev/null
+++ b/debian/patches-rt/0092-printk-ringbuffer-Cleanup-reader-terminology.patch
@@ -0,0 +1,67 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 6 Nov 2023 15:01:58 +0000
+Subject: [PATCH 092/134] printk: ringbuffer: Cleanup reader terminology
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+With the lockless ringbuffer, it is allowed that multiple
+CPUs/contexts write simultaneously into the buffer. This creates
+an ambiguity as some writers will finalize sooner.
+
+The documentation for the prb_read functions is not clear as it
+refers to "not yet written" and "no data available". Clarify the
+return values and language to be in terms of the reader: records
+available for reading.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -1987,11 +1987,13 @@ u64 prb_first_seq(struct printk_ringbuff
+ }
+
+ /*
+- * Non-blocking read of a record. Updates @seq to the last finalized record
+- * (which may have no data available).
++ * Non-blocking read of a record.
+ *
+- * See the description of prb_read_valid() and prb_read_valid_info()
+- * for details.
++ * On success @seq is updated to the record that was read and (if provided)
++ * @r and @line_count will contain the read/calculated data.
++ *
++ * On failure @seq is updated to a record that is not yet available to the
++ * reader, but it will be the next record available to the reader.
+ */
+ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
+ struct printk_record *r, unsigned int *line_count)
+@@ -2010,7 +2012,7 @@ static bool _prb_read_valid(struct print
+ *seq = tail_seq;
+
+ } else if (err == -ENOENT) {
+- /* Record exists, but no data available. Skip. */
++ /* Record exists, but the data was lost. Skip. */
+ (*seq)++;
+
+ } else {
+@@ -2043,7 +2045,7 @@ static bool _prb_read_valid(struct print
+ * On success, the reader must check r->info.seq to see which record was
+ * actually read. This allows the reader to detect dropped records.
+ *
+- * Failure means @seq refers to a not yet written record.
++ * Failure means @seq refers to a record not yet available to the reader.
+ */
+ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq,
+ struct printk_record *r)
+@@ -2073,7 +2075,7 @@ bool prb_read_valid(struct printk_ringbu
+ * On success, the reader must check info->seq to see which record meta data
+ * was actually read. This allows the reader to detect dropped records.
+ *
+- * Failure means @seq refers to a not yet written record.
++ * Failure means @seq refers to a record not yet available to the reader.
+ */
+ bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq,
+ struct printk_info *info, unsigned int *line_count)
diff --git a/debian/patches-rt/0093-printk-Wait-for-all-reserved-records-with-pr_flush.patch b/debian/patches-rt/0093-printk-Wait-for-all-reserved-records-with-pr_flush.patch
new file mode 100644
index 0000000000..661aea2105
--- /dev/null
+++ b/debian/patches-rt/0093-printk-Wait-for-all-reserved-records-with-pr_flush.patch
@@ -0,0 +1,170 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 6 Nov 2023 14:59:55 +0000
+Subject: [PATCH 093/134] printk: Wait for all reserved records with pr_flush()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Currently pr_flush() will only wait for records that were
+available to readers at the time of the call (using
+prb_next_seq()). But there may be more records (non-finalized)
+that have following finalized records. pr_flush() should wait
+for these to print as well. Particularly because any trailing
+finalized records may be the messages that the calling context
+wants to ensure are printed.
+
+Add a new ringbuffer function prb_next_reserve_seq() to return
+the sequence number following the most recently reserved record.
+This guarantees that pr_flush() will wait until all current
+printk() messages (completed or in progress) have been printed.
+
+Fixes: 3b604ca81202 ("printk: add pr_flush()")
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 2
+ kernel/printk/printk_ringbuffer.c | 113 ++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk_ringbuffer.h | 1
+ 3 files changed, 115 insertions(+), 1 deletion(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3756,7 +3756,7 @@ static bool __pr_flush(struct console *c
+
+ might_sleep();
+
+- seq = prb_next_seq(prb);
++ seq = prb_next_reserve_seq(prb);
+
+ /* Flush the consoles so that records up to @seq are printed. */
+ console_lock();
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -1986,6 +1986,119 @@ u64 prb_first_seq(struct printk_ringbuff
+ return seq;
+ }
+
++/**
++ * prb_next_reserve_seq() - Get the sequence number after the most recently
++ * reserved record.
++ *
++ * @rb: The ringbuffer to get the sequence number from.
++ *
++ * This is the public function available to readers to see what sequence
++ * number will be assigned to the next reserved record.
++ *
++ * Note that depending on the situation, this value can be equal to or
++ * higher than the sequence number returned by prb_next_seq().
++ *
++ * Context: Any context.
++ * Return: The sequence number that will be assigned to the next record
++ * reserved.
++ */
++u64 prb_next_reserve_seq(struct printk_ringbuffer *rb)
++{
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
++ unsigned long last_finalized_id;
++ atomic_long_t *state_var;
++ u64 last_finalized_seq;
++ unsigned long head_id;
++ struct prb_desc desc;
++ unsigned long diff;
++ struct prb_desc *d;
++ int err;
++
++ /*
++ * It may not be possible to read a sequence number for @head_id.
++ * So the ID of @last_finailzed_seq is used to calculate what the
++ * sequence number of @head_id will be.
++ */
++
++try_again:
++ last_finalized_seq = desc_last_finalized_seq(rb);
++
++ /*
++ * @head_id is loaded after @last_finalized_seq to ensure that it is
++ * at or beyond @last_finalized_seq.
++ *
++ * Memory barrier involvement:
++ *
++ * If desc_last_finalized_seq:A reads from
++ * desc_update_last_finalized:A, then
++ * prb_next_reserve_seq:A reads from desc_reserve:D.
++ *
++ * Relies on:
++ *
++ * RELEASE from desc_reserve:D to desc_update_last_finalized:A
++ * matching
++ * ACQUIRE from desc_last_finalized_seq:A to prb_next_reserve_seq:A
++ *
++ * Note: desc_reserve:D and desc_update_last_finalized:A can be
++ * different CPUs. However, the desc_update_last_finalized:A CPU
++ * (which performs the release) must have previously seen
++ * desc_read:C, which implies desc_reserve:D can be seen.
++ */
++ head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_next_reserve_seq:A) */
++
++ d = to_desc(desc_ring, last_finalized_seq);
++ state_var = &d->state_var;
++
++ /* Extract the ID, used to specify the descriptor to read. */
++ last_finalized_id = DESC_ID(atomic_long_read(state_var));
++
++ /* Ensure @last_finalized_id is correct. */
++ err = desc_read_finalized_seq(desc_ring, last_finalized_id, last_finalized_seq, &desc);
++
++ if (err == -EINVAL) {
++ if (last_finalized_seq == 0) {
++ /*
++ * @last_finalized_seq still contains its initial
++ * value. Probably no record has been finalized yet.
++ * This means the ringbuffer is not yet full and the
++ * @head_id value can be used directly (subtracting
++ * off the id value corresponding to seq=0).
++ */
++
++ /*
++ * Because of hack#2 of the bootstrapping phase, the
++ * @head_id initial value must be handled separately.
++ */
++ if (head_id == DESC0_ID(desc_ring->count_bits))
++ return 0;
++
++ /*
++ * The @head_id is initialized such that the first
++ * increment will yield the first record (seq=0).
++ * Therefore use the initial value +1 as the base to
++ * subtract from @head_id.
++ */
++ last_finalized_id = DESC0_ID(desc_ring->count_bits) + 1;
++ } else {
++ /* Record must have been overwritten. Try again. */
++ goto try_again;
++ }
++ }
++
++ /*
++ * @diff is the number of records beyond the last record available
++ * to readers.
++ */
++ diff = head_id - last_finalized_id;
++
++ /*
++ * @head_id points to the most recently reserved record, but this
++ * function returns the sequence number that will be assigned to the
++ * next (not yet reserved) record. Thus +1 is needed.
++ */
++ return (last_finalized_seq + diff + 1);
++}
++
+ /*
+ * Non-blocking read of a record.
+ *
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -395,6 +395,7 @@ bool prb_read_valid_info(struct printk_r
+ u64 prb_first_seq(struct printk_ringbuffer *rb);
+ u64 prb_first_valid_seq(struct printk_ringbuffer *rb);
+ u64 prb_next_seq(struct printk_ringbuffer *rb);
++u64 prb_next_reserve_seq(struct printk_ringbuffer *rb);
+
+ #ifdef CONFIG_64BIT
+
diff --git a/debian/patches-rt/0094-printk-ringbuffer-Skip-non-finalized-records-in-pani.patch b/debian/patches-rt/0094-printk-ringbuffer-Skip-non-finalized-records-in-pani.patch
new file mode 100644
index 0000000000..56c675cea9
--- /dev/null
+++ b/debian/patches-rt/0094-printk-ringbuffer-Skip-non-finalized-records-in-pani.patch
@@ -0,0 +1,68 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 13 Oct 2023 10:23:11 +0000
+Subject: [PATCH 094/134] printk: ringbuffer: Skip non-finalized records in
+ panic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Normally a reader will stop once reaching a non-finalized
+record. However, when a panic happens, writers from other CPUs
+(or an interrupted context on the panic CPU) may have been
+writing a record and were unable to finalize it. The panic CPU
+will reserve/commit/finalize its panic records, but these will
+be located after the non-finalized records. This results in
+panic() not flushing the panic messages.
+
+Extend _prb_read_valid() to skip over non-finalized records if
+on the panic CPU.
+
+Fixes: 896fbe20b4e2 ("printk: use the lockless ringbuffer")
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.c | 28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -2107,6 +2107,10 @@ u64 prb_next_reserve_seq(struct printk_r
+ *
+ * On failure @seq is updated to a record that is not yet available to the
+ * reader, but it will be the next record available to the reader.
++ *
++ * Note: When the current CPU is in panic, this function will skip over any
++ * non-existent/non-finalized records in order to allow the panic CPU
++ * to print any and all records that have been finalized.
+ */
+ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
+ struct printk_record *r, unsigned int *line_count)
+@@ -2129,8 +2133,28 @@ static bool _prb_read_valid(struct print
+ (*seq)++;
+
+ } else {
+- /* Non-existent/non-finalized record. Must stop. */
+- return false;
++ /*
++ * Non-existent/non-finalized record. Must stop.
++ *
++ * For panic situations it cannot be expected that
++ * non-finalized records will become finalized. But
++ * there may be other finalized records beyond that
++ * need to be printed for a panic situation. If this
++ * is the panic CPU, skip this
++ * non-existent/non-finalized record unless it is
++ * at or beyond the head, in which case it is not
++ * possible to continue.
++ *
++ * Note that new messages printed on panic CPU are
++ * finalized when we are here. The only exception
++ * might be the last message without trailing newline.
++ * But it would have the sequence number returned
++ * by "prb_next_reserve_seq() - 1".
++ */
++ if (this_cpu_in_panic() && ((*seq + 1) < prb_next_reserve_seq(rb)))
++ (*seq)++;
++ else
++ return false;
+ }
+ }
+
diff --git a/debian/patches-rt/0095-printk-ringbuffer-Consider-committed-as-finalized-in.patch b/debian/patches-rt/0095-printk-ringbuffer-Consider-committed-as-finalized-in.patch
new file mode 100644
index 0000000000..932ba13e7d
--- /dev/null
+++ b/debian/patches-rt/0095-printk-ringbuffer-Consider-committed-as-finalized-in.patch
@@ -0,0 +1,62 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 20 Nov 2023 12:46:35 +0100
+Subject: [PATCH 095/134] printk: ringbuffer: Consider committed as finalized
+ in panic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+A descriptor in the committed state means the record does not yet
+exist for the reader. However, for the panic CPU, committed
+records should be handled as finalized records since they contain
+message data in a consistent state and may contain additional
+hints as to the cause of the panic.
+
+Add an exception for records in the commit state to not be
+considered non-existing when reading from the panic CPU.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk_ringbuffer.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -1857,6 +1857,8 @@ static bool copy_data(struct prb_data_ri
+ * descriptor. However, it also verifies that the record is finalized and has
+ * the sequence number @seq. On success, 0 is returned.
+ *
++ * For the panic CPU, committed descriptors are also considered finalized.
++ *
+ * Error return values:
+ * -EINVAL: A finalized record with sequence number @seq does not exist.
+ * -ENOENT: A finalized record with sequence number @seq exists, but its data
+@@ -1875,17 +1877,26 @@ static int desc_read_finalized_seq(struc
+
+ /*
+ * An unexpected @id (desc_miss) or @seq mismatch means the record
+- * does not exist. A descriptor in the reserved or committed state
+- * means the record does not yet exist for the reader.
++ * does not exist. A descriptor in the reserved state means the
++ * record does not yet exist for the reader.
+ */
+ if (d_state == desc_miss ||
+ d_state == desc_reserved ||
+- d_state == desc_committed ||
+ s != seq) {
+ return -EINVAL;
+ }
+
+ /*
++ * A descriptor in the committed state means the record does not yet
++ * exist for the reader. However, for the panic CPU, committed
++ * records are also handled as finalized records since they contain
++ * message data in a consistent state and may contain additional
++ * hints as to the cause of the panic.
++ */
++ if (d_state == desc_committed && !this_cpu_in_panic())
++ return -EINVAL;
++
++ /*
+ * A descriptor in the reusable state may no longer have its data
+ * available; report it as existing but with lost data. Or the record
+ * may actually be a record with lost data.
diff --git a/debian/patches-rt/0096-printk-Disable-passing-console-lock-owner-completely.patch b/debian/patches-rt/0096-printk-Disable-passing-console-lock-owner-completely.patch
new file mode 100644
index 0000000000..d5dcdcdccc
--- /dev/null
+++ b/debian/patches-rt/0096-printk-Disable-passing-console-lock-owner-completely.patch
@@ -0,0 +1,107 @@
+From: Petr Mladek <pmladek@suse.com>
+Date: Fri, 13 Oct 2023 14:12:05 +0000
+Subject: [PATCH 096/134] printk: Disable passing console lock owner completely
+ during panic()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The commit d51507098ff91 ("printk: disable optimistic spin
+during panic") added checks to avoid becoming a console waiter
+if a panic is in progress.
+
+However, the transition to panic can occur while there is
+already a waiter. The current owner should not pass the lock to
+the waiter because it might get stopped or blocked anytime.
+
+Also the panic context might pass the console lock owner to an
+already stopped waiter by mistake. It might happen when
+console_flush_on_panic() ignores the current lock owner, for
+example:
+
+CPU0 CPU1
+---- ----
+console_lock_spinning_enable()
+ console_trylock_spinning()
+ [CPU1 now console waiter]
+NMI: panic()
+ panic_other_cpus_shutdown()
+ [stopped as console waiter]
+ console_flush_on_panic()
+ console_lock_spinning_enable()
+ [print 1 record]
+ console_lock_spinning_disable_and_check()
+ [handover to stopped CPU1]
+
+This results in panic() not flushing the panic messages.
+
+Fix these problems by disabling all spinning operations
+completely during panic().
+
+Another advantage is that it prevents possible deadlocks caused
+by "console_owner_lock". The panic() context does not need to
+take it any longer. The lockless checks are safe because the
+functions become NOPs when they see the panic in progress. All
+operations manipulating the state are still synchronized by the
+lock even when non-panic CPUs would notice the panic
+synchronously.
+
+The current owner might stay spinning. But non-panic() CPUs
+would get stopped anyway and the panic context will never start
+spinning.
+
+Fixes: dbdda842fe96 ("printk: Add console owner and waiter logic to load balance console writes")
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -1870,10 +1870,23 @@ static bool console_waiter;
+ */
+ static void console_lock_spinning_enable(void)
+ {
++ /*
++ * Do not use spinning in panic(). The panic CPU wants to keep the lock.
++ * Non-panic CPUs abandon the flush anyway.
++ *
++ * Just keep the lockdep annotation. The panic-CPU should avoid
++ * taking console_owner_lock because it might cause a deadlock.
++ * This looks like the easiest way how to prevent false lockdep
++ * reports without handling races a lockless way.
++ */
++ if (panic_in_progress())
++ goto lockdep;
++
+ raw_spin_lock(&console_owner_lock);
+ console_owner = current;
+ raw_spin_unlock(&console_owner_lock);
+
++lockdep:
+ /* The waiter may spin on us after setting console_owner */
+ spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
+ }
+@@ -1898,6 +1911,22 @@ static int console_lock_spinning_disable
+ {
+ int waiter;
+
++ /*
++ * Ignore spinning waiters during panic() because they might get stopped
++ * or blocked at any time,
++ *
++ * It is safe because nobody is allowed to start spinning during panic
++ * in the first place. If there has been a waiter then non panic CPUs
++ * might stay spinning. They would get stopped anyway. The panic context
++ * will never start spinning and an interrupted spin on panic CPU will
++ * never continue.
++ */
++ if (panic_in_progress()) {
++ /* Keep lockdep happy. */
++ spin_release(&console_owner_dep_map, _THIS_IP_);
++ return 0;
++ }
++
+ raw_spin_lock(&console_owner_lock);
+ waiter = READ_ONCE(console_waiter);
+ console_owner = NULL;
diff --git a/debian/patches-rt/0097-printk-Avoid-non-panic-CPUs-writing-to-ringbuffer.patch b/debian/patches-rt/0097-printk-Avoid-non-panic-CPUs-writing-to-ringbuffer.patch
new file mode 100644
index 0000000000..2f5a4ba17d
--- /dev/null
+++ b/debian/patches-rt/0097-printk-Avoid-non-panic-CPUs-writing-to-ringbuffer.patch
@@ -0,0 +1,78 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 20 Oct 2023 09:37:05 +0000
+Subject: [PATCH 097/134] printk: Avoid non-panic CPUs writing to ringbuffer
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Commit 13fb0f74d702 ("printk: Avoid livelock with heavy printk
+during panic") introduced a mechanism to silence non-panic CPUs
+if too many messages are being dropped. Aside from trying to
+workaround the livelock bugs of legacy consoles, it was also
+intended to avoid losing panic messages. However, if non-panic
+CPUs are writing to the ringbuffer, then reacting to dropped
+messages is too late.
+
+To avoid losing panic CPU messages, silence non-panic CPUs
+immediately on panic.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 26 ++++++--------------------
+ 1 file changed, 6 insertions(+), 20 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -462,12 +462,6 @@ static int console_msg_format = MSG_FORM
+ static DEFINE_MUTEX(syslog_lock);
+
+ #ifdef CONFIG_PRINTK
+-/*
+- * During panic, heavy printk by other CPUs can delay the
+- * panic and risk deadlock on console resources.
+- */
+-static int __read_mostly suppress_panic_printk;
+-
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+ /* All 3 protected by @syslog_lock. */
+ /* the next printk record to read by syslog(READ) or /proc/kmsg */
+@@ -2323,7 +2317,12 @@ asmlinkage int vprintk_emit(int facility
+ if (unlikely(suppress_printk))
+ return 0;
+
+- if (unlikely(suppress_panic_printk) && other_cpu_in_panic())
++ /*
++ * The messages on the panic CPU are the most important. If
++ * non-panic CPUs are generating any messages, they will be
++ * silently dropped.
++ */
++ if (other_cpu_in_panic())
+ return 0;
+
+ if (level == LOGLEVEL_SCHED) {
+@@ -2800,8 +2799,6 @@ void console_prepend_dropped(struct prin
+ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+ bool is_extended, bool may_suppress)
+ {
+- static int panic_console_dropped;
+-
+ struct printk_buffers *pbufs = pmsg->pbufs;
+ const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf);
+ const size_t outbuf_sz = sizeof(pbufs->outbuf);
+@@ -2829,17 +2826,6 @@ bool printk_get_next_message(struct prin
+ pmsg->seq = r.info->seq;
+ pmsg->dropped = r.info->seq - seq;
+
+- /*
+- * Check for dropped messages in panic here so that printk
+- * suppression can occur as early as possible if necessary.
+- */
+- if (pmsg->dropped &&
+- panic_in_progress() &&
+- panic_console_dropped++ > 10) {
+- suppress_panic_printk = 1;
+- pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
+- }
+-
+ /* Skip record that has level above the console loglevel. */
+ if (may_suppress && suppress_message_printing(r.info->level))
+ goto out;
diff --git a/debian/patches-rt/0098-panic-Flush-kernel-log-buffer-at-the-end.patch b/debian/patches-rt/0098-panic-Flush-kernel-log-buffer-at-the-end.patch
new file mode 100644
index 0000000000..ec3cbc5dd2
--- /dev/null
+++ b/debian/patches-rt/0098-panic-Flush-kernel-log-buffer-at-the-end.patch
@@ -0,0 +1,38 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Thu, 14 Dec 2023 20:48:23 +0000
+Subject: [PATCH 098/134] panic: Flush kernel log buffer at the end
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+If the kernel crashes in a context where printk() calls always
+defer printing (such as in NMI or inside a printk_safe section)
+then the final panic messages will be deferred to irq_work. But
+if irq_work is not available, the messages will not get printed
+unless explicitly flushed. The result is that the final
+"end Kernel panic" banner does not get printed.
+
+Add one final flush after the last printk() call to make sure
+the final panic messages make it out as well.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/panic.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -442,6 +442,14 @@ void panic(const char *fmt, ...)
+
+ /* Do not scroll important messages printed above */
+ suppress_printk = 1;
++
++ /*
++ * The final messages may not have been printed if in a context that
++ * defers printing (such as NMI) and irq_work is not available.
++ * Explicitly flush the kernel log buffer one last time.
++ */
++ console_flush_on_panic(CONSOLE_FLUSH_PENDING);
++
+ local_irq_enable();
+ for (i = 0; ; i += PANIC_TIMER_STEP) {
+ touch_softlockup_watchdog();
diff --git a/debian/patches-rt/0099-printk-Consider-nbcon-boot-consoles-on-seq-init.patch b/debian/patches-rt/0099-printk-Consider-nbcon-boot-consoles-on-seq-init.patch
new file mode 100644
index 0000000000..b4e61c7689
--- /dev/null
+++ b/debian/patches-rt/0099-printk-Consider-nbcon-boot-consoles-on-seq-init.patch
@@ -0,0 +1,51 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 22 Nov 2023 11:23:43 +0000
+Subject: [PATCH 099/134] printk: Consider nbcon boot consoles on seq init
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+If a non-boot console is registering and boot consoles exist, the
+consoles are flushed before being unregistered. This allows the
+non-boot console to continue where the boot console left off.
+
+If for whatever reason flushing fails, the lowest seq found from
+any of the enabled boot consoles is used. Until now con->seq was
+checked. However, if it is an nbcon boot console, the function
+nbcon_seq_read() must be used to read seq because con->seq is
+always 0.
+
+Check if it is an nbcon boot console and if so call
+nbcon_seq_read() to read seq.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3392,11 +3392,20 @@ static void console_init_seq(struct cons
+
+ newcon->seq = prb_next_seq(prb);
+ for_each_console(con) {
+- if ((con->flags & CON_BOOT) &&
+- (con->flags & CON_ENABLED) &&
+- con->seq < newcon->seq) {
+- newcon->seq = con->seq;
++ u64 seq;
++
++ if (!((con->flags & CON_BOOT) &&
++ (con->flags & CON_ENABLED))) {
++ continue;
+ }
++
++ if (con->flags & CON_NBCON)
++ seq = nbcon_seq_read(con);
++ else
++ seq = con->seq;
++
++ if (seq < newcon->seq)
++ newcon->seq = seq;
+ }
+ }
+
diff --git a/debian/patches-rt/0100-printk-Add-sparse-notation-to-console_srcu-locking.patch b/debian/patches-rt/0100-printk-Add-sparse-notation-to-console_srcu-locking.patch
new file mode 100644
index 0000000000..8a1473c93d
--- /dev/null
+++ b/debian/patches-rt/0100-printk-Add-sparse-notation-to-console_srcu-locking.patch
@@ -0,0 +1,36 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 9 Oct 2023 13:55:19 +0000
+Subject: [PATCH 100/134] printk: Add sparse notation to console_srcu locking
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+kernel/printk/printk.c:284:5: sparse: sparse: context imbalance in
+'console_srcu_read_lock' - wrong count at exit
+include/linux/srcu.h:301:9: sparse: sparse: context imbalance in
+'console_srcu_read_unlock' - unexpected unlock
+
+Reported-by: kernel test robot <lkp@intel.com>
+Fixes: 6c4afa79147e ("printk: Prepare for SRCU console list protection")
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -282,6 +282,7 @@ EXPORT_SYMBOL(console_list_unlock);
+ * Return: A cookie to pass to console_srcu_read_unlock().
+ */
+ int console_srcu_read_lock(void)
++ __acquires(&console_srcu)
+ {
+ return srcu_read_lock_nmisafe(&console_srcu);
+ }
+@@ -295,6 +296,7 @@ EXPORT_SYMBOL(console_srcu_read_lock);
+ * Counterpart to console_srcu_read_lock()
+ */
+ void console_srcu_read_unlock(int cookie)
++ __releases(&console_srcu)
+ {
+ srcu_read_unlock_nmisafe(&console_srcu, cookie);
+ }
diff --git a/debian/patches-rt/0101-printk-nbcon-Ensure-ownership-release-on-failed-emit.patch b/debian/patches-rt/0101-printk-nbcon-Ensure-ownership-release-on-failed-emit.patch
new file mode 100644
index 0000000000..d96f2dc2b9
--- /dev/null
+++ b/debian/patches-rt/0101-printk-nbcon-Ensure-ownership-release-on-failed-emit.patch
@@ -0,0 +1,58 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 20 Oct 2023 09:52:59 +0000
+Subject: [PATCH 101/134] printk: nbcon: Ensure ownership release on failed
+ emit
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Until now it was assumed that ownership has been lost when the
+write_atomic() callback fails. nbcon_emit_next_record() only
+returns false when ownership has been lost.
+
+Ensure ownership has been lost before reporting failure by
+explicitly attempting a release. If the current context is not
+the owner, the release has no effect.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/nbcon.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -852,7 +852,7 @@ static bool nbcon_emit_next_record(struc
+ unsigned long con_dropped;
+ struct nbcon_state cur;
+ unsigned long dropped;
+- bool done;
++ bool done = false;
+
+ /*
+ * The printk buffers are filled within an unsafe section. This
+@@ -891,17 +891,18 @@ static bool nbcon_emit_next_record(struc
+ nbcon_state_read(con, &cur);
+ wctxt->unsafe_takeover = cur.unsafe_takeover;
+
+- if (con->write_atomic) {
++ if (con->write_atomic)
+ done = con->write_atomic(con, wctxt);
+- } else {
+- nbcon_context_release(ctxt);
+- WARN_ON_ONCE(1);
+- done = false;
+- }
+
+- /* If not done, the emit was aborted. */
+- if (!done)
++ if (!done) {
++ /*
++ * The emit was aborted, probably due to a loss of ownership.
++ * Ensure ownership was lost or released before reporting the
++ * loss.
++ */
++ nbcon_context_release(ctxt);
+ return false;
++ }
+
+ /*
+ * Since any dropped message was successfully output, reset the
diff --git a/debian/patches-rt/0102-printk-Check-printk_deferred_enter-_exit-usage.patch b/debian/patches-rt/0102-printk-Check-printk_deferred_enter-_exit-usage.patch
new file mode 100644
index 0000000000..2e1d736ea7
--- /dev/null
+++ b/debian/patches-rt/0102-printk-Check-printk_deferred_enter-_exit-usage.patch
@@ -0,0 +1,58 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 22 Sep 2023 14:58:18 +0000
+Subject: [PATCH 102/134] printk: Check printk_deferred_enter()/_exit() usage
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add validation that printk_deferred_enter()/_exit() are called in
+non-migration contexts.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/printk.h | 7 +++++--
+ kernel/printk/printk_safe.c | 12 ++++++++++++
+ 2 files changed, 17 insertions(+), 2 deletions(-)
+
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -159,13 +159,16 @@ int _printk(const char *fmt, ...);
+
+ extern void __printk_safe_enter(void);
+ extern void __printk_safe_exit(void);
++extern void __printk_deferred_enter(void);
++extern void __printk_deferred_exit(void);
++
+ /*
+ * The printk_deferred_enter/exit macros are available only as a hack for
+ * some code paths that need to defer all printk console printing. Interrupts
+ * must be disabled for the deferred duration.
+ */
+-#define printk_deferred_enter __printk_safe_enter
+-#define printk_deferred_exit __printk_safe_exit
++#define printk_deferred_enter() __printk_deferred_enter()
++#define printk_deferred_exit() __printk_deferred_exit()
+
+ /*
+ * Please don't use printk_ratelimit(), because it shares ratelimiting state
+--- a/kernel/printk/printk_safe.c
++++ b/kernel/printk/printk_safe.c
+@@ -26,6 +26,18 @@ void __printk_safe_exit(void)
+ this_cpu_dec(printk_context);
+ }
+
++void __printk_deferred_enter(void)
++{
++ cant_migrate();
++ this_cpu_inc(printk_context);
++}
++
++void __printk_deferred_exit(void)
++{
++ cant_migrate();
++ this_cpu_dec(printk_context);
++}
++
+ asmlinkage int vprintk(const char *fmt, va_list args)
+ {
+ #ifdef CONFIG_KGDB_KDB
diff --git a/debian/patches-rt/0103-printk-nbcon-Implement-processing-in-port-lock-wrapp.patch b/debian/patches-rt/0103-printk-nbcon-Implement-processing-in-port-lock-wrapp.patch
new file mode 100644
index 0000000000..cee70cb44e
--- /dev/null
+++ b/debian/patches-rt/0103-printk-nbcon-Implement-processing-in-port-lock-wrapp.patch
@@ -0,0 +1,244 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 13 Sep 2023 08:35:23 +0000
+Subject: [PATCH 103/134] printk: nbcon: Implement processing in port->lock
+ wrapper
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Currently the port->lock wrappers uart_port_lock(),
+uart_port_unlock() (and their variants) only lock/unlock
+the spin_lock.
+
+If the port is an nbcon console, the wrappers must also
+acquire/release the console and mark the region as unsafe. This
+allows general port->lock synchronization to be synchronized
+with the nbcon console ownership.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 2 +
+ include/linux/printk.h | 13 +++++++
+ include/linux/serial_core.h | 18 +++++++++-
+ kernel/printk/nbcon.c | 77 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 108 insertions(+), 2 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -299,6 +299,7 @@ struct nbcon_write_context {
+ * @nbcon_state: State for nbcon consoles
+ * @nbcon_seq: Sequence number of the next record for nbcon to print
+ * @pbufs: Pointer to nbcon private buffer
++ * @locked_port: True, if the port lock is locked by nbcon
+ */
+ struct console {
+ char name[16];
+@@ -325,6 +326,7 @@ struct console {
+ atomic_t __private nbcon_state;
+ atomic_long_t __private nbcon_seq;
+ struct printk_buffers *pbufs;
++ bool locked_port;
+ };
+
+ #ifdef CONFIG_LOCKDEP
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -9,6 +9,8 @@
+ #include <linux/ratelimit_types.h>
+ #include <linux/once_lite.h>
+
++struct uart_port;
++
+ extern const char linux_banner[];
+ extern const char linux_proc_banner[];
+
+@@ -195,6 +197,8 @@ void show_regs_print_info(const char *lo
+ extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold;
+ extern asmlinkage void dump_stack(void) __cold;
+ void printk_trigger_flush(void);
++extern void nbcon_acquire(struct uart_port *up);
++extern void nbcon_release(struct uart_port *up);
+ #else
+ static inline __printf(1, 0)
+ int vprintk(const char *s, va_list args)
+@@ -274,6 +278,15 @@ static inline void dump_stack(void)
+ static inline void printk_trigger_flush(void)
+ {
+ }
++
++static inline void nbcon_acquire(struct uart_port *up)
++{
++}
++
++static inline void nbcon_release(struct uart_port *up)
++{
++}
++
+ #endif
+
+ #ifdef CONFIG_SMP
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -595,6 +595,7 @@ struct uart_port {
+ static inline void uart_port_lock(struct uart_port *up)
+ {
+ spin_lock(&up->lock);
++ nbcon_acquire(up);
+ }
+
+ /**
+@@ -604,6 +605,7 @@ static inline void uart_port_lock(struct
+ static inline void uart_port_lock_irq(struct uart_port *up)
+ {
+ spin_lock_irq(&up->lock);
++ nbcon_acquire(up);
+ }
+
+ /**
+@@ -614,6 +616,7 @@ static inline void uart_port_lock_irq(st
+ static inline void uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags)
+ {
+ spin_lock_irqsave(&up->lock, *flags);
++ nbcon_acquire(up);
+ }
+
+ /**
+@@ -624,7 +627,11 @@ static inline void uart_port_lock_irqsav
+ */
+ static inline bool uart_port_trylock(struct uart_port *up)
+ {
+- return spin_trylock(&up->lock);
++ if (!spin_trylock(&up->lock))
++ return false;
++
++ nbcon_acquire(up);
++ return true;
+ }
+
+ /**
+@@ -636,7 +643,11 @@ static inline bool uart_port_trylock(str
+ */
+ static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned long *flags)
+ {
+- return spin_trylock_irqsave(&up->lock, *flags);
++ if (!spin_trylock_irqsave(&up->lock, *flags))
++ return false;
++
++ nbcon_acquire(up);
++ return true;
+ }
+
+ /**
+@@ -645,6 +656,7 @@ static inline bool uart_port_trylock_irq
+ */
+ static inline void uart_port_unlock(struct uart_port *up)
+ {
++ nbcon_release(up);
+ spin_unlock(&up->lock);
+ }
+
+@@ -654,6 +666,7 @@ static inline void uart_port_unlock(stru
+ */
+ static inline void uart_port_unlock_irq(struct uart_port *up)
+ {
++ nbcon_release(up);
+ spin_unlock_irq(&up->lock);
+ }
+
+@@ -664,6 +677,7 @@ static inline void uart_port_unlock_irq(
+ */
+ static inline void uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags)
+ {
++ nbcon_release(up);
+ spin_unlock_irqrestore(&up->lock, flags);
+ }
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -6,6 +6,7 @@
+ #include <linux/console.h>
+ #include <linux/delay.h>
+ #include <linux/slab.h>
++#include <linux/serial_core.h>
+ #include "internal.h"
+ /*
+ * Printk console printing implementation for consoles which does not depend
+@@ -995,3 +996,79 @@ void nbcon_free(struct console *con)
+
+ con->pbufs = NULL;
+ }
++
++static inline bool uart_is_nbcon(struct uart_port *up)
++{
++ int cookie;
++ bool ret;
++
++ if (!uart_console(up))
++ return false;
++
++ cookie = console_srcu_read_lock();
++ ret = (console_srcu_read_flags(up->cons) & CON_NBCON);
++ console_srcu_read_unlock(cookie);
++ return ret;
++}
++
++/**
++ * nbcon_acquire - The second half of the port locking wrapper
++ * @up: The uart port whose @lock was locked
++ *
++ * The uart_port_lock() wrappers will first lock the spin_lock @up->lock.
++ * Then this function is called to implement nbcon-specific processing.
++ *
++ * If @up is an nbcon console, this console will be acquired and marked as
++ * unsafe. Otherwise this function does nothing.
++ */
++void nbcon_acquire(struct uart_port *up)
++{
++ struct console *con = up->cons;
++ struct nbcon_context ctxt;
++
++ if (!uart_is_nbcon(up))
++ return;
++
++ WARN_ON_ONCE(con->locked_port);
++
++ do {
++ do {
++ memset(&ctxt, 0, sizeof(ctxt));
++ ctxt.console = con;
++ ctxt.prio = NBCON_PRIO_NORMAL;
++ } while (!nbcon_context_try_acquire(&ctxt));
++
++ } while (!nbcon_context_enter_unsafe(&ctxt));
++
++ con->locked_port = true;
++}
++EXPORT_SYMBOL_GPL(nbcon_acquire);
++
++/**
++ * nbcon_release - The first half of the port unlocking wrapper
++ * @up: The uart port whose @lock is about to be unlocked
++ *
++ * The uart_port_unlock() wrappers will first call this function to implement
++ * nbcon-specific processing. Then afterwards the uart_port_unlock() wrappers
++ * will unlock the spin_lock @up->lock.
++ *
++ * If @up is an nbcon console, the console will be marked as safe and
++ * released. Otherwise this function does nothing.
++ */
++void nbcon_release(struct uart_port *up)
++{
++ struct console *con = up->cons;
++ struct nbcon_context ctxt = {
++ .console = con,
++ .prio = NBCON_PRIO_NORMAL,
++ };
++
++ if (!con->locked_port)
++ return;
++
++ if (nbcon_context_exit_unsafe(&ctxt))
++ nbcon_context_release(&ctxt);
++
++ con->locked_port = false;
++}
++EXPORT_SYMBOL_GPL(nbcon_release);
diff --git a/debian/patches-rt/0104-printk-nbcon-Add-driver_enter-driver_exit-console-ca.patch b/debian/patches-rt/0104-printk-nbcon-Add-driver_enter-driver_exit-console-ca.patch
new file mode 100644
index 0000000000..d314cb53d4
--- /dev/null
+++ b/debian/patches-rt/0104-printk-nbcon-Add-driver_enter-driver_exit-console-ca.patch
@@ -0,0 +1,42 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 8 Dec 2023 15:54:27 +0000
+Subject: [PATCH 104/134] printk: nbcon: Add driver_enter/driver_exit console
+ callbacks
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Console drivers need some mechanism to synchronize between "normal
+driver activity" and console printing. For uart serial drivers it
+is the port lock. Other types of console drivers (network,
+graphics, USB) will need something as well.
+
+Provide 2 new mandatory nbcon console callbacks (driver_enter and
+driver_exit) to allow the consoles drivers to implement the
+appropriate synchronization. The callbacks are also expected to
+disable/enable migration.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -296,6 +296,8 @@ struct nbcon_write_context {
+ * @node: hlist node for the console list
+ *
+ * @write_atomic: Write callback for atomic context
++ * @driver_enter: Callback to begin synchronization with driver code
++ * @driver_exit: Callback to finish synchronization with driver code
+ * @nbcon_state: State for nbcon consoles
+ * @nbcon_seq: Sequence number of the next record for nbcon to print
+ * @pbufs: Pointer to nbcon private buffer
+@@ -323,6 +325,8 @@ struct console {
+ /* nbcon console specific members */
+ bool (*write_atomic)(struct console *con,
+ struct nbcon_write_context *wctxt);
++ void (*driver_enter)(struct console *con, unsigned long *flags);
++ void (*driver_exit)(struct console *con, unsigned long flags);
+ atomic_t __private nbcon_state;
+ atomic_long_t __private nbcon_seq;
+ struct printk_buffers *pbufs;
diff --git a/debian/patches-rt/0105-printk-Make-console_is_usable-available-to-nbcon.patch b/debian/patches-rt/0105-printk-Make-console_is_usable-available-to-nbcon.patch
new file mode 100644
index 0000000000..a0bf51492a
--- /dev/null
+++ b/debian/patches-rt/0105-printk-Make-console_is_usable-available-to-nbcon.patch
@@ -0,0 +1,103 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 12 Sep 2023 13:25:41 +0000
+Subject: [PATCH 105/134] printk: Make console_is_usable() available to nbcon
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Move console_is_usable() as-is into internal.h so that it can
+be used by nbcon printing functions as well.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 32 ++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 30 ------------------------------
+ 2 files changed, 32 insertions(+), 30 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -78,6 +78,36 @@ bool nbcon_alloc(struct console *con);
+ void nbcon_init(struct console *con);
+ void nbcon_free(struct console *con);
+
++/*
++ * Check if the given console is currently capable and allowed to print
++ * records.
++ *
++ * Requires the console_srcu_read_lock.
++ */
++static inline bool console_is_usable(struct console *con)
++{
++ short flags = console_srcu_read_flags(con);
++
++ if (!(flags & CON_ENABLED))
++ return false;
++
++ if ((flags & CON_SUSPENDED))
++ return false;
++
++ if (!con->write)
++ return false;
++
++ /*
++ * Console drivers may assume that per-cpu resources have been
++ * allocated. So unless they're explicitly marked as being able to
++ * cope (CON_ANYTIME) don't call them until this CPU is officially up.
++ */
++ if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME))
++ return false;
++
++ return true;
++}
++
+ #else
+
+ #define PRINTK_PREFIX_MAX 0
+@@ -99,6 +129,8 @@ static inline bool nbcon_alloc(struct co
+ static inline void nbcon_init(struct console *con) { }
+ static inline void nbcon_free(struct console *con) { }
+
++static inline bool console_is_usable(struct console *con) { return false; }
++
+ #endif /* CONFIG_PRINTK */
+
+ extern struct printk_buffers printk_shared_pbufs;
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2695,36 +2695,6 @@ int is_console_locked(void)
+ }
+ EXPORT_SYMBOL(is_console_locked);
+
+-/*
+- * Check if the given console is currently capable and allowed to print
+- * records.
+- *
+- * Requires the console_srcu_read_lock.
+- */
+-static inline bool console_is_usable(struct console *con)
+-{
+- short flags = console_srcu_read_flags(con);
+-
+- if (!(flags & CON_ENABLED))
+- return false;
+-
+- if ((flags & CON_SUSPENDED))
+- return false;
+-
+- if (!con->write)
+- return false;
+-
+- /*
+- * Console drivers may assume that per-cpu resources have been
+- * allocated. So unless they're explicitly marked as being able to
+- * cope (CON_ANYTIME) don't call them until this CPU is officially up.
+- */
+- if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME))
+- return false;
+-
+- return true;
+-}
+-
+ static void __console_unlock(void)
+ {
+ console_locked = 0;
diff --git a/debian/patches-rt/0106-printk-Let-console_is_usable-handle-nbcon.patch b/debian/patches-rt/0106-printk-Let-console_is_usable-handle-nbcon.patch
new file mode 100644
index 0000000000..62a776cf2f
--- /dev/null
+++ b/debian/patches-rt/0106-printk-Let-console_is_usable-handle-nbcon.patch
@@ -0,0 +1,43 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 12 Sep 2023 13:53:21 +0000
+Subject: [PATCH 106/134] printk: Let console_is_usable() handle nbcon
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The nbcon consoles use a different printing callback. For nbcon
+consoles, check for the write_atomic() callback instead of
+write().
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -80,6 +80,8 @@ void nbcon_free(struct console *con);
+
+ /*
+ * Check if the given console is currently capable and allowed to print
++ * records. Note that this function does not consider the current context,
++ * which can also play a role in deciding if @con can be used to print
+ * records.
+ *
+ * Requires the console_srcu_read_lock.
+@@ -94,8 +96,13 @@ static inline bool console_is_usable(str
+ if ((flags & CON_SUSPENDED))
+ return false;
+
+- if (!con->write)
+- return false;
++ if (flags & CON_NBCON) {
++ if (!con->write_atomic)
++ return false;
++ } else {
++ if (!con->write)
++ return false;
++ }
+
+ /*
+ * Console drivers may assume that per-cpu resources have been
diff --git a/debian/patches-rt/0107-printk-Add-flags-argument-for-console_is_usable.patch b/debian/patches-rt/0107-printk-Add-flags-argument-for-console_is_usable.patch
new file mode 100644
index 0000000000..e8c4b4a739
--- /dev/null
+++ b/debian/patches-rt/0107-printk-Add-flags-argument-for-console_is_usable.patch
@@ -0,0 +1,67 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 12 Sep 2023 13:45:33 +0000
+Subject: [PATCH 107/134] printk: Add @flags argument for console_is_usable()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The caller of console_is_usable() usually needs @console->flags
+for its own checks. Rather than having console_is_usable() read
+its own copy, make the caller pass in the @flags. This also
+ensures that the caller saw the same @flags value.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 8 ++------
+ kernel/printk/printk.c | 5 +++--
+ 2 files changed, 5 insertions(+), 8 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -83,13 +83,9 @@ void nbcon_free(struct console *con);
+ * records. Note that this function does not consider the current context,
+ * which can also play a role in deciding if @con can be used to print
+ * records.
+- *
+- * Requires the console_srcu_read_lock.
+ */
+-static inline bool console_is_usable(struct console *con)
++static inline bool console_is_usable(struct console *con, short flags)
+ {
+- short flags = console_srcu_read_flags(con);
+-
+ if (!(flags & CON_ENABLED))
+ return false;
+
+@@ -136,7 +132,7 @@ static inline bool nbcon_alloc(struct co
+ static inline void nbcon_init(struct console *con) { }
+ static inline void nbcon_free(struct console *con) { }
+
+-static inline bool console_is_usable(struct console *con) { return false; }
++static inline bool console_is_usable(struct console *con, short flags) { return false; }
+
+ #endif /* CONFIG_PRINTK */
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2940,9 +2940,10 @@ static bool console_flush_all(bool do_co
+
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(con) {
++ short flags = console_srcu_read_flags(con);
+ bool progress;
+
+- if (!console_is_usable(con))
++ if (!console_is_usable(con, flags))
+ continue;
+ any_usable = true;
+
+@@ -3784,7 +3785,7 @@ static bool __pr_flush(struct console *c
+ * that they make forward progress, so only increment
+ * @diff for usable consoles.
+ */
+- if (!console_is_usable(c))
++ if (!console_is_usable(c, flags))
+ continue;
+
+ if (flags & CON_NBCON) {
diff --git a/debian/patches-rt/0108-printk-nbcon-Provide-function-to-flush-using-write_a.patch b/debian/patches-rt/0108-printk-nbcon-Provide-function-to-flush-using-write_a.patch
new file mode 100644
index 0000000000..14933eef67
--- /dev/null
+++ b/debian/patches-rt/0108-printk-nbcon-Provide-function-to-flush-using-write_a.patch
@@ -0,0 +1,186 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 12 Sep 2023 12:00:08 +0000
+Subject: [PATCH 108/134] printk: nbcon: Provide function to flush using
+ write_atomic()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Provide nbcon_atomic_flush_all() to perform flushing of all
+registered nbcon consoles using their write_atomic() callback.
+Like with legacy consoles, the nbcon consoles are flushed one
+record per console. This allows all nbcon consoles to print
+lines pseudo-simultaneously, rather than one console waiting
+for the full ringbuffer to dump to another console before
+printing anything.
+
+Unlike console_flush_all(), nbcon_atomic_flush_all() will only
+flush up through the newest record at the time of the call.
+This prevents a CPU from printing unbounded when other CPUs are
+adding records.
+
+Perform nbcon console atomic flushing in
+console_flush_on_panic(). This function is not only used in
+panic() but also other locations where there may be stored
+messages that need to be flushed.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 2
+ kernel/printk/nbcon.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++-
+ kernel/printk/printk.c | 2
+ 3 files changed, 102 insertions(+), 2 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -77,6 +77,7 @@ void nbcon_seq_force(struct console *con
+ bool nbcon_alloc(struct console *con);
+ void nbcon_init(struct console *con);
+ void nbcon_free(struct console *con);
++void nbcon_atomic_flush_all(void);
+
+ /*
+ * Check if the given console is currently capable and allowed to print
+@@ -131,6 +132,7 @@ static inline void nbcon_seq_force(struc
+ static inline bool nbcon_alloc(struct console *con) { return false; }
+ static inline void nbcon_init(struct console *con) { }
+ static inline void nbcon_free(struct console *con) { }
++static inline void nbcon_atomic_flush_all(void) { }
+
+ static inline bool console_is_usable(struct console *con, short flags) { return false; }
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -539,7 +539,6 @@ static struct printk_buffers panic_nbcon
+ * in an unsafe state. Otherwise, on success the caller may assume
+ * the console is not in an unsafe state.
+ */
+-__maybe_unused
+ static bool nbcon_context_try_acquire(struct nbcon_context *ctxt)
+ {
+ unsigned int cpu = smp_processor_id();
+@@ -841,7 +840,6 @@ EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
+ * When true is returned, @wctxt->ctxt.backlog indicates whether there are
+ * still records pending in the ringbuffer,
+ */
+-__maybe_unused
+ static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt)
+ {
+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
+@@ -931,6 +929,104 @@ static bool nbcon_emit_next_record(struc
+ }
+
+ /**
++ * nbcon_atomic_emit_one - Print one record for an nbcon console using the
++ * write_atomic() callback
++ * @wctxt: An initialized write context struct to use
++ * for this context
++ *
++ * Return: False if the given console could not print a record or there
++ * are no more records to print, otherwise true.
++ *
++ * This is an internal helper to handle the locking of the console before
++ * calling nbcon_emit_next_record().
++ */
++static bool nbcon_atomic_emit_one(struct nbcon_write_context *wctxt)
++{
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
++
++ if (!nbcon_context_try_acquire(ctxt))
++ return false;
++
++ /*
++ * nbcon_emit_next_record() returns false when the console was
++ * handed over or taken over. In both cases the context is no
++ * longer valid.
++ */
++ if (!nbcon_emit_next_record(wctxt))
++ return false;
++
++ nbcon_context_release(ctxt);
++
++ return ctxt->backlog;
++}
++
++/**
++ * __nbcon_atomic_flush_all - Flush all nbcon consoles using their
++ * write_atomic() callback
++ * @stop_seq: Flush up until this record
++ */
++static void __nbcon_atomic_flush_all(u64 stop_seq)
++{
++ struct nbcon_write_context wctxt = { };
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt);
++ struct console *con;
++ bool any_progress;
++ int cookie;
++
++ do {
++ any_progress = false;
++
++ cookie = console_srcu_read_lock();
++ for_each_console_srcu(con) {
++ short flags = console_srcu_read_flags(con);
++ unsigned long irq_flags;
++
++ if (!(flags & CON_NBCON))
++ continue;
++
++ if (!console_is_usable(con, flags))
++ continue;
++
++ if (nbcon_seq_read(con) >= stop_seq)
++ continue;
++
++ memset(ctxt, 0, sizeof(*ctxt));
++ ctxt->console = con;
++ ctxt->spinwait_max_us = 2000;
++ ctxt->prio = NBCON_PRIO_NORMAL;
++
++ /*
++ * Atomic flushing does not use console driver
++ * synchronization (i.e. it does not hold the port
++ * lock for uart consoles). Therefore IRQs must be
++ * disabled to avoid being interrupted and then
++ * calling into a driver that will deadlock trying
++ * acquire console ownership.
++ */
++ local_irq_save(irq_flags);
++
++ any_progress |= nbcon_atomic_emit_one(&wctxt);
++
++ local_irq_restore(irq_flags);
++ }
++ console_srcu_read_unlock(cookie);
++ } while (any_progress);
++}
++
++/**
++ * nbcon_atomic_flush_all - Flush all nbcon consoles using their
++ * write_atomic() callback
++ *
++ * Flush the backlog up through the currently newest record. Any new
++ * records added while flushing will not be flushed. This is to avoid
++ * one CPU printing unbounded because other CPUs continue to add records.
++ */
++void nbcon_atomic_flush_all(void)
++{
++ __nbcon_atomic_flush_all(prb_next_reserve_seq(prb));
++}
++
++/**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+ *
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3170,6 +3170,8 @@ void console_flush_on_panic(enum con_flu
+ console_srcu_read_unlock(cookie);
+ }
+
++ nbcon_atomic_flush_all();
++
+ console_flush_all(false, &next_seq, &handover);
+ }
+
diff --git a/debian/patches-rt/0109-printk-Track-registered-boot-consoles.patch b/debian/patches-rt/0109-printk-Track-registered-boot-consoles.patch
new file mode 100644
index 0000000000..51b866f20f
--- /dev/null
+++ b/debian/patches-rt/0109-printk-Track-registered-boot-consoles.patch
@@ -0,0 +1,78 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 24 Oct 2023 14:13:14 +0000
+Subject: [PATCH 109/134] printk: Track registered boot consoles
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Unfortunately it is not known if a boot console and a regular
+(legacy or nbcon) console use the same hardware. For this reason
+they must not be allowed to print simultaneously.
+
+For legacy consoles this is not an issue because they are
+already synchronized with the boot consoles using the console
+lock. However nbcon consoles can be triggered separately.
+
+Add a global flag @have_boot_console to identify if any boot
+consoles are registered. This will be used in follow-up commits
+to ensure that boot consoles and nbcon consoles cannot print
+simultaneously.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -463,6 +463,14 @@ static int console_msg_format = MSG_FORM
+ /* syslog_lock protects syslog_* variables and write access to clear_seq. */
+ static DEFINE_MUTEX(syslog_lock);
+
++/*
++ * Specifies if a boot console is registered. If boot consoles are present,
++ * nbcon consoles cannot print simultaneously and must be synchronized by
++ * the console lock. This is because boot consoles and nbcon consoles may
++ * have mapped the same hardware.
++ */
++bool have_boot_console;
++
+ #ifdef CONFIG_PRINTK
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+ /* All 3 protected by @syslog_lock. */
+@@ -3500,6 +3508,9 @@ void register_console(struct console *ne
+ if (newcon->flags & CON_NBCON)
+ nbcon_init(newcon);
+
++ if (newcon->flags & CON_BOOT)
++ have_boot_console = true;
++
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+@@ -3552,6 +3563,8 @@ EXPORT_SYMBOL(register_console);
+ /* Must be called under console_list_lock(). */
+ static int unregister_console_locked(struct console *console)
+ {
++ bool found_boot_con = false;
++ struct console *c;
+ int res;
+
+ lockdep_assert_console_list_lock_held();
+@@ -3599,6 +3612,17 @@ static int unregister_console_locked(str
+ if (console->exit)
+ res = console->exit(console);
+
++ /*
++ * With this console gone, the global flags tracking registered
++ * console types may have changed. Update them.
++ */
++ for_each_console(c) {
++ if (c->flags & CON_BOOT)
++ found_boot_con = true;
++ }
++ if (!found_boot_con)
++ have_boot_console = false;
++
+ return res;
+ }
+
diff --git a/debian/patches-rt/0110-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch b/debian/patches-rt/0110-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch
new file mode 100644
index 0000000000..b46ecd7655
--- /dev/null
+++ b/debian/patches-rt/0110-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch
@@ -0,0 +1,173 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 19 Sep 2023 14:33:27 +0000
+Subject: [PATCH 110/134] printk: nbcon: Use nbcon consoles in
+ console_flush_all()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Allow nbcon consoles to print messages in the printk() caller
+context by integrating them into console_flush_all(). The
+write_atomic() callback is used for printing.
+
+Provide nbcon_console_emit_next_record(), which acts as the
+nbcon variant of console_emit_next_record(). Call this variant
+within console_flush_all() for nbcon consoles. Since nbcon
+consoles use their own @nbcon_seq variable to track the next
+record to print, this also must be appropriately handled.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 5 ++++
+ kernel/printk/nbcon.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 19 +++++++++++++----
+ 3 files changed, 69 insertions(+), 5 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -71,6 +71,8 @@ void defer_console_output(void);
+
+ u16 printk_parse_prefix(const char *text, int *level,
+ enum printk_info_flags *flags);
++void console_lock_spinning_enable(void);
++int console_lock_spinning_disable_and_check(int cookie);
+
+ u64 nbcon_seq_read(struct console *con);
+ void nbcon_seq_force(struct console *con, u64 seq);
+@@ -78,6 +80,7 @@ bool nbcon_alloc(struct console *con);
+ void nbcon_init(struct console *con);
+ void nbcon_free(struct console *con);
+ void nbcon_atomic_flush_all(void);
++bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie);
+
+ /*
+ * Check if the given console is currently capable and allowed to print
+@@ -133,6 +136,8 @@ static inline bool nbcon_alloc(struct co
+ static inline void nbcon_init(struct console *con) { }
+ static inline void nbcon_free(struct console *con) { }
+ static inline void nbcon_atomic_flush_all(void) { }
++static inline bool nbcon_atomic_emit_next_record(struct console *con, bool *handover,
++ int cookie) { return false; }
+
+ static inline bool console_is_usable(struct console *con, short flags) { return false; }
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -532,6 +532,7 @@ static struct printk_buffers panic_nbcon
+ * nbcon_context_try_acquire - Try to acquire nbcon console
+ * @ctxt: The context of the caller
+ *
++ * Context: Any context which could not be migrated to another CPU.
+ * Return: True if the console was acquired. False otherwise.
+ *
+ * If the caller allowed an unsafe hostile takeover, on success the
+@@ -961,6 +962,55 @@ static bool nbcon_atomic_emit_one(struct
+ }
+
+ /**
++ * nbcon_atomic_emit_next_record - Print one record for an nbcon console
++ * using the write_atomic() callback
++ * @con: The console to print on
++ * @handover: Will be set to true if a printk waiter has taken over the
++ * console_lock, in which case the caller is no longer holding
++ * both the console_lock and the SRCU read lock. Otherwise it
++ * is set to false.
++ * @cookie: The cookie from the SRCU read lock.
++ *
++ * Context: Any context which could not be migrated to another CPU.
++ * Return: True if a record could be printed, otherwise false.
++ *
++ * This function is meant to be called by console_flush_all() to print records
++ * on nbcon consoles using the write_atomic() callback. Essentially it is the
++ * nbcon version of console_emit_next_record().
++ */
++bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie)
++{
++ struct nbcon_write_context wctxt = { };
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt);
++ unsigned long driver_flags;
++ bool progress = false;
++ unsigned long flags;
++
++ *handover = false;
++
++ /* Use the same locking order as console_emit_next_record(). */
++ printk_safe_enter_irqsave(flags);
++ console_lock_spinning_enable();
++ stop_critical_timings();
++
++ con->driver_enter(con, &driver_flags);
++ cant_migrate();
++
++ ctxt->console = con;
++ ctxt->prio = NBCON_PRIO_NORMAL;
++
++ progress = nbcon_atomic_emit_one(&wctxt);
++
++ con->driver_exit(con, driver_flags);
++
++ start_critical_timings();
++ *handover = console_lock_spinning_disable_and_check(cookie);
++ printk_safe_exit_irqrestore(flags);
++
++ return progress;
++}
++
++/**
+ * __nbcon_atomic_flush_all - Flush all nbcon consoles using their
+ * write_atomic() callback
+ * @stop_seq: Flush up until this record
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -1872,7 +1872,7 @@ static bool console_waiter;
+ * there may be a waiter spinning (like a spinlock). Also it must be
+ * ready to hand over the lock at the end of the section.
+ */
+-static void console_lock_spinning_enable(void)
++void console_lock_spinning_enable(void)
+ {
+ /*
+ * Do not use spinning in panic(). The panic CPU wants to keep the lock.
+@@ -1911,7 +1911,7 @@ static void console_lock_spinning_enable
+ *
+ * Return: 1 if the lock rights were passed, 0 otherwise.
+ */
+-static int console_lock_spinning_disable_and_check(int cookie)
++int console_lock_spinning_disable_and_check(int cookie)
+ {
+ int waiter;
+
+@@ -2949,13 +2949,22 @@ static bool console_flush_all(bool do_co
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(con) {
+ short flags = console_srcu_read_flags(con);
++ u64 printk_seq;
+ bool progress;
+
+ if (!console_is_usable(con, flags))
+ continue;
+ any_usable = true;
+
+- progress = console_emit_next_record(con, handover, cookie);
++ if (flags & CON_NBCON) {
++ progress = nbcon_atomic_emit_next_record(con, handover, cookie);
++
++ printk_seq = nbcon_seq_read(con);
++ } else {
++ progress = console_emit_next_record(con, handover, cookie);
++
++ printk_seq = con->seq;
++ }
+
+ /*
+ * If a handover has occurred, the SRCU read lock
+@@ -2965,8 +2974,8 @@ static bool console_flush_all(bool do_co
+ return false;
+
+ /* Track the next of the highest seq flushed. */
+- if (con->seq > *next_seq)
+- *next_seq = con->seq;
++ if (printk_seq > *next_seq)
++ *next_seq = printk_seq;
+
+ if (!progress)
+ continue;
diff --git a/debian/patches-rt/0111-printk-nbcon-Assign-priority-based-on-CPU-state.patch b/debian/patches-rt/0111-printk-nbcon-Assign-priority-based-on-CPU-state.patch
new file mode 100644
index 0000000000..7e826c3e49
--- /dev/null
+++ b/debian/patches-rt/0111-printk-nbcon-Assign-priority-based-on-CPU-state.patch
@@ -0,0 +1,113 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Thu, 14 Dec 2023 14:38:42 +0000
+Subject: [PATCH 111/134] printk: nbcon: Assign priority based on CPU state
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Use the current state of the CPU to determine which priority to
+assign to the printing context.
+
+Note: The uart_port wrapper, which is responsible for non-console-
+ printing activities, will always use NORMAL priority.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 2 ++
+ kernel/printk/nbcon.c | 30 ++++++++++++++++++++++++++++--
+ 2 files changed, 30 insertions(+), 2 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -79,6 +79,7 @@ void nbcon_seq_force(struct console *con
+ bool nbcon_alloc(struct console *con);
+ void nbcon_init(struct console *con);
+ void nbcon_free(struct console *con);
++enum nbcon_prio nbcon_get_default_prio(void);
+ void nbcon_atomic_flush_all(void);
+ bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie);
+
+@@ -135,6 +136,7 @@ static inline void nbcon_seq_force(struc
+ static inline bool nbcon_alloc(struct console *con) { return false; }
+ static inline void nbcon_init(struct console *con) { }
+ static inline void nbcon_free(struct console *con) { }
++static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; }
+ static inline void nbcon_atomic_flush_all(void) { }
+ static inline bool nbcon_atomic_emit_next_record(struct console *con, bool *handover,
+ int cookie) { return false; }
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -962,6 +962,22 @@ static bool nbcon_atomic_emit_one(struct
+ }
+
+ /**
++ * nbcon_get_default_prio - The appropriate nbcon priority to use for nbcon
++ * printing on the current CPU
++ *
++ * Context: Any context which could not be migrated to another CPU.
++ * Return: The nbcon_prio to use for acquiring an nbcon console in this
++ * context for printing.
++ */
++enum nbcon_prio nbcon_get_default_prio(void)
++{
++ if (this_cpu_in_panic())
++ return NBCON_PRIO_PANIC;
++
++ return NBCON_PRIO_NORMAL;
++}
++
++/**
+ * nbcon_atomic_emit_next_record - Print one record for an nbcon console
+ * using the write_atomic() callback
+ * @con: The console to print on
+@@ -997,7 +1013,7 @@ bool nbcon_atomic_emit_next_record(struc
+ cant_migrate();
+
+ ctxt->console = con;
+- ctxt->prio = NBCON_PRIO_NORMAL;
++ ctxt->prio = nbcon_get_default_prio();
+
+ progress = nbcon_atomic_emit_one(&wctxt);
+
+@@ -1043,7 +1059,6 @@ static void __nbcon_atomic_flush_all(u64
+ memset(ctxt, 0, sizeof(*ctxt));
+ ctxt->console = con;
+ ctxt->spinwait_max_us = 2000;
+- ctxt->prio = NBCON_PRIO_NORMAL;
+
+ /*
+ * Atomic flushing does not use console driver
+@@ -1052,9 +1067,14 @@ static void __nbcon_atomic_flush_all(u64
+ * disabled to avoid being interrupted and then
+ * calling into a driver that will deadlock trying
+ * acquire console ownership.
++ *
++ * This also disables migration in order to get the
++ * current CPU priority.
+ */
+ local_irq_save(irq_flags);
+
++ ctxt->prio = nbcon_get_default_prio();
++
+ any_progress |= nbcon_atomic_emit_one(&wctxt);
+
+ local_irq_restore(irq_flags);
+@@ -1166,6 +1186,9 @@ static inline bool uart_is_nbcon(struct
+ *
+ * If @up is an nbcon console, this console will be acquired and marked as
+ * unsafe. Otherwise this function does nothing.
++ *
++ * nbcon consoles acquired via the port lock wrapper always use priority
++ * NBCON_PRIO_NORMAL.
+ */
+ void nbcon_acquire(struct uart_port *up)
+ {
+@@ -1200,6 +1223,9 @@ EXPORT_SYMBOL_GPL(nbcon_acquire);
+ *
+ * If @up is an nbcon console, the console will be marked as safe and
+ * released. Otherwise this function does nothing.
++ *
++ * nbcon consoles acquired via the port lock wrapper always use priority
++ * NBCON_PRIO_NORMAL.
+ */
+ void nbcon_release(struct uart_port *up)
+ {
diff --git a/debian/patches-rt/0112-printk-nbcon-Add-unsafe-flushing-on-panic.patch b/debian/patches-rt/0112-printk-nbcon-Add-unsafe-flushing-on-panic.patch
new file mode 100644
index 0000000000..cc689de08e
--- /dev/null
+++ b/debian/patches-rt/0112-printk-nbcon-Add-unsafe-flushing-on-panic.patch
@@ -0,0 +1,96 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 20 Oct 2023 10:03:42 +0000
+Subject: [PATCH 112/134] printk: nbcon: Add unsafe flushing on panic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add nbcon_atomic_flush_unsafe() to flush all nbcon consoles
+using the write_atomic() callback and allowing unsafe hostile
+takeovers. Call this at the end of panic() as a final attempt
+to flush any pending messages.
+
+Note that legacy consoles use unsafe methods for flushing
+from the beginning of panic (see bust_spinlocks()). Therefore,
+systems using both legacy and nbcon consoles may still fail to
+see panic messages due to unsafe legacy console usage.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/printk.h | 5 +++++
+ kernel/panic.c | 1 +
+ kernel/printk/nbcon.c | 18 ++++++++++++++++--
+ 3 files changed, 22 insertions(+), 2 deletions(-)
+
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -199,6 +199,7 @@ extern asmlinkage void dump_stack(void)
+ void printk_trigger_flush(void);
+ extern void nbcon_acquire(struct uart_port *up);
+ extern void nbcon_release(struct uart_port *up);
++void nbcon_atomic_flush_unsafe(void);
+ #else
+ static inline __printf(1, 0)
+ int vprintk(const char *s, va_list args)
+@@ -287,6 +288,10 @@ static inline void nbcon_release(struct
+ {
+ }
+
++static inline void nbcon_atomic_flush_unsafe(void)
++{
++}
++
+ #endif
+
+ #ifdef CONFIG_SMP
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -449,6 +449,7 @@ void panic(const char *fmt, ...)
+ * Explicitly flush the kernel log buffer one last time.
+ */
+ console_flush_on_panic(CONSOLE_FLUSH_PENDING);
++ nbcon_atomic_flush_unsafe();
+
+ local_irq_enable();
+ for (i = 0; ; i += PANIC_TIMER_STEP) {
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -1030,8 +1030,9 @@ bool nbcon_atomic_emit_next_record(struc
+ * __nbcon_atomic_flush_all - Flush all nbcon consoles using their
+ * write_atomic() callback
+ * @stop_seq: Flush up until this record
++ * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers
+ */
+-static void __nbcon_atomic_flush_all(u64 stop_seq)
++static void __nbcon_atomic_flush_all(u64 stop_seq, bool allow_unsafe_takeover)
+ {
+ struct nbcon_write_context wctxt = { };
+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt);
+@@ -1059,6 +1060,7 @@ static void __nbcon_atomic_flush_all(u64
+ memset(ctxt, 0, sizeof(*ctxt));
+ ctxt->console = con;
+ ctxt->spinwait_max_us = 2000;
++ ctxt->allow_unsafe_takeover = allow_unsafe_takeover;
+
+ /*
+ * Atomic flushing does not use console driver
+@@ -1093,7 +1095,19 @@ static void __nbcon_atomic_flush_all(u64
+ */
+ void nbcon_atomic_flush_all(void)
+ {
+- __nbcon_atomic_flush_all(prb_next_reserve_seq(prb));
++ __nbcon_atomic_flush_all(prb_next_reserve_seq(prb), false);
++}
++
++/**
++ * nbcon_atomic_flush_unsafe - Flush all nbcon consoles using their
++ * write_atomic() callback and allowing unsafe hostile takeovers
++ *
++ * Flush the backlog up through the currently newest record. Unsafe hostile
++ * takeovers will be performed, if necessary.
++ */
++void nbcon_atomic_flush_unsafe(void)
++{
++ __nbcon_atomic_flush_all(prb_next_reserve_seq(prb), true);
+ }
+
+ /**
diff --git a/debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch b/debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch
new file mode 100644
index 0000000000..a733638677
--- /dev/null
+++ b/debian/patches-rt/0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch
@@ -0,0 +1,211 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 26 Sep 2023 12:44:07 +0000
+Subject: [PATCH 113/134] printk: Avoid console_lock dance if no legacy or boot
+ consoles
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Currently the console lock is used to attempt legacy-type
+printing even if there are no legacy or boot consoles registered.
+If no such consoles are registered, the console lock does not
+need to be taken.
+
+Also, if boot consoles are registered, nbcon consoles must
+perform their atomic printing under the console lock in order
+to be synchronized with boot consoles.
+
+Add tracking of legacy console registration and use it with
+boot console tracking to avoid unnecessary code paths, i.e.
+do not use the console lock if there are no boot consoles
+and no legacy consoles.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 12 +++++++++
+ kernel/printk/printk.c | 59 +++++++++++++++++++++++++++++++++++------------
+ 2 files changed, 56 insertions(+), 15 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -44,6 +44,16 @@ enum printk_info_flags {
+ };
+
+ extern struct printk_ringbuffer *prb;
++extern bool have_legacy_console;
++extern bool have_boot_console;
++
++/*
++ * Specifies if the console lock/unlock dance is needed for console
++ * printing. If @have_boot_console is true, the nbcon consoles will
++ * be printed serially along with the legacy consoles because nbcon
++ * consoles cannot print simultaneously with boot consoles.
++ */
++#define printing_via_unlock (have_legacy_console || have_boot_console)
+
+ __printf(4, 0)
+ int vprintk_store(int facility, int level,
+@@ -122,6 +132,8 @@ static inline bool console_is_usable(str
+ #define PRINTK_MESSAGE_MAX 0
+ #define PRINTKRB_RECORD_MAX 0
+
++#define printing_via_unlock (false)
++
+ /*
+ * In !PRINTK builds we still export console_sem
+ * semaphore and some of console functions (console_unlock()/etc.), so
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -464,6 +464,13 @@ static int console_msg_format = MSG_FORM
+ static DEFINE_MUTEX(syslog_lock);
+
+ /*
++ * Specifies if a legacy console is registered. If legacy consoles are
++ * present, it is necessary to perform the console_lock/console_unlock dance
++ * whenever console flushing should occur.
++ */
++bool have_legacy_console;
++
++/*
+ * Specifies if a boot console is registered. If boot consoles are present,
+ * nbcon consoles cannot print simultaneously and must be synchronized by
+ * the console lock. This is because boot consoles and nbcon consoles may
+@@ -2345,7 +2352,7 @@ asmlinkage int vprintk_emit(int facility
+ printed_len = vprintk_store(facility, level, dev_info, fmt, args);
+
+ /* If called from the scheduler, we can not call up(). */
+- if (!in_sched) {
++ if (!in_sched && printing_via_unlock) {
+ /*
+ * The caller may be holding system-critical or
+ * timing-sensitive locks. Disable preemption during
+@@ -2646,7 +2653,7 @@ void resume_console(void)
+ */
+ static int console_cpu_notify(unsigned int cpu)
+ {
+- if (!cpuhp_tasks_frozen) {
++ if (!cpuhp_tasks_frozen && printing_via_unlock) {
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
+@@ -3189,7 +3196,8 @@ void console_flush_on_panic(enum con_flu
+
+ nbcon_atomic_flush_all();
+
+- console_flush_all(false, &next_seq, &handover);
++ if (printing_via_unlock)
++ console_flush_all(false, &next_seq, &handover);
+ }
+
+ /*
+@@ -3514,8 +3522,11 @@ void register_console(struct console *ne
+ newcon->dropped = 0;
+ console_init_seq(newcon, bootcon_registered);
+
+- if (newcon->flags & CON_NBCON)
++ if (newcon->flags & CON_NBCON) {
+ nbcon_init(newcon);
++ } else {
++ have_legacy_console = true;
++ }
+
+ if (newcon->flags & CON_BOOT)
+ have_boot_console = true;
+@@ -3572,6 +3583,7 @@ EXPORT_SYMBOL(register_console);
+ /* Must be called under console_list_lock(). */
+ static int unregister_console_locked(struct console *console)
+ {
++ bool found_legacy_con = false;
+ bool found_boot_con = false;
+ struct console *c;
+ int res;
+@@ -3628,9 +3640,13 @@ static int unregister_console_locked(str
+ for_each_console(c) {
+ if (c->flags & CON_BOOT)
+ found_boot_con = true;
++ if (!(c->flags & CON_NBCON))
++ found_legacy_con = true;
+ }
+ if (!found_boot_con)
+ have_boot_console = false;
++ if (!found_legacy_con)
++ have_legacy_console = false;
+
+ return res;
+ }
+@@ -3782,6 +3798,7 @@ static bool __pr_flush(struct console *c
+ u64 last_diff = 0;
+ u64 printk_seq;
+ short flags;
++ bool locked;
+ int cookie;
+ u64 diff;
+ u64 seq;
+@@ -3791,22 +3808,28 @@ static bool __pr_flush(struct console *c
+ seq = prb_next_reserve_seq(prb);
+
+ /* Flush the consoles so that records up to @seq are printed. */
+- console_lock();
+- console_unlock();
++ if (printing_via_unlock) {
++ console_lock();
++ console_unlock();
++ }
+
+ for (;;) {
+ unsigned long begin_jiffies;
+ unsigned long slept_jiffies;
+
++ locked = false;
+ diff = 0;
+
+- /*
+- * Hold the console_lock to guarantee safe access to
+- * console->seq. Releasing console_lock flushes more
+- * records in case @seq is still not printed on all
+- * usable consoles.
+- */
+- console_lock();
++ if (printing_via_unlock) {
++ /*
++ * Hold the console_lock to guarantee safe access to
++ * console->seq. Releasing console_lock flushes more
++ * records in case @seq is still not printed on all
++ * usable consoles.
++ */
++ console_lock();
++ locked = true;
++ }
+
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(c) {
+@@ -3826,6 +3849,7 @@ static bool __pr_flush(struct console *c
+ if (flags & CON_NBCON) {
+ printk_seq = nbcon_seq_read(c);
+ } else {
++ WARN_ON_ONCE(!locked);
+ printk_seq = c->seq;
+ }
+
+@@ -3837,7 +3861,8 @@ static bool __pr_flush(struct console *c
+ if (diff != last_diff && reset_on_progress)
+ remaining_jiffies = timeout_jiffies;
+
+- console_unlock();
++ if (locked)
++ console_unlock();
+
+ /* Note: @diff is 0 if there are no usable consoles. */
+ if (diff == 0 || remaining_jiffies == 0)
+@@ -3959,7 +3984,11 @@ void defer_console_output(void)
+ * New messages may have been added directly to the ringbuffer
+ * using vprintk_store(), so wake any waiters as well.
+ */
+- __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT);
++ int val = PRINTK_PENDING_WAKEUP;
++
++ if (printing_via_unlock)
++ val |= PRINTK_PENDING_OUTPUT;
++ __wake_up_klogd(val);
+ }
+
+ void printk_trigger_flush(void)
diff --git a/debian/patches-rt/0114-printk-Track-nbcon-consoles.patch b/debian/patches-rt/0114-printk-Track-nbcon-consoles.patch
new file mode 100644
index 0000000000..fb85c5bbb5
--- /dev/null
+++ b/debian/patches-rt/0114-printk-Track-nbcon-consoles.patch
@@ -0,0 +1,67 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 11 Dec 2023 09:36:52 +0000
+Subject: [PATCH 114/134] printk: Track nbcon consoles
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add a global flag @have_nbcon_console to identify if any nbcon
+consoles are registered. This will be used in follow-up commits
+to preserve legacy behavior when no nbcon consoles are registered.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -471,6 +471,13 @@ static DEFINE_MUTEX(syslog_lock);
+ bool have_legacy_console;
+
+ /*
++ * Specifies if an nbcon console is registered. If nbcon consoles are present,
++ * synchronous printing of legacy consoles will not occur during panic until
++ * the backtrace has been stored to the ringbuffer.
++ */
++bool have_nbcon_console;
++
++/*
+ * Specifies if a boot console is registered. If boot consoles are present,
+ * nbcon consoles cannot print simultaneously and must be synchronized by
+ * the console lock. This is because boot consoles and nbcon consoles may
+@@ -3523,6 +3530,7 @@ void register_console(struct console *ne
+ console_init_seq(newcon, bootcon_registered);
+
+ if (newcon->flags & CON_NBCON) {
++ have_nbcon_console = true;
+ nbcon_init(newcon);
+ } else {
+ have_legacy_console = true;
+@@ -3584,6 +3592,7 @@ EXPORT_SYMBOL(register_console);
+ static int unregister_console_locked(struct console *console)
+ {
+ bool found_legacy_con = false;
++ bool found_nbcon_con = false;
+ bool found_boot_con = false;
+ struct console *c;
+ int res;
+@@ -3640,13 +3649,18 @@ static int unregister_console_locked(str
+ for_each_console(c) {
+ if (c->flags & CON_BOOT)
+ found_boot_con = true;
+- if (!(c->flags & CON_NBCON))
++
++ if (c->flags & CON_NBCON)
++ found_nbcon_con = true;
++ else
+ found_legacy_con = true;
+ }
+ if (!found_boot_con)
+ have_boot_console = false;
+ if (!found_legacy_con)
+ have_legacy_console = false;
++ if (!found_nbcon_con)
++ have_nbcon_console = false;
+
+ return res;
+ }
diff --git a/debian/patches-rt/0115-printk-Coordinate-direct-printing-in-panic.patch b/debian/patches-rt/0115-printk-Coordinate-direct-printing-in-panic.patch
new file mode 100644
index 0000000000..972df76688
--- /dev/null
+++ b/debian/patches-rt/0115-printk-Coordinate-direct-printing-in-panic.patch
@@ -0,0 +1,134 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 22 Nov 2023 11:56:58 +0000
+Subject: [PATCH 115/134] printk: Coordinate direct printing in panic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Perform printing by nbcon consoles on the panic CPU from the
+printk() caller context in order to get panic messages printed
+as soon as possible.
+
+If legacy and nbcon consoles are registered, the legacy consoles
+will no longer perform direct printing on the panic CPU until
+after the backtrace has been stored. This will give the safe
+nbcon consoles a chance to print the panic messages before
+allowing the unsafe legacy consoles to print.
+
+If no nbcon consoles are registered, there is no change in
+behavior (i.e. legacy consoles will always attempt to print
+from the printk() caller context).
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/printk.h | 2 +
+ kernel/panic.c | 2 +
+ kernel/printk/printk.c | 53 ++++++++++++++++++++++++++++++++++++++++++-------
+ 3 files changed, 50 insertions(+), 7 deletions(-)
+
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -782,3 +782,5 @@ static inline void print_hex_dump_debug(
+ print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true)
+
+ #endif
++
++void printk_legacy_allow_panic_sync(void);
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -366,6 +366,8 @@ void panic(const char *fmt, ...)
+ */
+ atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
+
++ printk_legacy_allow_panic_sync();
++
+ panic_print_sys_info(false);
+
+ kmsg_dump(KMSG_DUMP_PANIC);
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2330,12 +2330,23 @@ int vprintk_store(int facility, int leve
+ return ret;
+ }
+
++static bool legacy_allow_panic_sync;
++
++/*
++ * This acts as a one-way switch to allow legacy consoles to print from
++ * the printk() caller context on a panic CPU.
++ */
++void printk_legacy_allow_panic_sync(void)
++{
++ legacy_allow_panic_sync = true;
++}
++
+ asmlinkage int vprintk_emit(int facility, int level,
+ const struct dev_printk_info *dev_info,
+ const char *fmt, va_list args)
+ {
++ bool do_trylock_unlock = printing_via_unlock;
+ int printed_len;
+- bool in_sched = false;
+
+ /* Suppress unimportant messages after panic happens */
+ if (unlikely(suppress_printk))
+@@ -2351,15 +2362,43 @@ asmlinkage int vprintk_emit(int facility
+
+ if (level == LOGLEVEL_SCHED) {
+ level = LOGLEVEL_DEFAULT;
+- in_sched = true;
++ /* If called from the scheduler, we can not call up(). */
++ do_trylock_unlock = false;
+ }
+
+ printk_delay(level);
+
+ printed_len = vprintk_store(facility, level, dev_info, fmt, args);
+
+- /* If called from the scheduler, we can not call up(). */
+- if (!in_sched && printing_via_unlock) {
++ if (!have_boot_console && have_nbcon_console) {
++ bool is_panic_context = this_cpu_in_panic();
++
++ /*
++ * In panic, the legacy consoles are not allowed to print from
++ * the printk calling context unless explicitly allowed. This
++ * gives the safe nbcon consoles a chance to print out all the
++ * panic messages first. This restriction only applies if
++ * there are nbcon consoles registered.
++ */
++ if (is_panic_context)
++ do_trylock_unlock &= legacy_allow_panic_sync;
++
++ /*
++ * There are situations where nbcon atomic printing should
++ * happen in the printk() caller context:
++ *
++ * - When this CPU is in panic.
++ *
++ * Note that if boot consoles are registered, the
++ * console_lock/console_unlock dance must be relied upon
++ * instead because nbcon consoles cannot print simultaneously
++ * with boot consoles.
++ */
++ if (is_panic_context)
++ nbcon_atomic_flush_all();
++ }
++
++ if (do_trylock_unlock) {
+ /*
+ * The caller may be holding system-critical or
+ * timing-sensitive locks. Disable preemption during
+@@ -2379,10 +2418,10 @@ asmlinkage int vprintk_emit(int facility
+ preempt_enable();
+ }
+
+- if (in_sched)
+- defer_console_output();
+- else
++ if (do_trylock_unlock)
+ wake_up_klogd();
++ else
++ defer_console_output();
+
+ return printed_len;
+ }
diff --git a/debian/patches-rt/0116-printk-nbcon-Implement-emergency-sections.patch b/debian/patches-rt/0116-printk-nbcon-Implement-emergency-sections.patch
new file mode 100644
index 0000000000..11175cacb0
--- /dev/null
+++ b/debian/patches-rt/0116-printk-nbcon-Implement-emergency-sections.patch
@@ -0,0 +1,232 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 11 Sep 2023 15:21:57 +0000
+Subject: [PATCH 116/134] printk: nbcon: Implement emergency sections
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+In emergency situations (something has gone wrong but the
+system continues to operate), usually important information
+(such as a backtrace) is generated via printk(). Each
+individual printk record has little meaning. It is the
+collection of printk messages that is most often needed by
+developers and users.
+
+In order to help ensure that the collection of printk messages
+in an emergency situation are all stored to the ringbuffer as
+quickly as possible, disable console output for that CPU while
+it is in the emergency situation. When exiting the emergency
+situation, trigger the consoles to be flushed.
+
+Add per-CPU emergency nesting tracking because an emergency
+can arise while in an emergency situation.
+
+Add functions to mark the beginning and end of emergency
+sections where the urgent messages are generated.
+
+Do not print if the current CPU is in an emergency state.
+
+Trigger console flushing when exiting all emergency nesting.
+
+Note that the emergency state is not system-wide. While one CPU
+is in an emergency state, another CPU may continue to print
+console messages.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 4 ++
+ include/linux/printk.h | 7 ++--
+ kernel/printk/nbcon.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 25 +++++++++++---
+ 4 files changed, 109 insertions(+), 8 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -458,10 +458,14 @@ static inline bool console_is_registered
+ hlist_for_each_entry(con, &console_list, node)
+
+ #ifdef CONFIG_PRINTK
++extern void nbcon_cpu_emergency_enter(void);
++extern void nbcon_cpu_emergency_exit(void);
+ extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt);
+ extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt);
+ extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt);
+ #else
++static inline void nbcon_cpu_emergency_enter(void) { }
++static inline void nbcon_cpu_emergency_exit(void) { }
+ static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; }
+ static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; }
+ static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; }
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -197,6 +197,7 @@ void show_regs_print_info(const char *lo
+ extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold;
+ extern asmlinkage void dump_stack(void) __cold;
+ void printk_trigger_flush(void);
++void printk_legacy_allow_panic_sync(void);
+ extern void nbcon_acquire(struct uart_port *up);
+ extern void nbcon_release(struct uart_port *up);
+ void nbcon_atomic_flush_unsafe(void);
+@@ -280,6 +281,10 @@ static inline void printk_trigger_flush(
+ {
+ }
+
++static inline void printk_legacy_allow_panic_sync(void)
++{
++}
++
+ static inline void nbcon_acquire(struct uart_port *up)
+ {
+ }
+@@ -782,5 +787,3 @@ static inline void print_hex_dump_debug(
+ print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true)
+
+ #endif
+-
+-void printk_legacy_allow_panic_sync(void);
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -929,6 +929,29 @@ static bool nbcon_emit_next_record(struc
+ return nbcon_context_exit_unsafe(ctxt);
+ }
+
++/* Track the nbcon emergency nesting per CPU. */
++static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting);
++static unsigned int early_nbcon_pcpu_emergency_nesting __initdata;
++
++/**
++ * nbcon_get_cpu_emergency_nesting - Get the per CPU emergency nesting pointer
++ *
++ * Return: Either a pointer to the per CPU emergency nesting counter of
++ * the current CPU or to the init data during early boot.
++ */
++static __ref unsigned int *nbcon_get_cpu_emergency_nesting(void)
++{
++ /*
++ * The value of __printk_percpu_data_ready gets set in normal
++ * context and before SMP initialization. As a result it could
++ * never change while inside an nbcon emergency section.
++ */
++ if (!printk_percpu_data_ready())
++ return &early_nbcon_pcpu_emergency_nesting;
++
++ return this_cpu_ptr(&nbcon_pcpu_emergency_nesting);
++}
++
+ /**
+ * nbcon_atomic_emit_one - Print one record for an nbcon console using the
+ * write_atomic() callback
+@@ -971,9 +994,15 @@ static bool nbcon_atomic_emit_one(struct
+ */
+ enum nbcon_prio nbcon_get_default_prio(void)
+ {
++ unsigned int *cpu_emergency_nesting;
++
+ if (this_cpu_in_panic())
+ return NBCON_PRIO_PANIC;
+
++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
++ if (*cpu_emergency_nesting)
++ return NBCON_PRIO_EMERGENCY;
++
+ return NBCON_PRIO_NORMAL;
+ }
+
+@@ -1111,6 +1140,58 @@ void nbcon_atomic_flush_unsafe(void)
+ }
+
+ /**
++ * nbcon_cpu_emergency_enter - Enter an emergency section where printk()
++ * messages for that CPU are only stored
++ *
++ * Upon exiting the emergency section, all stored messages are flushed.
++ *
++ * Context: Any context. Disables preemption.
++ *
++ * When within an emergency section, no printing occurs on that CPU. This
++ * is to allow all emergency messages to be dumped into the ringbuffer before
++ * flushing the ringbuffer. The actual printing occurs when exiting the
++ * outermost emergency section.
++ */
++void nbcon_cpu_emergency_enter(void)
++{
++ unsigned int *cpu_emergency_nesting;
++
++ preempt_disable();
++
++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
++ (*cpu_emergency_nesting)++;
++}
++
++/**
++ * nbcon_cpu_emergency_exit - Exit an emergency section and flush the
++ * stored messages
++ *
++ * Flushing only occurs when exiting all nesting for the CPU.
++ *
++ * Context: Any context. Enables preemption.
++ */
++void nbcon_cpu_emergency_exit(void)
++{
++ unsigned int *cpu_emergency_nesting;
++ bool do_trigger_flush = false;
++
++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting();
++
++ WARN_ON_ONCE(*cpu_emergency_nesting == 0);
++
++ if (*cpu_emergency_nesting == 1)
++ do_trigger_flush = true;
++
++ /* Undo the nesting count of nbcon_cpu_emergency_enter(). */
++ (*cpu_emergency_nesting)--;
++
++ preempt_enable();
++
++ if (do_trigger_flush)
++ printk_trigger_flush();
++}
++
++/**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+ *
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2405,16 +2405,29 @@ asmlinkage int vprintk_emit(int facility
+ * printing of all remaining records to all consoles so that
+ * this context can return as soon as possible. Hopefully
+ * another printk() caller will take over the printing.
++ *
++ * Also, nbcon_get_default_prio() requires migration disabled.
+ */
+ preempt_disable();
++
+ /*
+- * Try to acquire and then immediately release the console
+- * semaphore. The release will print out buffers. With the
+- * spinning variant, this context tries to take over the
+- * printing from another printing context.
++ * Do not emit for EMERGENCY priority. The console will be
++ * explicitly flushed when exiting the emergency section.
+ */
+- if (console_trylock_spinning())
+- console_unlock();
++ if (nbcon_get_default_prio() == NBCON_PRIO_EMERGENCY) {
++ do_trylock_unlock = false;
++ } else {
++ /*
++ * Try to acquire and then immediately release the
++ * console semaphore. The release will print out
++ * buffers. With the spinning variant, this context
++ * tries to take over the printing from another
++ * printing context.
++ */
++ if (console_trylock_spinning())
++ console_unlock();
++ }
++
+ preempt_enable();
+ }
+
diff --git a/debian/patches-rt/0117-panic-Mark-emergency-section-in-warn.patch b/debian/patches-rt/0117-panic-Mark-emergency-section-in-warn.patch
new file mode 100644
index 0000000000..84201d25fe
--- /dev/null
+++ b/debian/patches-rt/0117-panic-Mark-emergency-section-in-warn.patch
@@ -0,0 +1,38 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 11 Sep 2023 15:53:04 +0000
+Subject: [PATCH 117/134] panic: Mark emergency section in warn
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Mark the full contents of __warn() as an emergency section. In
+this section, the CPU will not perform console output for the
+printk() calls. Instead, a flushing of the console output will
+triggered when exiting the emergency section.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/panic.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -663,6 +663,8 @@ struct warn_args {
+ void __warn(const char *file, int line, void *caller, unsigned taint,
+ struct pt_regs *regs, struct warn_args *args)
+ {
++ nbcon_cpu_emergency_enter();
++
+ disable_trace_on_warning();
+
+ if (file)
+@@ -693,6 +695,8 @@ void __warn(const char *file, int line,
+
+ /* Just a warning, don't kill lockdep. */
+ add_taint(taint, LOCKDEP_STILL_OK);
++
++ nbcon_cpu_emergency_exit();
+ }
+
+ #ifdef CONFIG_BUG
diff --git a/debian/patches-rt/0118-panic-Mark-emergency-section-in-oops.patch b/debian/patches-rt/0118-panic-Mark-emergency-section-in-oops.patch
new file mode 100644
index 0000000000..6e52fd3a69
--- /dev/null
+++ b/debian/patches-rt/0118-panic-Mark-emergency-section-in-oops.patch
@@ -0,0 +1,39 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 19 Sep 2023 17:07:34 +0000
+Subject: [PATCH 118/134] panic: Mark emergency section in oops
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Mark an emergency section beginning with oops_enter() until the
+end of oops_exit(). In this section, the CPU will not perform
+console output for the printk() calls. Instead, a flushing of the
+console output will triggered when exiting the emergency section.
+
+The very end of oops_exit() performs a kmsg_dump(). This is not
+included in the emergency section because it is another
+flushing mechanism that should occur after the consoles have
+been triggered to flush.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/panic.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -630,6 +630,7 @@ bool oops_may_print(void)
+ */
+ void oops_enter(void)
+ {
++ nbcon_cpu_emergency_enter();
+ tracing_off();
+ /* can't trust the integrity of the kernel anymore: */
+ debug_locks_off();
+@@ -652,6 +653,7 @@ void oops_exit(void)
+ {
+ do_oops_enter_exit();
+ print_oops_end_marker();
++ nbcon_cpu_emergency_exit();
+ kmsg_dump(KMSG_DUMP_OOPS);
+ }
+
diff --git a/debian/patches-rt/0119-rcu-Mark-emergency-section-in-rcu-stalls.patch b/debian/patches-rt/0119-rcu-Mark-emergency-section-in-rcu-stalls.patch
new file mode 100644
index 0000000000..d1d6efced4
--- /dev/null
+++ b/debian/patches-rt/0119-rcu-Mark-emergency-section-in-rcu-stalls.patch
@@ -0,0 +1,45 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 11 Sep 2023 15:53:39 +0000
+Subject: [PATCH 119/134] rcu: Mark emergency section in rcu stalls
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Mark an emergency section within print_other_cpu_stall(), where
+RCU stall information is printed. In this section, the CPU will
+not perform console output for the printk() calls. Instead, a
+flushing of the console output will triggered when exiting the
+emergency section.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/rcu/tree_stall.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/kernel/rcu/tree_stall.h
++++ b/kernel/rcu/tree_stall.h
+@@ -8,6 +8,7 @@
+ */
+
+ #include <linux/kvm_para.h>
++#include <linux/console.h>
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+@@ -603,6 +604,8 @@ static void print_other_cpu_stall(unsign
+ if (rcu_stall_is_suppressed())
+ return;
+
++ nbcon_cpu_emergency_enter();
++
+ /*
+ * OK, time to rat on our buddy...
+ * See Documentation/RCU/stallwarn.rst for info on how to debug
+@@ -657,6 +660,8 @@ static void print_other_cpu_stall(unsign
+ panic_on_rcu_stall();
+
+ rcu_force_quiescent_state(); /* Kick them all. */
++
++ nbcon_cpu_emergency_exit();
+ }
+
+ static void print_cpu_stall(unsigned long gps)
diff --git a/debian/patches-rt/0120-lockdep-Mark-emergency-section-in-lockdep-splats.patch b/debian/patches-rt/0120-lockdep-Mark-emergency-section-in-lockdep-splats.patch
new file mode 100644
index 0000000000..248d17afc2
--- /dev/null
+++ b/debian/patches-rt/0120-lockdep-Mark-emergency-section-in-lockdep-splats.patch
@@ -0,0 +1,45 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 18 Sep 2023 20:27:41 +0000
+Subject: [PATCH 120/134] lockdep: Mark emergency section in lockdep splats
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Mark an emergency section within print_usage_bug(), where
+lockdep bugs are printed. In this section, the CPU will not
+perform console output for the printk() calls. Instead, a
+flushing of the console output will triggered when exiting
+the emergency section.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/locking/lockdep.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -56,6 +56,7 @@
+ #include <linux/kprobes.h>
+ #include <linux/lockdep.h>
+ #include <linux/context_tracking.h>
++#include <linux/console.h>
+
+ #include <asm/sections.h>
+
+@@ -3971,6 +3972,8 @@ print_usage_bug(struct task_struct *curr
+ if (!debug_locks_off() || debug_locks_silent)
+ return;
+
++ nbcon_cpu_emergency_enter();
++
+ pr_warn("\n");
+ pr_warn("================================\n");
+ pr_warn("WARNING: inconsistent lock state\n");
+@@ -3999,6 +4002,8 @@ print_usage_bug(struct task_struct *curr
+
+ pr_warn("\nstack backtrace:\n");
+ dump_stack();
++
++ nbcon_cpu_emergency_exit();
+ }
+
+ /*
diff --git a/debian/patches-rt/0121-printk-nbcon-Introduce-printing-kthreads.patch b/debian/patches-rt/0121-printk-nbcon-Introduce-printing-kthreads.patch
new file mode 100644
index 0000000000..7b158ddb74
--- /dev/null
+++ b/debian/patches-rt/0121-printk-nbcon-Introduce-printing-kthreads.patch
@@ -0,0 +1,441 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 22 Sep 2023 14:12:21 +0000
+Subject: [PATCH 121/134] printk: nbcon: Introduce printing kthreads
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Provide the main implementation for running a printer kthread
+per nbcon console that is takeover/handover aware.
+
+The main print function nbcon_emit_next_record() will generate
+a warning if a task other than the dedicated printer thread
+tries to print using write_thread().
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 8 ++
+ kernel/printk/internal.h | 25 ++++++
+ kernel/printk/nbcon.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++-
+ kernel/printk/printk.c | 31 +++++++
+ 4 files changed, 249 insertions(+), 3 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -17,6 +17,7 @@
+ #include <linux/atomic.h>
+ #include <linux/bits.h>
+ #include <linux/rculist.h>
++#include <linux/rcuwait.h>
+ #include <linux/types.h>
+
+ struct vc_data;
+@@ -296,12 +297,15 @@ struct nbcon_write_context {
+ * @node: hlist node for the console list
+ *
+ * @write_atomic: Write callback for atomic context
++ * @write_thread: Write callback for non-atomic context
+ * @driver_enter: Callback to begin synchronization with driver code
+ * @driver_exit: Callback to finish synchronization with driver code
+ * @nbcon_state: State for nbcon consoles
+ * @nbcon_seq: Sequence number of the next record for nbcon to print
+ * @pbufs: Pointer to nbcon private buffer
+ * @locked_port: True, if the port lock is locked by nbcon
++ * @kthread: Printer kthread for this console
++ * @rcuwait: RCU-safe wait object for @kthread waking
+ */
+ struct console {
+ char name[16];
+@@ -325,12 +329,16 @@ struct console {
+ /* nbcon console specific members */
+ bool (*write_atomic)(struct console *con,
+ struct nbcon_write_context *wctxt);
++ bool (*write_thread)(struct console *con,
++ struct nbcon_write_context *wctxt);
+ void (*driver_enter)(struct console *con, unsigned long *flags);
+ void (*driver_exit)(struct console *con, unsigned long flags);
+ atomic_t __private nbcon_state;
+ atomic_long_t __private nbcon_seq;
+ struct printk_buffers *pbufs;
+ bool locked_port;
++ struct task_struct *kthread;
++ struct rcuwait rcuwait;
+ };
+
+ #ifdef CONFIG_LOCKDEP
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -92,6 +92,7 @@ void nbcon_free(struct console *con);
+ enum nbcon_prio nbcon_get_default_prio(void);
+ void nbcon_atomic_flush_all(void);
+ bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie);
++void nbcon_kthread_create(struct console *con);
+
+ /*
+ * Check if the given console is currently capable and allowed to print
+@@ -110,6 +111,8 @@ static inline bool console_is_usable(str
+ if (flags & CON_NBCON) {
+ if (!con->write_atomic)
+ return false;
++ if (!con->write_thread || !con->kthread)
++ return false;
+ } else {
+ if (!con->write)
+ return false;
+@@ -126,12 +129,34 @@ static inline bool console_is_usable(str
+ return true;
+ }
+
++/**
++ * nbcon_kthread_wake - Wake up a printk thread
++ * @con: Console to operate on
++ */
++static inline void nbcon_kthread_wake(struct console *con)
++{
++ /*
++ * Guarantee any new records can be seen by tasks preparing to wait
++ * before this context checks if the rcuwait is empty.
++ *
++ * The full memory barrier in rcuwait_wake_up() pairs with the full
++ * memory barrier within set_current_state() of
++ * ___rcuwait_wait_event(), which is called after prepare_to_rcuwait()
++ * adds the waiter but before it has checked the wait condition.
++ *
++ * This pairs with nbcon_kthread_func:A.
++ */
++ rcuwait_wake_up(&con->rcuwait); /* LMM(nbcon_kthread_wake:A) */
++}
++
+ #else
+
+ #define PRINTK_PREFIX_MAX 0
+ #define PRINTK_MESSAGE_MAX 0
+ #define PRINTKRB_RECORD_MAX 0
+
++static inline void nbcon_kthread_wake(struct console *con) { }
++static inline void nbcon_kthread_create(struct console *con) { }
+ #define printing_via_unlock (false)
+
+ /*
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -5,8 +5,10 @@
+ #include <linux/kernel.h>
+ #include <linux/console.h>
+ #include <linux/delay.h>
++#include <linux/kthread.h>
+ #include <linux/slab.h>
+ #include <linux/serial_core.h>
++#include "printk_ringbuffer.h"
+ #include "internal.h"
+ /*
+ * Printk console printing implementation for consoles which does not depend
+@@ -828,6 +830,7 @@ EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
+ /**
+ * nbcon_emit_next_record - Emit a record in the acquired context
+ * @wctxt: The write context that will be handed to the write function
++ * @use_atomic: True if the write_atomic callback is to be used
+ *
+ * Return: True if this context still owns the console. False if
+ * ownership was handed over or taken.
+@@ -841,7 +844,7 @@ EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
+ * When true is returned, @wctxt->ctxt.backlog indicates whether there are
+ * still records pending in the ringbuffer,
+ */
+-static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt)
++static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt, bool use_atomic)
+ {
+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
+ struct console *con = ctxt->console;
+@@ -891,9 +894,17 @@ static bool nbcon_emit_next_record(struc
+ nbcon_state_read(con, &cur);
+ wctxt->unsafe_takeover = cur.unsafe_takeover;
+
+- if (con->write_atomic)
++ if (use_atomic &&
++ con->write_atomic) {
+ done = con->write_atomic(con, wctxt);
+
++ } else if (!use_atomic &&
++ con->write_thread &&
++ con->kthread) {
++ WARN_ON_ONCE(con->kthread != current);
++ done = con->write_thread(con, wctxt);
++ }
++
+ if (!done) {
+ /*
+ * The emit was aborted, probably due to a loss of ownership.
+@@ -929,6 +940,118 @@ static bool nbcon_emit_next_record(struc
+ return nbcon_context_exit_unsafe(ctxt);
+ }
+
++/**
++ * nbcon_kthread_should_wakeup - Check whether a printer thread should wakeup
++ * @con: Console to operate on
++ * @ctxt: The acquire context that contains the state
++ * at console_acquire()
++ *
++ * Return: True if the thread should shutdown or if the console is
++ * allowed to print and a record is available. False otherwise.
++ *
++ * After the thread wakes up, it must first check if it should shutdown before
++ * attempting any printing.
++ */
++static bool nbcon_kthread_should_wakeup(struct console *con, struct nbcon_context *ctxt)
++{
++ bool is_usable;
++ short flags;
++ int cookie;
++
++ if (kthread_should_stop())
++ return true;
++
++ cookie = console_srcu_read_lock();
++ flags = console_srcu_read_flags(con);
++ is_usable = console_is_usable(con, flags);
++ console_srcu_read_unlock(cookie);
++
++ if (!is_usable)
++ return false;
++
++ /* Bring the sequence in @ctxt up to date */
++ ctxt->seq = nbcon_seq_read(con);
++
++ return prb_read_valid(prb, ctxt->seq, NULL);
++}
++
++/**
++ * nbcon_kthread_func - The printer thread function
++ * @__console: Console to operate on
++ */
++static int nbcon_kthread_func(void *__console)
++{
++ struct console *con = __console;
++ struct nbcon_write_context wctxt = {
++ .ctxt.console = con,
++ .ctxt.prio = NBCON_PRIO_NORMAL,
++ };
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt);
++ unsigned long flags;
++ short con_flags;
++ bool backlog;
++ int cookie;
++ int ret;
++
++wait_for_event:
++ /*
++ * Guarantee this task is visible on the rcuwait before
++ * checking the wake condition.
++ *
++ * The full memory barrier within set_current_state() of
++ * ___rcuwait_wait_event() pairs with the full memory
++ * barrier within rcuwait_has_sleeper().
++ *
++ * This pairs with rcuwait_has_sleeper:A and nbcon_kthread_wake:A.
++ */
++ ret = rcuwait_wait_event(&con->rcuwait,
++ nbcon_kthread_should_wakeup(con, ctxt),
++ TASK_INTERRUPTIBLE); /* LMM(nbcon_kthread_func:A) */
++
++ if (kthread_should_stop())
++ return 0;
++
++ /* Wait was interrupted by a spurious signal, go back to sleep. */
++ if (ret)
++ goto wait_for_event;
++
++ do {
++ backlog = false;
++
++ cookie = console_srcu_read_lock();
++
++ con_flags = console_srcu_read_flags(con);
++
++ if (console_is_usable(con, con_flags)) {
++ con->driver_enter(con, &flags);
++
++ /*
++ * Ensure this stays on the CPU to make handover and
++ * takeover possible.
++ */
++ cant_migrate();
++
++ if (nbcon_context_try_acquire(ctxt)) {
++ /*
++ * If the emit fails, this context is no
++ * longer the owner.
++ */
++ if (nbcon_emit_next_record(&wctxt, false)) {
++ nbcon_context_release(ctxt);
++ backlog = ctxt->backlog;
++ }
++ }
++
++ con->driver_exit(con, flags);
++ }
++
++ console_srcu_read_unlock(cookie);
++
++ } while (backlog);
++
++ goto wait_for_event;
++}
++
+ /* Track the nbcon emergency nesting per CPU. */
+ static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting);
+ static unsigned int early_nbcon_pcpu_emergency_nesting __initdata;
+@@ -976,7 +1099,7 @@ static bool nbcon_atomic_emit_one(struct
+ * handed over or taken over. In both cases the context is no
+ * longer valid.
+ */
+- if (!nbcon_emit_next_record(wctxt))
++ if (!nbcon_emit_next_record(wctxt, true))
+ return false;
+
+ nbcon_context_release(ctxt);
+@@ -1192,6 +1315,63 @@ void nbcon_cpu_emergency_exit(void)
+ }
+
+ /**
++ * nbcon_kthread_stop - Stop a printer thread
++ * @con: Console to operate on
++ */
++static void nbcon_kthread_stop(struct console *con)
++{
++ lockdep_assert_console_list_lock_held();
++
++ if (!con->kthread)
++ return;
++
++ kthread_stop(con->kthread);
++ con->kthread = NULL;
++}
++
++/**
++ * nbcon_kthread_create - Create a printer thread
++ * @con: Console to operate on
++ *
++ * If it fails, let the console proceed. The atomic part might
++ * be usable and useful.
++ */
++void nbcon_kthread_create(struct console *con)
++{
++ struct task_struct *kt;
++
++ lockdep_assert_console_list_lock_held();
++
++ if (!(con->flags & CON_NBCON) || !con->write_thread)
++ return;
++
++ if (con->kthread)
++ return;
++
++ /*
++ * Printer threads cannot be started as long as any boot console is
++ * registered because there is no way to synchronize the hardware
++ * registers between boot console code and regular console code.
++ */
++ if (have_boot_console)
++ return;
++
++ kt = kthread_run(nbcon_kthread_func, con, "pr/%s%d", con->name, con->index);
++ if (IS_ERR(kt)) {
++ con_printk(KERN_ERR, con, "failed to start printing thread\n");
++ return;
++ }
++
++ con->kthread = kt;
++
++ /*
++ * It is important that console printing threads are scheduled
++ * shortly after a printk call and with generous runtime budgets.
++ */
++ sched_set_normal(con->kthread, -20);
++}
++
++/**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+ *
+@@ -1237,6 +1417,7 @@ void nbcon_init(struct console *con)
+ /* nbcon_alloc() must have been called and successful! */
+ BUG_ON(!con->pbufs);
+
++ rcuwait_init(&con->rcuwait);
+ nbcon_seq_force(con, con->seq);
+ nbcon_state_set(con, &state);
+ }
+@@ -1249,6 +1430,7 @@ void nbcon_free(struct console *con)
+ {
+ struct nbcon_state state = { };
+
++ nbcon_kthread_stop(con);
+ nbcon_state_set(con, &state);
+
+ /* Boot consoles share global printk buffers. */
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2682,6 +2682,8 @@ void suspend_console(void)
+ void resume_console(void)
+ {
+ struct console *con;
++ short flags;
++ int cookie;
+
+ if (!console_suspend_enabled)
+ return;
+@@ -2698,6 +2700,14 @@ void resume_console(void)
+ */
+ synchronize_srcu(&console_srcu);
+
++ cookie = console_srcu_read_lock();
++ for_each_console_srcu(con) {
++ flags = console_srcu_read_flags(con);
++ if (flags & CON_NBCON)
++ nbcon_kthread_wake(con);
++ }
++ console_srcu_read_unlock(cookie);
++
+ pr_flush(1000, true);
+ }
+
+@@ -3018,6 +3028,13 @@ static bool console_flush_all(bool do_co
+ u64 printk_seq;
+ bool progress;
+
++ /*
++ * console_flush_all() is only for legacy consoles,
++ * unless the nbcon console has no kthread printer.
++ */
++ if ((flags & CON_NBCON) && con->kthread)
++ continue;
++
+ if (!console_is_usable(con, flags))
+ continue;
+ any_usable = true;
+@@ -3313,9 +3330,23 @@ EXPORT_SYMBOL(console_stop);
+
+ void console_start(struct console *console)
+ {
++ short flags;
++
+ console_list_lock();
+ console_srcu_write_flags(console, console->flags | CON_ENABLED);
++ flags = console->flags;
+ console_list_unlock();
++
++ /*
++ * Ensure that all SRCU list walks have completed. The related
++ * printing context must be able to see it is enabled so that
++ * it is guaranteed to wake up and resume printing.
++ */
++ synchronize_srcu(&console_srcu);
++
++ if (flags & CON_NBCON)
++ nbcon_kthread_wake(console);
++
+ __pr_flush(console, 1000, true);
+ }
+ EXPORT_SYMBOL(console_start);
diff --git a/debian/patches-rt/0122-printk-Atomic-print-in-printk-context-on-shutdown.patch b/debian/patches-rt/0122-printk-Atomic-print-in-printk-context-on-shutdown.patch
new file mode 100644
index 0000000000..35c88289b1
--- /dev/null
+++ b/debian/patches-rt/0122-printk-Atomic-print-in-printk-context-on-shutdown.patch
@@ -0,0 +1,41 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 23 Oct 2023 17:43:48 +0000
+Subject: [PATCH 122/134] printk: Atomic print in printk context on shutdown
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+For nbcon consoles, normally the printing is handled by the
+dedicated console printing threads. However, on shutdown the
+printing threads may not get a chance to print the final
+messages.
+
+When shutting down or rebooting (system_state > SYSTEM_RUNNING),
+perform atomic printing from the printk() caller context.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2389,13 +2389,18 @@ asmlinkage int vprintk_emit(int facility
+ *
+ * - When this CPU is in panic.
+ *
++ * - During shutdown, since the printing threads may not get
++ * a chance to print the final messages.
++ *
+ * Note that if boot consoles are registered, the
+ * console_lock/console_unlock dance must be relied upon
+ * instead because nbcon consoles cannot print simultaneously
+ * with boot consoles.
+ */
+- if (is_panic_context)
++ if (is_panic_context ||
++ (system_state > SYSTEM_RUNNING)) {
+ nbcon_atomic_flush_all();
++ }
+ }
+
+ if (do_trylock_unlock) {
diff --git a/debian/patches-rt/0123-printk-nbcon-Add-context-to-console_is_usable.patch b/debian/patches-rt/0123-printk-nbcon-Add-context-to-console_is_usable.patch
new file mode 100644
index 0000000000..26a494c165
--- /dev/null
+++ b/debian/patches-rt/0123-printk-nbcon-Add-context-to-console_is_usable.patch
@@ -0,0 +1,111 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 26 Sep 2023 14:43:30 +0000
+Subject: [PATCH 123/134] printk: nbcon: Add context to console_is_usable()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The nbcon consoles have two callbacks to be used for different
+contexts. In order to determine if an nbcon console is usable,
+console_is_usable() needs to know if it is a context that will
+use the write_atomic() callback or the write_thread() callback.
+
+Add an extra parameter @use_atomic to specify this.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 16 ++++++++++------
+ kernel/printk/nbcon.c | 6 +++---
+ kernel/printk/printk.c | 6 ++++--
+ 3 files changed, 17 insertions(+), 11 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -100,7 +100,7 @@ void nbcon_kthread_create(struct console
+ * which can also play a role in deciding if @con can be used to print
+ * records.
+ */
+-static inline bool console_is_usable(struct console *con, short flags)
++static inline bool console_is_usable(struct console *con, short flags, bool use_atomic)
+ {
+ if (!(flags & CON_ENABLED))
+ return false;
+@@ -109,10 +109,13 @@ static inline bool console_is_usable(str
+ return false;
+
+ if (flags & CON_NBCON) {
+- if (!con->write_atomic)
+- return false;
+- if (!con->write_thread || !con->kthread)
+- return false;
++ if (use_atomic) {
++ if (!con->write_atomic)
++ return false;
++ } else {
++ if (!con->write_thread || !con->kthread)
++ return false;
++ }
+ } else {
+ if (!con->write)
+ return false;
+@@ -178,7 +181,8 @@ static inline void nbcon_atomic_flush_al
+ static inline bool nbcon_atomic_emit_next_record(struct console *con, bool *handover,
+ int cookie) { return false; }
+
+-static inline bool console_is_usable(struct console *con, short flags) { return false; }
++static inline bool console_is_usable(struct console *con, short flags,
++ bool use_atomic) { return false; }
+
+ #endif /* CONFIG_PRINTK */
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -963,7 +963,7 @@ static bool nbcon_kthread_should_wakeup(
+
+ cookie = console_srcu_read_lock();
+ flags = console_srcu_read_flags(con);
+- is_usable = console_is_usable(con, flags);
++ is_usable = console_is_usable(con, flags, false);
+ console_srcu_read_unlock(cookie);
+
+ if (!is_usable)
+@@ -1022,7 +1022,7 @@ static int nbcon_kthread_func(void *__co
+
+ con_flags = console_srcu_read_flags(con);
+
+- if (console_is_usable(con, con_flags)) {
++ if (console_is_usable(con, con_flags, false)) {
+ con->driver_enter(con, &flags);
+
+ /*
+@@ -1203,7 +1203,7 @@ static void __nbcon_atomic_flush_all(u64
+ if (!(flags & CON_NBCON))
+ continue;
+
+- if (!console_is_usable(con, flags))
++ if (!console_is_usable(con, flags, true))
+ continue;
+
+ if (nbcon_seq_read(con) >= stop_seq)
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3040,7 +3040,7 @@ static bool console_flush_all(bool do_co
+ if ((flags & CON_NBCON) && con->kthread)
+ continue;
+
+- if (!console_is_usable(con, flags))
++ if (!console_is_usable(con, flags, true))
+ continue;
+ any_usable = true;
+
+@@ -3945,8 +3945,10 @@ static bool __pr_flush(struct console *c
+ * that they make forward progress, so only increment
+ * @diff for usable consoles.
+ */
+- if (!console_is_usable(c, flags))
++ if (!console_is_usable(c, flags, true) &&
++ !console_is_usable(c, flags, false)) {
+ continue;
++ }
+
+ if (flags & CON_NBCON) {
+ printk_seq = nbcon_seq_read(c);
diff --git a/debian/patches-rt/0124-printk-nbcon-Add-printer-thread-wakeups.patch b/debian/patches-rt/0124-printk-nbcon-Add-printer-thread-wakeups.patch
new file mode 100644
index 0000000000..18e02593f8
--- /dev/null
+++ b/debian/patches-rt/0124-printk-nbcon-Add-printer-thread-wakeups.patch
@@ -0,0 +1,164 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 26 Sep 2023 13:03:52 +0000
+Subject: [PATCH 124/134] printk: nbcon: Add printer thread wakeups
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Add a function to wakeup the printer threads. Use the new function
+when:
+
+ - records are added to the printk ringbuffer
+ - consoles are resumed
+ - triggered via printk_trigger_flush()
+
+The actual waking is performed via irq_work so that the wakeup can
+be triggered from any context.
+
+Co-developed-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Thomas Gleixner (Intel) <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 3 ++
+ kernel/printk/internal.h | 1
+ kernel/printk/nbcon.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
+ kernel/printk/printk.c | 7 +++++
+ 4 files changed, 67 insertions(+)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -16,6 +16,7 @@
+
+ #include <linux/atomic.h>
+ #include <linux/bits.h>
++#include <linux/irq_work.h>
+ #include <linux/rculist.h>
+ #include <linux/rcuwait.h>
+ #include <linux/types.h>
+@@ -306,6 +307,7 @@ struct nbcon_write_context {
+ * @locked_port: True, if the port lock is locked by nbcon
+ * @kthread: Printer kthread for this console
+ * @rcuwait: RCU-safe wait object for @kthread waking
++ * @irq_work: Defer @kthread waking to IRQ work context
+ */
+ struct console {
+ char name[16];
+@@ -339,6 +341,7 @@ struct console {
+ bool locked_port;
+ struct task_struct *kthread;
+ struct rcuwait rcuwait;
++ struct irq_work irq_work;
+ };
+
+ #ifdef CONFIG_LOCKDEP
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -93,6 +93,7 @@ enum nbcon_prio nbcon_get_default_prio(v
+ void nbcon_atomic_flush_all(void);
+ bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie);
+ void nbcon_kthread_create(struct console *con);
++void nbcon_wake_threads(void);
+
+ /*
+ * Check if the given console is currently capable and allowed to print
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -1052,6 +1052,61 @@ static int nbcon_kthread_func(void *__co
+ goto wait_for_event;
+ }
+
++/**
++ * nbcon_irq_work - irq work to wake printk thread
++ * @irq_work: The irq work to operate on
++ */
++static void nbcon_irq_work(struct irq_work *irq_work)
++{
++ struct console *con = container_of(irq_work, struct console, irq_work);
++
++ nbcon_kthread_wake(con);
++}
++
++static inline bool rcuwait_has_sleeper(struct rcuwait *w)
++{
++ bool has_sleeper;
++
++ rcu_read_lock();
++ /*
++ * Guarantee any new records can be seen by tasks preparing to wait
++ * before this context checks if the rcuwait is empty.
++ *
++ * This full memory barrier pairs with the full memory barrier within
++ * set_current_state() of ___rcuwait_wait_event(), which is called
++ * after prepare_to_rcuwait() adds the waiter but before it has
++ * checked the wait condition.
++ *
++ * This pairs with nbcon_kthread_func:A.
++ */
++ smp_mb(); /* LMM(rcuwait_has_sleeper:A) */
++ has_sleeper = !!rcu_dereference(w->task);
++ rcu_read_unlock();
++
++ return has_sleeper;
++}
++
++/**
++ * nbcon_wake_threads - Wake up printing threads using irq_work
++ */
++void nbcon_wake_threads(void)
++{
++ struct console *con;
++ int cookie;
++
++ cookie = console_srcu_read_lock();
++ for_each_console_srcu(con) {
++ /*
++ * Only schedule irq_work if the printing thread is
++ * actively waiting. If not waiting, the thread will
++ * notice by itself that it has work to do.
++ */
++ if (con->kthread && rcuwait_has_sleeper(&con->rcuwait))
++ irq_work_queue(&con->irq_work);
++ }
++ console_srcu_read_unlock(cookie);
++}
++
+ /* Track the nbcon emergency nesting per CPU. */
+ static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting);
+ static unsigned int early_nbcon_pcpu_emergency_nesting __initdata;
+@@ -1418,6 +1473,7 @@ void nbcon_init(struct console *con)
+ BUG_ON(!con->pbufs);
+
+ rcuwait_init(&con->rcuwait);
++ init_irq_work(&con->irq_work, nbcon_irq_work);
+ nbcon_seq_force(con, con->seq);
+ nbcon_state_set(con, &state);
+ }
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2403,6 +2403,8 @@ asmlinkage int vprintk_emit(int facility
+ }
+ }
+
++ nbcon_wake_threads();
++
+ if (do_trylock_unlock) {
+ /*
+ * The caller may be holding system-critical or
+@@ -2705,6 +2707,10 @@ void resume_console(void)
+ */
+ synchronize_srcu(&console_srcu);
+
++ /*
++ * Since this runs in task context, wake the threaded printers
++ * directly rather than scheduling irq_work to do it.
++ */
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(con) {
+ flags = console_srcu_read_flags(con);
+@@ -4097,6 +4103,7 @@ void defer_console_output(void)
+
+ void printk_trigger_flush(void)
+ {
++ nbcon_wake_threads();
+ defer_console_output();
+ }
+
diff --git a/debian/patches-rt/0125-printk-nbcon-Stop-threads-on-shutdown-reboot.patch b/debian/patches-rt/0125-printk-nbcon-Stop-threads-on-shutdown-reboot.patch
new file mode 100644
index 0000000000..55ec76c5c0
--- /dev/null
+++ b/debian/patches-rt/0125-printk-nbcon-Stop-threads-on-shutdown-reboot.patch
@@ -0,0 +1,60 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 26 Sep 2023 13:04:15 +0000
+Subject: [PATCH 125/134] printk: nbcon: Stop threads on shutdown/reboot
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Register a syscore_ops shutdown function to stop all threaded
+printers on shutdown/reboot. This allows printk to transition back
+to atomic printing in order to provide a robust mechanism for
+outputting the final messages.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/nbcon.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -8,6 +8,7 @@
+ #include <linux/kthread.h>
+ #include <linux/slab.h>
+ #include <linux/serial_core.h>
++#include <linux/syscore_ops.h>
+ #include "printk_ringbuffer.h"
+ #include "internal.h"
+ /*
+@@ -1577,3 +1578,33 @@ void nbcon_release(struct uart_port *up)
+ con->locked_port = false;
+ }
+ EXPORT_SYMBOL_GPL(nbcon_release);
++
++/**
++ * printk_kthread_shutdown - shutdown all threaded printers
++ *
++ * On system shutdown all threaded printers are stopped. This allows printk
++ * to transition back to atomic printing, thus providing a robust mechanism
++ * for the final shutdown/reboot messages to be output.
++ */
++static void printk_kthread_shutdown(void)
++{
++ struct console *con;
++
++ console_list_lock();
++ for_each_console(con) {
++ if (con->flags & CON_NBCON)
++ nbcon_kthread_stop(con);
++ }
++ console_list_unlock();
++}
++
++static struct syscore_ops printk_syscore_ops = {
++ .shutdown = printk_kthread_shutdown,
++};
++
++static int __init printk_init_ops(void)
++{
++ register_syscore_ops(&printk_syscore_ops);
++ return 0;
++}
++device_initcall(printk_init_ops);
diff --git a/debian/patches-rt/0126-printk-nbcon-Start-printing-threads.patch b/debian/patches-rt/0126-printk-nbcon-Start-printing-threads.patch
new file mode 100644
index 0000000000..ec41221636
--- /dev/null
+++ b/debian/patches-rt/0126-printk-nbcon-Start-printing-threads.patch
@@ -0,0 +1,135 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 5 Dec 2023 14:09:31 +0000
+Subject: [PATCH 126/134] printk: nbcon: Start printing threads
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+If there are no boot consoles, the printing threads are started
+in early_initcall.
+
+If there are boot consoles, the printing threads are started
+after the last boot console has unregistered. The printing
+threads do not need to be concerned about boot consoles because
+boot consoles cannot register once a non-boot console has
+registered.
+
+Until a printing thread of a console has started, that console
+will print using atomic_write() in the printk() caller context.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 2 ++
+ kernel/printk/nbcon.c | 18 +++++++++++++++++-
+ kernel/printk/printk.c | 14 ++++++++++++++
+ 3 files changed, 33 insertions(+), 1 deletion(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -44,6 +44,7 @@ enum printk_info_flags {
+ };
+
+ extern struct printk_ringbuffer *prb;
++extern bool printk_threads_enabled;
+ extern bool have_legacy_console;
+ extern bool have_boot_console;
+
+@@ -161,6 +162,7 @@ static inline void nbcon_kthread_wake(st
+
+ static inline void nbcon_kthread_wake(struct console *con) { }
+ static inline void nbcon_kthread_create(struct console *con) { }
++#define printk_threads_enabled (false)
+ #define printing_via_unlock (false)
+
+ /*
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -205,6 +205,8 @@ static void nbcon_seq_try_update(struct
+ }
+ }
+
++bool printk_threads_enabled __ro_after_init;
++
+ /**
+ * nbcon_context_try_acquire_direct - Try to acquire directly
+ * @ctxt: The context of the caller
+@@ -1401,7 +1403,7 @@ void nbcon_kthread_create(struct console
+ if (!(con->flags & CON_NBCON) || !con->write_thread)
+ return;
+
+- if (con->kthread)
++ if (!printk_threads_enabled || con->kthread)
+ return;
+
+ /*
+@@ -1427,6 +1429,19 @@ void nbcon_kthread_create(struct console
+ sched_set_normal(con->kthread, -20);
+ }
+
++static int __init printk_setup_threads(void)
++{
++ struct console *con;
++
++ console_list_lock();
++ printk_threads_enabled = true;
++ for_each_console(con)
++ nbcon_kthread_create(con);
++ console_list_unlock();
++ return 0;
++}
++early_initcall(printk_setup_threads);
++
+ /**
+ * nbcon_alloc - Allocate buffers needed by the nbcon console
+ * @con: Console to allocate buffers for
+@@ -1477,6 +1492,7 @@ void nbcon_init(struct console *con)
+ init_irq_work(&con->irq_work, nbcon_irq_work);
+ nbcon_seq_force(con, con->seq);
+ nbcon_state_set(con, &state);
++ nbcon_kthread_create(con);
+ }
+
+ /**
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2389,6 +2389,9 @@ asmlinkage int vprintk_emit(int facility
+ *
+ * - When this CPU is in panic.
+ *
++ * - When booting, before the printing threads have been
++ * started.
++ *
+ * - During shutdown, since the printing threads may not get
+ * a chance to print the final messages.
+ *
+@@ -2398,6 +2401,7 @@ asmlinkage int vprintk_emit(int facility
+ * with boot consoles.
+ */
+ if (is_panic_context ||
++ !printk_threads_enabled ||
+ (system_state > SYSTEM_RUNNING)) {
+ nbcon_atomic_flush_all();
+ }
+@@ -3685,6 +3689,7 @@ EXPORT_SYMBOL(register_console);
+ /* Must be called under console_list_lock(). */
+ static int unregister_console_locked(struct console *console)
+ {
++ bool is_boot_con = (console->flags & CON_BOOT);
+ bool found_legacy_con = false;
+ bool found_nbcon_con = false;
+ bool found_boot_con = false;
+@@ -3756,6 +3761,15 @@ static int unregister_console_locked(str
+ if (!found_nbcon_con)
+ have_nbcon_console = false;
+
++ /*
++ * When the last boot console unregisters, start up the
++ * printing threads.
++ */
++ if (is_boot_con && !have_boot_console) {
++ for_each_console(c)
++ nbcon_kthread_create(c);
++ }
++
+ return res;
+ }
+
diff --git a/debian/patches-rt/0127-proc-Add-nbcon-support-for-proc-consoles.patch b/debian/patches-rt/0127-proc-Add-nbcon-support-for-proc-consoles.patch
new file mode 100644
index 0000000000..615ecb02a3
--- /dev/null
+++ b/debian/patches-rt/0127-proc-Add-nbcon-support-for-proc-consoles.patch
@@ -0,0 +1,53 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Tue, 26 Sep 2023 13:31:00 +0000
+Subject: [PATCH 127/134] proc: Add nbcon support for /proc/consoles
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Update /proc/consoles output to show 'W' if an nbcon write
+callback is implemented (write_atomic or write_thread).
+
+Also update /proc/consoles output to show 'N' if it is an
+nbcon console.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ fs/proc/consoles.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/fs/proc/consoles.c
++++ b/fs/proc/consoles.c
+@@ -21,12 +21,14 @@ static int show_console_dev(struct seq_f
+ { CON_ENABLED, 'E' },
+ { CON_CONSDEV, 'C' },
+ { CON_BOOT, 'B' },
++ { CON_NBCON, 'N' },
+ { CON_PRINTBUFFER, 'p' },
+ { CON_BRL, 'b' },
+ { CON_ANYTIME, 'a' },
+ };
+ char flags[ARRAY_SIZE(con_flags) + 1];
+ struct console *con = v;
++ char con_write = '-';
+ unsigned int a;
+ dev_t dev = 0;
+
+@@ -57,9 +59,15 @@ static int show_console_dev(struct seq_f
+ seq_setwidth(m, 21 - 1);
+ seq_printf(m, "%s%d", con->name, con->index);
+ seq_pad(m, ' ');
+- seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-',
+- con->write ? 'W' : '-', con->unblank ? 'U' : '-',
+- flags);
++ if (con->flags & CON_NBCON) {
++ if (con->write_atomic || con->write_thread)
++ con_write = 'W';
++ } else {
++ if (con->write)
++ con_write = 'W';
++ }
++ seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-', con_write,
++ con->unblank ? 'U' : '-', flags);
+ if (dev)
+ seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev));
+
diff --git a/debian/patches-rt/0128-tty-sysfs-Add-nbcon-support-for-active.patch b/debian/patches-rt/0128-tty-sysfs-Add-nbcon-support-for-active.patch
new file mode 100644
index 0000000000..f8b285f432
--- /dev/null
+++ b/debian/patches-rt/0128-tty-sysfs-Add-nbcon-support-for-active.patch
@@ -0,0 +1,33 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 22 Sep 2023 14:31:09 +0000
+Subject: [PATCH 128/134] tty: sysfs: Add nbcon support for 'active'
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Allow the 'active' attribute to list nbcon consoles.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/tty_io.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -3540,8 +3540,15 @@ static ssize_t show_cons_active(struct d
+ for_each_console(c) {
+ if (!c->device)
+ continue;
+- if (!c->write)
+- continue;
++ if (c->flags & CON_NBCON) {
++ if (!c->write_atomic &&
++ !(c->write_thread && c->kthread)) {
++ continue;
++ }
++ } else {
++ if (!c->write)
++ continue;
++ }
+ if ((c->flags & CON_ENABLED) == 0)
+ continue;
+ cs[i++] = c;
diff --git a/debian/patches-rt/0129-printk-nbcon-Provide-function-to-reacquire-ownership.patch b/debian/patches-rt/0129-printk-nbcon-Provide-function-to-reacquire-ownership.patch
new file mode 100644
index 0000000000..e878a4b1b7
--- /dev/null
+++ b/debian/patches-rt/0129-printk-nbcon-Provide-function-to-reacquire-ownership.patch
@@ -0,0 +1,92 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 20 Oct 2023 10:01:58 +0000
+Subject: [PATCH 129/134] printk: nbcon: Provide function to reacquire
+ ownership
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Contexts may become nbcon owners for various reasons, not just
+for printing. Indeed, the port->lock wrapper takes ownership
+for anything relating to the hardware.
+
+Since ownership can be lost at any time due to handover or
+takeover, a context _should_ be prepared to back out
+immediately and carefully. However, there are many scenarios
+where the context _must_ reacquire ownership in order to
+finalize or revert hardware changes.
+
+One such example is when interrupts are disabled by a context.
+No other context will automagically re-enable the interrupts.
+For this case, the disabling context _must_ reacquire nbcon
+ownership so that it can re-enable the interrupts.
+
+Provide nbcon_reacquire() for exactly this purpose.
+
+Note that for printing contexts, after a successful reacquire
+the context will have no output buffer because that has been
+lost. nbcon_reacquire() cannot be used to resume printing.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 2 ++
+ kernel/printk/nbcon.c | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -474,12 +474,14 @@ extern void nbcon_cpu_emergency_exit(voi
+ extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt);
+ extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt);
+ extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt);
++extern void nbcon_reacquire(struct nbcon_write_context *wctxt);
+ #else
+ static inline void nbcon_cpu_emergency_enter(void) { }
+ static inline void nbcon_cpu_emergency_exit(void) { }
+ static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; }
+ static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; }
+ static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; }
++static inline void nbcon_reacquire(struct nbcon_write_context *wctxt) { }
+ #endif
+
+ extern int console_set_on_cmdline;
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -831,6 +831,38 @@ bool nbcon_exit_unsafe(struct nbcon_writ
+ EXPORT_SYMBOL_GPL(nbcon_exit_unsafe);
+
+ /**
++ * nbcon_reacquire - Reacquire a console after losing ownership
++ * @wctxt: The write context that was handed to the write function
++ *
++ * Since ownership can be lost at any time due to handover or takeover, a
++ * printing context _should_ be prepared to back out immediately and
++ * carefully. However, there are many scenarios where the context _must_
++ * reacquire ownership in order to finalize or revert hardware changes.
++ *
++ * This function allows a context to reacquire ownership using the same
++ * priority as its previous ownership.
++ *
++ * Note that for printing contexts, after a successful reacquire the
++ * context will have no output buffer because that has been lost. This
++ * function cannot be used to resume printing.
++ */
++void nbcon_reacquire(struct nbcon_write_context *wctxt)
++{
++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt);
++ struct console *con = ctxt->console;
++ struct nbcon_state cur;
++
++ while (!nbcon_context_try_acquire(ctxt))
++ cpu_relax();
++
++ wctxt->outbuf = NULL;
++ wctxt->len = 0;
++ nbcon_state_read(con, &cur);
++ wctxt->unsafe_takeover = cur.unsafe_takeover;
++}
++EXPORT_SYMBOL_GPL(nbcon_reacquire);
++
++/**
+ * nbcon_emit_next_record - Emit a record in the acquired context
+ * @wctxt: The write context that will be handed to the write function
+ * @use_atomic: True if the write_atomic callback is to be used
diff --git a/debian/patches-rt/0130-serial-core-Provide-low-level-functions-to-port-lock.patch b/debian/patches-rt/0130-serial-core-Provide-low-level-functions-to-port-lock.patch
new file mode 100644
index 0000000000..e8e506fe52
--- /dev/null
+++ b/debian/patches-rt/0130-serial-core-Provide-low-level-functions-to-port-lock.patch
@@ -0,0 +1,43 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 11 Dec 2023 09:19:18 +0000
+Subject: [PATCH 130/134] serial: core: Provide low-level functions to port
+ lock
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The nbcon console's driver_enter() and driver_exit() callbacks need
+to lock the port lock in order to synchronize against other hardware
+activity (such as adjusting baud rates). However, they cannot use
+the uart_port_lock() wrappers because the printk subsystem will
+perform nbcon locking after calling the driver_enter() callback.
+
+Provide low-level variants __uart_port_lock_irqsave() and
+__uart_port_unlock_irqrestore() for this purpose. These are only
+to be used by the driver_enter()/driver_exit() callbacks.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/serial_core.h | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -681,6 +681,18 @@ static inline void uart_port_unlock_irqr
+ spin_unlock_irqrestore(&up->lock, flags);
+ }
+
++/* Only for use in the console->driver_enter() callback. */
++static inline void __uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags)
++{
++ spin_lock_irqsave(&up->lock, *flags);
++}
++
++/* Only for use in the console->driver_exit() callback. */
++static inline void __uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags)
++{
++ spin_unlock_irqrestore(&up->lock, flags);
++}
++
+ static inline int serial_port_in(struct uart_port *up, int offset)
+ {
+ return up->serial_in(up, offset);
diff --git a/debian/patches-rt/0131-serial-8250-Switch-to-nbcon-console.patch b/debian/patches-rt/0131-serial-8250-Switch-to-nbcon-console.patch
new file mode 100644
index 0000000000..7ba577d9c4
--- /dev/null
+++ b/debian/patches-rt/0131-serial-8250-Switch-to-nbcon-console.patch
@@ -0,0 +1,335 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 13 Sep 2023 15:30:36 +0000
+Subject: [PATCH 131/134] serial: 8250: Switch to nbcon console
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Implement the necessary callbacks to switch the 8250 console driver
+to perform as an nbcon console.
+
+Add implementations for the nbcon consoles (write_atomic, write_thread,
+driver_enter, driver_exit) and add CON_NBCON to the initial flags.
+
+The legacy code is kept in order to easily switch back to legacy mode
+by defining CONFIG_SERIAL_8250_LEGACY_CONSOLE.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_core.c | 42 +++++++++
+ drivers/tty/serial/8250/8250_port.c | 156 +++++++++++++++++++++++++++++++++++-
+ include/linux/serial_8250.h | 6 +
+ 3 files changed, 201 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -592,6 +592,7 @@ serial8250_register_ports(struct uart_dr
+
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+
++#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE
+ static void univ8250_console_write(struct console *co, const char *s,
+ unsigned int count)
+ {
+@@ -599,6 +600,37 @@ static void univ8250_console_write(struc
+
+ serial8250_console_write(up, s, count);
+ }
++#else
++static bool univ8250_console_write_atomic(struct console *co,
++ struct nbcon_write_context *wctxt)
++{
++ struct uart_8250_port *up = &serial8250_ports[co->index];
++
++ return serial8250_console_write_atomic(up, wctxt);
++}
++
++static bool univ8250_console_write_thread(struct console *co,
++ struct nbcon_write_context *wctxt)
++{
++ struct uart_8250_port *up = &serial8250_ports[co->index];
++
++ return serial8250_console_write_thread(up, wctxt);
++}
++
++static void univ8250_console_driver_enter(struct console *con, unsigned long *flags)
++{
++ struct uart_port *up = &serial8250_ports[con->index].port;
++
++ __uart_port_lock_irqsave(up, flags);
++}
++
++static void univ8250_console_driver_exit(struct console *con, unsigned long flags)
++{
++ struct uart_port *up = &serial8250_ports[con->index].port;
++
++ __uart_port_unlock_irqrestore(up, flags);
++}
++#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */
+
+ static int univ8250_console_setup(struct console *co, char *options)
+ {
+@@ -698,12 +730,20 @@ static int univ8250_console_match(struct
+
+ static struct console univ8250_console = {
+ .name = "ttyS",
++#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE
+ .write = univ8250_console_write,
++ .flags = CON_PRINTBUFFER | CON_ANYTIME,
++#else
++ .write_atomic = univ8250_console_write_atomic,
++ .write_thread = univ8250_console_write_thread,
++ .driver_enter = univ8250_console_driver_enter,
++ .driver_exit = univ8250_console_driver_exit,
++ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON,
++#endif
+ .device = uart_console_device,
+ .setup = univ8250_console_setup,
+ .exit = univ8250_console_exit,
+ .match = univ8250_console_match,
+- .flags = CON_PRINTBUFFER | CON_ANYTIME,
+ .index = -1,
+ .data = &serial8250_reg,
+ };
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -557,6 +557,11 @@ static int serial8250_em485_init(struct
+ if (!p->em485)
+ return -ENOMEM;
+
++#ifndef CONFIG_SERIAL_8250_LEGACY_CONSOLE
++ if (uart_console(&p->port))
++ dev_warn(p->port.dev, "no atomic printing for rs485 consoles\n");
++#endif
++
+ hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC,
+@@ -709,7 +714,11 @@ static void serial8250_set_sleep(struct
+ serial8250_rpm_put(p);
+ }
+
+-static void serial8250_clear_IER(struct uart_8250_port *up)
++/*
++ * Only to be used by write_atomic() and the legacy write(), which do not
++ * require port lock.
++ */
++static void __serial8250_clear_IER(struct uart_8250_port *up)
+ {
+ if (up->capabilities & UART_CAP_UUE)
+ serial_out(up, UART_IER, UART_IER_UUE);
+@@ -717,6 +726,11 @@ static void serial8250_clear_IER(struct
+ serial_out(up, UART_IER, 0);
+ }
+
++static inline void serial8250_clear_IER(struct uart_8250_port *up)
++{
++ __serial8250_clear_IER(up);
++}
++
+ #ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * Attempts to turn on the RSA FIFO. Returns zero on failure.
+@@ -3328,6 +3342,11 @@ static void serial8250_console_putchar(s
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_port_out(port, UART_TX, ch);
++
++ if (ch == '\n')
++ up->console_newline_needed = false;
++ else
++ up->console_newline_needed = true;
+ }
+
+ /*
+@@ -3356,6 +3375,7 @@ static void serial8250_console_restore(s
+ serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
+ }
+
++#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE
+ /*
+ * Print a string to the serial port using the device FIFO
+ *
+@@ -3414,7 +3434,7 @@ void serial8250_console_write(struct uar
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_port_in(port, UART_IER);
+- serial8250_clear_IER(up);
++ __serial8250_clear_IER(up);
+
+ /* check scratch reg to see if port powered off during system sleep */
+ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
+@@ -3480,6 +3500,135 @@ void serial8250_console_write(struct uar
+ if (locked)
+ uart_port_unlock_irqrestore(port, flags);
+ }
++#else
++bool serial8250_console_write_thread(struct uart_8250_port *up,
++ struct nbcon_write_context *wctxt)
++{
++ struct uart_8250_em485 *em485 = up->em485;
++ struct uart_port *port = &up->port;
++ bool done = false;
++ unsigned int ier;
++
++ touch_nmi_watchdog();
++
++ if (!nbcon_enter_unsafe(wctxt))
++ return false;
++
++ /* First save IER then disable the interrupts. */
++ ier = serial_port_in(port, UART_IER);
++ serial8250_clear_IER(up);
++
++ /* Check scratch reg if port powered off during system sleep. */
++ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
++ serial8250_console_restore(up);
++ up->canary = 0;
++ }
++
++ if (em485) {
++ if (em485->tx_stopped)
++ up->rs485_start_tx(up);
++ mdelay(port->rs485.delay_rts_before_send);
++ }
++
++ if (nbcon_exit_unsafe(wctxt)) {
++ int len = READ_ONCE(wctxt->len);
++ int i;
++
++ /*
++ * Write out the message. Toggle unsafe for each byte in order
++ * to give another (higher priority) context the opportunity
++ * for a friendly takeover. If such a takeover occurs, this
++ * context must reacquire ownership in order to perform final
++ * actions (such as re-enabling the interrupts).
++ *
++ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid
++ * after a reacquire so writing the message must be
++ * aborted.
++ */
++ for (i = 0; i < len; i++) {
++ if (!nbcon_enter_unsafe(wctxt)) {
++ nbcon_reacquire(wctxt);
++ break;
++ }
++
++ uart_console_write(port, wctxt->outbuf + i, 1, serial8250_console_putchar);
++
++ if (!nbcon_exit_unsafe(wctxt)) {
++ nbcon_reacquire(wctxt);
++ break;
++ }
++ }
++ done = (i == len);
++ } else {
++ nbcon_reacquire(wctxt);
++ }
++
++ while (!nbcon_enter_unsafe(wctxt))
++ nbcon_reacquire(wctxt);
++
++ /* Finally, wait for transmitter to become empty and restore IER. */
++ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
++ if (em485) {
++ mdelay(port->rs485.delay_rts_after_send);
++ if (em485->tx_stopped)
++ up->rs485_stop_tx(up);
++ }
++ serial_port_out(port, UART_IER, ier);
++
++ /*
++ * The receive handling will happen properly because the receive ready
++ * bit will still be set; it is not cleared on read. However, modem
++ * control will not, we must call it if we have saved something in the
++ * saved flags while processing with interrupts off.
++ */
++ if (up->msr_saved_flags)
++ serial8250_modem_status(up);
++
++ /* Success if no handover/takeover and message fully printed. */
++ return (nbcon_exit_unsafe(wctxt) && done);
++}
++
++bool serial8250_console_write_atomic(struct uart_8250_port *up,
++ struct nbcon_write_context *wctxt)
++{
++ struct uart_port *port = &up->port;
++ unsigned int ier;
++
++ /* Atomic console not supported for rs485 mode. */
++ if (up->em485)
++ return false;
++
++ touch_nmi_watchdog();
++
++ if (!nbcon_enter_unsafe(wctxt))
++ return false;
++
++ /*
++ * First save IER then disable the interrupts. The special variant to
++ * clear IER is used because atomic printing may occur without holding
++ * the port lock.
++ */
++ ier = serial_port_in(port, UART_IER);
++ __serial8250_clear_IER(up);
++
++ /* Check scratch reg if port powered off during system sleep. */
++ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
++ serial8250_console_restore(up);
++ up->canary = 0;
++ }
++
++ if (up->console_newline_needed)
++ uart_console_write(port, "\n", 1, serial8250_console_putchar);
++ uart_console_write(port, wctxt->outbuf, wctxt->len, serial8250_console_putchar);
++
++ /* Finally, wait for transmitter to become empty and restore IER. */
++ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
++ serial_port_out(port, UART_IER, ier);
++
++ /* Success if no handover/takeover. */
++ return nbcon_exit_unsafe(wctxt);
++}
++#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */
+
+ static unsigned int probe_baud(struct uart_port *port)
+ {
+@@ -3498,6 +3647,7 @@ static unsigned int probe_baud(struct ua
+
+ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
+ {
++ struct uart_8250_port *up = up_to_u8250p(port);
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+@@ -3507,6 +3657,8 @@ int serial8250_console_setup(struct uart
+ if (!port->iobase && !port->membase)
+ return -ENODEV;
+
++ up->console_newline_needed = false;
++
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else if (probe)
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -153,6 +153,8 @@ struct uart_8250_port {
+ #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+
++ bool console_newline_needed;
++
+ struct uart_8250_dma *dma;
+ const struct uart_8250_ops *ops;
+
+@@ -204,6 +206,10 @@ void serial8250_init_port(struct uart_82
+ void serial8250_set_defaults(struct uart_8250_port *up);
+ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ unsigned int count);
++bool serial8250_console_write_atomic(struct uart_8250_port *up,
++ struct nbcon_write_context *wctxt);
++bool serial8250_console_write_thread(struct uart_8250_port *up,
++ struct nbcon_write_context *wctxt);
+ int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
+ int serial8250_console_exit(struct uart_port *port);
+
diff --git a/debian/patches-rt/0132-printk-Add-kthread-for-all-legacy-consoles.patch b/debian/patches-rt/0132-printk-Add-kthread-for-all-legacy-consoles.patch
new file mode 100644
index 0000000000..7c46be7133
--- /dev/null
+++ b/debian/patches-rt/0132-printk-Add-kthread-for-all-legacy-consoles.patch
@@ -0,0 +1,422 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 22 Sep 2023 17:35:04 +0000
+Subject: [PATCH 132/134] printk: Add kthread for all legacy consoles
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The write callback of legacy consoles make use of spinlocks.
+This is not permitted with PREEMPT_RT in atomic contexts.
+
+Create a new kthread to handle printing of all the legacy
+consoles (and nbcon consoles if boot consoles are registered).
+
+Since the consoles are printing in a task context, it is no
+longer appropriate to support the legacy handover mechanism.
+
+These changes exist only for CONFIG_PREEMPT_RT.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/internal.h | 1
+ kernel/printk/nbcon.c | 18 ++-
+ kernel/printk/printk.c | 237 +++++++++++++++++++++++++++++++++++++++--------
+ 3 files changed, 210 insertions(+), 46 deletions(-)
+
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -95,6 +95,7 @@ void nbcon_atomic_flush_all(void);
+ bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie);
+ void nbcon_kthread_create(struct console *con);
+ void nbcon_wake_threads(void);
++void nbcon_legacy_kthread_create(void);
+
+ /*
+ * Check if the given console is currently capable and allowed to print
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -1247,9 +1247,11 @@ bool nbcon_atomic_emit_next_record(struc
+ *handover = false;
+
+ /* Use the same locking order as console_emit_next_record(). */
+- printk_safe_enter_irqsave(flags);
+- console_lock_spinning_enable();
+- stop_critical_timings();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
++ printk_safe_enter_irqsave(flags);
++ console_lock_spinning_enable();
++ stop_critical_timings();
++ }
+
+ con->driver_enter(con, &driver_flags);
+ cant_migrate();
+@@ -1261,9 +1263,11 @@ bool nbcon_atomic_emit_next_record(struc
+
+ con->driver_exit(con, driver_flags);
+
+- start_critical_timings();
+- *handover = console_lock_spinning_disable_and_check(cookie);
+- printk_safe_exit_irqrestore(flags);
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
++ start_critical_timings();
++ *handover = console_lock_spinning_disable_and_check(cookie);
++ printk_safe_exit_irqrestore(flags);
++ }
+
+ return progress;
+ }
+@@ -1469,6 +1473,8 @@ static int __init printk_setup_threads(v
+ printk_threads_enabled = true;
+ for_each_console(con)
+ nbcon_kthread_create(con);
++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && printing_via_unlock)
++ nbcon_legacy_kthread_create();
+ console_list_unlock();
+ return 0;
+ }
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -487,6 +487,9 @@ bool have_boot_console;
+
+ #ifdef CONFIG_PRINTK
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
++
++static DECLARE_WAIT_QUEUE_HEAD(legacy_wait);
++
+ /* All 3 protected by @syslog_lock. */
+ /* the next printk record to read by syslog(READ) or /proc/kmsg */
+ static u64 syslog_seq;
+@@ -2345,7 +2348,8 @@ asmlinkage int vprintk_emit(int facility
+ const struct dev_printk_info *dev_info,
+ const char *fmt, va_list args)
+ {
+- bool do_trylock_unlock = printing_via_unlock;
++ bool do_trylock_unlock = printing_via_unlock &&
++ !IS_ENABLED(CONFIG_PREEMPT_RT);
+ int printed_len;
+
+ /* Suppress unimportant messages after panic happens */
+@@ -2473,6 +2477,14 @@ EXPORT_SYMBOL(_printk);
+ static bool pr_flush(int timeout_ms, bool reset_on_progress);
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
+
++static struct task_struct *nbcon_legacy_kthread;
++
++static inline void wake_up_legacy_kthread(void)
++{
++ if (nbcon_legacy_kthread)
++ wake_up_interruptible(&legacy_wait);
++}
++
+ #else /* CONFIG_PRINTK */
+
+ #define printk_time false
+@@ -2486,6 +2498,8 @@ static u64 syslog_seq;
+ static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; }
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
+
++static inline void nbcon_legacy_kthread_create(void) { }
++static inline void wake_up_legacy_kthread(void) { }
+ #endif /* CONFIG_PRINTK */
+
+ #ifdef CONFIG_EARLY_PRINTK
+@@ -2723,6 +2737,8 @@ void resume_console(void)
+ }
+ console_srcu_read_unlock(cookie);
+
++ wake_up_legacy_kthread();
++
+ pr_flush(1000, true);
+ }
+
+@@ -2737,7 +2753,8 @@ void resume_console(void)
+ */
+ static int console_cpu_notify(unsigned int cpu)
+ {
+- if (!cpuhp_tasks_frozen && printing_via_unlock) {
++ if (!cpuhp_tasks_frozen && printing_via_unlock &&
++ !IS_ENABLED(CONFIG_PREEMPT_RT)) {
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
+@@ -2962,31 +2979,43 @@ static bool console_emit_next_record(str
+ con->dropped = 0;
+ }
+
+- /*
+- * While actively printing out messages, if another printk()
+- * were to occur on another CPU, it may wait for this one to
+- * finish. This task can not be preempted if there is a
+- * waiter waiting to take over.
+- *
+- * Interrupts are disabled because the hand over to a waiter
+- * must not be interrupted until the hand over is completed
+- * (@console_waiter is cleared).
+- */
+- printk_safe_enter_irqsave(flags);
+- console_lock_spinning_enable();
++ /* Write everything out to the hardware. */
+
+- /* Do not trace print latency. */
+- stop_critical_timings();
++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
++ /*
++ * On PREEMPT_RT this function is either in a thread or
++ * panic context. So there is no need for concern about
++ * printk reentrance or handovers.
++ */
+
+- /* Write everything out to the hardware. */
+- con->write(con, outbuf, pmsg.outbuf_len);
++ con->write(con, outbuf, pmsg.outbuf_len);
++ con->seq = pmsg.seq + 1;
++ } else {
++ /*
++ * While actively printing out messages, if another printk()
++ * were to occur on another CPU, it may wait for this one to
++ * finish. This task can not be preempted if there is a
++ * waiter waiting to take over.
++ *
++ * Interrupts are disabled because the hand over to a waiter
++ * must not be interrupted until the hand over is completed
++ * (@console_waiter is cleared).
++ */
++ printk_safe_enter_irqsave(flags);
++ console_lock_spinning_enable();
+
+- start_critical_timings();
++ /* Do not trace print latency. */
++ stop_critical_timings();
+
+- con->seq = pmsg.seq + 1;
++ con->write(con, outbuf, pmsg.outbuf_len);
+
+- *handover = console_lock_spinning_disable_and_check(cookie);
+- printk_safe_exit_irqrestore(flags);
++ start_critical_timings();
++
++ con->seq = pmsg.seq + 1;
++
++ *handover = console_lock_spinning_disable_and_check(cookie);
++ printk_safe_exit_irqrestore(flags);
++ }
+ skip:
+ return true;
+ }
+@@ -3096,19 +3125,7 @@ static bool console_flush_all(bool do_co
+ return false;
+ }
+
+-/**
+- * console_unlock - unblock the console subsystem from printing
+- *
+- * Releases the console_lock which the caller holds to block printing of
+- * the console subsystem.
+- *
+- * While the console_lock was held, console output may have been buffered
+- * by printk(). If this is the case, console_unlock(); emits
+- * the output prior to releasing the lock.
+- *
+- * console_unlock(); may be called from any context.
+- */
+-void console_unlock(void)
++static void console_flush_and_unlock(void)
+ {
+ bool do_cond_resched;
+ bool handover;
+@@ -3152,6 +3169,32 @@ void console_unlock(void)
+ */
+ } while (prb_read_valid(prb, next_seq, NULL) && console_trylock());
+ }
++
++/**
++ * console_unlock - unblock the console subsystem from printing
++ *
++ * Releases the console_lock which the caller holds to block printing of
++ * the console subsystem.
++ *
++ * While the console_lock was held, console output may have been buffered
++ * by printk(). If this is the case, console_unlock(); emits
++ * the output prior to releasing the lock.
++ *
++ * console_unlock(); may be called from any context.
++ */
++void console_unlock(void)
++{
++ /*
++ * PREEMPT_RT relies on kthread and atomic consoles for printing.
++ * It never attempts to print from console_unlock().
++ */
++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
++ __console_unlock();
++ return;
++ }
++
++ console_flush_and_unlock();
++}
+ EXPORT_SYMBOL(console_unlock);
+
+ /**
+@@ -3361,11 +3404,106 @@ void console_start(struct console *conso
+
+ if (flags & CON_NBCON)
+ nbcon_kthread_wake(console);
++ else
++ wake_up_legacy_kthread();
+
+ __pr_flush(console, 1000, true);
+ }
+ EXPORT_SYMBOL(console_start);
+
++#ifdef CONFIG_PRINTK
++static bool printer_should_wake(void)
++{
++ bool available = false;
++ struct console *con;
++ int cookie;
++
++ if (kthread_should_stop())
++ return true;
++
++ cookie = console_srcu_read_lock();
++ for_each_console_srcu(con) {
++ short flags = console_srcu_read_flags(con);
++ u64 printk_seq;
++
++ /*
++ * The legacy printer thread is only for legacy consoles,
++ * unless the nbcon console has no kthread printer.
++ */
++ if ((flags & CON_NBCON) && con->kthread)
++ continue;
++
++ if (!console_is_usable(con, flags, true))
++ continue;
++
++ if (flags & CON_NBCON) {
++ printk_seq = nbcon_seq_read(con);
++ } else {
++ /*
++ * It is safe to read @seq because only this
++ * thread context updates @seq.
++ */
++ printk_seq = con->seq;
++ }
++
++ if (prb_read_valid(prb, printk_seq, NULL)) {
++ available = true;
++ break;
++ }
++ }
++ console_srcu_read_unlock(cookie);
++
++ return available;
++}
++
++static int nbcon_legacy_kthread_func(void *unused)
++{
++ int error;
++
++ for (;;) {
++ error = wait_event_interruptible(legacy_wait, printer_should_wake());
++
++ if (kthread_should_stop())
++ break;
++
++ if (error)
++ continue;
++
++ console_lock();
++ console_flush_and_unlock();
++ }
++
++ return 0;
++}
++
++void nbcon_legacy_kthread_create(void)
++{
++ struct task_struct *kt;
++
++ lockdep_assert_held(&console_mutex);
++
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ return;
++
++ if (!printk_threads_enabled || nbcon_legacy_kthread)
++ return;
++
++ kt = kthread_run(nbcon_legacy_kthread_func, NULL, "pr/legacy");
++ if (IS_ERR(kt)) {
++ pr_err("unable to start legacy printing thread\n");
++ return;
++ }
++
++ nbcon_legacy_kthread = kt;
++
++ /*
++ * It is important that console printing threads are scheduled
++ * shortly after a printk call and with generous runtime budgets.
++ */
++ sched_set_normal(nbcon_legacy_kthread, -20);
++}
++#endif /* CONFIG_PRINTK */
++
+ static int __read_mostly keep_bootcon;
+
+ static int __init keep_bootcon_setup(char *str)
+@@ -3632,6 +3770,7 @@ void register_console(struct console *ne
+ nbcon_init(newcon);
+ } else {
+ have_legacy_console = true;
++ nbcon_legacy_kthread_create();
+ }
+
+ if (newcon->flags & CON_BOOT)
+@@ -3770,6 +3909,13 @@ static int unregister_console_locked(str
+ nbcon_kthread_create(c);
+ }
+
++#ifdef CONFIG_PRINTK
++ if (!printing_via_unlock && nbcon_legacy_kthread) {
++ kthread_stop(nbcon_legacy_kthread);
++ nbcon_legacy_kthread = NULL;
++ }
++#endif
++
+ return res;
+ }
+
+@@ -3929,8 +4075,12 @@ static bool __pr_flush(struct console *c
+
+ seq = prb_next_reserve_seq(prb);
+
+- /* Flush the consoles so that records up to @seq are printed. */
+- if (printing_via_unlock) {
++ /*
++ * Flush the consoles so that records up to @seq are printed.
++ * Otherwise this function will just wait for the threaded printers
++ * to print up to @seq.
++ */
++ if (printing_via_unlock && !IS_ENABLED(CONFIG_PREEMPT_RT)) {
+ console_lock();
+ console_unlock();
+ }
+@@ -4038,9 +4188,16 @@ static void wake_up_klogd_work_func(stru
+ int pending = this_cpu_xchg(printk_pending, 0);
+
+ if (pending & PRINTK_PENDING_OUTPUT) {
+- /* If trylock fails, someone else is doing the printing */
+- if (console_trylock())
+- console_unlock();
++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
++ wake_up_interruptible(&legacy_wait);
++ } else {
++ /*
++ * If trylock fails, some other context
++ * will do the printing.
++ */
++ if (console_trylock())
++ console_unlock();
++ }
+ }
+
+ if (pending & PRINTK_PENDING_WAKEUP)
diff --git a/debian/patches-rt/0133-serial-8250-revert-drop-lockdep-annotation-from-seri.patch b/debian/patches-rt/0133-serial-8250-revert-drop-lockdep-annotation-from-seri.patch
new file mode 100644
index 0000000000..c9eba0a738
--- /dev/null
+++ b/debian/patches-rt/0133-serial-8250-revert-drop-lockdep-annotation-from-seri.patch
@@ -0,0 +1,29 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 2 Oct 2023 15:30:43 +0000
+Subject: [PATCH 133/134] serial: 8250: revert "drop lockdep annotation from
+ serial8250_clear_IER()"
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The 8250 driver no longer depends on @oops_in_progress and
+will no longer violate the port->lock locking constraints.
+
+This reverts commit 3d9e6f556e235ddcdc9f73600fdd46fe1736b090.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250_port.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -728,6 +728,9 @@ static void __serial8250_clear_IER(struc
+
+ static inline void serial8250_clear_IER(struct uart_8250_port *up)
+ {
++ /* Port locked to synchronize UART_IER access against the console. */
++ lockdep_assert_held_once(&up->port.lock);
++
+ __serial8250_clear_IER(up);
+ }
+
diff --git a/debian/patches-rt/0134-printk-Avoid-false-positive-lockdep-report-for-legac.patch b/debian/patches-rt/0134-printk-Avoid-false-positive-lockdep-report-for-legac.patch
new file mode 100644
index 0000000000..225e8db694
--- /dev/null
+++ b/debian/patches-rt/0134-printk-Avoid-false-positive-lockdep-report-for-legac.patch
@@ -0,0 +1,64 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 11 Dec 2023 09:34:16 +0000
+Subject: [PATCH 134/134] printk: Avoid false positive lockdep report for
+ legacy driver.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+printk may invoke the legacy console driver from atomic context. This leads to
+a lockdep splat because the console driver will acquire a sleeping lock and the
+caller may also hold a spinning lock. This is noticed by lockdep on !PREEMPT_RT
+configurations because it will also lead to a problem on PREEMPT_RT.
+
+On PREEMPT_RT the atomic path is always avoided and the console driver is
+always invoked from a dedicated thread. Thus the lockdep splat is a false
+positive.
+
+Override the lock-context before invoking the console driver.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2817,6 +2817,8 @@ static void __console_unlock(void)
+ up_console_sem();
+ }
+
++static DEFINE_WAIT_OVERRIDE_MAP(printk_legacy_map, LD_WAIT_SLEEP);
++
+ #ifdef CONFIG_PRINTK
+
+ /*
+@@ -2985,7 +2987,7 @@ static bool console_emit_next_record(str
+ /*
+ * On PREEMPT_RT this function is either in a thread or
+ * panic context. So there is no need for concern about
+- * printk reentrance or handovers.
++ * printk reentrance, handovers, or lockdep complaints.
+ */
+
+ con->write(con, outbuf, pmsg.outbuf_len);
+@@ -3007,7 +3009,9 @@ static bool console_emit_next_record(str
+ /* Do not trace print latency. */
+ stop_critical_timings();
+
++ lock_map_acquire_try(&printk_legacy_map);
+ con->write(con, outbuf, pmsg.outbuf_len);
++ lock_map_release(&printk_legacy_map);
+
+ start_critical_timings();
+
+@@ -3084,7 +3088,10 @@ static bool console_flush_all(bool do_co
+ any_usable = true;
+
+ if (flags & CON_NBCON) {
++
++ lock_map_acquire_try(&printk_legacy_map);
+ progress = nbcon_atomic_emit_next_record(con, handover, cookie);
++ lock_map_release(&printk_legacy_map);
+
+ printk_seq = nbcon_seq_read(con);
+ } else {
diff --git a/debian/patches-rt/ARM64__Allow_to_enable_RT.patch b/debian/patches-rt/ARM64__Allow_to_enable_RT.patch
new file mode 100644
index 0000000000..3657ef8700
--- /dev/null
+++ b/debian/patches-rt/ARM64__Allow_to_enable_RT.patch
@@ -0,0 +1,27 @@
+Subject: ARM64: Allow to enable RT
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri Oct 11 13:14:35 2019 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+Allow to select RT.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/arm64/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+---
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -97,6 +97,7 @@ config ARM64
+ select ARCH_SUPPORTS_NUMA_BALANCING
+ select ARCH_SUPPORTS_PAGE_TABLE_CHECK
+ select ARCH_SUPPORTS_PER_VMA_LOCK
++ select ARCH_SUPPORTS_RT
+ select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
+ select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
+ select ARCH_WANT_DEFAULT_BPF_JIT
diff --git a/debian/patches-rt/ARM__Allow_to_enable_RT.patch b/debian/patches-rt/ARM__Allow_to_enable_RT.patch
new file mode 100644
index 0000000000..902eca18c3
--- /dev/null
+++ b/debian/patches-rt/ARM__Allow_to_enable_RT.patch
@@ -0,0 +1,35 @@
+Subject: ARM: Allow to enable RT
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri Oct 11 13:14:29 2019 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+Allow to select RT.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/arm/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+---
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -34,6 +34,7 @@ config ARM
+ select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
+ select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE
++ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK
+ select ARCH_USE_BUILTIN_BSWAP
+ select ARCH_USE_CMPXCHG_LOCKREF
+ select ARCH_USE_MEMTEST
+@@ -118,6 +119,7 @@ config ARM
+ select HAVE_PERF_EVENTS
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
++ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM
+ select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
+ select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RSEQ
diff --git a/debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch b/debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch
new file mode 100644
index 0000000000..ce42fd3a27
--- /dev/null
+++ b/debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch
@@ -0,0 +1,91 @@
+Subject: ARM: enable irq in translation/section permission fault handlers
+From: Yadi.hu <yadi.hu@windriver.com>
+Date: Wed Dec 10 10:32:09 2014 +0800
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Yadi.hu <yadi.hu@windriver.com>
+
+Probably happens on all ARM, with
+CONFIG_PREEMPT_RT
+CONFIG_DEBUG_ATOMIC_SLEEP
+
+This simple program....
+
+int main() {
+ *((char*)0xc0001000) = 0;
+};
+
+[ 512.742724] BUG: sleeping function called from invalid context at kernel/rtmutex.c:658
+[ 512.743000] in_atomic(): 0, irqs_disabled(): 128, pid: 994, name: a
+[ 512.743217] INFO: lockdep is turned off.
+[ 512.743360] irq event stamp: 0
+[ 512.743482] hardirqs last enabled at (0): [< (null)>] (null)
+[ 512.743714] hardirqs last disabled at (0): [<c0426370>] copy_process+0x3b0/0x11c0
+[ 512.744013] softirqs last enabled at (0): [<c0426370>] copy_process+0x3b0/0x11c0
+[ 512.744303] softirqs last disabled at (0): [< (null)>] (null)
+[ 512.744631] [<c041872c>] (unwind_backtrace+0x0/0x104)
+[ 512.745001] [<c09af0c4>] (dump_stack+0x20/0x24)
+[ 512.745355] [<c0462490>] (__might_sleep+0x1dc/0x1e0)
+[ 512.745717] [<c09b6770>] (rt_spin_lock+0x34/0x6c)
+[ 512.746073] [<c0441bf0>] (do_force_sig_info+0x34/0xf0)
+[ 512.746457] [<c0442668>] (force_sig_info+0x18/0x1c)
+[ 512.746829] [<c041d880>] (__do_user_fault+0x9c/0xd8)
+[ 512.747185] [<c041d938>] (do_bad_area+0x7c/0x94)
+[ 512.747536] [<c041d990>] (do_sect_fault+0x40/0x48)
+[ 512.747898] [<c040841c>] (do_DataAbort+0x40/0xa0)
+[ 512.748181] Exception stack(0xecaa1fb0 to 0xecaa1ff8)
+
+Oxc0000000 belongs to kernel address space, user task can not be
+allowed to access it. For above condition, correct result is that
+test case should receive a “segment fault” and exits but not stacks.
+
+the root cause is commit 02fe2845d6a8 ("avoid enabling interrupts in
+prefetch/data abort handlers"),it deletes irq enable block in Data
+abort assemble code and move them into page/breakpiont/alignment fault
+handlers instead. But author does not enable irq in translation/section
+permission fault handlers. ARM disables irq when it enters exception/
+interrupt mode, if kernel doesn't enable irq, it would be still disabled
+during translation/section permission fault.
+
+We see the above splat because do_force_sig_info is still called with
+IRQs off, and that code eventually does a:
+
+ spin_lock_irqsave(&t->sighand->siglock, flags);
+
+As this is architecture independent code, and we've not seen any other
+need for other arch to have the siglock converted to raw lock, we can
+conclude that we should enable irq for ARM translation/section
+permission exception.
+
+
+Signed-off-by: Yadi.hu <yadi.hu@windriver.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/arm/mm/fault.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+---
+--- a/arch/arm/mm/fault.c
++++ b/arch/arm/mm/fault.c
+@@ -404,6 +404,9 @@ do_translation_fault(unsigned long addr,
+ if (addr < TASK_SIZE)
+ return do_page_fault(addr, fsr, regs);
+
++ if (interrupts_enabled(regs))
++ local_irq_enable();
++
+ if (user_mode(regs))
+ goto bad_area;
+
+@@ -474,6 +477,9 @@ do_translation_fault(unsigned long addr,
+ static int
+ do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+ {
++ if (interrupts_enabled(regs))
++ local_irq_enable();
++
+ do_bad_area(addr, fsr, regs);
+ return 0;
+ }
diff --git a/debian/patches-rt/Add_localversion_for_-RT_release.patch b/debian/patches-rt/Add_localversion_for_-RT_release.patch
new file mode 100644
index 0000000000..55db77eff5
--- /dev/null
+++ b/debian/patches-rt/Add_localversion_for_-RT_release.patch
@@ -0,0 +1,19 @@
+Subject: Add localversion for -RT release
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri Jul 8 20:25:16 2011 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ localversion-rt | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 localversion-rt
+---
+--- /dev/null
++++ b/localversion-rt
+@@ -0,0 +1 @@
++-rt18
diff --git a/debian/patches-rt/POWERPC__Allow_to_enable_RT.patch b/debian/patches-rt/POWERPC__Allow_to_enable_RT.patch
new file mode 100644
index 0000000000..797e2084b4
--- /dev/null
+++ b/debian/patches-rt/POWERPC__Allow_to_enable_RT.patch
@@ -0,0 +1,35 @@
+Subject: POWERPC: Allow to enable RT
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri Oct 11 13:14:41 2019 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+Allow to select RT.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/powerpc/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+---
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -166,6 +166,7 @@ config PPC
+ select ARCH_STACKWALK
+ select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x
++ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK
+ select ARCH_USE_BUILTIN_BSWAP
+ select ARCH_USE_CMPXCHG_LOCKREF if PPC64
+ select ARCH_USE_MEMTEST
+@@ -268,6 +269,7 @@ config PPC
+ select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RELIABLE_STACKTRACE
++ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM
+ select HAVE_RSEQ
+ select HAVE_SETUP_PER_CPU_AREA if PPC64
+ select HAVE_SOFTIRQ_ON_OWN_STACK
diff --git a/debian/patches-rt/PREEMPT_AUTO.patch b/debian/patches-rt/PREEMPT_AUTO.patch
new file mode 100644
index 0000000000..859dadc20c
--- /dev/null
+++ b/debian/patches-rt/PREEMPT_AUTO.patch
@@ -0,0 +1,779 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Sat, 23 Sep 2023 03:11:05 +0200
+Subject: [PATCH] sched: define TIF_ALLOW_RESCHED
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+On Fri, Sep 22 2023 at 00:55, Thomas Gleixner wrote:
+> On Thu, Sep 21 2023 at 09:00, Linus Torvalds wrote:
+>> That said - I think as a proof of concept and "look, with this we get
+>> the expected scheduling event counts", that patch is perfect. I think
+>> you more than proved the concept.
+>
+> There is certainly quite some analyis work to do to make this a one to
+> one replacement.
+>
+> With a handful of benchmarks the PoC (tweaked with some obvious fixes)
+> is pretty much on par with the current mainline variants (NONE/FULL),
+> but the memtier benchmark makes a massive dent.
+>
+> It sports a whopping 10% regression with the LAZY mode versus the mainline
+> NONE model. Non-LAZY and FULL behave unsurprisingly in the same way.
+>
+> That benchmark is really sensitive to the preemption model. With current
+> mainline (DYNAMIC_PREEMPT enabled) the preempt=FULL model has ~20%
+> performance drop versus preempt=NONE.
+
+That 20% was a tired pilot error. The real number is in the 5% ballpark.
+
+> I have no clue what's going on there yet, but that shows that there is
+> obviously quite some work ahead to get this sorted.
+
+It took some head scratching to figure that out. The initial fix broke
+the handling of the hog issue, i.e. the problem that Ankur tried to
+solve, but I hacked up a "solution" for that too.
+
+With that the memtier benchmark is roughly back to the mainline numbers,
+but my throughput benchmark know how is pretty close to zero, so that
+should be looked at by people who actually understand these things.
+
+Likewise the hog prevention is just at the PoC level and clearly beyond
+my knowledge of scheduler details: It unconditionally forces a
+reschedule when the looping task is not responding to a lazy reschedule
+request before the next tick. IOW it forces a reschedule on the second
+tick, which is obviously different from the cond_resched()/might_sleep()
+behaviour.
+
+The changes vs. the original PoC aside of the bug and thinko fixes:
+
+ 1) A hack to utilize the TRACE_FLAG_IRQS_NOSUPPORT flag to trace the
+ lazy preempt bit as the trace_entry::flags field is full already.
+
+ That obviously breaks the tracer ABI, but if we go there then
+ this needs to be fixed. Steven?
+
+ 2) debugfs file to validate that loops can be force preempted w/o
+ cond_resched()
+
+ The usage is:
+
+ # taskset -c 1 bash
+ # echo 1 > /sys/kernel/debug/sched/hog &
+ # echo 1 > /sys/kernel/debug/sched/hog &
+ # echo 1 > /sys/kernel/debug/sched/hog &
+
+ top shows ~33% CPU for each of the hogs and tracing confirms that
+ the crude hack in the scheduler tick works:
+
+ bash-4559 [001] dlh2. 2253.331202: resched_curr <-__update_curr
+ bash-4560 [001] dlh2. 2253.340199: resched_curr <-__update_curr
+ bash-4561 [001] dlh2. 2253.346199: resched_curr <-__update_curr
+ bash-4559 [001] dlh2. 2253.353199: resched_curr <-__update_curr
+ bash-4561 [001] dlh2. 2253.358199: resched_curr <-__update_curr
+ bash-4560 [001] dlh2. 2253.370202: resched_curr <-__update_curr
+ bash-4559 [001] dlh2. 2253.378198: resched_curr <-__update_curr
+ bash-4561 [001] dlh2. 2253.389199: resched_curr <-__update_curr
+
+ The 'l' instead of the usual 'N' reflects that the lazy resched
+ bit is set. That makes __update_curr() invoke resched_curr()
+ instead of the lazy variant. resched_curr() sets TIF_NEED_RESCHED
+ and folds it into preempt_count so that preemption happens at the
+ next possible point, i.e. either in return from interrupt or at
+ the next preempt_enable().
+
+That's as much as I wanted to demonstrate and I'm not going to spend
+more cycles on it as I have already too many other things on flight and
+the resulting scheduler woes are clearly outside of my expertice.
+
+Though definitely I'm putting a permanent NAK in place for any attempts
+to duct tape the preempt=NONE model any further by sprinkling more
+cond*() and whatever warts around.
+
+Thanks,
+
+ tglx
+
+[tglx: s@CONFIG_PREEMPT_AUTO@CONFIG_PREEMPT_BUILD_AUTO@ ]
+
+Link: https://lore.kernel.org/all/87jzshhexi.ffs@tglx/
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/x86/Kconfig | 1
+ arch/x86/include/asm/thread_info.h | 6 ++--
+ drivers/acpi/processor_idle.c | 2 -
+ include/linux/entry-common.h | 2 -
+ include/linux/entry-kvm.h | 2 -
+ include/linux/sched.h | 12 +++++---
+ include/linux/sched/idle.h | 8 ++---
+ include/linux/thread_info.h | 24 +++++++++++++++++
+ include/linux/trace_events.h | 8 ++---
+ kernel/Kconfig.preempt | 17 +++++++++++-
+ kernel/entry/common.c | 4 +-
+ kernel/entry/kvm.c | 2 -
+ kernel/sched/core.c | 50 +++++++++++++++++++++++++------------
+ kernel/sched/debug.c | 19 ++++++++++++++
+ kernel/sched/fair.c | 46 ++++++++++++++++++++++------------
+ kernel/sched/features.h | 2 +
+ kernel/sched/idle.c | 3 --
+ kernel/sched/sched.h | 1
+ kernel/trace/trace.c | 2 +
+ kernel/trace/trace_output.c | 16 ++++++++++-
+ 20 files changed, 171 insertions(+), 56 deletions(-)
+
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -272,6 +272,7 @@ config X86
+ select HAVE_STATIC_CALL
+ select HAVE_STATIC_CALL_INLINE if HAVE_OBJTOOL
+ select HAVE_PREEMPT_DYNAMIC_CALL
++ select HAVE_PREEMPT_AUTO
+ select HAVE_RSEQ
+ select HAVE_RUST if X86_64
+ select HAVE_SYSCALL_TRACEPOINTS
+--- a/arch/x86/include/asm/thread_info.h
++++ b/arch/x86/include/asm/thread_info.h
+@@ -81,8 +81,9 @@ struct thread_info {
+ #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
+ #define TIF_SIGPENDING 2 /* signal pending */
+ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+-#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
+-#define TIF_SSBD 5 /* Speculative store bypass disable */
++#define TIF_ARCH_RESCHED_LAZY 4 /* Lazy rescheduling */
++#define TIF_SINGLESTEP 5 /* reenable singlestep on user return*/
++#define TIF_SSBD 6 /* Speculative store bypass disable */
+ #define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */
+ #define TIF_SPEC_L1D_FLUSH 10 /* Flush L1D on mm switches (processes) */
+ #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */
+@@ -104,6 +105,7 @@ struct thread_info {
+ #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
+ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
+ #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
++#define _TIF_ARCH_RESCHED_LAZY (1 << TIF_ARCH_RESCHED_LAZY)
+ #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
+ #define _TIF_SSBD (1 << TIF_SSBD)
+ #define _TIF_SPEC_IB (1 << TIF_SPEC_IB)
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -108,7 +108,7 @@ static const struct dmi_system_id proces
+ */
+ static void __cpuidle acpi_safe_halt(void)
+ {
+- if (!tif_need_resched()) {
++ if (!need_resched()) {
+ raw_safe_halt();
+ raw_local_irq_disable();
+ }
+--- a/include/linux/entry-common.h
++++ b/include/linux/entry-common.h
+@@ -60,7 +60,7 @@
+ #define EXIT_TO_USER_MODE_WORK \
+ (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+ _TIF_NEED_RESCHED | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \
+- ARCH_EXIT_TO_USER_MODE_WORK)
++ _TIF_NEED_RESCHED_LAZY | ARCH_EXIT_TO_USER_MODE_WORK)
+
+ /**
+ * arch_enter_from_user_mode - Architecture specific sanity check for user mode regs
+--- a/include/linux/entry-kvm.h
++++ b/include/linux/entry-kvm.h
+@@ -18,7 +18,7 @@
+
+ #define XFER_TO_GUEST_MODE_WORK \
+ (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \
+- _TIF_NOTIFY_RESUME | ARCH_XFER_TO_GUEST_MODE_WORK)
++ _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED_LAZY | ARCH_XFER_TO_GUEST_MODE_WORK)
+
+ struct kvm_vcpu;
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2050,17 +2050,17 @@ static inline void update_tsk_thread_fla
+ update_ti_thread_flag(task_thread_info(tsk), flag, value);
+ }
+
+-static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag)
++static inline bool test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag)
+ {
+ return test_and_set_ti_thread_flag(task_thread_info(tsk), flag);
+ }
+
+-static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag)
++static inline bool test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag)
+ {
+ return test_and_clear_ti_thread_flag(task_thread_info(tsk), flag);
+ }
+
+-static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag)
++static inline bool test_tsk_thread_flag(struct task_struct *tsk, int flag)
+ {
+ return test_ti_thread_flag(task_thread_info(tsk), flag);
+ }
+@@ -2073,9 +2073,11 @@ static inline void set_tsk_need_resched(
+ static inline void clear_tsk_need_resched(struct task_struct *tsk)
+ {
+ clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
++ if (IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO))
++ clear_tsk_thread_flag(tsk, TIF_NEED_RESCHED_LAZY);
+ }
+
+-static inline int test_tsk_need_resched(struct task_struct *tsk)
++static inline bool test_tsk_need_resched(struct task_struct *tsk)
+ {
+ return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED));
+ }
+@@ -2256,7 +2258,7 @@ static inline int rwlock_needbreak(rwloc
+
+ static __always_inline bool need_resched(void)
+ {
+- return unlikely(tif_need_resched());
++ return unlikely(tif_need_resched_lazy() || tif_need_resched());
+ }
+
+ /*
+--- a/include/linux/sched/idle.h
++++ b/include/linux/sched/idle.h
+@@ -63,7 +63,7 @@ static __always_inline bool __must_check
+ */
+ smp_mb__after_atomic();
+
+- return unlikely(tif_need_resched());
++ return unlikely(need_resched());
+ }
+
+ static __always_inline bool __must_check current_clr_polling_and_test(void)
+@@ -76,7 +76,7 @@ static __always_inline bool __must_check
+ */
+ smp_mb__after_atomic();
+
+- return unlikely(tif_need_resched());
++ return unlikely(need_resched());
+ }
+
+ #else
+@@ -85,11 +85,11 @@ static inline void __current_clr_polling
+
+ static inline bool __must_check current_set_polling_and_test(void)
+ {
+- return unlikely(tif_need_resched());
++ return unlikely(need_resched());
+ }
+ static inline bool __must_check current_clr_polling_and_test(void)
+ {
+- return unlikely(tif_need_resched());
++ return unlikely(need_resched());
+ }
+ #endif
+
+--- a/include/linux/thread_info.h
++++ b/include/linux/thread_info.h
+@@ -59,6 +59,16 @@ enum syscall_work_bit {
+
+ #include <asm/thread_info.h>
+
++#ifdef CONFIG_PREEMPT_BUILD_AUTO
++# define TIF_NEED_RESCHED_LAZY TIF_ARCH_RESCHED_LAZY
++# define _TIF_NEED_RESCHED_LAZY _TIF_ARCH_RESCHED_LAZY
++# define TIF_NEED_RESCHED_LAZY_OFFSET (TIF_NEED_RESCHED_LAZY - TIF_NEED_RESCHED)
++#else
++# define TIF_NEED_RESCHED_LAZY TIF_NEED_RESCHED
++# define _TIF_NEED_RESCHED_LAZY _TIF_NEED_RESCHED
++# define TIF_NEED_RESCHED_LAZY_OFFSET 0
++#endif
++
+ #ifdef __KERNEL__
+
+ #ifndef arch_set_restart_data
+@@ -185,6 +195,13 @@ static __always_inline bool tif_need_res
+ (unsigned long *)(&current_thread_info()->flags));
+ }
+
++static __always_inline bool tif_need_resched_lazy(void)
++{
++ return IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) &&
++ arch_test_bit(TIF_NEED_RESCHED_LAZY,
++ (unsigned long *)(&current_thread_info()->flags));
++}
++
+ #else
+
+ static __always_inline bool tif_need_resched(void)
+@@ -193,6 +210,13 @@ static __always_inline bool tif_need_res
+ (unsigned long *)(&current_thread_info()->flags));
+ }
+
++static __always_inline bool tif_need_resched_lazy(void)
++{
++ return IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) &&
++ test_bit(TIF_NEED_RESCHED_LAZY,
++ (unsigned long *)(&current_thread_info()->flags));
++}
++
+ #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */
+
+ #ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
+--- a/include/linux/trace_events.h
++++ b/include/linux/trace_events.h
+@@ -178,8 +178,8 @@ unsigned int tracing_gen_ctx_irq_test(un
+
+ enum trace_flag_type {
+ TRACE_FLAG_IRQS_OFF = 0x01,
+- TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
+- TRACE_FLAG_NEED_RESCHED = 0x04,
++ TRACE_FLAG_NEED_RESCHED = 0x02,
++ TRACE_FLAG_NEED_RESCHED_LAZY = 0x04,
+ TRACE_FLAG_HARDIRQ = 0x08,
+ TRACE_FLAG_SOFTIRQ = 0x10,
+ TRACE_FLAG_PREEMPT_RESCHED = 0x20,
+@@ -205,11 +205,11 @@ static inline unsigned int tracing_gen_c
+
+ static inline unsigned int tracing_gen_ctx_flags(unsigned long irqflags)
+ {
+- return tracing_gen_ctx_irq_test(TRACE_FLAG_IRQS_NOSUPPORT);
++ return tracing_gen_ctx_irq_test(0);
+ }
+ static inline unsigned int tracing_gen_ctx(void)
+ {
+- return tracing_gen_ctx_irq_test(TRACE_FLAG_IRQS_NOSUPPORT);
++ return tracing_gen_ctx_irq_test(0);
+ }
+ #endif
+
+--- a/kernel/Kconfig.preempt
++++ b/kernel/Kconfig.preempt
+@@ -11,6 +11,13 @@ config PREEMPT_BUILD
+ select PREEMPTION
+ select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK
+
++config PREEMPT_BUILD_AUTO
++ bool
++ select PREEMPT_BUILD
++
++config HAVE_PREEMPT_AUTO
++ bool
++
+ choice
+ prompt "Preemption Model"
+ default PREEMPT_NONE
+@@ -67,9 +74,17 @@ config PREEMPT
+ embedded system with latency requirements in the milliseconds
+ range.
+
++config PREEMPT_AUTO
++ bool "Automagic preemption mode with runtime tweaking support"
++ depends on HAVE_PREEMPT_AUTO
++ select PREEMPT_BUILD_AUTO
++ help
++ Add some sensible blurb here
++
+ config PREEMPT_RT
+ bool "Fully Preemptible Kernel (Real-Time)"
+ depends on EXPERT && ARCH_SUPPORTS_RT
++ select PREEMPT_BUILD_AUTO if HAVE_PREEMPT_AUTO
+ select PREEMPTION
+ help
+ This option turns the kernel into a real-time kernel by replacing
+@@ -95,7 +110,7 @@ config PREEMPTION
+
+ config PREEMPT_DYNAMIC
+ bool "Preemption behaviour defined on boot"
+- depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT
++ depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT && !PREEMPT_AUTO
+ select JUMP_LABEL if HAVE_PREEMPT_DYNAMIC_KEY
+ select PREEMPT_BUILD
+ default y if HAVE_PREEMPT_DYNAMIC_CALL
+--- a/kernel/entry/common.c
++++ b/kernel/entry/common.c
+@@ -155,7 +155,7 @@ static unsigned long exit_to_user_mode_l
+
+ local_irq_enable_exit_to_user(ti_work);
+
+- if (ti_work & _TIF_NEED_RESCHED)
++ if (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY))
+ schedule();
+
+ if (ti_work & _TIF_UPROBE)
+@@ -385,7 +385,7 @@ void raw_irqentry_exit_cond_resched(void
+ rcu_irq_exit_check_preempt();
+ if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
+ WARN_ON_ONCE(!on_thread_stack());
+- if (need_resched())
++ if (test_tsk_need_resched(current))
+ preempt_schedule_irq();
+ }
+ }
+--- a/kernel/entry/kvm.c
++++ b/kernel/entry/kvm.c
+@@ -13,7 +13,7 @@ static int xfer_to_guest_mode_work(struc
+ return -EINTR;
+ }
+
+- if (ti_work & _TIF_NEED_RESCHED)
++ if (ti_work & (_TIF_NEED_RESCHED | TIF_NEED_RESCHED_LAZY))
+ schedule();
+
+ if (ti_work & _TIF_NOTIFY_RESUME)
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -898,14 +898,15 @@ static inline void hrtick_rq_init(struct
+
+ #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
+ /*
+- * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
++ * Atomically set TIF_NEED_RESCHED[_LAZY] and test for TIF_POLLING_NRFLAG,
+ * this avoids any races wrt polling state changes and thereby avoids
+ * spurious IPIs.
+ */
+-static inline bool set_nr_and_not_polling(struct task_struct *p)
++static inline bool set_nr_and_not_polling(struct task_struct *p, int tif_bit)
+ {
+ struct thread_info *ti = task_thread_info(p);
+- return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
++
++ return !(fetch_or(&ti->flags, 1 << tif_bit) & _TIF_POLLING_NRFLAG);
+ }
+
+ /*
+@@ -922,7 +923,7 @@ static bool set_nr_if_polling(struct tas
+ for (;;) {
+ if (!(val & _TIF_POLLING_NRFLAG))
+ return false;
+- if (val & _TIF_NEED_RESCHED)
++ if (val & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY))
+ return true;
+ if (try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED))
+ break;
+@@ -931,9 +932,9 @@ static bool set_nr_if_polling(struct tas
+ }
+
+ #else
+-static inline bool set_nr_and_not_polling(struct task_struct *p)
++static inline bool set_nr_and_not_polling(struct task_struct *p, int tif_bit)
+ {
+- set_tsk_need_resched(p);
++ set_tsk_thread_flag(p, tif_bit);
+ return true;
+ }
+
+@@ -1038,28 +1039,47 @@ void wake_up_q(struct wake_q_head *head)
+ * might also involve a cross-CPU call to trigger the scheduler on
+ * the target CPU.
+ */
+-void resched_curr(struct rq *rq)
++static void __resched_curr(struct rq *rq, int lazy)
+ {
++ int cpu, tif_bit = TIF_NEED_RESCHED + lazy;
+ struct task_struct *curr = rq->curr;
+- int cpu;
+
+ lockdep_assert_rq_held(rq);
+
+- if (test_tsk_need_resched(curr))
++ if (unlikely(test_tsk_thread_flag(curr, tif_bit)))
+ return;
+
+ cpu = cpu_of(rq);
+
+ if (cpu == smp_processor_id()) {
+- set_tsk_need_resched(curr);
+- set_preempt_need_resched();
++ set_tsk_thread_flag(curr, tif_bit);
++ if (!lazy)
++ set_preempt_need_resched();
+ return;
+ }
+
+- if (set_nr_and_not_polling(curr))
+- smp_send_reschedule(cpu);
+- else
++ if (set_nr_and_not_polling(curr, tif_bit)) {
++ if (!lazy)
++ smp_send_reschedule(cpu);
++ } else {
+ trace_sched_wake_idle_without_ipi(cpu);
++ }
++}
++
++void resched_curr(struct rq *rq)
++{
++ __resched_curr(rq, 0);
++}
++
++void resched_curr_lazy(struct rq *rq)
++{
++ int lazy = IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && !sched_feat(FORCE_NEED_RESCHED) ?
++ TIF_NEED_RESCHED_LAZY_OFFSET : 0;
++
++ if (lazy && unlikely(test_tsk_thread_flag(rq->curr, TIF_NEED_RESCHED)))
++ return;
++
++ __resched_curr(rq, lazy);
+ }
+
+ void resched_cpu(int cpu)
+@@ -1132,7 +1152,7 @@ static void wake_up_idle_cpu(int cpu)
+ if (cpu == smp_processor_id())
+ return;
+
+- if (set_nr_and_not_polling(rq->idle))
++ if (set_nr_and_not_polling(rq->idle, TIF_NEED_RESCHED))
+ smp_send_reschedule(cpu);
+ else
+ trace_sched_wake_idle_without_ipi(cpu);
+--- a/kernel/sched/debug.c
++++ b/kernel/sched/debug.c
+@@ -333,6 +333,23 @@ static const struct file_operations sche
+ .release = seq_release,
+ };
+
++static ssize_t sched_hog_write(struct file *filp, const char __user *ubuf,
++ size_t cnt, loff_t *ppos)
++{
++ unsigned long end = jiffies + 60 * HZ;
++
++ for (; time_before(jiffies, end) && !signal_pending(current);)
++ cpu_relax();
++
++ return cnt;
++}
++
++static const struct file_operations sched_hog_fops = {
++ .write = sched_hog_write,
++ .open = simple_open,
++ .llseek = default_llseek,
++};
++
+ static struct dentry *debugfs_sched;
+
+ static __init int sched_init_debug(void)
+@@ -374,6 +391,8 @@ static __init int sched_init_debug(void)
+
+ debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops);
+
++ debugfs_create_file("hog", 0200, debugfs_sched, NULL, &sched_hog_fops);
++
+ return 0;
+ }
+ late_initcall(sched_init_debug);
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -1016,8 +1016,10 @@ static void clear_buddies(struct cfs_rq
+ * XXX: strictly: vd_i += N*r_i/w_i such that: vd_i > ve_i
+ * this is probably good enough.
+ */
+-static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se)
++static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se, bool tick)
+ {
++ struct rq *rq = rq_of(cfs_rq);
++
+ if ((s64)(se->vruntime - se->deadline) < 0)
+ return;
+
+@@ -1036,10 +1038,19 @@ static void update_deadline(struct cfs_r
+ /*
+ * The task has consumed its request, reschedule.
+ */
+- if (cfs_rq->nr_running > 1) {
+- resched_curr(rq_of(cfs_rq));
+- clear_buddies(cfs_rq, se);
++ if (cfs_rq->nr_running < 2)
++ return;
++
++ if (!IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) || sched_feat(FORCE_NEED_RESCHED)) {
++ resched_curr(rq);
++ } else {
++ /* Did the task ignore the lazy reschedule request? */
++ if (tick && test_tsk_thread_flag(rq->curr, TIF_NEED_RESCHED_LAZY))
++ resched_curr(rq);
++ else
++ resched_curr_lazy(rq);
+ }
++ clear_buddies(cfs_rq, se);
+ }
+
+ #include "pelt.h"
+@@ -1147,7 +1158,7 @@ static void update_tg_load_avg(struct cf
+ /*
+ * Update the current task's runtime statistics.
+ */
+-static void update_curr(struct cfs_rq *cfs_rq)
++static void __update_curr(struct cfs_rq *cfs_rq, bool tick)
+ {
+ struct sched_entity *curr = cfs_rq->curr;
+ u64 now = rq_clock_task(rq_of(cfs_rq));
+@@ -1174,7 +1185,7 @@ static void update_curr(struct cfs_rq *c
+ schedstat_add(cfs_rq->exec_clock, delta_exec);
+
+ curr->vruntime += calc_delta_fair(delta_exec, curr);
+- update_deadline(cfs_rq, curr);
++ update_deadline(cfs_rq, curr, tick);
+ update_min_vruntime(cfs_rq);
+
+ if (entity_is_task(curr)) {
+@@ -1188,6 +1199,11 @@ static void update_curr(struct cfs_rq *c
+ account_cfs_rq_runtime(cfs_rq, delta_exec);
+ }
+
++static inline void update_curr(struct cfs_rq *cfs_rq)
++{
++ __update_curr(cfs_rq, false);
++}
++
+ static void update_curr_fair(struct rq *rq)
+ {
+ update_curr(cfs_rq_of(&rq->curr->se));
+@@ -5398,7 +5414,7 @@ entity_tick(struct cfs_rq *cfs_rq, struc
+ /*
+ * Update run-time statistics of the 'current'.
+ */
+- update_curr(cfs_rq);
++ __update_curr(cfs_rq, true);
+
+ /*
+ * Ensure that runnable average is periodically updated.
+@@ -5412,7 +5428,7 @@ entity_tick(struct cfs_rq *cfs_rq, struc
+ * validating it and just reschedule.
+ */
+ if (queued) {
+- resched_curr(rq_of(cfs_rq));
++ resched_curr_lazy(rq_of(cfs_rq));
+ return;
+ }
+ /*
+@@ -5558,7 +5574,7 @@ static void __account_cfs_rq_runtime(str
+ * hierarchy can be throttled
+ */
+ if (!assign_cfs_rq_runtime(cfs_rq) && likely(cfs_rq->curr))
+- resched_curr(rq_of(cfs_rq));
++ resched_curr_lazy(rq_of(cfs_rq));
+ }
+
+ static __always_inline
+@@ -5818,7 +5834,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cf
+
+ /* Determine whether we need to wake up potentially idle CPU: */
+ if (rq->curr == rq->idle && rq->cfs.nr_running)
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ }
+
+ #ifdef CONFIG_SMP
+@@ -6523,7 +6539,7 @@ static void hrtick_start_fair(struct rq
+
+ if (delta < 0) {
+ if (task_current(rq, p))
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ return;
+ }
+ hrtick_start(rq, delta);
+@@ -8175,7 +8191,7 @@ static void check_preempt_wakeup(struct
+ * prevents us from potentially nominating it as a false LAST_BUDDY
+ * below.
+ */
+- if (test_tsk_need_resched(curr))
++ if (need_resched())
+ return;
+
+ /* Idle tasks are by definition preempted by non-idle tasks. */
+@@ -8217,7 +8233,7 @@ static void check_preempt_wakeup(struct
+ return;
+
+ preempt:
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ }
+
+ #ifdef CONFIG_SMP
+@@ -12374,7 +12390,7 @@ static inline void task_tick_core(struct
+ */
+ if (rq->core->core_forceidle_count && rq->cfs.nr_running == 1 &&
+ __entity_slice_used(&curr->se, MIN_NR_TASKS_DURING_FORCEIDLE))
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ }
+
+ /*
+@@ -12539,7 +12555,7 @@ prio_changed_fair(struct rq *rq, struct
+ */
+ if (task_current(rq, p)) {
+ if (p->prio > oldprio)
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ } else
+ check_preempt_curr(rq, p, 0);
+ }
+--- a/kernel/sched/features.h
++++ b/kernel/sched/features.h
+@@ -89,3 +89,5 @@ SCHED_FEAT(UTIL_EST_FASTUP, true)
+ SCHED_FEAT(LATENCY_WARN, false)
+
+ SCHED_FEAT(HZ_BW, true)
++
++SCHED_FEAT(FORCE_NEED_RESCHED, false)
+--- a/kernel/sched/idle.c
++++ b/kernel/sched/idle.c
+@@ -57,8 +57,7 @@ static noinline int __cpuidle cpu_idle_p
+ ct_cpuidle_enter();
+
+ raw_local_irq_enable();
+- while (!tif_need_resched() &&
+- (cpu_idle_force_poll || tick_check_broadcast_expired()))
++ while (!need_resched() && (cpu_idle_force_poll || tick_check_broadcast_expired()))
+ cpu_relax();
+ raw_local_irq_disable();
+
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -2435,6 +2435,7 @@ extern void init_sched_fair_class(void);
+ extern void reweight_task(struct task_struct *p, int prio);
+
+ extern void resched_curr(struct rq *rq);
++extern void resched_curr_lazy(struct rq *rq);
+ extern void resched_cpu(int cpu);
+
+ extern struct rt_bandwidth def_rt_bandwidth;
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -2722,6 +2722,8 @@ unsigned int tracing_gen_ctx_irq_test(un
+
+ if (tif_need_resched())
+ trace_flags |= TRACE_FLAG_NEED_RESCHED;
++ if (tif_need_resched_lazy())
++ trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY;
+ if (test_preempt_need_resched())
+ trace_flags |= TRACE_FLAG_PREEMPT_RESCHED;
+ return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) |
+--- a/kernel/trace/trace_output.c
++++ b/kernel/trace/trace_output.c
+@@ -460,17 +460,29 @@ int trace_print_lat_fmt(struct trace_seq
+ (entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' :
+ (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
+ bh_off ? 'b' :
+- (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
++ !IS_ENABLED(CONFIG_TRACE_IRQFLAGS_SUPPORT) ? 'X' :
+ '.';
+
+- switch (entry->flags & (TRACE_FLAG_NEED_RESCHED |
++ switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY |
+ TRACE_FLAG_PREEMPT_RESCHED)) {
++ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
++ need_resched = 'B';
++ break;
+ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
+ need_resched = 'N';
+ break;
++ case TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
++ need_resched = 'L';
++ break;
++ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY:
++ need_resched = 'b';
++ break;
+ case TRACE_FLAG_NEED_RESCHED:
+ need_resched = 'n';
+ break;
++ case TRACE_FLAG_NEED_RESCHED_LAZY:
++ need_resched = 'l';
++ break;
+ case TRACE_FLAG_PREEMPT_RESCHED:
+ need_resched = 'p';
+ break;
diff --git a/debian/patches-rt/RISC-V-Probe-misaligned-access-speed-in-parallel.patch b/debian/patches-rt/RISC-V-Probe-misaligned-access-speed-in-parallel.patch
new file mode 100644
index 0000000000..78e57b07a5
--- /dev/null
+++ b/debian/patches-rt/RISC-V-Probe-misaligned-access-speed-in-parallel.patch
@@ -0,0 +1,197 @@
+From: Evan Green <evan@rivosinc.com>
+Date: Mon, 6 Nov 2023 14:58:55 -0800
+Subject: [PATCH] RISC-V: Probe misaligned access speed in parallel
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Probing for misaligned access speed takes about 0.06 seconds. On a
+system with 64 cores, doing this in smp_callin() means it's done
+serially, extending boot time by 3.8 seconds. That's a lot of boot time.
+
+Instead of measuring each CPU serially, let's do the measurements on
+all CPUs in parallel. If we disable preemption on all CPUs, the
+jiffies stop ticking, so we can do this in stages of 1) everybody
+except core 0, then 2) core 0. The allocations are all done outside of
+on_each_cpu() to avoid calling alloc_pages() with interrupts disabled.
+
+For hotplugged CPUs that come in after the boot time measurement,
+register CPU hotplug callbacks, and do the measurement there. Interrupts
+are enabled in those callbacks, so they're fine to do alloc_pages() in.
+
+[bigeasy: merge the individual patches into the final step.]
+
+Reported-by: Jisheng Zhang <jszhang@kernel.org>
+Closes: https://lore.kernel.org/all/mhng-9359993d-6872-4134-83ce-c97debe1cf9a@palmer-ri-x1c9/T/#mae9b8f40016f9df428829d33360144dc5026bcbf
+Fixes: 584ea6564bca ("RISC-V: Probe for unaligned access speed")
+Signed-off-by: Evan Green <evan@rivosinc.com>
+Link: https://lore.kernel.org/r/20231106225855.3121724-1-evan@rivosinc.com
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/riscv/include/asm/cpufeature.h | 2
+ arch/riscv/kernel/cpufeature.c | 90 ++++++++++++++++++++++++++++++------
+ arch/riscv/kernel/smpboot.c | 1
+ 3 files changed, 76 insertions(+), 17 deletions(-)
+
+--- a/arch/riscv/include/asm/cpufeature.h
++++ b/arch/riscv/include/asm/cpufeature.h
+@@ -30,6 +30,4 @@ DECLARE_PER_CPU(long, misaligned_access_
+ /* Per-cpu ISA extensions. */
+ extern struct riscv_isainfo hart_isa[NR_CPUS];
+
+-void check_unaligned_access(int cpu);
+-
+ #endif
+--- a/arch/riscv/kernel/cpufeature.c
++++ b/arch/riscv/kernel/cpufeature.c
+@@ -8,6 +8,7 @@
+
+ #include <linux/acpi.h>
+ #include <linux/bitmap.h>
++#include <linux/cpuhotplug.h>
+ #include <linux/ctype.h>
+ #include <linux/log2.h>
+ #include <linux/memory.h>
+@@ -29,6 +30,7 @@
+
+ #define MISALIGNED_ACCESS_JIFFIES_LG2 1
+ #define MISALIGNED_BUFFER_SIZE 0x4000
++#define MISALIGNED_BUFFER_ORDER get_order(MISALIGNED_BUFFER_SIZE)
+ #define MISALIGNED_COPY_SIZE ((MISALIGNED_BUFFER_SIZE / 2) - 0x80)
+
+ unsigned long elf_hwcap __read_mostly;
+@@ -556,24 +558,19 @@ unsigned long riscv_get_elf_hwcap(void)
+ return hwcap;
+ }
+
+-void check_unaligned_access(int cpu)
++static int check_unaligned_access(void *param)
+ {
++ int cpu = smp_processor_id();
+ u64 start_cycles, end_cycles;
+ u64 word_cycles;
+ u64 byte_cycles;
+ int ratio;
+ unsigned long start_jiffies, now;
+- struct page *page;
++ struct page *page = param;
+ void *dst;
+ void *src;
+ long speed = RISCV_HWPROBE_MISALIGNED_SLOW;
+
+- page = alloc_pages(GFP_NOWAIT, get_order(MISALIGNED_BUFFER_SIZE));
+- if (!page) {
+- pr_warn("Can't alloc pages to measure memcpy performance");
+- return;
+- }
+-
+ /* Make an unaligned destination buffer. */
+ dst = (void *)((unsigned long)page_address(page) | 0x1);
+ /* Unalign src as well, but differently (off by 1 + 2 = 3). */
+@@ -626,7 +623,7 @@ void check_unaligned_access(int cpu)
+ pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned access speed\n",
+ cpu);
+
+- goto out;
++ return 0;
+ }
+
+ if (word_cycles < byte_cycles)
+@@ -640,18 +637,83 @@ void check_unaligned_access(int cpu)
+ (speed == RISCV_HWPROBE_MISALIGNED_FAST) ? "fast" : "slow");
+
+ per_cpu(misaligned_access_speed, cpu) = speed;
++ return 0;
++}
+
+-out:
+- __free_pages(page, get_order(MISALIGNED_BUFFER_SIZE));
++static void check_unaligned_access_nonboot_cpu(void *param)
++{
++ unsigned int cpu = smp_processor_id();
++ struct page **pages = param;
++
++ if (smp_processor_id() != 0)
++ check_unaligned_access(pages[cpu]);
++}
++
++static int riscv_online_cpu(unsigned int cpu)
++{
++ static struct page *buf;
++
++ /* We are already set since the last check */
++ if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_UNKNOWN)
++ return 0;
++
++ buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
++ if (!buf) {
++ pr_warn("Allocation failure, not measuring misaligned performance\n");
++ return -ENOMEM;
++ }
++
++ check_unaligned_access(buf);
++ __free_pages(buf, MISALIGNED_BUFFER_ORDER);
++ return 0;
+ }
+
+-static int check_unaligned_access_boot_cpu(void)
++/* Measure unaligned access on all CPUs present at boot in parallel. */
++static int check_unaligned_access_all_cpus(void)
+ {
+- check_unaligned_access(0);
++ unsigned int cpu;
++ unsigned int cpu_count = num_possible_cpus();
++ struct page **bufs = kzalloc(cpu_count * sizeof(struct page *),
++ GFP_KERNEL);
++
++ if (!bufs) {
++ pr_warn("Allocation failure, not measuring misaligned performance\n");
++ return 0;
++ }
++
++ /*
++ * Allocate separate buffers for each CPU so there's no fighting over
++ * cache lines.
++ */
++ for_each_cpu(cpu, cpu_online_mask) {
++ bufs[cpu] = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
++ if (!bufs[cpu]) {
++ pr_warn("Allocation failure, not measuring misaligned performance\n");
++ goto out;
++ }
++ }
++
++ /* Check everybody except 0, who stays behind to tend jiffies. */
++ on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1);
++
++ /* Check core 0. */
++ smp_call_on_cpu(0, check_unaligned_access, bufs[0], true);
++
++ /* Setup hotplug callback for any new CPUs that come online. */
++ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online",
++ riscv_online_cpu, NULL);
++
++out:
++ for_each_cpu(cpu, cpu_online_mask) {
++ if (bufs[cpu])
++ __free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER);
++ }
++
++ kfree(bufs);
+ return 0;
+ }
+
+-arch_initcall(check_unaligned_access_boot_cpu);
++arch_initcall(check_unaligned_access_all_cpus);
+
+ #ifdef CONFIG_RISCV_ALTERNATIVE
+ /*
+--- a/arch/riscv/kernel/smpboot.c
++++ b/arch/riscv/kernel/smpboot.c
+@@ -246,7 +246,6 @@ asmlinkage __visible void smp_callin(voi
+
+ numa_add_cpu(curr_cpuid);
+ set_cpu_online(curr_cpuid, 1);
+- check_unaligned_access(curr_cpuid);
+
+ if (has_vector()) {
+ if (riscv_v_setup_vsize())
diff --git a/debian/patches-rt/Revert-drm-i915-Depend-on-PREEMPT_RT.patch b/debian/patches-rt/Revert-drm-i915-Depend-on-PREEMPT_RT.patch
new file mode 100644
index 0000000000..dc62e007e8
--- /dev/null
+++ b/debian/patches-rt/Revert-drm-i915-Depend-on-PREEMPT_RT.patch
@@ -0,0 +1,23 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 21 Feb 2022 17:59:14 +0100
+Subject: [PATCH] Revert "drm/i915: Depend on !PREEMPT_RT."
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Once the known issues are addressed, it should be safe to enable the
+driver.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/Kconfig | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/Kconfig
++++ b/drivers/gpu/drm/i915/Kconfig
+@@ -3,7 +3,6 @@ config DRM_I915
+ tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
+ depends on DRM
+ depends on X86 && PCI
+- depends on !PREEMPT_RT
+ select INTEL_GTT if X86
+ select INTERVAL_TREE
+ # we need shmfs for the swappable backing store, and in particular
diff --git a/debian/patches-rt/drm-i915-Do-not-disable-preemption-for-resets.patch b/debian/patches-rt/drm-i915-Do-not-disable-preemption-for-resets.patch
new file mode 100644
index 0000000000..5869667030
--- /dev/null
+++ b/debian/patches-rt/drm-i915-Do-not-disable-preemption-for-resets.patch
@@ -0,0 +1,99 @@
+From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Date: Wed, 5 Jul 2023 10:30:25 +0100
+Subject: [PATCH] drm/i915: Do not disable preemption for resets
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Commit ade8a0f59844 ("drm/i915: Make all GPU resets atomic") added a
+preempt disable section over the hardware reset callback to prepare the
+driver for being able to reset from atomic contexts.
+
+In retrospect I can see that the work item at a time was about removing
+the struct mutex from the reset path. Code base also briefly entertained
+the idea of doing the reset under stop_machine in order to serialize
+userspace mmap and temporary glitch in the fence registers (see
+eb8d0f5af4ec ("drm/i915: Remove GPU reset dependence on struct_mutex"),
+but that never materialized and was soon removed in 2caffbf11762
+("drm/i915: Revoke mmaps and prevent access to fence registers across
+reset") and replaced with a SRCU based solution.
+
+As such, as far as I can see, today we still have a requirement that
+resets must not sleep (invoked from submission tasklets), but no need to
+support invoking them from a truly atomic context.
+
+Given that the preemption section is problematic on RT kernels, since the
+uncore lock becomes a sleeping lock and so is invalid in such section,
+lets try and remove it. Potential downside is that our short waits on GPU
+to complete the reset may get extended if CPU scheduling interferes, but
+in practice that probably isn't a deal breaker.
+
+In terms of mechanics, since the preemption disabled block is being
+removed we just need to replace a few of the wait_for_atomic macros into
+busy looping versions which will work (and not complain) when called from
+non-atomic sections.
+
+Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Cc: Chris Wilson <chris.p.wilson@intel.com>
+Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
+Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20230705093025.3689748-1-tvrtko.ursulin@linux.intel.com
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/gt/intel_reset.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/i915/gt/intel_reset.c
++++ b/drivers/gpu/drm/i915/gt/intel_reset.c
+@@ -164,13 +164,13 @@ static int i915_do_reset(struct intel_gt
+ /* Assert reset for at least 20 usec, and wait for acknowledgement. */
+ pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
+ udelay(50);
+- err = wait_for_atomic(i915_in_reset(pdev), 50);
++ err = _wait_for_atomic(i915_in_reset(pdev), 50, 0);
+
+ /* Clear the reset request. */
+ pci_write_config_byte(pdev, I915_GDRST, 0);
+ udelay(50);
+ if (!err)
+- err = wait_for_atomic(!i915_in_reset(pdev), 50);
++ err = _wait_for_atomic(!i915_in_reset(pdev), 50, 0);
+
+ return err;
+ }
+@@ -190,7 +190,7 @@ static int g33_do_reset(struct intel_gt
+ struct pci_dev *pdev = to_pci_dev(gt->i915->drm.dev);
+
+ pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE);
+- return wait_for_atomic(g4x_reset_complete(pdev), 50);
++ return _wait_for_atomic(g4x_reset_complete(pdev), 50, 0);
+ }
+
+ static int g4x_do_reset(struct intel_gt *gt,
+@@ -207,7 +207,7 @@ static int g4x_do_reset(struct intel_gt
+
+ pci_write_config_byte(pdev, I915_GDRST,
+ GRDOM_MEDIA | GRDOM_RESET_ENABLE);
+- ret = wait_for_atomic(g4x_reset_complete(pdev), 50);
++ ret = _wait_for_atomic(g4x_reset_complete(pdev), 50, 0);
+ if (ret) {
+ GT_TRACE(gt, "Wait for media reset failed\n");
+ goto out;
+@@ -215,7 +215,7 @@ static int g4x_do_reset(struct intel_gt
+
+ pci_write_config_byte(pdev, I915_GDRST,
+ GRDOM_RENDER | GRDOM_RESET_ENABLE);
+- ret = wait_for_atomic(g4x_reset_complete(pdev), 50);
++ ret = _wait_for_atomic(g4x_reset_complete(pdev), 50, 0);
+ if (ret) {
+ GT_TRACE(gt, "Wait for render reset failed\n");
+ goto out;
+@@ -785,9 +785,7 @@ int __intel_gt_reset(struct intel_gt *gt
+ reset_mask = wa_14015076503_start(gt, engine_mask, !retry);
+
+ GT_TRACE(gt, "engine_mask=%x\n", reset_mask);
+- preempt_disable();
+ ret = reset(gt, reset_mask, retry);
+- preempt_enable();
+
+ wa_14015076503_end(gt, reset_mask);
+ }
diff --git a/debian/patches-rt/drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch b/debian/patches-rt/drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch
new file mode 100644
index 0000000000..0f030b42f2
--- /dev/null
+++ b/debian/patches-rt/drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch
@@ -0,0 +1,29 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 3 Oct 2023 21:37:21 +0200
+Subject: [PATCH] drm/i915/guc: Consider also RCU depth in busy loop.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+intel_guc_send_busy_loop() looks at in_atomic() and irqs_disabled() to
+decide if it should busy-spin while waiting or if it may sleep.
+Both checks will report false on PREEMPT_RT if sleeping spinlocks are
+acquired leading to RCU splats while the function sleeps.
+
+Check also if RCU has been disabled.
+
+Reported-by: "John B. Wyatt IV" <jwyatt@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+@@ -317,7 +317,7 @@ static inline int intel_guc_send_busy_lo
+ {
+ int err;
+ unsigned int sleep_period_ms = 1;
+- bool not_atomic = !in_atomic() && !irqs_disabled();
++ bool not_atomic = !in_atomic() && !irqs_disabled() && !rcu_preempt_depth();
+
+ /*
+ * FIXME: Have caller pass in if we are in an atomic context to avoid
diff --git a/debian/patches-rt/net-Avoid-the-IPI-to-free-the.patch b/debian/patches-rt/net-Avoid-the-IPI-to-free-the.patch
new file mode 100644
index 0000000000..6005e7a2e6
--- /dev/null
+++ b/debian/patches-rt/net-Avoid-the-IPI-to-free-the.patch
@@ -0,0 +1,119 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 15 Aug 2022 17:29:50 +0200
+Subject: [PATCH] net: Avoid the IPI to free the
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+skb_attempt_defer_free() collects a skbs, which was allocated on a
+remote CPU, on a per-CPU list. These skbs are either freed on that
+remote CPU once the CPU enters NET_RX or an remote IPI function is
+invoked in to raise the NET_RX softirq if a threshold of pending skb has
+been exceeded.
+This remote IPI can cause the wakeup of ksoftirqd on PREEMPT_RT if the
+remote CPU idle was idle. This is undesired because once the ksoftirqd
+is running it will acquire all pending softirqs and they will not be
+executed as part of the threaded interrupt until ksoftird goes idle
+again.
+
+To void all this, schedule the deferred clean up from a worker.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/netdevice.h | 4 ++++
+ net/core/dev.c | 39 ++++++++++++++++++++++++++++++---------
+ net/core/skbuff.c | 7 ++++++-
+ 3 files changed, 40 insertions(+), 10 deletions(-)
+
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -3258,7 +3258,11 @@ struct softnet_data {
+ int defer_count;
+ int defer_ipi_scheduled;
+ struct sk_buff *defer_list;
++#ifndef CONFIG_PREEMPT_RT
+ call_single_data_t defer_csd;
++#else
++ struct work_struct defer_work;
++#endif
+ };
+
+ static inline void input_queue_head_incr(struct softnet_data *sd)
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4702,15 +4702,6 @@ static void rps_trigger_softirq(void *da
+
+ #endif /* CONFIG_RPS */
+
+-/* Called from hardirq (IPI) context */
+-static void trigger_rx_softirq(void *data)
+-{
+- struct softnet_data *sd = data;
+-
+- __raise_softirq_irqoff(NET_RX_SOFTIRQ);
+- smp_store_release(&sd->defer_ipi_scheduled, 0);
+-}
+-
+ /*
+ * After we queued a packet into sd->input_pkt_queue,
+ * we need to make sure this queue is serviced soon.
+@@ -6679,6 +6670,32 @@ static void skb_defer_free_flush(struct
+ }
+ }
+
++#ifndef CONFIG_PREEMPT_RT
++
++/* Called from hardirq (IPI) context */
++static void trigger_rx_softirq(void *data)
++{
++ struct softnet_data *sd = data;
++
++ __raise_softirq_irqoff(NET_RX_SOFTIRQ);
++ smp_store_release(&sd->defer_ipi_scheduled, 0);
++}
++
++#else
++
++static void trigger_rx_softirq(struct work_struct *defer_work)
++{
++ struct softnet_data *sd;
++
++ sd = container_of(defer_work, struct softnet_data, defer_work);
++ smp_store_release(&sd->defer_ipi_scheduled, 0);
++ local_bh_disable();
++ skb_defer_free_flush(sd);
++ local_bh_enable();
++}
++
++#endif
++
+ static int napi_threaded_poll(void *data)
+ {
+ struct napi_struct *napi = data;
+@@ -11603,7 +11620,11 @@ static int __init net_dev_init(void)
+ INIT_CSD(&sd->csd, rps_trigger_softirq, sd);
+ sd->cpu = i;
+ #endif
++#ifndef CONFIG_PREEMPT_RT
+ INIT_CSD(&sd->defer_csd, trigger_rx_softirq, sd);
++#else
++ INIT_WORK(&sd->defer_work, trigger_rx_softirq);
++#endif
+ spin_lock_init(&sd->defer_lock);
+
+ init_gro_hash(&sd->backlog);
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6841,8 +6841,13 @@ nodefer: __kfree_skb(skb);
+ /* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU
+ * if we are unlucky enough (this seems very unlikely).
+ */
+- if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1))
++ if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) {
++#ifndef CONFIG_PREEMPT_RT
+ smp_call_function_single_async(cpu, &sd->defer_csd);
++#else
++ schedule_work_on(cpu, &sd->defer_work);
++#endif
++ }
+ }
+
+ static void skb_splice_csum_page(struct sk_buff *skb, struct page *page,
diff --git a/debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch b/debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch
new file mode 100644
index 0000000000..6eb1f4c871
--- /dev/null
+++ b/debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch
@@ -0,0 +1,27 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 9 Mar 2023 09:13:52 +0100
+Subject: [PATCH] powerpc/pseries: Select the generic memory allocator.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The RTAS work area allocator is using the generic memory allocator and
+as such it must select it.
+
+Select the generic memory allocator on pseries.
+
+Fixes: 43033bc62d349 ("powerpc/pseries: add RTAS work area allocator")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/20230309135110.uAxhqRFk@linutronix.de
+---
+ arch/powerpc/platforms/pseries/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/powerpc/platforms/pseries/Kconfig
++++ b/arch/powerpc/platforms/pseries/Kconfig
+@@ -2,6 +2,7 @@
+ config PPC_PSERIES
+ depends on PPC64 && PPC_BOOK3S
+ bool "IBM pSeries & new (POWER5-based) iSeries"
++ select GENERIC_ALLOCATOR
+ select HAVE_PCSPKR_PLATFORM
+ select MPIC
+ select OF_DYNAMIC
diff --git a/debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch b/debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch
new file mode 100644
index 0000000000..de8c14fd76
--- /dev/null
+++ b/debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch
@@ -0,0 +1,38 @@
+Subject: powerpc: traps: Use PREEMPT_RT
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri Jul 26 11:30:49 2019 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+Add PREEMPT_RT to the backtrace if enabled.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/powerpc/kernel/traps.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+---
+--- a/arch/powerpc/kernel/traps.c
++++ b/arch/powerpc/kernel/traps.c
+@@ -261,12 +261,17 @@ static char *get_mmu_str(void)
+
+ static int __die(const char *str, struct pt_regs *regs, long err)
+ {
++ const char *pr = "";
++
+ printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
+
++ if (IS_ENABLED(CONFIG_PREEMPTION))
++ pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT";
++
+ printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s %s\n",
+ IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? "LE" : "BE",
+ PAGE_SIZE / 1024, get_mmu_str(),
+- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
++ pr,
+ IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
+ IS_ENABLED(CONFIG_SMP) ? (" NR_CPUS=" __stringify(NR_CPUS)) : "",
+ debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "",
diff --git a/debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch b/debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch
new file mode 100644
index 0000000000..f53f527b3a
--- /dev/null
+++ b/debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch
@@ -0,0 +1,43 @@
+Subject: powerpc/kvm: Disable in-kernel MPIC emulation for PREEMPT_RT
+From: Bogdan Purcareata <bogdan.purcareata@freescale.com>
+Date: Fri Apr 24 15:53:13 2015 +0000
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Bogdan Purcareata <bogdan.purcareata@freescale.com>
+
+While converting the openpic emulation code to use a raw_spinlock_t enables
+guests to run on RT, there's still a performance issue. For interrupts sent in
+directed delivery mode with a multiple CPU mask, the emulated openpic will loop
+through all of the VCPUs, and for each VCPUs, it call IRQ_check, which will loop
+through all the pending interrupts for that VCPU. This is done while holding the
+raw_lock, meaning that in all this time the interrupts and preemption are
+disabled on the host Linux. A malicious user app can max both these number and
+cause a DoS.
+
+This temporary fix is sent for two reasons. First is so that users who want to
+use the in-kernel MPIC emulation are aware of the potential latencies, thus
+making sure that the hardware MPIC and their usage scenario does not involve
+interrupts sent in directed delivery mode, and the number of possible pending
+interrupts is kept small. Secondly, this should incentivize the development of a
+proper openpic emulation that would be better suited for RT.
+
+Acked-by: Scott Wood <scottwood@freescale.com>
+Signed-off-by: Bogdan Purcareata <bogdan.purcareata@freescale.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/powerpc/kvm/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+---
+--- a/arch/powerpc/kvm/Kconfig
++++ b/arch/powerpc/kvm/Kconfig
+@@ -224,6 +224,7 @@ config KVM_E500MC
+ config KVM_MPIC
+ bool "KVM in-kernel MPIC emulation"
+ depends on KVM && PPC_E500
++ depends on !PREEMPT_RT
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQFD
+ select HAVE_KVM_IRQ_ROUTING
diff --git a/debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch b/debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch
new file mode 100644
index 0000000000..f20adf29e0
--- /dev/null
+++ b/debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch
@@ -0,0 +1,115 @@
+Subject: powerpc/pseries/iommu: Use a locallock instead local_irq_save()
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue Mar 26 18:31:54 2019 +0100
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+The locallock protects the per-CPU variable tce_page. The function
+attempts to allocate memory while tce_page is protected (by disabling
+interrupts).
+
+Use local_irq_save() instead of local_irq_disable().
+
+Cc: stable-rt@vger.kernel.org
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/powerpc/platforms/pseries/iommu.c | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+---
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -25,6 +25,7 @@
+ #include <linux/of_address.h>
+ #include <linux/iommu.h>
+ #include <linux/rculist.h>
++#include <linux/local_lock.h>
+ #include <asm/io.h>
+ #include <asm/prom.h>
+ #include <asm/rtas.h>
+@@ -206,7 +207,13 @@ static int tce_build_pSeriesLP(unsigned
+ return ret;
+ }
+
+-static DEFINE_PER_CPU(__be64 *, tce_page);
++struct tce_page {
++ __be64 * page;
++ local_lock_t lock;
++};
++static DEFINE_PER_CPU(struct tce_page, tce_page) = {
++ .lock = INIT_LOCAL_LOCK(lock),
++};
+
+ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+ long npages, unsigned long uaddr,
+@@ -229,9 +236,10 @@ static int tce_buildmulti_pSeriesLP(stru
+ direction, attrs);
+ }
+
+- local_irq_save(flags); /* to protect tcep and the page behind it */
++ /* to protect tcep and the page behind it */
++ local_lock_irqsave(&tce_page.lock, flags);
+
+- tcep = __this_cpu_read(tce_page);
++ tcep = __this_cpu_read(tce_page.page);
+
+ /* This is safe to do since interrupts are off when we're called
+ * from iommu_alloc{,_sg}()
+@@ -240,12 +248,12 @@ static int tce_buildmulti_pSeriesLP(stru
+ tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
+ /* If allocation fails, fall back to the loop implementation */
+ if (!tcep) {
+- local_irq_restore(flags);
++ local_unlock_irqrestore(&tce_page.lock, flags);
+ return tce_build_pSeriesLP(tbl->it_index, tcenum,
+ tceshift,
+ npages, uaddr, direction, attrs);
+ }
+- __this_cpu_write(tce_page, tcep);
++ __this_cpu_write(tce_page.page, tcep);
+ }
+
+ rpn = __pa(uaddr) >> tceshift;
+@@ -275,7 +283,7 @@ static int tce_buildmulti_pSeriesLP(stru
+ tcenum += limit;
+ } while (npages > 0 && !rc);
+
+- local_irq_restore(flags);
++ local_unlock_irqrestore(&tce_page.lock, flags);
+
+ if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
+ ret = (int)rc;
+@@ -459,16 +467,17 @@ static int tce_setrange_multi_pSeriesLP(
+ DMA_BIDIRECTIONAL, 0);
+ }
+
+- local_irq_disable(); /* to protect tcep and the page behind it */
+- tcep = __this_cpu_read(tce_page);
++ /* to protect tcep and the page behind it */
++ local_lock_irq(&tce_page.lock);
++ tcep = __this_cpu_read(tce_page.page);
+
+ if (!tcep) {
+ tcep = (__be64 *)__get_free_page(GFP_ATOMIC);
+ if (!tcep) {
+- local_irq_enable();
++ local_unlock_irq(&tce_page.lock);
+ return -ENOMEM;
+ }
+- __this_cpu_write(tce_page, tcep);
++ __this_cpu_write(tce_page.page, tcep);
+ }
+
+ proto_tce = TCE_PCI_READ | TCE_PCI_WRITE;
+@@ -511,7 +520,7 @@ static int tce_setrange_multi_pSeriesLP(
+
+ /* error cleanup: caller will clear whole range */
+
+- local_irq_enable();
++ local_unlock_irq(&tce_page.lock);
+ return rc;
+ }
+
diff --git a/debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch b/debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch
new file mode 100644
index 0000000000..c8994ca9d6
--- /dev/null
+++ b/debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch
@@ -0,0 +1,37 @@
+Subject: powerpc/stackprotector: work around stack-guard init from atomic
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue Mar 26 18:31:29 2019 +0100
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+This is invoked from the secondary CPU in atomic context. On x86 we use
+tsc instead. On Power we XOR it against mftb() so lets use stack address
+as the initial value.
+
+Cc: stable-rt@vger.kernel.org
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/powerpc/include/asm/stackprotector.h | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+---
+--- a/arch/powerpc/include/asm/stackprotector.h
++++ b/arch/powerpc/include/asm/stackprotector.h
+@@ -19,8 +19,13 @@
+ */
+ static __always_inline void boot_init_stack_canary(void)
+ {
+- unsigned long canary = get_random_canary();
++ unsigned long canary;
+
++#ifndef CONFIG_PREEMPT_RT
++ canary = get_random_canary();
++#else
++ canary = ((unsigned long)&canary) & CANARY_MASK;
++#endif
+ current->stack_canary = canary;
+ #ifdef CONFIG_PPC64
+ get_paca()->canary = canary;
diff --git a/debian/patches-rt/preempt-Put-preempt_enable-within-an-instrumentation.patch b/debian/patches-rt/preempt-Put-preempt_enable-within-an-instrumentation.patch
new file mode 100644
index 0000000000..beddd4726f
--- /dev/null
+++ b/debian/patches-rt/preempt-Put-preempt_enable-within-an-instrumentation.patch
@@ -0,0 +1,47 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 8 Mar 2023 16:29:38 +0100
+Subject: [PATCH] preempt: Put preempt_enable() within an instrumentation*()
+ section.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Callers of preempt_enable() can be within an noinstr section leading to:
+| vmlinux.o: warning: objtool: native_sched_clock+0x97: call to preempt_schedule_notrace_thunk() leaves .noinstr.text section
+| vmlinux.o: warning: objtool: kvm_clock_read+0x22: call to preempt_schedule_notrace_thunk() leaves .noinstr.text section
+| vmlinux.o: warning: objtool: local_clock+0xb4: call to preempt_schedule_notrace_thunk() leaves .noinstr.text section
+| vmlinux.o: warning: objtool: enter_from_user_mode+0xea: call to preempt_schedule_thunk() leaves .noinstr.text section
+| vmlinux.o: warning: objtool: syscall_enter_from_user_mode+0x140: call to preempt_schedule_thunk() leaves .noinstr.text section
+| vmlinux.o: warning: objtool: syscall_enter_from_user_mode_prepare+0xf2: call to preempt_schedule_thunk() leaves .noinstr.text section
+| vmlinux.o: warning: objtool: irqentry_enter_from_user_mode+0xea: call to preempt_schedule_thunk() leaves .noinstr.text section
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20230309072724.3F6zRkvw@linutronix.de
+---
+ include/linux/preempt.h | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/include/linux/preempt.h
++++ b/include/linux/preempt.h
+@@ -230,15 +230,21 @@ do { \
+ #define preempt_enable() \
+ do { \
+ barrier(); \
+- if (unlikely(preempt_count_dec_and_test())) \
++ if (unlikely(preempt_count_dec_and_test())) { \
++ instrumentation_begin(); \
+ __preempt_schedule(); \
++ instrumentation_end(); \
++ } \
+ } while (0)
+
+ #define preempt_enable_notrace() \
+ do { \
+ barrier(); \
+- if (unlikely(__preempt_count_dec_and_test())) \
++ if (unlikely(__preempt_count_dec_and_test())) { \
++ instrumentation_begin(); \
+ __preempt_schedule_notrace(); \
++ instrumentation_end(); \
++ } \
+ } while (0)
+
+ #define preempt_check_resched() \
diff --git a/debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch b/debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch
new file mode 100644
index 0000000000..a75971478b
--- /dev/null
+++ b/debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch
@@ -0,0 +1,71 @@
+From: Frederic Weisbecker <frederic@kernel.org>
+Date: Tue, 5 Apr 2022 03:07:51 +0200
+Subject: [PATCH] rcutorture: Also force sched priority to timersd on
+ boosting test.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+ksoftirqd is statically boosted to the priority level right above the
+one of rcu_torture_boost() so that timers, which torture readers rely on,
+get a chance to run while rcu_torture_boost() is polling.
+
+However timers processing got split from ksoftirqd into their own kthread
+(timersd) that isn't boosted. It has the same SCHED_FIFO low prio as
+rcu_torture_boost() and therefore timers can't preempt it and may
+starve.
+
+The issue can be triggered in practice on v5.17.1-rt17 using:
+
+ ./kvm.sh --allcpus --configs TREE04 --duration 10m --kconfig "CONFIG_EXPERT=y CONFIG_PREEMPT_RT=y"
+
+Fix this with statically boosting timersd just like is done with
+ksoftirqd in commit
+ ea6d962e80b61 ("rcutorture: Judge RCU priority boosting on grace periods, not callbacks")
+
+Suggested-by: Mel Gorman <mgorman@suse.de>
+Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Link: https://lkml.kernel.org/r/20220405010752.1347437-1-frederic@kernel.org
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/interrupt.h | 1 +
+ kernel/rcu/rcutorture.c | 6 ++++++
+ kernel/softirq.c | 2 +-
+ 3 files changed, 8 insertions(+), 1 deletion(-)
+
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -610,6 +610,7 @@ extern void raise_softirq_irqoff(unsigne
+ extern void raise_softirq(unsigned int nr);
+
+ #ifdef CONFIG_PREEMPT_RT
++DECLARE_PER_CPU(struct task_struct *, timersd);
+ extern void raise_timer_softirq(void);
+ extern void raise_hrtimer_softirq(void);
+
+--- a/kernel/rcu/rcutorture.c
++++ b/kernel/rcu/rcutorture.c
+@@ -2408,6 +2408,12 @@ static int rcutorture_booster_init(unsig
+ WARN_ON_ONCE(!t);
+ sp.sched_priority = 2;
+ sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
++#ifdef CONFIG_PREEMPT_RT
++ t = per_cpu(timersd, cpu);
++ WARN_ON_ONCE(!t);
++ sp.sched_priority = 2;
++ sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
++#endif
+ }
+
+ /* Don't allow time recalculation while creating a new task. */
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -620,7 +620,7 @@ static inline void tick_irq_exit(void)
+ }
+
+ #ifdef CONFIG_PREEMPT_RT
+-static DEFINE_PER_CPU(struct task_struct *, timersd);
++DEFINE_PER_CPU(struct task_struct *, timersd);
+ static DEFINE_PER_CPU(unsigned long, pending_timer_softirq);
+
+ static unsigned int local_pending_timers(void)
diff --git a/debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch b/debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch
new file mode 100644
index 0000000000..60c3bf3aa1
--- /dev/null
+++ b/debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch
@@ -0,0 +1,44 @@
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Tue, 31 Oct 2023 22:35:20 +0800
+Subject: [PATCH] riscv: add PREEMPT_AUTO support
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+riscv has switched to GENERIC_ENTRY, so adding PREEMPT_AUTO is as simple
+as adding TIF_ARCH_RESCHED_LAZY related definitions and enabling
+HAVE_PREEMPT_AUTO.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/riscv/Kconfig | 1 +
+ arch/riscv/include/asm/thread_info.h | 2 ++
+ 2 files changed, 3 insertions(+)
+
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -135,6 +135,7 @@ config RISCV
+ select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK
+ select HAVE_PREEMPT_DYNAMIC_KEY if !XIP_KERNEL
++ select HAVE_PREEMPT_AUTO
+ select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RETHOOK if !XIP_KERNEL
+ select HAVE_RSEQ
+--- a/arch/riscv/include/asm/thread_info.h
++++ b/arch/riscv/include/asm/thread_info.h
+@@ -82,6 +82,7 @@ int arch_dup_task_struct(struct task_str
+ * - pending work-to-be-done flags are in lowest half-word
+ * - other flags in upper half-word(s)
+ */
++#define TIF_ARCH_RESCHED_LAZY 0 /* Lazy rescheduling */
+ #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
+ #define TIF_SIGPENDING 2 /* signal pending */
+ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+@@ -96,6 +97,7 @@ int arch_dup_task_struct(struct task_str
+ #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+ #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
+ #define _TIF_UPROBE (1 << TIF_UPROBE)
++#define _TIF_ARCH_RESCHED_LAZY (1 << TIF_ARCH_RESCHED_LAZY)
+
+ #define _TIF_WORK_MASK \
+ (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | \
diff --git a/debian/patches-rt/riscv-allow-to-enable-RT.patch b/debian/patches-rt/riscv-allow-to-enable-RT.patch
new file mode 100644
index 0000000000..66fcfc8e7f
--- /dev/null
+++ b/debian/patches-rt/riscv-allow-to-enable-RT.patch
@@ -0,0 +1,23 @@
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Tue, 31 Oct 2023 22:35:21 +0800
+Subject: [PATCH] riscv: allow to enable RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+Now, it's ready to enable RT on riscv.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/riscv/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -48,6 +48,7 @@ config RISCV
+ select ARCH_SUPPORTS_HUGETLBFS if MMU
+ select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU
+ select ARCH_SUPPORTS_PER_VMA_LOCK if MMU
++ select ARCH_SUPPORTS_RT
+ select ARCH_USE_MEMTEST
+ select ARCH_USE_QUEUED_RWLOCKS
+ select ARCH_USES_CFI_TRAPS if CFI_CLANG
diff --git a/debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch b/debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch
new file mode 100644
index 0000000000..01e19e8fcc
--- /dev/null
+++ b/debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch
@@ -0,0 +1,58 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 1 Aug 2023 17:26:48 +0200
+Subject: [PATCH] sched/rt: Don't try push tasks if there are none.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+I have a RT task X at a high priority and cyclictest on each CPU with
+lower priority than X's. If X is active and each CPU wakes their own
+cylictest thread then it ends in a longer rto_push storm.
+A random CPU determines via balance_rt() that the CPU on which X is
+running needs to push tasks. X has the highest priority, cyclictest is
+next in line so there is nothing that can be done since the task with
+the higher priority is not touched.
+
+tell_cpu_to_push() increments rto_loop_next and schedules
+rto_push_irq_work_func() on X's CPU. The other CPUs also increment the
+loop counter and do the same. Once rto_push_irq_work_func() is active it
+does nothing because it has _no_ pushable tasks on its runqueue. Then
+checks rto_next_cpu() and decides to queue irq_work on the local CPU
+because another CPU requested a push by incrementing the counter.
+
+I have traces where ~30 CPUs request this ~3 times each before it
+finally ends. This greatly increases X's runtime while X isn't making
+much progress.
+
+Teach rto_next_cpu() to only return CPUs which also have tasks on their
+runqueue which can be pushed away. This does not reduce the
+tell_cpu_to_push() invocations (rto_loop_next counter increments) but
+reduces the amount of issued rto_push_irq_work_func() if nothing can be
+done. As the result the overloaded CPU is blocked less often.
+
+There are still cases where the "same job" is repeated several times
+(for instance the current CPU needs to resched but didn't yet because
+the irq-work is repeated a few times and so the old task remains on the
+CPU) but the majority of request end in tell_cpu_to_push() before an IPI
+is issued.
+
+Reviewed-by: "Steven Rostedt (Google)" <rostedt@goodmis.org>
+Link: https://lore.kernel.org/r/20230801152648._y603AS_@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/sched/rt.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -2249,8 +2249,11 @@ static int rto_next_cpu(struct root_doma
+
+ rd->rto_cpu = cpu;
+
+- if (cpu < nr_cpu_ids)
++ if (cpu < nr_cpu_ids) {
++ if (!has_pushable_tasks(cpu_rq(cpu)))
++ continue;
+ return cpu;
++ }
+
+ rd->rto_cpu = -1;
+
diff --git a/debian/patches-rt/series b/debian/patches-rt/series
new file mode 100644
index 0000000000..9269d7464f
--- /dev/null
+++ b/debian/patches-rt/series
@@ -0,0 +1,255 @@
+# Applied upstream
+
+###########################################################################
+# Posted and applied
+###########################################################################
+
+# signal_x86__Delay_calling_signals_in_atomic.patch
+
+###########################################################################
+# Posted
+###########################################################################
+0001-sched-Constrain-locks-in-sched_submit_work.patch
+0002-locking-rtmutex-Avoid-unconditional-slowpath-for-DEB.patch
+0003-sched-Extract-__schedule_loop.patch
+0004-sched-Provide-rt_mutex-specific-scheduler-helpers.patch
+0005-locking-rtmutex-Use-rt_mutex-specific-scheduler-help.patch
+0006-locking-rtmutex-Add-a-lockdep-assert-to-catch-potent.patch
+0007-futex-pi-Fix-recursive-rt_mutex-waiter-state.patch
+
+# Hacks to get ptrace to work.
+0001-signal-Add-proper-comment-about-the-preempt-disable-.patch
+0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch
+
+# DRM AMD GPU
+0001-drm-amd-display-Remove-migrate_en-dis-from-dc_fpu_be.patch
+0002-drm-amd-display-Simplify-the-per-CPU-usage.patch
+0003-drm-amd-display-Add-a-warning-if-the-FPU-is-used-out.patch
+0004-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch
+0005-drm-amd-display-Move-the-memory-allocation-out-of-dc.patch
+
+###########################################################################
+# Post
+###########################################################################
+net-Avoid-the-IPI-to-free-the.patch
+
+###########################################################################
+# X86:
+###########################################################################
+x86__Allow_to_enable_RT.patch
+x86__Enable_RT_also_on_32bit.patch
+
+###########################################################################
+# For later, not essencial
+###########################################################################
+# Posted
+sched-rt-Don-t-try-push-tasks-if-there-are-none.patch
+
+# Needs discussion first.
+softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
+rcutorture-Also-force-sched-priority-to-timersd-on-b.patch
+tick-Fix-timer-storm-since-introduction-of-timersd.patch
+softirq-Wake-ktimers-thread-also-in-softirq.patch
+zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch
+preempt-Put-preempt_enable-within-an-instrumentation.patch
+
+# Sched
+0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch
+0002-softirq-Add-function-to-preempt-serving-softirqs.patch
+0003-time-Allow-to-preempt-after-a-callback.patch
+
+###########################################################################
+# John's printk queue
+###########################################################################
+0002-serial-core-Use-lock-wrappers.patch
+0003-serial-21285-Use-port-lock-wrappers.patch
+0004-serial-8250_aspeed_vuart-Use-port-lock-wrappers.patch
+0005-serial-8250_bcm7271-Use-port-lock-wrappers.patch
+0006-serial-8250-Use-port-lock-wrappers.patch
+0007-serial-8250_dma-Use-port-lock-wrappers.patch
+0008-serial-8250_dw-Use-port-lock-wrappers.patch
+0009-serial-8250_exar-Use-port-lock-wrappers.patch
+0010-serial-8250_fsl-Use-port-lock-wrappers.patch
+0011-serial-8250_mtk-Use-port-lock-wrappers.patch
+0012-serial-8250_omap-Use-port-lock-wrappers.patch
+0013-serial-8250_pci1xxxx-Use-port-lock-wrappers.patch
+0014-serial-altera_jtaguart-Use-port-lock-wrappers.patch
+0015-serial-altera_uart-Use-port-lock-wrappers.patch
+0016-serial-amba-pl010-Use-port-lock-wrappers.patch
+0017-serial-amba-pl011-Use-port-lock-wrappers.patch
+0018-serial-apb-Use-port-lock-wrappers.patch
+0019-serial-ar933x-Use-port-lock-wrappers.patch
+0020-serial-arc_uart-Use-port-lock-wrappers.patch
+0021-serial-atmel-Use-port-lock-wrappers.patch
+0022-serial-bcm63xx-uart-Use-port-lock-wrappers.patch
+0023-serial-cpm_uart-Use-port-lock-wrappers.patch
+0024-serial-digicolor-Use-port-lock-wrappers.patch
+0025-serial-dz-Use-port-lock-wrappers.patch
+0026-serial-linflexuart-Use-port-lock-wrappers.patch
+0027-serial-fsl_lpuart-Use-port-lock-wrappers.patch
+0028-serial-icom-Use-port-lock-wrappers.patch
+0029-serial-imx-Use-port-lock-wrappers.patch
+0030-serial-ip22zilog-Use-port-lock-wrappers.patch
+0031-serial-jsm-Use-port-lock-wrappers.patch
+0032-serial-liteuart-Use-port-lock-wrappers.patch
+0033-serial-lpc32xx_hs-Use-port-lock-wrappers.patch
+0034-serial-ma35d1-Use-port-lock-wrappers.patch
+0035-serial-mcf-Use-port-lock-wrappers.patch
+0036-serial-men_z135_uart-Use-port-lock-wrappers.patch
+0037-serial-meson-Use-port-lock-wrappers.patch
+0038-serial-milbeaut_usio-Use-port-lock-wrappers.patch
+0039-serial-mpc52xx-Use-port-lock-wrappers.patch
+0040-serial-mps2-uart-Use-port-lock-wrappers.patch
+0041-serial-msm-Use-port-lock-wrappers.patch
+0042-serial-mvebu-uart-Use-port-lock-wrappers.patch
+0043-serial-omap-Use-port-lock-wrappers.patch
+0044-serial-owl-Use-port-lock-wrappers.patch
+0045-serial-pch-Use-port-lock-wrappers.patch
+0046-serial-pic32-Use-port-lock-wrappers.patch
+0047-serial-pmac_zilog-Use-port-lock-wrappers.patch
+0048-serial-pxa-Use-port-lock-wrappers.patch
+0049-serial-qcom-geni-Use-port-lock-wrappers.patch
+0050-serial-rda-Use-port-lock-wrappers.patch
+0051-serial-rp2-Use-port-lock-wrappers.patch
+0052-serial-sa1100-Use-port-lock-wrappers.patch
+0053-serial-samsung_tty-Use-port-lock-wrappers.patch
+0054-serial-sb1250-duart-Use-port-lock-wrappers.patch
+0056-serial-tegra-Use-port-lock-wrappers.patch
+0057-serial-core-Use-port-lock-wrappers.patch
+0058-serial-mctrl_gpio-Use-port-lock-wrappers.patch
+0059-serial-txx9-Use-port-lock-wrappers.patch
+0060-serial-sh-sci-Use-port-lock-wrappers.patch
+0061-serial-sifive-Use-port-lock-wrappers.patch
+0062-serial-sprd-Use-port-lock-wrappers.patch
+0063-serial-st-asc-Use-port-lock-wrappers.patch
+0064-serial-stm32-Use-port-lock-wrappers.patch
+0065-serial-sunhv-Use-port-lock-wrappers.patch
+0066-serial-sunplus-uart-Use-port-lock-wrappers.patch
+0067-serial-sunsab-Use-port-lock-wrappers.patch
+0068-serial-sunsu-Use-port-lock-wrappers.patch
+0069-serial-sunzilog-Use-port-lock-wrappers.patch
+0070-serial-timbuart-Use-port-lock-wrappers.patch
+0071-serial-uartlite-Use-port-lock-wrappers.patch
+0072-serial-ucc_uart-Use-port-lock-wrappers.patch
+0073-serial-vt8500-Use-port-lock-wrappers.patch
+0074-serial-xilinx_uartps-Use-port-lock-wrappers.patch
+0075-printk-Add-non-BKL-nbcon-console-basic-infrastructur.patch
+0076-printk-nbcon-Add-acquire-release-logic.patch
+0077-printk-Make-static-printk-buffers-available-to-nbcon.patch
+0078-printk-nbcon-Add-buffer-management.patch
+0079-printk-nbcon-Add-ownership-state-functions.patch
+0080-printk-nbcon-Add-sequence-handling.patch
+0081-printk-nbcon-Add-emit-function-and-callback-function.patch
+0082-printk-nbcon-Allow-drivers-to-mark-unsafe-regions-an.patch
+0083-printk-fix-illegal-pbufs-access-for-CONFIG_PRINTK.patch
+0084-printk-Reduce-pr_flush-pooling-time.patch
+0085-printk-nbcon-Relocate-32bit-seq-macros.patch
+0086-printk-Adjust-mapping-for-32bit-seq-macros.patch
+0087-printk-Use-prb_first_seq-as-base-for-32bit-seq-macro.patch
+0088-printk-ringbuffer-Do-not-skip-non-finalized-records-.patch
+0089-printk-ringbuffer-Clarify-special-lpos-values.patch
+0090-printk-For-suppress_panic_printk-check-for-other-CPU.patch
+0091-printk-Add-this_cpu_in_panic.patch
+0092-printk-ringbuffer-Cleanup-reader-terminology.patch
+0093-printk-Wait-for-all-reserved-records-with-pr_flush.patch
+0094-printk-ringbuffer-Skip-non-finalized-records-in-pani.patch
+0095-printk-ringbuffer-Consider-committed-as-finalized-in.patch
+0096-printk-Disable-passing-console-lock-owner-completely.patch
+0097-printk-Avoid-non-panic-CPUs-writing-to-ringbuffer.patch
+0098-panic-Flush-kernel-log-buffer-at-the-end.patch
+0099-printk-Consider-nbcon-boot-consoles-on-seq-init.patch
+0100-printk-Add-sparse-notation-to-console_srcu-locking.patch
+0101-printk-nbcon-Ensure-ownership-release-on-failed-emit.patch
+0102-printk-Check-printk_deferred_enter-_exit-usage.patch
+0103-printk-nbcon-Implement-processing-in-port-lock-wrapp.patch
+0104-printk-nbcon-Add-driver_enter-driver_exit-console-ca.patch
+0105-printk-Make-console_is_usable-available-to-nbcon.patch
+0106-printk-Let-console_is_usable-handle-nbcon.patch
+0107-printk-Add-flags-argument-for-console_is_usable.patch
+0108-printk-nbcon-Provide-function-to-flush-using-write_a.patch
+0109-printk-Track-registered-boot-consoles.patch
+0110-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch
+0111-printk-nbcon-Assign-priority-based-on-CPU-state.patch
+0112-printk-nbcon-Add-unsafe-flushing-on-panic.patch
+0113-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch
+0114-printk-Track-nbcon-consoles.patch
+0115-printk-Coordinate-direct-printing-in-panic.patch
+0116-printk-nbcon-Implement-emergency-sections.patch
+0117-panic-Mark-emergency-section-in-warn.patch
+0118-panic-Mark-emergency-section-in-oops.patch
+0119-rcu-Mark-emergency-section-in-rcu-stalls.patch
+0120-lockdep-Mark-emergency-section-in-lockdep-splats.patch
+0121-printk-nbcon-Introduce-printing-kthreads.patch
+0122-printk-Atomic-print-in-printk-context-on-shutdown.patch
+0123-printk-nbcon-Add-context-to-console_is_usable.patch
+0124-printk-nbcon-Add-printer-thread-wakeups.patch
+0125-printk-nbcon-Stop-threads-on-shutdown-reboot.patch
+0126-printk-nbcon-Start-printing-threads.patch
+0127-proc-Add-nbcon-support-for-proc-consoles.patch
+0128-tty-sysfs-Add-nbcon-support-for-active.patch
+0129-printk-nbcon-Provide-function-to-reacquire-ownership.patch
+0130-serial-core-Provide-low-level-functions-to-port-lock.patch
+0131-serial-8250-Switch-to-nbcon-console.patch
+0132-printk-Add-kthread-for-all-legacy-consoles.patch
+0133-serial-8250-revert-drop-lockdep-annotation-from-seri.patch
+0134-printk-Avoid-false-positive-lockdep-report-for-legac.patch
+
+###########################################################################
+# DRM:
+###########################################################################
+0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
+0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
+0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
+0006-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch
+0007-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch
+0008-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch
+0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
+0010-drm-i915-Drop-the-irqs_disabled-check.patch
+drm-i915-Do-not-disable-preemption-for-resets.patch
+drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch
+Revert-drm-i915-Depend-on-PREEMPT_RT.patch
+
+###########################################################################
+# Lazy preemption
+###########################################################################
+PREEMPT_AUTO.patch
+
+###########################################################################
+# ARM/ARM64
+###########################################################################
+0001-arm-Disable-jump-label-on-PREEMPT_RT.patch
+ARM__enable_irq_in_translation_section_permission_fault_handlers.patch
+# arm64-signal-Use-ARCH_RT_DELAYS_SIGNAL_SEND.patch
+tty_serial_omap__Make_the_locking_RT_aware.patch
+tty_serial_pl011__Make_the_locking_work_on_RT.patch
+0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch
+0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch
+0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch
+0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch
+ARM__Allow_to_enable_RT.patch
+ARM64__Allow_to_enable_RT.patch
+
+###########################################################################
+# POWERPC
+###########################################################################
+powerpc__traps__Use_PREEMPT_RT.patch
+powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch
+powerpc-pseries-Select-the-generic-memory-allocator.patch
+powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch
+powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch
+POWERPC__Allow_to_enable_RT.patch
+
+###########################################################################
+# RISC-V
+###########################################################################
+#RISC-V-Probe-misaligned-access-speed-in-parallel.patch
+riscv-add-PREEMPT_AUTO-support.patch
+riscv-allow-to-enable-RT.patch
+
+# Sysfs file vs uname() -v
+sysfs__Add__sys_kernel_realtime_entry.patch
+
+###########################################################################
+# RT release version
+###########################################################################
+Add_localversion_for_-RT_release.patch
diff --git a/debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch b/debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
new file mode 100644
index 0000000000..949ff6da70
--- /dev/null
+++ b/debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
@@ -0,0 +1,222 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 1 Dec 2021 17:41:09 +0100
+Subject: [PATCH] softirq: Use a dedicated thread for timer wakeups.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+A timer/hrtimer softirq is raised in-IRQ context. With threaded
+interrupts enabled or on PREEMPT_RT this leads to waking the ksoftirqd
+for the processing of the softirq.
+Once the ksoftirqd is marked as pending (or is running) it will collect
+all raised softirqs. This in turn means that a softirq which would have
+been processed at the end of the threaded interrupt, which runs at an
+elevated priority, is now moved to ksoftirqd which runs at SCHED_OTHER
+priority and competes with every regular task for CPU resources.
+This introduces long delays on heavy loaded systems and is not desired
+especially if the system is not overloaded by the softirqs.
+
+Split the TIMER_SOFTIRQ and HRTIMER_SOFTIRQ processing into a dedicated
+timers thread and let it run at the lowest SCHED_FIFO priority.
+RT tasks are are woken up from hardirq context so only timer_list timers
+and hrtimers for "regular" tasks are processed here. The higher priority
+ensures that wakeups are performed before scheduling SCHED_OTHER tasks.
+
+Using a dedicated variable to store the pending softirq bits values
+ensure that the timer are not accidentally picked up by ksoftirqd and
+other threaded interrupts.
+It shouldn't be picked up by ksoftirqd since it runs at lower priority.
+However if the timer bits are ORed while a threaded interrupt is
+running, then the timer softirq would be performed at higher priority.
+The new timer thread will block on the softirq lock before it starts
+softirq work. This "race window" isn't closed because while timer thread
+is performing the softirq it can get PI-boosted via the softirq lock by
+a random force-threaded thread.
+The timer thread can pick up pending softirqs from ksoftirqd but only
+if the softirq load is high. It is not be desired that the picked up
+softirqs are processed at SCHED_FIFO priority under high softirq load
+but this can already happen by a PI-boost by a force-threaded interrupt.
+
+Reported-by: kernel test robot <lkp@intel.com> [ static timer_threads ]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/interrupt.h | 16 ++++++++
+ kernel/softirq.c | 92 ++++++++++++++++++++++++++++++++++++++++++++--
+ kernel/time/hrtimer.c | 4 +-
+ kernel/time/timer.c | 2 -
+ 4 files changed, 108 insertions(+), 6 deletions(-)
+
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -609,6 +609,22 @@ extern void __raise_softirq_irqoff(unsig
+ extern void raise_softirq_irqoff(unsigned int nr);
+ extern void raise_softirq(unsigned int nr);
+
++#ifdef CONFIG_PREEMPT_RT
++extern void raise_timer_softirq(void);
++extern void raise_hrtimer_softirq(void);
++
++#else
++static inline void raise_timer_softirq(void)
++{
++ raise_softirq(TIMER_SOFTIRQ);
++}
++
++static inline void raise_hrtimer_softirq(void)
++{
++ raise_softirq_irqoff(HRTIMER_SOFTIRQ);
++}
++#endif
++
+ DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
+
+ static inline struct task_struct *this_cpu_ksoftirqd(void)
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -619,6 +619,29 @@ static inline void tick_irq_exit(void)
+ #endif
+ }
+
++#ifdef CONFIG_PREEMPT_RT
++static DEFINE_PER_CPU(struct task_struct *, timersd);
++static DEFINE_PER_CPU(unsigned long, pending_timer_softirq);
++
++static unsigned int local_pending_timers(void)
++{
++ return __this_cpu_read(pending_timer_softirq);
++}
++
++static void wake_timersd(void)
++{
++ struct task_struct *tsk = __this_cpu_read(timersd);
++
++ if (tsk)
++ wake_up_process(tsk);
++}
++
++#else
++
++static inline void wake_timersd(void) { }
++
++#endif
++
+ static inline void __irq_exit_rcu(void)
+ {
+ #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
+@@ -628,8 +651,13 @@ static inline void __irq_exit_rcu(void)
+ #endif
+ account_hardirq_exit(current);
+ preempt_count_sub(HARDIRQ_OFFSET);
+- if (!in_interrupt() && local_softirq_pending())
+- invoke_softirq();
++ if (!in_interrupt()) {
++ if (local_softirq_pending())
++ invoke_softirq();
++
++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers())
++ wake_timersd();
++ }
+
+ tick_irq_exit();
+ }
+@@ -963,12 +991,70 @@ static struct smp_hotplug_thread softirq
+ .thread_comm = "ksoftirqd/%u",
+ };
+
++#ifdef CONFIG_PREEMPT_RT
++static void timersd_setup(unsigned int cpu)
++{
++ sched_set_fifo_low(current);
++}
++
++static int timersd_should_run(unsigned int cpu)
++{
++ return local_pending_timers();
++}
++
++static void run_timersd(unsigned int cpu)
++{
++ unsigned int timer_si;
++
++ ksoftirqd_run_begin();
++
++ timer_si = local_pending_timers();
++ __this_cpu_write(pending_timer_softirq, 0);
++ or_softirq_pending(timer_si);
++
++ __do_softirq();
++
++ ksoftirqd_run_end();
++}
++
++static void raise_ktimers_thread(unsigned int nr)
++{
++ trace_softirq_raise(nr);
++ __this_cpu_or(pending_timer_softirq, 1 << nr);
++}
++
++void raise_hrtimer_softirq(void)
++{
++ raise_ktimers_thread(HRTIMER_SOFTIRQ);
++}
++
++void raise_timer_softirq(void)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++ raise_ktimers_thread(TIMER_SOFTIRQ);
++ wake_timersd();
++ local_irq_restore(flags);
++}
++
++static struct smp_hotplug_thread timer_threads = {
++ .store = &timersd,
++ .setup = timersd_setup,
++ .thread_should_run = timersd_should_run,
++ .thread_fn = run_timersd,
++ .thread_comm = "ktimers/%u",
++};
++#endif
++
+ static __init int spawn_ksoftirqd(void)
+ {
+ cpuhp_setup_state_nocalls(CPUHP_SOFTIRQ_DEAD, "softirq:dead", NULL,
+ takeover_tasklets);
+ BUG_ON(smpboot_register_percpu_thread(&softirq_threads));
+-
++#ifdef CONFIG_PREEMPT_RT
++ BUG_ON(smpboot_register_percpu_thread(&timer_threads));
++#endif
+ return 0;
+ }
+ early_initcall(spawn_ksoftirqd);
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -1808,7 +1808,7 @@ void hrtimer_interrupt(struct clock_even
+ if (!ktime_before(now, cpu_base->softirq_expires_next)) {
+ cpu_base->softirq_expires_next = KTIME_MAX;
+ cpu_base->softirq_activated = 1;
+- raise_softirq_irqoff(HRTIMER_SOFTIRQ);
++ raise_hrtimer_softirq();
+ }
+
+ __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD);
+@@ -1921,7 +1921,7 @@ void hrtimer_run_queues(void)
+ if (!ktime_before(now, cpu_base->softirq_expires_next)) {
+ cpu_base->softirq_expires_next = KTIME_MAX;
+ cpu_base->softirq_activated = 1;
+- raise_softirq_irqoff(HRTIMER_SOFTIRQ);
++ raise_hrtimer_softirq();
+ }
+
+ __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD);
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -2054,7 +2054,7 @@ static void run_local_timers(void)
+ if (time_before(jiffies, base->next_expiry))
+ return;
+ }
+- raise_softirq(TIMER_SOFTIRQ);
++ raise_timer_softirq();
+ }
+
+ /*
diff --git a/debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch b/debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch
new file mode 100644
index 0000000000..21609fe207
--- /dev/null
+++ b/debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch
@@ -0,0 +1,44 @@
+From: Junxiao Chang <junxiao.chang@intel.com>
+Date: Mon, 20 Feb 2023 09:12:20 +0100
+Subject: [PATCH] softirq: Wake ktimers thread also in softirq.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+If the hrtimer is raised while a softirq is processed then it does not
+wake the corresponding ktimers thread. This is due to the optimisation in the
+irq-exit path which is also used to wake the ktimers thread. For the other
+softirqs, this is okay because the additional softirq bits will be handled by
+the currently running softirq handler.
+The timer related softirq bits are added to a different variable and rely on
+the ktimers thread.
+As a consuequence the wake up of ktimersd is delayed until the next timer tick.
+
+Always wake the ktimers thread if a timer related softirq is pending.
+
+Reported-by: Peh, Hock Zhang <hock.zhang.peh@intel.com>
+Signed-off-by: Junxiao Chang <junxiao.chang@intel.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/softirq.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -646,13 +646,12 @@ static inline void __irq_exit_rcu(void)
+ #endif
+ account_hardirq_exit(current);
+ preempt_count_sub(HARDIRQ_OFFSET);
+- if (!in_interrupt()) {
+- if (local_softirq_pending())
+- invoke_softirq();
++ if (!in_interrupt() && local_softirq_pending())
++ invoke_softirq();
+
+- if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers())
+- wake_timersd();
+- }
++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers() &&
++ !(in_nmi() | in_hardirq()))
++ wake_timersd();
+
+ tick_irq_exit();
+ }
diff --git a/debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch b/debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch
new file mode 100644
index 0000000000..2e6928846b
--- /dev/null
+++ b/debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch
@@ -0,0 +1,53 @@
+Subject: sysfs: Add /sys/kernel/realtime entry
+From: Clark Williams <williams@redhat.com>
+Date: Sat Jul 30 21:55:53 2011 -0500
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Clark Williams <williams@redhat.com>
+
+Add a /sys/kernel entry to indicate that the kernel is a
+realtime kernel.
+
+Clark says that he needs this for udev rules, udev needs to evaluate
+if its a PREEMPT_RT kernel a few thousand times and parsing uname
+output is too slow or so.
+
+Are there better solutions? Should it exist and return 0 on !-rt?
+
+Signed-off-by: Clark Williams <williams@redhat.com>
+Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ kernel/ksysfs.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+---
+--- a/kernel/ksysfs.c
++++ b/kernel/ksysfs.c
+@@ -179,6 +179,15 @@ KERNEL_ATTR_RO(crash_elfcorehdr_size);
+
+ #endif /* CONFIG_CRASH_CORE */
+
++#if defined(CONFIG_PREEMPT_RT)
++static ssize_t realtime_show(struct kobject *kobj,
++ struct kobj_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%d\n", 1);
++}
++KERNEL_ATTR_RO(realtime);
++#endif
++
+ /* whether file capabilities are enabled */
+ static ssize_t fscaps_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+@@ -275,6 +284,9 @@ static struct attribute * kernel_attrs[]
+ &rcu_expedited_attr.attr,
+ &rcu_normal_attr.attr,
+ #endif
++#ifdef CONFIG_PREEMPT_RT
++ &realtime_attr.attr,
++#endif
+ NULL
+ };
+
diff --git a/debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch b/debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch
new file mode 100644
index 0000000000..874c7b3b3d
--- /dev/null
+++ b/debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch
@@ -0,0 +1,106 @@
+From: Frederic Weisbecker <frederic@kernel.org>
+Date: Tue, 5 Apr 2022 03:07:52 +0200
+Subject: [PATCH] tick: Fix timer storm since introduction of timersd
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+If timers are pending while the tick is reprogrammed on nohz_mode, the
+next expiry is not armed to fire now, it is delayed one jiffy forward
+instead so as not to raise an inextinguishable timer storm with such
+scenario:
+
+1) IRQ triggers and queue a timer
+2) ksoftirqd() is woken up
+3) IRQ tail: timer is reprogrammed to fire now
+4) IRQ exit
+5) TIMER interrupt
+6) goto 3)
+
+...all that until we finally reach ksoftirqd.
+
+Unfortunately we are checking the wrong softirq vector bitmask since
+timersd kthread has split from ksoftirqd. Timers now have their own
+vector state field that must be checked separately. As a result, the
+old timer storm is back. This shows up early on boot with extremely long
+initcalls:
+
+ [ 333.004807] initcall dquot_init+0x0/0x111 returned 0 after 323822879 usecs
+
+and the cause is uncovered with the right trace events showing just
+10 microseconds between ticks (~100 000 Hz):
+
+|swapper/-1 1dn.h111 60818582us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415486608
+|swapper/-1 1dn.h111 60818592us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415496082
+|swapper/-1 1dn.h111 60818601us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415505550
+
+Fix this by checking the right timer vector state from the nohz code.
+
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lkml.kernel.org/r/20220405010752.1347437-2-frederic@kernel.org
+---
+ include/linux/interrupt.h | 12 ++++++++++++
+ kernel/softirq.c | 7 +------
+ kernel/time/tick-sched.c | 2 +-
+ 3 files changed, 14 insertions(+), 7 deletions(-)
+
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -611,9 +611,16 @@ extern void raise_softirq(unsigned int n
+
+ #ifdef CONFIG_PREEMPT_RT
+ DECLARE_PER_CPU(struct task_struct *, timersd);
++DECLARE_PER_CPU(unsigned long, pending_timer_softirq);
++
+ extern void raise_timer_softirq(void);
+ extern void raise_hrtimer_softirq(void);
+
++static inline unsigned int local_pending_timers(void)
++{
++ return __this_cpu_read(pending_timer_softirq);
++}
++
+ #else
+ static inline void raise_timer_softirq(void)
+ {
+@@ -624,6 +631,11 @@ static inline void raise_hrtimer_softirq
+ {
+ raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+ }
++
++static inline unsigned int local_pending_timers(void)
++{
++ return local_softirq_pending();
++}
+ #endif
+
+ DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -621,12 +621,7 @@ static inline void tick_irq_exit(void)
+
+ #ifdef CONFIG_PREEMPT_RT
+ DEFINE_PER_CPU(struct task_struct *, timersd);
+-static DEFINE_PER_CPU(unsigned long, pending_timer_softirq);
+-
+-static unsigned int local_pending_timers(void)
+-{
+- return __this_cpu_read(pending_timer_softirq);
+-}
++DEFINE_PER_CPU(unsigned long, pending_timer_softirq);
+
+ static void wake_timersd(void)
+ {
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -795,7 +795,7 @@ static void tick_nohz_restart(struct tic
+
+ static inline bool local_timer_softirq_pending(void)
+ {
+- return local_softirq_pending() & BIT(TIMER_SOFTIRQ);
++ return local_pending_timers() & BIT(TIMER_SOFTIRQ);
+ }
+
+ static ktime_t tick_nohz_next_event(struct tick_sched *ts, int cpu)
diff --git a/debian/patches-rt/tty_serial_omap__Make_the_locking_RT_aware.patch b/debian/patches-rt/tty_serial_omap__Make_the_locking_RT_aware.patch
new file mode 100644
index 0000000000..89d7447401
--- /dev/null
+++ b/debian/patches-rt/tty_serial_omap__Make_the_locking_RT_aware.patch
@@ -0,0 +1,47 @@
+Subject: tty/serial/omap: Make the locking RT aware
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu Jul 28 13:32:57 2011 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+The lock is a sleeping lock and local_irq_save() is not the
+optimsation we are looking for. Redo it to make it work on -RT and
+non-RT.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ drivers/tty/serial/omap-serial.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+---
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1212,13 +1212,10 @@ serial_omap_console_write(struct console
+ unsigned int ier;
+ int locked = 1;
+
+- local_irq_save(flags);
+- if (up->port.sysrq)
+- locked = 0;
+- else if (oops_in_progress)
+- locked = uart_port_trylock(&up->port);
++ if (up->port.sysrq || oops_in_progress)
++ locked = uart_port_trylock_irqsave(&up->port, &flags);
+ else
+- uart_port_lock(&up->port);
++ uart_port_lock_irqsave(&up->port, &flags);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -1245,8 +1242,7 @@ serial_omap_console_write(struct console
+ check_modem_status(up);
+
+ if (locked)
+- uart_port_unlock(&up->port);
+- local_irq_restore(flags);
++ uart_port_unlock_irqrestore(&up->port, flags);
+ }
+
+ static int __init
diff --git a/debian/patches-rt/tty_serial_pl011__Make_the_locking_work_on_RT.patch b/debian/patches-rt/tty_serial_pl011__Make_the_locking_work_on_RT.patch
new file mode 100644
index 0000000000..32ff14fba0
--- /dev/null
+++ b/debian/patches-rt/tty_serial_pl011__Make_the_locking_work_on_RT.patch
@@ -0,0 +1,46 @@
+Subject: tty/serial/pl011: Make the locking work on RT
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue Jan 8 21:36:51 2013 +0100
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+The lock is a sleeping lock and local_irq_save() is not the optimsation
+we are looking for. Redo it to make it work on -RT and non-RT.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ drivers/tty/serial/amba-pl011.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+---
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -2332,13 +2332,10 @@ pl011_console_write(struct console *co,
+
+ clk_enable(uap->clk);
+
+- local_irq_save(flags);
+- if (uap->port.sysrq)
+- locked = 0;
+- else if (oops_in_progress)
+- locked = uart_port_trylock(&uap->port);
++ if (uap->port.sysrq || oops_in_progress)
++ locked = uart_port_trylock_irqsave(&uap->port, &flags);
+ else
+- uart_port_lock(&uap->port);
++ uart_port_lock_irqsave(&uap->port, &flags);
+
+ /*
+ * First save the CR then disable the interrupts
+@@ -2364,8 +2361,7 @@ pl011_console_write(struct console *co,
+ pl011_write(old_cr, uap, REG_CR);
+
+ if (locked)
+- uart_port_unlock(&uap->port);
+- local_irq_restore(flags);
++ uart_port_unlock_irqrestore(&uap->port, flags);
+
+ clk_disable(uap->clk);
+ }
diff --git a/debian/patches-rt/x86__Allow_to_enable_RT.patch b/debian/patches-rt/x86__Allow_to_enable_RT.patch
new file mode 100644
index 0000000000..3fa433084a
--- /dev/null
+++ b/debian/patches-rt/x86__Allow_to_enable_RT.patch
@@ -0,0 +1,27 @@
+Subject: x86: Allow to enable RT
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed Aug 7 18:15:38 2019 +0200
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+Allow to select RT.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/x86/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+---
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -28,6 +28,7 @@ config X86_64
+ select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
+ select ARCH_SUPPORTS_PER_VMA_LOCK
++ select ARCH_SUPPORTS_RT
+ select ARCH_USE_CMPXCHG_LOCKREF
+ select HAVE_ARCH_SOFT_DIRTY
+ select MODULES_USE_ELF_RELA
diff --git a/debian/patches-rt/x86__Enable_RT_also_on_32bit.patch b/debian/patches-rt/x86__Enable_RT_also_on_32bit.patch
new file mode 100644
index 0000000000..3092b41acb
--- /dev/null
+++ b/debian/patches-rt/x86__Enable_RT_also_on_32bit.patch
@@ -0,0 +1,33 @@
+Subject: x86: Enable RT also on 32bit
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu Nov 7 17:49:20 2019 +0100
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
+
+---
+ arch/x86/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+---
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -28,7 +28,6 @@ config X86_64
+ select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
+ select ARCH_SUPPORTS_PER_VMA_LOCK
+- select ARCH_SUPPORTS_RT
+ select ARCH_USE_CMPXCHG_LOCKREF
+ select HAVE_ARCH_SOFT_DIRTY
+ select MODULES_USE_ELF_RELA
+@@ -118,6 +117,7 @@ config X86
+ select ARCH_USES_CFI_TRAPS if X86_64 && CFI_CLANG
+ select ARCH_SUPPORTS_LTO_CLANG
+ select ARCH_SUPPORTS_LTO_CLANG_THIN
++ select ARCH_SUPPORTS_RT
+ select ARCH_USE_BUILTIN_BSWAP
+ select ARCH_USE_MEMTEST
+ select ARCH_USE_QUEUED_RWLOCKS
diff --git a/debian/patches-rt/zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch b/debian/patches-rt/zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch
new file mode 100644
index 0000000000..0ccb2d87cc
--- /dev/null
+++ b/debian/patches-rt/zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch
@@ -0,0 +1,94 @@
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Thu, 31 Mar 2016 04:08:28 +0200
+Subject: [PATCH] zram: Replace bit spinlocks with spinlock_t for PREEMPT_RT.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.6/older/patches-6.6.7-rt18.tar.xz
+
+The bit spinlock disables preemption. The spinlock_t lock becomes a sleeping
+lock on PREEMPT_RT and it can not be acquired in this context. In this locked
+section, zs_free() acquires a zs_pool::lock, and there is access to
+zram::wb_limit_lock.
+
+Use a spinlock_t on PREEMPT_RT for locking and set/ clear ZRAM_LOCK bit after
+the lock has been acquired/ dropped.
+
+Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lkml.kernel.org/r/YqIbMuHCPiQk+Ac2@linutronix.de
+Link: https://lore.kernel.org/20230323161830.jFbWCosd@linutronix.de
+---
+ drivers/block/zram/zram_drv.c | 37 +++++++++++++++++++++++++++++++++++++
+ drivers/block/zram/zram_drv.h | 3 +++
+ 2 files changed, 40 insertions(+)
+
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -57,6 +57,41 @@ static void zram_free_page(struct zram *
+ static int zram_read_page(struct zram *zram, struct page *page, u32 index,
+ struct bio *parent);
+
++#ifdef CONFIG_PREEMPT_RT
++static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages)
++{
++ size_t index;
++
++ for (index = 0; index < num_pages; index++)
++ spin_lock_init(&zram->table[index].lock);
++}
++
++static int zram_slot_trylock(struct zram *zram, u32 index)
++{
++ int ret;
++
++ ret = spin_trylock(&zram->table[index].lock);
++ if (ret)
++ __set_bit(ZRAM_LOCK, &zram->table[index].flags);
++ return ret;
++}
++
++static void zram_slot_lock(struct zram *zram, u32 index)
++{
++ spin_lock(&zram->table[index].lock);
++ __set_bit(ZRAM_LOCK, &zram->table[index].flags);
++}
++
++static void zram_slot_unlock(struct zram *zram, u32 index)
++{
++ __clear_bit(ZRAM_LOCK, &zram->table[index].flags);
++ spin_unlock(&zram->table[index].lock);
++}
++
++#else
++
++static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages) { }
++
+ static int zram_slot_trylock(struct zram *zram, u32 index)
+ {
+ return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags);
+@@ -71,6 +106,7 @@ static void zram_slot_unlock(struct zram
+ {
+ bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags);
+ }
++#endif
+
+ static inline bool init_done(struct zram *zram)
+ {
+@@ -1245,6 +1281,7 @@ static bool zram_meta_alloc(struct zram
+
+ if (!huge_class_size)
+ huge_class_size = zs_huge_class_size(zram->mem_pool);
++ zram_meta_init_table_locks(zram, num_pages);
+ return true;
+ }
+
+--- a/drivers/block/zram/zram_drv.h
++++ b/drivers/block/zram/zram_drv.h
+@@ -69,6 +69,9 @@ struct zram_table_entry {
+ unsigned long element;
+ };
+ unsigned long flags;
++#ifdef CONFIG_PREEMPT_RT
++ spinlock_t lock;
++#endif
+ #ifdef CONFIG_ZRAM_MEMORY_TRACKING
+ ktime_t ac_time;
+ #endif
diff --git a/debian/patches/bugfix/all/cpupower-fix-checks-for-cpu-existence.patch b/debian/patches/bugfix/all/cpupower-fix-checks-for-cpu-existence.patch
new file mode 100644
index 0000000000..d8352b8610
--- /dev/null
+++ b/debian/patches/bugfix/all/cpupower-fix-checks-for-cpu-existence.patch
@@ -0,0 +1,49 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 03 Nov 2016 15:25:26 -0600
+Subject: cpupower: Fix checks for CPU existence
+Forwarded: https://lore.kernel.org/all/20170418023118.GD4152@decadent.org.uk/
+
+Calls to cpufreq_cpu_exists(cpu) were converted to
+cpupower_is_cpu_online(cpu) when libcpupower was introduced and the
+former function was deleted. However, cpupower_is_cpu_online() does
+not distinguish physically absent and offline CPUs, and does not set
+errno.
+
+cpufreq-set has already been fixed (commit c25badc9ceb6).
+
+In cpufreq-bench, which prints an error message for offline CPUs,
+properly distinguish and report the zero and negative cases.
+
+Fixes: ac5a181d065d ("cpupower: Add cpuidle parts into library")
+Fixes: 53d1cd6b125f ("cpupowerutils: bench - Fix cpu online check")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+[carnil: Update/Refresh patch for 4.14.17: The issue with the
+incorrect check has been fixed with upstream commit 53d1cd6b125f.
+Keep in the patch the distinction and report for the zero and
+negative cases.]
+---
+--- a/tools/power/cpupower/bench/system.c
++++ b/tools/power/cpupower/bench/system.c
+@@ -58,12 +58,19 @@ long long int get_time()
+
+ int set_cpufreq_governor(char *governor, unsigned int cpu)
+ {
++ int rc;
+
+ dprintf("set %s as cpufreq governor\n", governor);
+
+- if (cpupower_is_cpu_online(cpu) != 1) {
+- perror("cpufreq_cpu_exists");
+- fprintf(stderr, "error: cpu %u does not exist\n", cpu);
++ rc = cpupower_is_cpu_online(cpu);
++ if (rc != 1) {
++ if (rc < 0)
++ fprintf(stderr, "cpupower_is_cpu_online: %s\n",
++ strerror(-rc));
++ else
++ fprintf(stderr,
++ "error: cpu %u is offline or does not exist\n",
++ cpu);
+ return -1;
+ }
+
diff --git a/debian/patches/bugfix/all/disable-some-marvell-phys.patch b/debian/patches/bugfix/all/disable-some-marvell-phys.patch
new file mode 100644
index 0000000000..472e54ce5b
--- /dev/null
+++ b/debian/patches/bugfix/all/disable-some-marvell-phys.patch
@@ -0,0 +1,91 @@
+From: Ian Campbell <ijc@hellion.org.uk>
+Subject: phy/marvell: disable 4-port phys
+Date: Wed, 20 Nov 2013 08:30:14 +0000
+Bug-Debian: https://bugs.debian.org/723177
+Forwarded: https://lore.kernel.org/netdev/1386932764.20787.85.camel@dagon.hellion.org.uk/
+
+The Marvell PHY was originally disabled because it can cause networking
+failures on some systems. According to Lennert Buytenhek this is because some
+of the variants added did not share the same register layout. Since the known
+cases are all 4-ports disable those variants (indicated by a 4 in the
+penultimate position of the model name) until they can be audited for
+correctness.
+
+[bwh: Also #if-out the init functions for these PHYs to avoid
+ compiler warnings]
+
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -1320,6 +1320,7 @@ static int m88e1118_config_init(struct phy_device *phydev)
+ return genphy_soft_reset(phydev);
+ }
+
++#if 0
+ static int m88e1149_config_init(struct phy_device *phydev)
+ {
+ int err;
+@@ -1345,7 +1346,9 @@ static int m88e1149_config_init(struct phy_device *phydev)
+
+ return genphy_soft_reset(phydev);
+ }
++#endif
+
++#if 0
+ static int m88e1145_config_init_rgmii(struct phy_device *phydev)
+ {
+ int err;
+@@ -1423,6 +1426,7 @@ static int m88e1145_config_init(struct phy_device *phydev)
+
+ return 0;
+ }
++#endif
+
+ static int m88e1540_get_fld(struct phy_device *phydev, u8 *msecs)
+ {
+@@ -3414,6 +3418,7 @@ static struct phy_driver marvell_drivers[] = {
+ .led_hw_control_set = m88e1318_led_hw_control_set,
+ .led_hw_control_get = m88e1318_led_hw_control_get,
+ },
++#if 0
+ {
+ .phy_id = MARVELL_PHY_ID_88E1145,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+@@ -3434,6 +3439,8 @@ static struct phy_driver marvell_drivers[] = {
+ .get_tunable = m88e1111_get_tunable,
+ .set_tunable = m88e1111_set_tunable,
+ },
++#endif
++#if 0
+ {
+ .phy_id = MARVELL_PHY_ID_88E1149R,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+@@ -3452,6 +3459,8 @@ static struct phy_driver marvell_drivers[] = {
+ .get_strings = marvell_get_strings,
+ .get_stats = marvell_get_stats,
+ },
++#endif
++#if 0
+ {
+ .phy_id = MARVELL_PHY_ID_88E1240,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+@@ -3472,6 +3481,7 @@ static struct phy_driver marvell_drivers[] = {
+ .get_tunable = m88e1011_get_tunable,
+ .set_tunable = m88e1011_set_tunable,
+ },
++#endif
+ {
+ .phy_id = MARVELL_PHY_ID_88E1116R,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+@@ -3744,9 +4074,9 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = {
+ { MARVELL_PHY_ID_88E1111_FINISAR, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK },
+- { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK },
+- { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK },
+- { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK },
++/* { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK }, */
++/* { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK }, */
++/* { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK }, */
+ { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK },
+ { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
diff --git a/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch b/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch
new file mode 100644
index 0000000000..e6eec33dd7
--- /dev/null
+++ b/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch
@@ -0,0 +1,2396 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: firmware: Remove redundant log messages from drivers
+Date: Sun, 09 Dec 2012 16:40:31 +0000
+Forwarded: no
+
+Now that firmware_class logs every success and failure consistently,
+many other log messages can be removed from drivers.
+
+This will probably need to be split up into multiple patches prior to
+upstream submission.
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -912,10 +912,8 @@ static enum ucode_state request_microcod
+ if (c->x86 >= 0x15)
+ snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
+
+- if (request_firmware_direct(&fw, (const char *)fw_name, device)) {
+- pr_debug("failed to load file %s\n", fw_name);
++ if (request_firmware_direct(&fw, (const char *)fw_name, device))
+ goto out;
+- }
+
+ ret = UCODE_ERROR;
+ if (!verify_container(fw->data, fw->size, false))
+--- a/drivers/atm/fore200e.c
++++ b/drivers/atm/fore200e.c
+@@ -2398,10 +2398,9 @@ static int fore200e_load_and_start_fw(st
+ int err;
+
+ sprintf(buf, "%s%s", fore200e->bus->proc_name, FW_EXT);
+- if ((err = request_firmware(&firmware, buf, fore200e->dev)) < 0) {
+- printk(FORE200E "problem loading firmware image %s\n", fore200e->bus->model_name);
++ err = request_firmware(&firmware, buf, fore200e->dev);
++ if (err)
+ return err;
+- }
+
+ fw_data = (const __le32 *)firmware->data;
+ fw_size = firmware->size / sizeof(u32);
+--- a/drivers/bluetooth/ath3k.c
++++ b/drivers/bluetooth/ath3k.c
+@@ -381,10 +381,8 @@ static int ath3k_load_patch(struct usb_d
+ le32_to_cpu(fw_version.rom_version));
+
+ ret = request_firmware(&firmware, filename, &udev->dev);
+- if (ret < 0) {
+- BT_ERR("Patch file not found %s", filename);
++ if (ret)
+ return ret;
+- }
+
+ pt_rom_version = get_unaligned_le32(firmware->data +
+ firmware->size - 8);
+@@ -444,10 +442,8 @@ static int ath3k_load_syscfg(struct usb_
+ le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
+
+ ret = request_firmware(&firmware, filename, &udev->dev);
+- if (ret < 0) {
+- BT_ERR("Configuration file not found %s", filename);
++ if (ret)
+ return ret;
+- }
+
+ ret = ath3k_load_fwfile(udev, firmware);
+ release_firmware(firmware);
+--- a/drivers/bluetooth/bcm203x.c
++++ b/drivers/bluetooth/bcm203x.c
+@@ -173,7 +173,6 @@ static int bcm203x_probe(struct usb_inte
+ return -ENOMEM;
+
+ if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
+- BT_ERR("Mini driver request failed");
+ usb_free_urb(data->urb);
+ return -EIO;
+ }
+@@ -198,7 +197,6 @@ static int bcm203x_probe(struct usb_inte
+ release_firmware(firmware);
+
+ if (request_firmware(&firmware, "BCM2033-FW.bin", &udev->dev) < 0) {
+- BT_ERR("Firmware request failed");
+ usb_free_urb(data->urb);
+ kfree(data->buffer);
+ return -EIO;
+--- a/drivers/bluetooth/bfusb.c
++++ b/drivers/bluetooth/bfusb.c
+@@ -639,10 +639,8 @@ static int bfusb_probe(struct usb_interf
+ skb_queue_head_init(&data->pending_q);
+ skb_queue_head_init(&data->completed_q);
+
+- if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
+- BT_ERR("Firmware request failed");
++ if (request_firmware(&firmware, "bfubase.frm", &udev->dev))
+ goto done;
+- }
+
+ BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
+
+--- a/drivers/bluetooth/bt3c_cs.c
++++ b/drivers/bluetooth/bt3c_cs.c
+@@ -569,10 +569,8 @@ static int bt3c_open(struct bt3c_info *i
+
+ /* Load firmware */
+ err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
+- if (err < 0) {
+- BT_ERR("Firmware request failed");
++ if (err)
+ goto error;
+- }
+
+ err = bt3c_load_firmware(info, firmware->data, firmware->size);
+
+--- a/drivers/bluetooth/btmrvl_sdio.c
++++ b/drivers/bluetooth/btmrvl_sdio.c
+@@ -470,8 +470,6 @@ static int btmrvl_sdio_download_helper(s
+ ret = request_firmware(&fw_helper, card->helper,
+ &card->func->dev);
+ if ((ret < 0) || !fw_helper) {
+- BT_ERR("request_firmware(helper) failed, error code = %d",
+- ret);
+ ret = -ENOENT;
+ goto done;
+ }
+@@ -570,8 +568,6 @@ static int btmrvl_sdio_download_fw_w_hel
+ ret = request_firmware(&fw_firmware, card->firmware,
+ &card->func->dev);
+ if ((ret < 0) || !fw_firmware) {
+- BT_ERR("request_firmware(firmware) failed, error code = %d",
+- ret);
+ ret = -ENOENT;
+ goto done;
+ }
+--- a/drivers/char/dsp56k.c
++++ b/drivers/char/dsp56k.c
+@@ -142,11 +142,8 @@ static int dsp56k_upload(u_char __user *
+ }
+ err = request_firmware(&fw, fw_name, &pdev->dev);
+ platform_device_unregister(pdev);
+- if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fw_name, err);
++ if (err)
+ return err;
+- }
+ if (fw->size % 3) {
+ printk(KERN_ERR "Bogus length %d in image \"%s\"\n",
+ fw->size, fw_name);
+--- a/drivers/dma/imx-sdma.c
++++ b/drivers/dma/imx-sdma.c
+@@ -1933,11 +1933,8 @@ static void sdma_load_firmware(const str
+ const struct sdma_script_start_addrs *addr;
+ unsigned short *ram_code;
+
+- if (!fw) {
+- dev_info(sdma->dev, "external firmware not found, using ROM firmware\n");
+- /* In this case we just use the ROM firmware. */
++ if (!fw)
+ return;
+- }
+
+ if (fw->size < sizeof(*header))
+ goto err_firmware;
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+@@ -2579,10 +2579,8 @@ gf100_gr_load_fw(struct gf100_gr *gr, co
+ if (ret) {
+ snprintf(f, sizeof(f), "nouveau/%s", name);
+ ret = request_firmware(&fw, f, device->dev);
+- if (ret) {
+- nvkm_error(subdev, "failed to load %s\n", name);
++ if (ret)
+ return ret;
+- }
+ }
+
+ blob->size = fw->size;
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -820,9 +820,6 @@ int ni_init_microcode(struct radeon_devi
+
+ out:
+ if (err) {
+- if (err != -EINVAL)
+- pr_err("ni_cp: Failed to load firmware \"%s\"\n",
+- fw_name);
+ release_firmware(rdev->pfp_fw);
+ rdev->pfp_fw = NULL;
+ release_firmware(rdev->me_fw);
+--- a/drivers/gpu/drm/radeon/r100.c
++++ b/drivers/gpu/drm/radeon/r100.c
+@@ -1057,9 +1057,7 @@ static int r100_cp_init_microcode(struct
+ }
+
+ err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
+- if (err) {
+- pr_err("radeon_cp: Failed to load firmware \"%s\"\n", fw_name);
+- } else if (rdev->me_fw->size % 8) {
++ if (err == 0 && rdev->me_fw->size % 8) {
+ pr_err("radeon_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->me_fw->size, fw_name);
+ err = -EINVAL;
+--- a/drivers/gpu/drm/radeon/r600.c
++++ b/drivers/gpu/drm/radeon/r600.c
+@@ -2600,9 +2600,6 @@ int r600_init_microcode(struct radeon_de
+
+ out:
+ if (err) {
+- if (err != -EINVAL)
+- pr_err("r600_cp: Failed to load firmware \"%s\"\n",
+- fw_name);
+ release_firmware(rdev->pfp_fw);
+ rdev->pfp_fw = NULL;
+ release_firmware(rdev->me_fw);
+--- a/drivers/infiniband/hw/qib/qib_sd7220.c
++++ b/drivers/infiniband/hw/qib/qib_sd7220.c
+@@ -406,10 +406,8 @@ int qib_sd7220_init(struct qib_devdata *
+ }
+
+ ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev);
+- if (ret) {
+- qib_dev_err(dd, "Failed to load IB SERDES image\n");
++ if (ret)
+ goto done;
+- }
+
+ /* Substitute our deduced value for was_reset */
+ ret = qib_ibsd_ucode_loaded(dd->pport, fw);
+--- a/drivers/input/touchscreen/atmel_mxt_ts.c
++++ b/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2927,10 +2927,8 @@ static int mxt_load_fw(struct device *de
+ int ret;
+
+ ret = request_firmware(&fw, fn, dev);
+- if (ret) {
+- dev_err(dev, "Unable to open firmware %s\n", fn);
++ if (ret)
+ return ret;
+- }
+
+ /* Check for incorrect enc file */
+ ret = mxt_check_firmware_format(dev, fw);
+--- a/drivers/isdn/hardware/mISDN/speedfax.c
++++ b/drivers/isdn/hardware/mISDN/speedfax.c
+@@ -379,11 +379,8 @@ setup_instance(struct sfax_hw *card)
+ card->isar.owner = THIS_MODULE;
+
+ err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev);
+- if (err < 0) {
+- pr_info("%s: firmware request failed %d\n",
+- card->name, err);
++ if (err)
+ goto error_fw;
+- }
+ if (debug & DEBUG_HW)
+ pr_notice("%s: got firmware %zu bytes\n",
+ card->name, firmware->size);
+--- a/drivers/media/common/siano/smscoreapi.c
++++ b/drivers/media/common/siano/smscoreapi.c
+@@ -1152,10 +1152,8 @@ static int smscore_load_firmware_from_fi
+ return -EINVAL;
+
+ rc = request_firmware(&fw, fw_filename, coredev->device);
+- if (rc < 0) {
+- pr_err("failed to open firmware file '%s'\n", fw_filename);
++ if (rc < 0)
+ return rc;
+- }
+ pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size);
+ fw_buf = kmalloc(ALIGN(fw->size + sizeof(struct sms_firmware),
+ SMS_ALLOC_ALIGNMENT), GFP_KERNEL | coredev->gfp_buf_flags);
+--- a/drivers/media/dvb-frontends/af9013.c
++++ b/drivers/media/dvb-frontends/af9013.c
+@@ -1049,14 +1049,8 @@ static int af9013_download_firmware(stru
+
+ /* Request the firmware, will block and timeout */
+ ret = request_firmware(&firmware, name, &client->dev);
+- if (ret) {
+- dev_info(&client->dev, "firmware file '%s' not found %d\n",
+- name, ret);
++ if (ret)
+ goto err;
+- }
+-
+- dev_info(&client->dev, "downloading firmware from file '%s'\n",
+- name);
+
+ /* Write firmware checksum & size */
+ for (i = 0; i < firmware->size; i++)
+--- a/drivers/media/dvb-frontends/bcm3510.c
++++ b/drivers/media/dvb-frontends/bcm3510.c
+@@ -636,10 +636,9 @@ static int bcm3510_download_firmware(str
+ int ret,i;
+
+ deb_info("requesting firmware\n");
+- if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
+- err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
++ ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE);
++ if (ret)
+ return ret;
+- }
+ deb_info("got firmware: %zu\n", fw->size);
+
+ b = fw->data;
+--- a/drivers/media/dvb-frontends/cx24116.c
++++ b/drivers/media/dvb-frontends/cx24116.c
+@@ -479,13 +479,8 @@ static int cx24116_firmware_ondemand(str
+ __func__, CX24116_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
+ state->i2c->dev.parent);
+- printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
+- __func__);
+- if (ret) {
+- printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
+- __func__);
++ if (ret)
+ return ret;
+- }
+
+ /* Make sure we don't recurse back through here
+ * during loading */
+--- a/drivers/media/dvb-frontends/drxd_hard.c
++++ b/drivers/media/dvb-frontends/drxd_hard.c
+@@ -891,10 +891,8 @@ static int load_firmware(struct drxd_sta
+ {
+ const struct firmware *fw;
+
+- if (request_firmware(&fw, fw_name, state->dev) < 0) {
+- printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name);
++ if (request_firmware(&fw, fw_name, state->dev))
+ return -EIO;
+- }
+
+ state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
+ if (!state->microcode) {
+--- a/drivers/media/dvb-frontends/drxk_hard.c
++++ b/drivers/media/dvb-frontends/drxk_hard.c
+@@ -6228,10 +6228,6 @@ static void load_firmware_cb(const struc
+
+ dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
+ if (!fw) {
+- pr_err("Could not load firmware file %s.\n",
+- state->microcode_name);
+- pr_info("Copy %s to your hotplug directory!\n",
+- state->microcode_name);
+ state->microcode_name = NULL;
+
+ /*
+--- a/drivers/media/dvb-frontends/ds3000.c
++++ b/drivers/media/dvb-frontends/ds3000.c
+@@ -348,12 +348,8 @@ static int ds3000_firmware_ondemand(stru
+ DS3000_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE,
+ state->i2c->dev.parent);
+- printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__);
+- if (ret) {
+- printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
+- __func__);
++ if (ret)
+ return ret;
+- }
+
+ ret = ds3000_load_firmware(fe, fw);
+ if (ret)
+--- a/drivers/media/dvb-frontends/nxt200x.c
++++ b/drivers/media/dvb-frontends/nxt200x.c
+@@ -861,12 +861,8 @@ static int nxt2002_init(struct dvb_front
+ __func__, NXT2002_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,
+ state->i2c->dev.parent);
+- pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
+- if (ret) {
+- pr_err("%s: No firmware uploaded (timeout or file not found?)\n",
+- __func__);
++ if (ret)
+ return ret;
+- }
+
+ ret = nxt2002_load_firmware(fe, fw);
+ release_firmware(fw);
+@@ -928,12 +924,8 @@ static int nxt2004_init(struct dvb_front
+ __func__, NXT2004_DEFAULT_FIRMWARE);
+ ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,
+ state->i2c->dev.parent);
+- pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
+- if (ret) {
+- pr_err("%s: No firmware uploaded (timeout or file not found?)\n",
+- __func__);
++ if (ret)
+ return ret;
+- }
+
+ ret = nxt2004_load_firmware(fe, fw);
+ release_firmware(fw);
+--- a/drivers/media/dvb-frontends/or51132.c
++++ b/drivers/media/dvb-frontends/or51132.c
+@@ -326,10 +326,8 @@ static int or51132_set_parameters(struct
+ printk("or51132: Waiting for firmware upload(%s)...\n",
+ fwname);
+ ret = request_firmware(&fw, fwname, state->i2c->dev.parent);
+- if (ret) {
+- printk(KERN_WARNING "or51132: No firmware uploaded(timeout or file not found?)\n");
++ if (ret)
+ return ret;
+- }
+ ret = or51132_load_firmware(fe, fw);
+ release_firmware(fw);
+ if (ret) {
+--- a/drivers/media/dvb-frontends/or51211.c
++++ b/drivers/media/dvb-frontends/or51211.c
+@@ -361,11 +361,8 @@ static int or51211_init(struct dvb_front
+ OR51211_DEFAULT_FIRMWARE);
+ ret = config->request_firmware(fe, &fw,
+ OR51211_DEFAULT_FIRMWARE);
+- pr_info("Got Hotplug firmware\n");
+- if (ret) {
+- pr_warn("No firmware uploaded (timeout or file not found?)\n");
++ if (ret)
+ return ret;
+- }
+
+ ret = or51211_load_firmware(fe, fw);
+ release_firmware(fw);
+--- a/drivers/media/dvb-frontends/sp887x.c
++++ b/drivers/media/dvb-frontends/sp887x.c
+@@ -525,10 +525,8 @@ static int sp887x_init(struct dvb_fronte
+ /* request the firmware, this will block until someone uploads it */
+ printk("sp887x: waiting for firmware upload (%s)...\n", SP887X_DEFAULT_FIRMWARE);
+ ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE);
+- if (ret) {
+- printk("sp887x: no firmware upload (timeout or file not found?)\n");
++ if (ret)
+ return ret;
+- }
+
+ ret = sp887x_initial_setup(fe, fw);
+ release_firmware(fw);
+--- a/drivers/media/dvb-frontends/tda10048.c
++++ b/drivers/media/dvb-frontends/tda10048.c
+@@ -483,8 +483,6 @@ static int tda10048_firmware_upload(stru
+ ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
+ state->i2c->dev.parent);
+ if (ret) {
+- printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
+- __func__);
+ return -EIO;
+ } else {
+ printk(KERN_INFO "%s: firmware read %zu bytes.\n",
+--- a/drivers/media/dvb-frontends/tda1004x.c
++++ b/drivers/media/dvb-frontends/tda1004x.c
+@@ -388,10 +388,8 @@ static int tda10045_fwupload(struct dvb_
+ /* request the firmware, this will block until someone uploads it */
+ printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
+ ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
+- if (ret) {
+- printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
++ if (ret)
+ return ret;
+- }
+
+ /* reset chip */
+ tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0);
+@@ -532,7 +530,6 @@ static int tda10046_fwupload(struct dvb_
+ /* remain compatible to old bug: try to load with tda10045 image name */
+ ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
+ if (ret) {
+- printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
+ return ret;
+ } else {
+ printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n",
+--- a/drivers/media/dvb-frontends/tda10071.c
++++ b/drivers/media/dvb-frontends/tda10071.c
+@@ -838,12 +838,8 @@ static int tda10071_init(struct dvb_fron
+
+ /* request the firmware, this will block and timeout */
+ ret = request_firmware(&fw, fw_file, &client->dev);
+- if (ret) {
+- dev_err(&client->dev,
+- "did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware\n",
+- fw_file, ret);
++ if (ret)
+ goto error;
+- }
+
+ /* init */
+ for (i = 0; i < ARRAY_SIZE(tab2); i++) {
+--- a/drivers/media/i2c/cx25840/cx25840-firmware.c
++++ b/drivers/media/i2c/cx25840/cx25840-firmware.c
+@@ -113,10 +113,8 @@ int cx25840_loadfw(struct i2c_client *cl
+ if (is_cx231xx(state) && max_buf_size > 16)
+ max_buf_size = 16;
+
+- if (request_firmware(&fw, fwname, FWDEV(client)) != 0) {
+- v4l_err(client, "unable to open firmware %s\n", fwname);
++ if (request_firmware(&fw, fwname, FWDEV(client)) != 0)
+ return -EINVAL;
+- }
+
+ start_fw_load(client);
+
+--- a/drivers/media/pci/bt8xx/bttv-cards.c
++++ b/drivers/media/pci/bt8xx/bttv-cards.c
+@@ -3901,10 +3901,8 @@ static int pvr_boot(struct bttv *btv)
+ int rc;
+
+ rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
+- if (rc != 0) {
+- pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
++ if (rc != 0)
+ return rc;
+- }
+ rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
+ pr_info("%d: altera firmware upload %s\n",
+ btv->c.nr, (rc < 0) ? "failed" : "ok");
+--- a/drivers/media/pci/cx18/cx18-av-firmware.c
++++ b/drivers/media/pci/cx18/cx18-av-firmware.c
+@@ -70,10 +70,8 @@ int cx18_av_loadfw(struct cx18 *cx)
+ int i;
+ int retries1 = 0;
+
+- if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) {
+- CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE);
++ if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0)
+ return -EINVAL;
+- }
+
+ /* The firmware load often has byte errors, so allow for several
+ retries, both at byte level and at the firmware load level. */
+--- a/drivers/media/pci/cx18/cx18-dvb.c
++++ b/drivers/media/pci/cx18/cx18-dvb.c
+@@ -127,9 +127,7 @@ static int yuan_mpc718_mt352_reqfw(struc
+ int ret;
+
+ ret = request_firmware(fw, fn, &cx->pci_dev->dev);
+- if (ret)
+- CX18_ERR("Unable to open firmware file %s\n", fn);
+- else {
++ if (!ret) {
+ size_t sz = (*fw)->size;
+ if (sz < 2 || sz > 64 || (sz % 2) != 0) {
+ CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
+--- a/drivers/media/pci/cx18/cx18-firmware.c
++++ b/drivers/media/pci/cx18/cx18-firmware.c
+@@ -92,11 +92,8 @@ static int load_cpu_fw_direct(const char
+ u32 __iomem *dst = (u32 __iomem *)mem;
+ const u32 *src;
+
+- if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
+- CX18_ERR("Unable to open firmware %s\n", fn);
+- CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
++ if (request_firmware(&fw, fn, &cx->pci_dev->dev))
+ return -ENOMEM;
+- }
+
+ src = (const u32 *)fw->data;
+
+@@ -137,8 +134,6 @@ static int load_apu_fw_direct(const char
+ int sz;
+
+ if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
+- CX18_ERR("unable to open firmware %s\n", fn);
+- CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
+ cx18_setup_page(cx, 0);
+ return -ENOMEM;
+ }
+--- a/drivers/media/pci/cx23885/cx23885-417.c
++++ b/drivers/media/pci/cx23885/cx23885-417.c
+@@ -920,12 +920,8 @@ static int cx23885_load_firmware(struct
+ retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
+ &dev->pci->dev);
+
+- if (retval != 0) {
+- pr_err("ERROR: Hotplug firmware request failed (%s).\n",
+- CX23885_FIRM_IMAGE_NAME);
+- pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
++ if (retval != 0)
+ return -1;
+- }
+
+ if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
+ pr_err("ERROR: Firmware size mismatch (have %zu, expected %d)\n",
+--- a/drivers/media/pci/cx23885/cx23885-cards.c
++++ b/drivers/media/pci/cx23885/cx23885-cards.c
+@@ -2480,10 +2480,7 @@ void cx23885_card_setup(struct cx23885_d
+ cinfo.rev, filename);
+
+ ret = request_firmware(&fw, filename, &dev->pci->dev);
+- if (ret != 0)
+- pr_err("did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware.",
+- filename);
+- else
++ if (ret == 0)
+ altera_init(&netup_config, fw);
+
+ release_firmware(fw);
+--- a/drivers/media/pci/cx88/cx88-blackbird.c
++++ b/drivers/media/pci/cx88/cx88-blackbird.c
+@@ -462,12 +462,8 @@ static int blackbird_load_firmware(struc
+ retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
+ &dev->pci->dev);
+
+- if (retval != 0) {
+- pr_err("Hotplug firmware request failed (%s).\n",
+- CX2341X_FIRM_ENC_FILENAME);
+- pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
++ if (retval != 0)
+ return -EIO;
+- }
+
+ if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
+ pr_err("Firmware size mismatch (have %zd, expected %d)\n",
+--- a/drivers/media/pci/ivtv/ivtv-firmware.c
++++ b/drivers/media/pci/ivtv/ivtv-firmware.c
+@@ -68,8 +68,6 @@ retry:
+ release_firmware(fw);
+ return size;
+ }
+- IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size);
+- IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n");
+ return -ENOMEM;
+ }
+
+--- a/drivers/media/pci/ngene/ngene-core.c
++++ b/drivers/media/pci/ngene/ngene-core.c
+@@ -1236,19 +1236,14 @@ static int ngene_load_firm(struct ngene
+ break;
+ }
+
+- if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) {
+- dev_err(pdev, "Could not load firmware file %s.\n", fw_name);
+- dev_info(pdev, "Copy %s to your hotplug directory!\n",
+- fw_name);
++ if (request_firmware(&fw, fw_name, &dev->pci_dev->dev))
+ return -1;
+- }
+ if (size == 0)
+ size = fw->size;
+ if (size != fw->size) {
+ dev_err(pdev, "Firmware %s has invalid size!", fw_name);
+ err = -1;
+ } else {
+- dev_info(pdev, "Loading firmware file %s.\n", fw_name);
+ ngene_fw = (u8 *) fw->data;
+ err = ngene_command_load_firmware(dev, ngene_fw, size);
+ }
+--- a/drivers/media/pci/saa7164/saa7164-fw.c
++++ b/drivers/media/pci/saa7164/saa7164-fw.c
+@@ -405,11 +405,8 @@ int saa7164_downloadfirmware(struct saa7
+ __func__, fwname);
+
+ ret = request_firmware(&fw, fwname, &dev->pci->dev);
+- if (ret) {
+- printk(KERN_ERR "%s() Upload failed. (file not found?)\n",
+- __func__);
++ if (ret)
+ return -ENOMEM;
+- }
+
+ printk(KERN_INFO "%s() firmware read %zu bytes.\n",
+ __func__, fw->size);
+--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
++++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
+@@ -65,10 +65,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc
+ }
+ }
+
+- if (err != 0) {
+- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
++ if (err != 0)
+ return -EINVAL;
+- }
+ if (fw_blob->size > dev->fw_buf.size) {
+ mfc_err("MFC firmware is too big to be loaded\n");
+ release_firmware(fw_blob);
+--- a/drivers/media/radio/radio-wl1273.c
++++ b/drivers/media/radio/radio-wl1273.c
+@@ -502,11 +502,8 @@ static int wl1273_fm_upload_firmware_pat
+ * Uploading the firmware patch is not always necessary,
+ * so we only print an info message.
+ */
+- if (request_firmware(&fw_p, fw_name, dev)) {
+- dev_info(dev, "%s - %s not found\n", __func__, fw_name);
+-
++ if (request_firmware(&fw_p, fw_name, dev))
+ return 0;
+- }
+
+ ptr = (__u8 *) fw_p->data;
+ packet_num = ptr[0];
+--- a/drivers/media/radio/wl128x/fmdrv_common.c
++++ b/drivers/media/radio/wl128x/fmdrv_common.c
+@@ -1240,10 +1240,8 @@ static int fm_download_firmware(struct f
+
+ ret = request_firmware(&fw_entry, fw_name,
+ &fmdev->radio_dev->dev);
+- if (ret < 0) {
+- fmerr("Unable to read firmware(%s) content\n", fw_name);
++ if (ret)
+ return ret;
+- }
+ fmdbg("Firmware(%s) length : %zu bytes\n", fw_name, fw_entry->size);
+
+ fw_data = (void *)fw_entry->data;
+--- a/drivers/media/tuners/xc2028.c
++++ b/drivers/media/tuners/xc2028.c
+@@ -1366,7 +1366,6 @@ static void load_firmware_cb(const struc
+
+ tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
+ if (!fw) {
+- tuner_err("Could not load firmware %s.\n", priv->fname);
+ priv->state = XC2028_NODEV;
+ return;
+ }
+--- a/drivers/media/usb/cx231xx/cx231xx-417.c
++++ b/drivers/media/usb/cx231xx/cx231xx-417.c
+@@ -983,11 +983,6 @@ static int cx231xx_load_firmware(struct
+ dev->dev);
+
+ if (retval != 0) {
+- dev_err(dev->dev,
+- "ERROR: Hotplug firmware request failed (%s).\n",
+- CX231xx_FIRM_IMAGE_NAME);
+- dev_err(dev->dev,
+- "Please fix your hotplug setup, the board will not work without firmware loaded!\n");
+ vfree(p_current_fw);
+ vfree(p_buffer);
+ return retval;
+--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
++++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
+@@ -2401,12 +2401,9 @@ static int stk9090m_frontend_attach(stru
+
+ dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80);
+
+- if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) {
+- deb_info("%s: Upload failed. (file not found?)\n", __func__);
++ if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev))
+ return -ENODEV;
+- } else {
+- deb_info("%s: firmware read %zu bytes.\n", __func__, state->frontend_firmware->size);
+- }
++ deb_info("%s: firmware read %zu bytes.\n", __func__, state->frontend_firmware->size);
+ stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
+ stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
+
+@@ -2471,12 +2468,9 @@ static int nim9090md_frontend_attach(str
+ msleep(20);
+ dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+- if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) {
+- deb_info("%s: Upload failed. (file not found?)\n", __func__);
++ if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev))
+ return -EIO;
+- } else {
+- deb_info("%s: firmware read %zu bytes.\n", __func__, state->frontend_firmware->size);
+- }
++ deb_info("%s: firmware read %zu bytes.\n", __func__, state->frontend_firmware->size);
+ nim9090md_config[0].microcode_B_fe_size = state->frontend_firmware->size;
+ nim9090md_config[0].microcode_B_fe_buffer = state->frontend_firmware->data;
+ nim9090md_config[1].microcode_B_fe_size = state->frontend_firmware->size;
+--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
+@@ -90,13 +90,9 @@ int dvb_usb_download_firmware(struct usb
+ int ret;
+ const struct firmware *fw = NULL;
+
+- if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
+- err("did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",
+- props->firmware,ret);
++ ret = request_firmware(&fw, props->firmware, &udev->dev);
++ if (ret)
+ return ret;
+- }
+-
+- info("downloading firmware from file '%s'",props->firmware);
+
+ switch (props->usb_ctrl) {
+ case CYPRESS_AN2135:
+--- a/drivers/media/usb/dvb-usb/gp8psk.c
++++ b/drivers/media/usb/dvb-usb/gp8psk.c
+@@ -131,19 +131,14 @@ static int gp8psk_load_bcm4500fw(struct
+ const u8 *ptr;
+ u8 *buf;
+ if ((ret = request_firmware(&fw, bcm4500_firmware,
+- &d->udev->dev)) != 0) {
+- err("did not find the bcm4500 firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",
+- bcm4500_firmware,ret);
++ &d->udev->dev)) != 0)
+ return ret;
+- }
+
+ ret = -EINVAL;
+
+ if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
+ goto out_rel_fw;
+
+- info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
+-
+ ptr = fw->data;
+ buf = kmalloc(64, GFP_KERNEL);
+ if (!buf) {
+--- a/drivers/media/usb/dvb-usb/opera1.c
++++ b/drivers/media/usb/dvb-usb/opera1.c
+@@ -459,8 +459,6 @@ static int opera1_xilinx_load_firmware(s
+ info("start downloading fpga firmware %s",filename);
+
+ if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
+- err("did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",
+- filename);
+ return ret;
+ } else {
+ p = kmalloc(fw->size, GFP_KERNEL);
+--- a/drivers/media/usb/go7007/go7007-driver.c
++++ b/drivers/media/usb/go7007/go7007-driver.c
+@@ -84,10 +84,8 @@ static int go7007_load_encoder(struct go
+ u16 intr_val, intr_data;
+
+ if (go->boot_fw == NULL) {
+- if (request_firmware(&fw_entry, fw_name, go->dev)) {
+- v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
++ if (request_firmware(&fw_entry, fw_name, go->dev))
+ return -1;
+- }
+ if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
+ v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
+ release_firmware(fw_entry);
+--- a/drivers/media/usb/go7007/go7007-fw.c
++++ b/drivers/media/usb/go7007/go7007-fw.c
+@@ -1565,12 +1565,8 @@ int go7007_construct_fw_image(struct go7
+ default:
+ return -1;
+ }
+- if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev)) {
+- dev_err(go->dev,
+- "unable to load firmware from file \"%s\"\n",
+- GO7007_FW_NAME);
++ if (request_firmware(&fw_entry, GO7007_FW_NAME, go->dev))
+ return -1;
+- }
+ code = kcalloc(codespace, 2, GFP_KERNEL);
+ if (code == NULL)
+ goto fw_failed;
+--- a/drivers/media/usb/go7007/go7007-loader.c
++++ b/drivers/media/usb/go7007/go7007-loader.c
+@@ -67,11 +67,8 @@ static int go7007_loader_probe(struct us
+
+ dev_info(&interface->dev, "loading firmware %s\n", fw1);
+
+- if (request_firmware(&fw, fw1, &usbdev->dev)) {
+- dev_err(&interface->dev,
+- "unable to load firmware from file \"%s\"\n", fw1);
++ if (request_firmware(&fw, fw1, &usbdev->dev))
+ goto failed2;
+- }
+ ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+ release_firmware(fw);
+ if (0 != ret) {
+@@ -82,11 +79,8 @@ static int go7007_loader_probe(struct us
+ if (fw2 == NULL)
+ return 0;
+
+- if (request_firmware(&fw, fw2, &usbdev->dev)) {
+- dev_err(&interface->dev,
+- "unable to load firmware from file \"%s\"\n", fw2);
++ if (request_firmware(&fw, fw2, &usbdev->dev))
+ goto failed2;
+- }
+ ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2);
+ release_firmware(fw);
+ if (0 != ret) {
+--- a/drivers/media/usb/gspca/vicam.c
++++ b/drivers/media/usb/gspca/vicam.c
+@@ -230,10 +230,8 @@ static int sd_init(struct gspca_dev *gsp
+
+ ret = request_ihex_firmware(&fw, VICAM_FIRMWARE,
+ &gspca_dev->dev->dev);
+- if (ret) {
+- pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
++ if (ret)
+ return ret;
+- }
+
+ firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!firmware_buf) {
+--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
++++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+@@ -1370,25 +1370,6 @@ static int pvr2_locate_firmware(struct p
+ "request_firmware fatal error with code=%d",ret);
+ return ret;
+ }
+- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+- "***WARNING*** Device %s firmware seems to be missing.",
+- fwtypename);
+- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+- "Did you install the pvrusb2 firmware files in their proper location?");
+- if (fwcount == 1) {
+- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+- "request_firmware unable to locate %s file %s",
+- fwtypename,fwnames[0]);
+- } else {
+- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+- "request_firmware unable to locate one of the following %s files:",
+- fwtypename);
+- for (idx = 0; idx < fwcount; idx++) {
+- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+- "request_firmware: Failed to find %s",
+- fwnames[idx]);
+- }
+- }
+ return ret;
+ }
+
+--- a/drivers/media/usb/s2255/s2255drv.c
++++ b/drivers/media/usb/s2255/s2255drv.c
+@@ -2276,10 +2276,8 @@ static int s2255_probe(struct usb_interf
+ }
+ /* load the first chunk */
+ if (request_firmware(&dev->fw_data->fw,
+- FIRMWARE_FILE_NAME, &dev->udev->dev)) {
+- dev_err(&interface->dev, "sensoray 2255 failed to get firmware\n");
++ FIRMWARE_FILE_NAME, &dev->udev->dev))
+ goto errorREQFW;
+- }
+ /* check the firmware is valid */
+ fw_size = dev->fw_data->fw->size;
+ pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8];
+--- a/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
++++ b/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
+@@ -282,10 +282,8 @@ static int ttusb_boot_dsp(struct ttusb *
+
+ err = request_firmware(&fw, "ttusb-budget/dspbootcode.bin",
+ &ttusb->dev->dev);
+- if (err) {
+- pr_err("failed to request firmware\n");
++ if (err)
+ return err;
+- }
+
+ /* BootBlock */
+ b[0] = 0xaa;
+--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c
++++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c
+@@ -1317,11 +1317,8 @@ static int ttusb_dec_boot_dsp(struct ttu
+ dprintk("%s\n", __func__);
+
+ result = request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev);
+- if (result) {
+- printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
+- __func__, dec->firmware_name);
++ if (result)
+ return result;
+- }
+
+ firmware = fw_entry->data;
+ firmware_size = fw_entry->size;
+--- a/drivers/misc/ti-st/st_kim.c
++++ b/drivers/misc/ti-st/st_kim.c
+@@ -288,11 +288,8 @@ static long download_firmware(struct kim
+ request_firmware(&kim_gdata->fw_entry, bts_scr_name,
+ &kim_gdata->kim_pdev->dev);
+ if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) ||
+- (kim_gdata->fw_entry->size == 0))) {
+- pr_err(" request_firmware failed(errno %ld) for %s", err,
+- bts_scr_name);
++ (kim_gdata->fw_entry->size == 0)))
+ return -EINVAL;
+- }
+ ptr = (void *)kim_gdata->fw_entry->data;
+ len = kim_gdata->fw_entry->size;
+ /*
+--- a/drivers/net/can/softing/softing_fw.c
++++ b/drivers/net/can/softing/softing_fw.c
+@@ -226,11 +226,8 @@ int softing_load_app_fw(const char *file
+ int8_t type_end = 0, type_entrypoint = 0;
+
+ ret = request_firmware(&fw, file, &card->pdev->dev);
+- if (ret) {
+- dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n",
+- file, ret);
++ if (ret)
+ return ret;
+- }
+ dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n",
+ file, (unsigned long)fw->size);
+ /* parse the firmware */
+--- a/drivers/net/ethernet/3com/typhoon.c
++++ b/drivers/net/ethernet/3com/typhoon.c
+@@ -1279,11 +1279,8 @@ typhoon_request_firmware(struct typhoon
+ return 0;
+
+ err = request_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev);
+- if (err) {
+- netdev_err(tp->dev, "Failed to load firmware \"%s\"\n",
+- FIRMWARE_NAME);
++ if (err)
+ return err;
+- }
+
+ image_data = typhoon_fw->data;
+ remaining = typhoon_fw->size;
+--- a/drivers/net/ethernet/adaptec/starfire.c
++++ b/drivers/net/ethernet/adaptec/starfire.c
+@@ -1004,11 +1004,8 @@ static int netdev_open(struct net_device
+ #endif /* VLAN_SUPPORT */
+
+ retval = request_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev);
+- if (retval) {
+- printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+- FIRMWARE_RX);
++ if (retval)
+ goto out_init;
+- }
+ if (fw_rx->size % 4) {
+ printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+ fw_rx->size, FIRMWARE_RX);
+@@ -1016,11 +1013,8 @@ static int netdev_open(struct net_device
+ goto out_rx;
+ }
+ retval = request_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev);
+- if (retval) {
+- printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
+- FIRMWARE_TX);
++ if (retval)
+ goto out_rx;
+- }
+ if (fw_tx->size % 4) {
+ printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
+ fw_tx->size, FIRMWARE_TX);
+--- a/drivers/net/ethernet/alacritech/slicoss.c
++++ b/drivers/net/ethernet/alacritech/slicoss.c
+@@ -1051,11 +1051,8 @@ static int slic_load_rcvseq_firmware(str
+ file = (sdev->model == SLIC_MODEL_OASIS) ? SLIC_RCV_FIRMWARE_OASIS :
+ SLIC_RCV_FIRMWARE_MOJAVE;
+ err = request_firmware(&fw, file, &sdev->pdev->dev);
+- if (err) {
+- dev_err(&sdev->pdev->dev,
+- "failed to load receive sequencer firmware %s\n", file);
++ if (err)
+ return err;
+- }
+ /* Do an initial sanity check concerning firmware size now. A further
+ * check follows below.
+ */
+@@ -1126,10 +1123,8 @@ static int slic_load_firmware(struct sli
+ file = (sdev->model == SLIC_MODEL_OASIS) ? SLIC_FIRMWARE_OASIS :
+ SLIC_FIRMWARE_MOJAVE;
+ err = request_firmware(&fw, file, &sdev->pdev->dev);
+- if (err) {
+- dev_err(&sdev->pdev->dev, "failed to load firmware %s\n", file);
++ if (err)
+ return err;
+- }
+ /* Do an initial sanity check concerning firmware size now. A further
+ * check follows below.
+ */
+--- a/drivers/net/ethernet/alteon/acenic.c
++++ b/drivers/net/ethernet/alteon/acenic.c
+@@ -2877,11 +2877,8 @@ static int ace_load_firmware(struct net_
+ fw_name = "acenic/tg1.bin";
+
+ ret = request_firmware(&fw, fw_name, &ap->pdev->dev);
+- if (ret) {
+- printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
+- ap->name, fw_name);
++ if (ret)
+ return ret;
+- }
+
+ fw_data = (void *)fw->data;
+
+--- a/drivers/net/ethernet/broadcom/bnx2.c
++++ b/drivers/net/ethernet/broadcom/bnx2.c
+@@ -3710,16 +3710,13 @@ static int bnx2_request_uncached_firmwar
+ }
+
+ rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev);
+- if (rc) {
+- pr_err("Can't load firmware file \"%s\"\n", mips_fw_file);
++ if (rc)
+ goto out;
+- }
+
+ rc = request_firmware(&bp->rv2p_firmware, rv2p_fw_file, &bp->pdev->dev);
+- if (rc) {
+- pr_err("Can't load firmware file \"%s\"\n", rv2p_fw_file);
++ if (rc)
+ goto err_release_mips_firmware;
+- }
++
+ mips_fw = (const struct bnx2_mips_fw_file *) bp->mips_firmware->data;
+ rv2p_fw = (const struct bnx2_rv2p_fw_file *) bp->rv2p_firmware->data;
+ if (bp->mips_firmware->size < sizeof(*mips_fw) ||
+--- a/drivers/net/ethernet/broadcom/tg3.c
++++ b/drivers/net/ethernet/broadcom/tg3.c
+@@ -11394,11 +11394,8 @@ static int tg3_request_firmware(struct t
+ {
+ const struct tg3_firmware_hdr *fw_hdr;
+
+- if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) {
+- netdev_err(tp->dev, "Failed to load firmware \"%s\"\n",
+- tp->fw_needed);
++ if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev))
+ return -ENOENT;
+- }
+
+ fw_hdr = (struct tg3_firmware_hdr *)tp->fw->data;
+
+--- a/drivers/net/ethernet/brocade/bna/cna_fwimg.c
++++ b/drivers/net/ethernet/brocade/bna/cna_fwimg.c
+@@ -24,10 +24,8 @@ cna_read_firmware(struct pci_dev *pdev,
+ const struct firmware *fw;
+ u32 n;
+
+- if (request_firmware(&fw, fw_name, &pdev->dev)) {
+- dev_alert(&pdev->dev, "can't load firmware %s\n", fw_name);
++ if (request_firmware(&fw, fw_name, &pdev->dev))
+ goto error;
+- }
+
+ *bfi_image = (u32 *)fw->data;
+ *bfi_image_size = fw->size/sizeof(u32);
+--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+@@ -1035,12 +1035,8 @@ int t3_get_edc_fw(struct cphy *phy, int
+ fw_name = get_edc_fw_name(edc_idx);
+ if (fw_name)
+ ret = request_firmware(&fw, fw_name, &adapter->pdev->dev);
+- if (ret < 0) {
+- dev_err(&adapter->pdev->dev,
+- "could not upgrade firmware: unable to load %s\n",
+- fw_name);
++ if (ret)
+ return ret;
+- }
+
+ /* check size, take checksum in account */
+ if (fw->size > size + 4) {
+@@ -1077,11 +1073,8 @@ static int upgrade_fw(struct adapter *ad
+ struct device *dev = &adap->pdev->dev;
+
+ ret = request_firmware(&fw, FW_FNAME, dev);
+- if (ret < 0) {
+- dev_err(dev, "could not upgrade firmware: unable to load %s\n",
+- FW_FNAME);
++ if (ret)
+ return ret;
+- }
+ ret = t3_load_fw(adap, fw->data, fw->size);
+ release_firmware(fw);
+
+@@ -1126,11 +1119,8 @@ static int update_tpsram(struct adapter
+ snprintf(buf, sizeof(buf), TPSRAM_NAME, rev);
+
+ ret = request_firmware(&tpsram, buf, dev);
+- if (ret < 0) {
+- dev_err(dev, "could not load TP SRAM: unable to load %s\n",
+- buf);
++ if (ret)
+ return ret;
+- }
+
+ ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
+ if (ret)
+--- a/drivers/net/ethernet/intel/e100.c
++++ b/drivers/net/ethernet/intel/e100.c
+@@ -1262,9 +1262,6 @@ static const struct firmware *e100_reque
+
+ if (err) {
+ if (required) {
+- netif_err(nic, probe, nic->netdev,
+- "Failed to load firmware \"%s\": %d\n",
+- fw_name, err);
+ return ERR_PTR(err);
+ } else {
+ netif_info(nic, probe, nic->netdev,
+--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+@@ -580,8 +580,6 @@ static int myri10ge_load_hotplug_firmwar
+ unsigned i;
+
+ if (request_firmware(&fw, mgp->fw_name, dev) < 0) {
+- dev_err(dev, "Unable to load %s firmware image via hotplug\n",
+- mgp->fw_name);
+ status = -EINVAL;
+ goto abort_with_nothing;
+ }
+--- a/drivers/net/ethernet/smsc/smc91c92_cs.c
++++ b/drivers/net/ethernet/smsc/smc91c92_cs.c
+@@ -651,10 +651,8 @@ static int osi_load_firmware(struct pcmc
+ int i, err;
+
+ err = request_firmware(&fw, FIRMWARE_NAME, &link->dev);
+- if (err) {
+- pr_err("Failed to load firmware \"%s\"\n", FIRMWARE_NAME);
++ if (err)
+ return err;
+- }
+
+ /* Download the Seven of Diamonds firmware */
+ for (i = 0; i < fw->size; i++) {
+--- a/drivers/net/ethernet/sun/cassini.c
++++ b/drivers/net/ethernet/sun/cassini.c
+@@ -792,11 +792,8 @@ static void cas_saturn_firmware_init(str
+ return;
+
+ err = request_firmware(&fw, fw_name, &cp->pdev->dev);
+- if (err) {
+- pr_err("Failed to load firmware \"%s\"\n",
+- fw_name);
++ if (err)
+ return;
+- }
+ if (fw->size < 2) {
+ pr_err("bogus length %zu in \"%s\"\n",
+ fw->size, fw_name);
+--- a/drivers/net/hamradio/yam.c
++++ b/drivers/net/hamradio/yam.c
+@@ -357,11 +357,8 @@ static unsigned char *add_mcs(unsigned c
+ }
+ err = request_firmware(&fw, fw_name[predef], &pdev->dev);
+ platform_device_unregister(pdev);
+- if (err) {
+- printk(KERN_ERR "Failed to load firmware \"%s\"\n",
+- fw_name[predef]);
++ if (err)
+ return NULL;
+- }
+ if (fw->size != YAM_FPGA_SIZE) {
+ printk(KERN_ERR "Bogus length %zu in firmware \"%s\"\n",
+ fw->size, fw_name[predef]);
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -305,10 +305,8 @@ static int kaweth_download_firmware(stru
+ int ret;
+
+ ret = request_firmware(&fw, fwname, &kaweth->dev->dev);
+- if (ret) {
+- dev_err(&kaweth->intf->dev, "Firmware request failed\n");
++ if (ret)
+ return ret;
+- }
+
+ if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) {
+ dev_err(&kaweth->intf->dev, "Firmware too big: %zu\n",
+--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -1250,9 +1250,6 @@ static void ath9k_hif_usb_firmware_cb(co
+ if (!ret)
+ return;
+
+- dev_err(&hif_dev->udev->dev,
+- "ath9k_htc: Failed to get firmware %s\n",
+- hif_dev->fw_name);
+ goto err_fw;
+ }
+
+--- a/drivers/net/wireless/ath/carl9170/usb.c
++++ b/drivers/net/wireless/ath/carl9170/usb.c
+@@ -1029,7 +1029,6 @@ static void carl9170_usb_firmware_step2(
+ return;
+ }
+
+- dev_err(&ar->udev->dev, "firmware not found.\n");
+ carl9170_usb_firmware_failed(ar);
+ }
+
+--- a/drivers/net/wireless/atmel/at76c50x-usb.c
++++ b/drivers/net/wireless/atmel/at76c50x-usb.c
+@@ -1616,13 +1616,8 @@ static struct fwentry *at76_load_firmwar
+
+ at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname);
+ ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev);
+- if (ret < 0) {
+- dev_err(&udev->dev, "firmware %s not found!\n",
+- fwe->fwname);
+- dev_err(&udev->dev,
+- "you may need to download the firmware from http://developer.berlios.de/projects/at76c503a/\n");
++ if (ret)
+ goto exit;
+- }
+
+ at76_dbg(DBG_FW, "got it.");
+ fwh = (struct at76_fw_header *)(fwe->fw->data);
+--- a/drivers/net/wireless/atmel/atmel.c
++++ b/drivers/net/wireless/atmel/atmel.c
+@@ -3892,12 +3892,8 @@ static int reset_atmel_card(struct net_d
+ strcpy(priv->firmware_id, "atmel_at76c502.bin");
+ }
+ err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev);
+- if (err != 0) {
+- printk(KERN_ALERT
+- "%s: firmware %s is missing, cannot continue.\n",
+- dev->name, priv->firmware_id);
++ if (err != 0)
+ return err;
+- }
+ } else {
+ int fw_index = 0;
+ int success = 0;
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2245,19 +2245,8 @@ int b43_do_request_fw(struct b43_request
+ }
+ err = request_firmware(&ctx->blob, ctx->fwname,
+ ctx->dev->dev->dev);
+- if (err == -ENOENT) {
+- snprintf(ctx->errors[ctx->req_type],
+- sizeof(ctx->errors[ctx->req_type]),
+- "Firmware file \"%s\" not found\n",
+- ctx->fwname);
++ if (err)
+ return err;
+- } else if (err) {
+- snprintf(ctx->errors[ctx->req_type],
+- sizeof(ctx->errors[ctx->req_type]),
+- "Firmware file \"%s\" request failed (err=%d)\n",
+- ctx->fwname, err);
+- return err;
+- }
+ fw_ready:
+ if (ctx->blob->size < sizeof(struct b43_fw_header))
+ goto err_format;
+--- a/drivers/net/wireless/broadcom/b43legacy/main.c
++++ b/drivers/net/wireless/broadcom/b43legacy/main.c
+@@ -1524,11 +1524,8 @@ static int do_request_fw(struct b43legac
+ } else {
+ err = request_firmware(fw, path, dev->dev->dev);
+ }
+- if (err) {
+- b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
+- "or load failed.\n", path);
++ if (err)
+ return err;
+- }
+ if ((*fw)->size < sizeof(struct b43legacy_fw_header))
+ goto err_format;
+ hdr = (struct b43legacy_fw_header *)((*fw)->data);
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
+@@ -376,19 +376,13 @@ static int brcms_request_fw(struct brcms
+ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+- if (status) {
+- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+- KBUILD_MODNAME, fw_name);
++ if (status)
+ return status;
+- }
+ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+- if (status) {
+- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+- KBUILD_MODNAME, fw_name);
++ if (status)
+ return status;
+- }
+ wl->fw.hdr_num_entries[i] =
+ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+ }
+--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
++++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+@@ -8359,12 +8359,8 @@ static int ipw2100_get_firmware(struct i
+
+ rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev);
+
+- if (rc < 0) {
+- printk(KERN_ERR DRV_NAME ": "
+- "%s: Firmware '%s' not available or load failed.\n",
+- priv->net_dev->name, fw_name);
++ if (rc)
+ return rc;
+- }
+ IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data,
+ fw->fw_entry->size);
+
+--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
++++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+@@ -3350,10 +3350,8 @@ static int ipw_get_fw(struct ipw_priv *p
+
+ /* ask firmware_class module to get the boot firmware off disk */
+ rc = request_firmware(raw, name, &priv->pci_dev->dev);
+- if (rc < 0) {
+- IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc);
++ if (rc)
+ return rc;
+- }
+
+ if ((*raw)->size < sizeof(*fw)) {
+ IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size);
+--- a/drivers/net/wireless/intel/iwlegacy/3945-mac.c
++++ b/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+@@ -1829,7 +1829,6 @@ il3945_read_ucode(struct il_priv *il)
+ sprintf(buf, "%s%u%s", name_pre, idx, ".ucode");
+ ret = request_firmware(&ucode_raw, buf, &il->pci_dev->dev);
+ if (ret < 0) {
+- IL_ERR("%s firmware file req failed: %d\n", buf, ret);
+ if (ret == -ENOENT)
+ continue;
+ else
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+@@ -241,8 +241,6 @@ static int iwl_request_firmware(struct i
+ drv->fw_index--;
+
+ if (drv->fw_index < cfg->ucode_api_min) {
+- IWL_ERR(drv, "no suitable firmware found!\n");
+-
+ if (cfg->ucode_api_min == cfg->ucode_api_max) {
+ IWL_ERR(drv, "%s-%d is required\n", fw_name_pre,
+ cfg->ucode_api_max);
+--- a/drivers/net/wireless/intersil/orinoco/fw.c
++++ b/drivers/net/wireless/intersil/orinoco/fw.c
+@@ -132,7 +132,6 @@ orinoco_dl_firmware(struct orinoco_priva
+ err = request_firmware(&fw_entry, firmware, priv->dev);
+
+ if (err) {
+- dev_err(dev, "Cannot find firmware %s\n", firmware);
+ err = -ENOENT;
+ goto free;
+ }
+@@ -292,10 +291,8 @@ symbol_dl_firmware(struct orinoco_privat
+ const struct firmware *fw_entry;
+
+ if (!orinoco_cached_fw_get(priv, true)) {
+- if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) {
+- dev_err(dev, "Cannot find firmware: %s\n", fw->pri_fw);
++ if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0)
+ return -ENOENT;
+- }
+ } else
+ fw_entry = orinoco_cached_fw_get(priv, true);
+
+@@ -311,10 +308,8 @@ symbol_dl_firmware(struct orinoco_privat
+ }
+
+ if (!orinoco_cached_fw_get(priv, false)) {
+- if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) {
+- dev_err(dev, "Cannot find firmware: %s\n", fw->sta_fw);
++ if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0)
+ return -ENOENT;
+- }
+ } else
+ fw_entry = orinoco_cached_fw_get(priv, false);
+
+--- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
++++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+@@ -1708,7 +1708,6 @@ static int ezusb_probe(struct usb_interf
+ if (ezusb_firmware_download(upriv, &firmware) < 0)
+ goto error;
+ } else {
+- err("No firmware to download");
+ goto error;
+ }
+
+--- a/drivers/net/wireless/intersil/p54/p54pci.c
++++ b/drivers/net/wireless/intersil/p54/p54pci.c
+@@ -502,7 +502,6 @@ static void p54p_firmware_step2(const st
+ int err;
+
+ if (!fw) {
+- dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n");
+ err = -ENOENT;
+ goto out;
+ }
+--- a/drivers/net/wireless/intersil/p54/p54spi.c
++++ b/drivers/net/wireless/intersil/p54/p54spi.c
+@@ -158,10 +158,8 @@ static int p54spi_request_firmware(struc
+ /* FIXME: should driver use it's own struct device? */
+ ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev);
+
+- if (ret < 0) {
+- dev_err(&priv->spi->dev, "request_firmware() failed: %d", ret);
++ if (ret)
+ return ret;
+- }
+
+ ret = p54_parse_firmware(dev, priv->firmware);
+ if (ret) {
+--- a/drivers/net/wireless/intersil/p54/p54usb.c
++++ b/drivers/net/wireless/intersil/p54/p54usb.c
+@@ -929,7 +929,6 @@ static void p54u_load_firmware_cb(const
+ err = p54u_start_ops(priv);
+ } else {
+ err = -ENOENT;
+- dev_err(&udev->dev, "Firmware not found.\n");
+ }
+
+ complete(&priv->fw_wait_load);
+--- a/drivers/net/wireless/marvell/libertas_tf/if_usb.c
++++ b/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+@@ -820,8 +820,6 @@ static int if_usb_prog_firmware(struct l
+ kernel_param_lock(THIS_MODULE);
+ ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
+ if (ret < 0) {
+- pr_err("request_firmware() failed with %#x\n", ret);
+- pr_err("firmware %s not found\n", lbtf_fw_name);
+ kernel_param_unlock(THIS_MODULE);
+ goto done;
+ }
+--- a/drivers/net/wireless/marvell/mwifiex/main.c
++++ b/drivers/net/wireless/marvell/mwifiex/main.c
+@@ -549,11 +549,8 @@ static int _mwifiex_fw_dpc(const struct
+ struct wireless_dev *wdev;
+ struct completion *fw_done = adapter->fw_done;
+
+- if (!firmware) {
+- mwifiex_dbg(adapter, ERROR,
+- "Failed to get firmware %s\n", adapter->fw_name);
++ if (!firmware)
+ goto err_dnld_fw;
+- }
+
+ memset(&fw, 0, sizeof(struct mwifiex_fw_image));
+ adapter->firmware = firmware;
+--- a/drivers/net/wireless/marvell/mwl8k.c
++++ b/drivers/net/wireless/marvell/mwl8k.c
+@@ -5736,16 +5736,12 @@ static int mwl8k_firmware_load_success(s
+ static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
+ {
+ struct mwl8k_priv *priv = context;
+- struct mwl8k_device_info *di = priv->device_info;
+ int rc;
+
+ switch (priv->fw_state) {
+ case FW_STATE_INIT:
+- if (!fw) {
+- printk(KERN_ERR "%s: Error requesting helper fw %s\n",
+- pci_name(priv->pdev), di->helper_image);
++ if (!fw)
+ goto fail;
+- }
+ priv->fw_helper = fw;
+ rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode,
+ true);
+@@ -5780,11 +5776,8 @@ static void mwl8k_fw_state_machine(const
+ break;
+
+ case FW_STATE_LOADING_ALT:
+- if (!fw) {
+- printk(KERN_ERR "%s: Error requesting alt fw %s\n",
+- pci_name(priv->pdev), di->helper_image);
++ if (!fw)
+ goto fail;
+- }
+ priv->fw_ucode = fw;
+ rc = mwl8k_firmware_load_success(priv);
+ if (rc)
+@@ -5822,10 +5815,8 @@ retry:
+
+ /* Ask userland hotplug daemon for the device firmware */
+ rc = mwl8k_request_firmware(priv, fw_image, nowait);
+- if (rc) {
+- wiphy_err(hw->wiphy, "Firmware files not found\n");
++ if (rc)
+ return rc;
+- }
+
+ if (nowait)
+ return rc;
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
+@@ -38,10 +38,8 @@ static int rt2x00lib_request_firmware(st
+ rt2x00_info(rt2x00dev, "Loading firmware file '%s'\n", fw_name);
+
+ retval = request_firmware(&fw, fw_name, device);
+- if (retval) {
+- rt2x00_err(rt2x00dev, "Failed to request Firmware\n");
++ if (retval)
+ return retval;
+- }
+
+ if (!fw || !fw->size || !fw->data) {
+ rt2x00_err(rt2x00dev, "Failed to read Firmware\n");
+--- a/drivers/net/wireless/realtek/rtlwifi/core.c
++++ b/drivers/net/wireless/realtek/rtlwifi/core.c
+@@ -88,7 +88,6 @@ static void rtl_fw_do_work(const struct
+ if (!err)
+ goto found_alt;
+ }
+- pr_err("Selected firmware is not available\n");
+ rtlpriv->max_fw_size = 0;
+ goto exit;
+ }
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+@@ -63,13 +63,11 @@ static void rtl92se_fw_cb(const struct f
+ struct ieee80211_hw *hw = context;
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rt_firmware *pfirmware = NULL;
+- char *fw_name = "rtlwifi/rtl8192sefw.bin";
+
+ rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
+ "Firmware callback routine entered!\n");
+ complete(&rtlpriv->firmware_loading_complete);
+ if (!firmware) {
+- pr_err("Firmware %s not available\n", fw_name);
+ rtlpriv->max_fw_size = 0;
+ return;
+ }
+--- a/drivers/net/wireless/ti/wl1251/main.c
++++ b/drivers/net/wireless/ti/wl1251/main.c
+@@ -57,10 +57,8 @@ static int wl1251_fetch_firmware(struct
+
+ ret = request_firmware(&fw, WL1251_FW_NAME, dev);
+
+- if (ret < 0) {
+- wl1251_error("could not get firmware: %d", ret);
++ if (ret)
+ return ret;
+- }
+
+ if (fw->size % 4) {
+ wl1251_error("firmware size is not multiple of 32 bits: %zu",
+@@ -96,10 +94,8 @@ static int wl1251_fetch_nvs(struct wl125
+
+ ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
+
+- if (ret < 0) {
+- wl1251_error("could not get nvs file: %d", ret);
++ if (ret)
+ return ret;
+- }
+
+ if (fw->size % 4) {
+ wl1251_error("nvs size is not multiple of 32 bits: %zu",
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -756,10 +756,8 @@ static int wl12xx_fetch_firmware(struct
+
+ ret = request_firmware(&fw, fw_name, wl->dev);
+
+- if (ret < 0) {
+- wl1271_error("could not get firmware %s: %d", fw_name, ret);
++ if (ret)
+ return ret;
+- }
+
+ if (fw->size % 4) {
+ wl1271_error("firmware size is not multiple of 32 bits: %zu",
+--- a/drivers/net/wireless/zydas/zd1201.c
++++ b/drivers/net/wireless/zydas/zd1201.c
+@@ -62,8 +62,6 @@ static int zd1201_fw_upload(struct usb_d
+
+ err = request_firmware(&fw_entry, fwfile, &dev->dev);
+ if (err) {
+- dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
+- dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
+ dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
+ return err;
+ }
+--- a/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
++++ b/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
+@@ -107,16 +107,9 @@ static void int_urb_complete(struct urb
+ static int request_fw_file(
+ const struct firmware **fw, const char *name, struct device *device)
+ {
+- int r;
+-
+ dev_dbg_f(device, "fw name %s\n", name);
+
+- r = request_firmware(fw, name, device);
+- if (r)
+- dev_err(device,
+- "Could not load firmware file %s. Error number %d\n",
+- name, r);
+- return r;
++ return request_firmware(fw, name, device);
+ }
+
+ static inline u16 get_bcdDevice(const struct usb_device *udev)
+--- a/drivers/scsi/advansys.c
++++ b/drivers/scsi/advansys.c
+@@ -4054,8 +4054,6 @@ static int AscInitAsc1000Driver(ASC_DVC_
+
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fwname, err);
+ asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+ return err;
+ }
+@@ -4420,8 +4418,6 @@ static int AdvInitAsc3550Driver(ADV_DVC_
+
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fwname, err);
+ asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
+ return err;
+ }
+@@ -4920,8 +4916,6 @@ static int AdvInitAsc38C0800Driver(ADV_D
+
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fwname, err);
+ asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
+ return err;
+ }
+@@ -5408,8 +5402,6 @@ static int AdvInitAsc38C1600Driver(ADV_D
+
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fwname, err);
+ asc_dvc->err_code = ASC_IERR_MCODE_CHKSUM;
+ return err;
+ }
+--- a/drivers/scsi/aic94xx/aic94xx_init.c
++++ b/drivers/scsi/aic94xx/aic94xx_init.c
+@@ -370,8 +370,6 @@ static ssize_t asd_store_update_bios(str
+ filename_ptr,
+ &asd_ha->pcidev->dev);
+ if (err) {
+- asd_printk("Failed to load bios image file %s, error %d\n",
+- filename_ptr, err);
+ err = FAIL_OPEN_BIOS_FILE;
+ goto out1;
+ }
+--- a/drivers/scsi/aic94xx/aic94xx_seq.c
++++ b/drivers/scsi/aic94xx/aic94xx_seq.c
+@@ -1302,11 +1302,8 @@ int asd_init_seqs(struct asd_ha_struct *
+
+ err = asd_request_firmware(asd_ha);
+
+- if (err) {
+- asd_printk("Failed to load sequencer firmware file %s, error %d\n",
+- SAS_RAZOR_SEQUENCER_FW_FILE, err);
++ if (err)
+ return err;
+- }
+
+ err = asd_seq_download_seqs(asd_ha);
+ if (err) {
+--- a/drivers/scsi/bfa/bfad.c
++++ b/drivers/scsi/bfa/bfad.c
+@@ -1737,7 +1737,6 @@ bfad_read_firmware(struct pci_dev *pdev,
+ const struct firmware *fw;
+
+ if (request_firmware(&fw, fw_name, &pdev->dev)) {
+- printk(KERN_ALERT "Can't locate firmware %s\n", fw_name);
+ *bfi_image = NULL;
+ goto out;
+ }
+--- a/drivers/scsi/ipr.c
++++ b/drivers/scsi/ipr.c
+@@ -4009,10 +4009,8 @@ static ssize_t ipr_store_update_fw(struc
+ if (endline)
+ *endline = '\0';
+
+- if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) {
+- dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname);
++ if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev))
+ return -EIO;
+- }
+
+ image_hdr = (struct ipr_ucode_image_header *)fw_entry->data;
+
+--- a/drivers/scsi/pm8001/pm8001_ctl.c
++++ b/drivers/scsi/pm8001/pm8001_ctl.c
+@@ -842,9 +842,6 @@ static ssize_t pm8001_store_update_fw(st
+ pm8001_ha->dev);
+
+ if (ret) {
+- pm8001_dbg(pm8001_ha, FAIL,
+- "Failed to load firmware image file %s, error %d\n",
+- filename_ptr, ret);
+ pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE;
+ goto out;
+ }
+--- a/drivers/scsi/qla1280.c
++++ b/drivers/scsi/qla1280.c
+@@ -1504,8 +1504,6 @@ qla1280_request_firmware(struct scsi_qla
+ err = request_firmware(&fw, fwname, &ha->pdev->dev);
+
+ if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fwname, err);
+ fw = ERR_PTR(err);
+ goto unlock;
+ }
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -8560,10 +8560,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha,
+ /* Load firmware blob. */
+ blob = qla2x00_request_firmware(vha);
+ if (!blob) {
+- ql_log(ql_log_info, vha, 0x0083,
+- "Firmware image unavailable.\n");
+- ql_log(ql_log_info, vha, 0x0084,
+- "Firmware images can be retrieved from: "QLA_FW_URL ".\n");
+ return QLA_FUNCTION_FAILED;
+ }
+
+@@ -8666,9 +8662,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t *
+
+ blob = qla2x00_request_firmware(vha);
+ if (!blob) {
+- ql_log(ql_log_warn, vha, 0x0092,
+- "-> Firmware file not found.\n");
+-
+ return QLA_FUNCTION_FAILED;
+ }
+
+--- a/drivers/scsi/qla2xxx/qla_nx.c
++++ b/drivers/scsi/qla2xxx/qla_nx.c
+@@ -2427,11 +2427,8 @@ try_blob_fw:
+
+ /* Load firmware blob. */
+ blob = ha->hablob = qla2x00_request_firmware(vha);
+- if (!blob) {
+- ql_log(ql_log_fatal, vha, 0x00a3,
+- "Firmware image not present.\n");
++ if (!blob)
+ goto fw_load_failed;
+- }
+
+ /* Validating firmware blob */
+ if (qla82xx_validate_firmware_blob(vha,
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -7696,8 +7696,6 @@ qla2x00_request_firmware(scsi_qla_host_t
+ goto out;
+
+ if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
+- ql_log(ql_log_warn, vha, 0x0063,
+- "Failed to load firmware image (%s).\n", blob->name);
+ blob->fw = NULL;
+ blob = NULL;
+ }
+--- a/drivers/scsi/qlogicpti.c
++++ b/drivers/scsi/qlogicpti.c
+@@ -486,11 +486,8 @@ static int qlogicpti_load_firmware(struc
+ int i, timeout;
+
+ err = request_firmware(&fw, fwname, &qpti->op->dev);
+- if (err) {
+- printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+- fwname, err);
++ if (err)
+ return err;
+- }
+ if (fw->size % 2) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, fwname);
+--- a/drivers/staging/rtl8192u/r819xU_firmware.c
++++ b/drivers/staging/rtl8192u/r819xU_firmware.c
+@@ -240,10 +240,8 @@ bool init_firmware(struct net_device *de
+ */
+ if (rst_opt == OPT_SYSTEM_RESET) {
+ rc = request_firmware(&fw_entry, fw_name[init_step], &priv->udev->dev);
+- if (rc < 0) {
+- RT_TRACE(COMP_ERR, "request firmware fail!\n");
++ if (rc)
+ goto download_firmware_fail;
+- }
+
+ if (fw_entry->size > sizeof(pfirmware->firmware_buf)) {
+ RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
+--- a/drivers/staging/rtl8712/hal_init.c
++++ b/drivers/staging/rtl8712/hal_init.c
+@@ -72,8 +72,6 @@ int rtl871x_load_fw(struct _adapter *pad
+ dev_info(dev, "r8712u: Loading firmware from \"%s\"\n", firmware_file);
+ rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
+ GFP_KERNEL, padapter, rtl871x_load_fw_cb);
+- if (rc)
+- dev_err(dev, "r8712u: Firmware request error %d\n", rc);
+ return rc;
+ }
+ MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
+--- a/drivers/staging/vt6656/main_usb.c
++++ b/drivers/staging/vt6656/main_usb.c
+@@ -107,11 +107,8 @@ static int vnt_download_firmware(struct
+ dev_dbg(dev, "---->Download firmware\n");
+
+ ret = request_firmware(&fw, FIRMWARE_NAME, dev);
+- if (ret) {
+- dev_err(dev, "firmware file %s request failed (%d)\n",
+- FIRMWARE_NAME, ret);
++ if (ret)
+ goto end;
+- }
+
+ for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
+ length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
+--- a/drivers/tty/moxa.c
++++ b/drivers/tty/moxa.c
+@@ -1154,13 +1154,8 @@ static int moxa_init_board(struct moxa_b
+ }
+
+ ret = request_firmware(&fw, file, dev);
+- if (ret) {
+- printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
+- "you've placed '%s' file into your firmware "
+- "loader directory (e.g. /lib/firmware)\n",
+- file);
++ if (ret)
+ goto err_free;
+- }
+
+ ret = moxa_load_fw(brd, fw);
+
+--- a/drivers/tty/serial/icom.c
++++ b/drivers/tty/serial/icom.c
+@@ -621,7 +621,6 @@ static void load_code(struct icom_port *
+
+ /* Load Call Setup into Adapter */
+ if (request_firmware(&fw, "icom_call_setup.bin", &dev->dev) < 0) {
+- dev_err(&dev->dev,"Unable to load icom_call_setup.bin firmware image\n");
+ status = -1;
+ goto load_code_exit;
+ }
+@@ -641,7 +640,6 @@ static void load_code(struct icom_port *
+
+ /* Load Resident DCE portion of Adapter */
+ if (request_firmware(&fw, "icom_res_dce.bin", &dev->dev) < 0) {
+- dev_err(&dev->dev,"Unable to load icom_res_dce.bin firmware image\n");
+ status = -1;
+ goto load_code_exit;
+ }
+@@ -686,7 +684,6 @@ static void load_code(struct icom_port *
+ }
+
+ if (request_firmware(&fw, "icom_asc.bin", &dev->dev) < 0) {
+- dev_err(&dev->dev,"Unable to load icom_asc.bin firmware image\n");
+ status = -1;
+ goto load_code_exit;
+ }
+--- a/drivers/tty/serial/ucc_uart.c
++++ b/drivers/tty/serial/ucc_uart.c
+@@ -1149,10 +1149,8 @@ static void uart_firmware_cont(const str
+ struct device *dev = context;
+ int ret;
+
+- if (!fw) {
+- dev_err(dev, "firmware not found\n");
++ if (!fw)
+ return;
+- }
+
+ firmware = (struct qe_firmware *) fw->data;
+
+--- a/drivers/usb/atm/cxacru.c
++++ b/drivers/usb/atm/cxacru.c
+@@ -1084,8 +1084,6 @@ static int cxacru_find_firmware(struct c
+ return -ENOENT;
+ }
+
+- usb_info(usbatm, "found firmware %s\n", buf);
+-
+ return 0;
+ }
+
+--- a/drivers/usb/atm/ueagle-atm.c
++++ b/drivers/usb/atm/ueagle-atm.c
+@@ -606,10 +606,8 @@ static void uea_upload_pre_firmware(cons
+ int ret, size;
+
+ uea_enters(usb);
+- if (!fw_entry) {
+- uea_err(usb, "firmware is not available\n");
++ if (!fw_entry)
+ goto err;
+- }
+
+ pfw = fw_entry->data;
+ size = fw_entry->size;
+@@ -704,10 +702,6 @@ static int uea_load_firmware(struct usb_
+ ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev,
+ GFP_KERNEL, usb,
+ uea_upload_pre_firmware);
+- if (ret)
+- uea_err(usb, "firmware %s is not available\n", fw_name);
+- else
+- uea_info(usb, "loading firmware %s\n", fw_name);
+
+ uea_leaves(usb);
+ return ret;
+@@ -869,12 +863,8 @@ static int request_dsp(struct uea_softc
+ }
+
+ ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);
+- if (ret < 0) {
+- uea_err(INS_TO_USBDEV(sc),
+- "requesting firmware %s failed with error %d\n",
+- dsp_name, ret);
++ if (ret)
+ return ret;
+- }
+
+ if (UEA_CHIP_VERSION(sc) == EAGLE_IV)
+ ret = check_dsp_e4(sc->dsp_firm->data, sc->dsp_firm->size);
+@@ -1587,12 +1577,8 @@ static int request_cmvs_old(struct uea_s
+
+ cmvs_file_name(sc, cmv_name, 1);
+ ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev);
+- if (ret < 0) {
+- uea_err(INS_TO_USBDEV(sc),
+- "requesting firmware %s failed with error %d\n",
+- cmv_name, ret);
++ if (ret)
+ return ret;
+- }
+
+ data = (u8 *) (*fw)->data;
+ size = (*fw)->size;
+@@ -1629,9 +1615,6 @@ static int request_cmvs(struct uea_softc
+ "try to get older cmvs\n", cmv_name);
+ return request_cmvs_old(sc, cmvs, fw);
+ }
+- uea_err(INS_TO_USBDEV(sc),
+- "requesting firmware %s failed with error %d\n",
+- cmv_name, ret);
+ return ret;
+ }
+
+@@ -1914,11 +1897,8 @@ static int load_XILINX_firmware(struct u
+ uea_enters(INS_TO_USBDEV(sc));
+
+ ret = request_firmware(&fw_entry, fw_name, &sc->usb_dev->dev);
+- if (ret) {
+- uea_err(INS_TO_USBDEV(sc), "firmware %s is not available\n",
+- fw_name);
++ if (ret)
+ goto err0;
+- }
+
+ pfw = fw_entry->data;
+ size = fw_entry->size;
+--- a/drivers/usb/misc/emi26.c
++++ b/drivers/usb/misc/emi26.c
+@@ -85,21 +85,17 @@ static int emi26_load_firmware (struct u
+
+ err = request_ihex_firmware(&loader_fw, "emi26/loader.fw", &dev->dev);
+ if (err)
+- goto nofw;
++ goto wraperr;
+
+ err = request_ihex_firmware(&bitstream_fw, "emi26/bitstream.fw",
+ &dev->dev);
+ if (err)
+- goto nofw;
++ goto wraperr;
+
+ err = request_ihex_firmware(&firmware_fw, "emi26/firmware.fw",
+ &dev->dev);
+- if (err) {
+- nofw:
+- dev_err(&dev->dev, "%s - request_firmware() failed\n",
+- __func__);
++ if (err)
+ goto wraperr;
+- }
+
+ /* Assert reset (stop the CPU in the EMI) */
+ err = emi26_set_reset(dev,1);
+--- a/drivers/usb/misc/ezusb.c
++++ b/drivers/usb/misc/ezusb.c
+@@ -64,12 +64,8 @@ static int ezusb_ihex_firmware_download(
+ const struct ihex_binrec *record;
+
+ if (request_ihex_firmware(&firmware, firmware_path,
+- &dev->dev)) {
+- dev_err(&dev->dev,
+- "%s - request \"%s\" failed\n",
+- __func__, firmware_path);
++ &dev->dev))
+ goto out;
+- }
+
+ ret = ezusb_set_reset(dev, fx.cpucs_reg, 0);
+ if (ret < 0)
+--- a/drivers/usb/misc/isight_firmware.c
++++ b/drivers/usb/misc/isight_firmware.c
+@@ -45,7 +45,6 @@ static int isight_firmware_load(struct u
+ return -ENOMEM;
+
+ if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) {
+- printk(KERN_ERR "Unable to load isight firmware\n");
+ ret = -ENODEV;
+ goto out;
+ }
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -332,11 +332,8 @@ static void update_edgeport_E2PROM(struc
+
+ response = request_ihex_firmware(&fw, fw_name,
+ &edge_serial->serial->dev->dev);
+- if (response) {
+- dev_err(dev, "Failed to load image \"%s\" err %d\n",
+- fw_name, response);
++ if (response)
+ return;
+- }
+
+ rec = (const struct ihex_binrec *)fw->data;
+ BootMajorVersion = rec->data[0];
+--- a/drivers/usb/serial/io_ti.c
++++ b/drivers/usb/serial/io_ti.c
+@@ -1009,8 +1009,6 @@ static int download_fw(struct edgeport_s
+
+ status = request_firmware(&fw, fw_name, dev);
+ if (status) {
+- dev_err(dev, "Failed to load image \"%s\" err %d\n",
+- fw_name, status);
+ return status;
+ }
+
+--- a/drivers/usb/serial/ti_usb_3410_5052.c
++++ b/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -1635,10 +1635,8 @@ static int ti_download_firmware(struct t
+ }
+
+ check_firmware:
+- if (status) {
+- dev_err(&dev->dev, "%s - firmware not found\n", __func__);
++ if (status)
+ return -ENOENT;
+- }
+ if (fw_p->size > TI_FIRMWARE_BUF_SIZE) {
+ dev_err(&dev->dev, "%s - firmware too large %zu\n", __func__, fw_p->size);
+ release_firmware(fw_p);
+--- a/drivers/video/fbdev/broadsheetfb.c
++++ b/drivers/video/fbdev/broadsheetfb.c
+@@ -743,10 +743,8 @@ static ssize_t broadsheet_loadstore_wave
+ return -EINVAL;
+
+ err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
+- if (err < 0) {
+- dev_err(dev, "Failed to get broadsheet waveform\n");
++ if (err)
+ goto err_failed;
+- }
+
+ /* try to enforce reasonable min max on waveform */
+ if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
+--- a/drivers/video/fbdev/metronomefb.c
++++ b/drivers/video/fbdev/metronomefb.c
+@@ -621,10 +621,8 @@ static int metronomefb_probe(struct plat
+ a) request the waveform file from userspace
+ b) process waveform and decode into metromem */
+ retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
+- if (retval < 0) {
+- dev_err(&dev->dev, "Failed to get waveform\n");
++ if (retval)
+ goto err_csum_table;
+- }
+
+ retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
+ par);
+--- a/sound/drivers/vx/vx_hwdep.c
++++ b/sound/drivers/vx/vx_hwdep.c
+@@ -58,10 +58,8 @@ int snd_vx_setup_firmware(struct vx_core
+ if (! fw_files[chip->type][i])
+ continue;
+ sprintf(path, "vx/%s", fw_files[chip->type][i]);
+- if (request_firmware(&fw, path, chip->dev)) {
+- snd_printk(KERN_ERR "vx: can't load firmware %s\n", path);
++ if (request_firmware(&fw, path, chip->dev))
+ return -ENOENT;
+- }
+ err = chip->ops->load_dsp(chip, i, fw);
+ if (err < 0) {
+ release_firmware(fw);
+--- a/sound/isa/msnd/msnd_pinnacle.c
++++ b/sound/isa/msnd/msnd_pinnacle.c
+@@ -376,15 +376,11 @@ static int upload_dsp_code(struct snd_ca
+ outb(HPBLKSEL_0, chip->io + HP_BLKS);
+
+ err = request_firmware(&init_fw, INITCODEFILE, card->dev);
+- if (err < 0) {
+- printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);
++ if (err)
+ goto cleanup1;
+- }
+ err = request_firmware(&perm_fw, PERMCODEFILE, card->dev);
+- if (err < 0) {
+- printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE);
++ if (err)
+ goto cleanup;
+- }
+
+ memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size);
+ if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) {
+--- a/sound/isa/sscape.c
++++ b/sound/isa/sscape.c
+@@ -520,10 +520,8 @@ static int sscape_upload_bootblock(struc
+ int ret;
+
+ ret = request_firmware(&init_fw, "scope.cod", card->dev);
+- if (ret < 0) {
+- snd_printk(KERN_ERR "sscape: Error loading scope.cod");
++ if (ret)
+ return ret;
+- }
+ ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
+
+ release_firmware(init_fw);
+@@ -560,11 +558,8 @@ static int sscape_upload_microcode(struc
+ scnprintf(name, sizeof(name), "sndscape.co%d", version);
+
+ err = request_firmware(&init_fw, name, card->dev);
+- if (err < 0) {
+- snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d",
+- version);
++ if (err)
+ return err;
+- }
+ err = upload_dma_data(sscape, init_fw->data, init_fw->size);
+ if (err == 0)
+ snd_printk(KERN_INFO "sscape: MIDI firmware loaded %zu KBs\n",
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -1970,10 +1970,8 @@ wavefront_download_firmware (snd_wavefro
+ const struct firmware *firmware;
+
+ err = request_firmware(&firmware, path, dev->card->dev);
+- if (err < 0) {
+- snd_printk(KERN_ERR "firmware (%s) download failed!!!\n", path);
++ if (err)
+ return 1;
+- }
+
+ len = 0;
+ buf = firmware->data;
+--- a/sound/pci/asihpi/hpidspcd.c
++++ b/sound/pci/asihpi/hpidspcd.c
+@@ -35,8 +35,6 @@ short hpi_dsp_code_open(u32 adapter, voi
+ err = request_firmware(&firmware, fw_name, &dev->dev);
+
+ if (err || !firmware) {
+- dev_err(&dev->dev, "%d, request_firmware failed for %s\n",
+- err, fw_name);
+ goto error1;
+ }
+ if (firmware->size < sizeof(header)) {
+--- a/sound/pci/cs46xx/cs46xx_lib.c
++++ b/sound/pci/cs46xx/cs46xx_lib.c
+@@ -3196,11 +3196,8 @@ int snd_cs46xx_start_dsp(struct snd_cs46
+ #ifdef CONFIG_SND_CS46XX_NEW_DSP
+ for (i = 0; i < CS46XX_DSP_MODULES; i++) {
+ err = load_firmware(chip, &chip->modules[i], module_names[i]);
+- if (err < 0) {
+- dev_err(chip->card->dev, "firmware load error [%s]\n",
+- module_names[i]);
++ if (err < 0)
+ return err;
+- }
+ err = cs46xx_dsp_load_module(chip, chip->modules[i]);
+ if (err < 0) {
+ dev_err(chip->card->dev, "image download error [%s]\n",
+--- a/sound/pci/echoaudio/echoaudio.c
++++ b/sound/pci/echoaudio/echoaudio.c
+@@ -48,11 +48,8 @@ static int get_firmware(const struct fir
+ "firmware requested: %s\n", card_fw[fw_index].data);
+ snprintf(name, sizeof(name), "ea/%s", card_fw[fw_index].data);
+ err = request_firmware(fw_entry, name, &chip->pci->dev);
+- if (err < 0)
+- dev_err(chip->card->dev,
+- "get_firmware(): Firmware not available (%d)\n", err);
+ #ifdef CONFIG_PM_SLEEP
+- else
++ if (!err)
+ chip->fw_cache[fw_index] = *fw_entry;
+ #endif
+ return err;
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -864,10 +864,8 @@ static int snd_emu10k1_emu1010_init(stru
+ dev_info(emu->card->dev, "emu1010: EMU_HANA_ID = 0x%x\n", reg);
+
+ err = snd_emu1010_load_firmware(emu, 0, &emu->firmware);
+- if (err < 0) {
+- dev_info(emu->card->dev, "emu1010: Loading Firmware failed\n");
++ if (err < 0)
+ return err;
+- }
+
+ /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -2040,8 +2040,6 @@ static void azx_firmware_cb(const struct
+
+ if (fw)
+ chip->fw = fw;
+- else
+- dev_err(card->dev, "Cannot load firmware, continue without patching\n");
+ if (!chip->disabled) {
+ /* continue probing */
+ azx_probe_continue(chip);
+--- a/sound/pci/korg1212/korg1212.c
++++ b/sound/pci/korg1212/korg1212.c
+@@ -2232,7 +2232,6 @@ static int snd_korg1212_create(struct sn
+
+ err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
+ if (err < 0) {
+- snd_printk(KERN_ERR "firmware not available\n");
+ return err;
+ }
+
+--- a/sound/pci/mixart/mixart_hwdep.c
++++ b/sound/pci/mixart/mixart_hwdep.c
+@@ -566,11 +566,8 @@ int snd_mixart_setup_firmware(struct mix
+
+ for (i = 0; i < 3; i++) {
+ sprintf(path, "mixart/%s", fw_files[i]);
+- if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
+- dev_err(&mgr->pci->dev,
+- "miXart: can't load firmware %s\n", path);
++ if (request_firmware(&fw_entry, path, &mgr->pci->dev))
+ return -ENOENT;
+- }
+ /* fake hwdep dsp record */
+ err = mixart_dsp_load(mgr, i, fw_entry);
+ release_firmware(fw_entry);
+--- a/sound/pci/pcxhr/pcxhr_hwdep.c
++++ b/sound/pci/pcxhr/pcxhr_hwdep.c
+@@ -375,12 +375,8 @@ int pcxhr_setup_firmware(struct pcxhr_mg
+ if (!fw_files[fw_set][i])
+ continue;
+ sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
+- if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
+- dev_err(&mgr->pci->dev,
+- "pcxhr: can't load firmware %s\n",
+- path);
++ if (request_firmware(&fw_entry, path, &mgr->pci->dev))
+ return -ENOENT;
+- }
+ /* fake hwdep dsp record */
+ err = pcxhr_dsp_load(mgr, i, fw_entry);
+ release_firmware(fw_entry);
+--- a/sound/pci/riptide/riptide.c
++++ b/sound/pci/riptide/riptide.c
+@@ -1222,11 +1222,8 @@ static int try_to_load_firmware(struct c
+ if (!chip->fw_entry) {
+ err = request_firmware(&chip->fw_entry, "riptide.hex",
+ &chip->pci->dev);
+- if (err) {
+- snd_printk(KERN_ERR
+- "Riptide: Firmware not available %d\n", err);
++ if (err)
+ return -EIO;
+- }
+ }
+ err = loadfirmware(cif, chip->fw_entry->data, chip->fw_entry->size);
+ if (err) {
+--- a/sound/pci/rme9652/hdsp.c
++++ b/sound/pci/rme9652/hdsp.c
+@@ -5171,11 +5171,8 @@ static int hdsp_request_fw_loader(struct
+ return -EINVAL;
+ }
+
+- if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
+- dev_err(hdsp->card->dev,
+- "cannot load firmware %s\n", fwfile);
++ if (request_firmware(&fw, fwfile, &hdsp->pci->dev))
+ return -ENOENT;
+- }
+ if (fw->size < HDSP_FIRMWARE_SIZE) {
+ dev_err(hdsp->card->dev,
+ "too short firmware size %d (expected %d)\n",
+--- a/sound/soc/codecs/wm2000.c
++++ b/sound/soc/codecs/wm2000.c
+@@ -891,10 +891,8 @@ static int wm2000_i2c_probe(struct i2c_c
+ }
+
+ ret = request_firmware(&fw, filename, &i2c->dev);
+- if (ret != 0) {
+- dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
++ if (ret != 0)
+ goto err_supplies;
+- }
+
+ /* Pre-cook the concatenation of the register address onto the image */
+ wm2000->anc_download_size = fw->size + 2;
+--- a/sound/usb/6fire/firmware.c
++++ b/sound/usb/6fire/firmware.c
+@@ -203,8 +203,6 @@ static int usb6fire_fw_ezusb_upload(
+ ret = request_firmware(&fw, fwname, &device->dev);
+ if (ret < 0) {
+ kfree(rec);
+- dev_err(&intf->dev,
+- "error requesting ezusb firmware %s.\n", fwname);
+ return ret;
+ }
+ ret = usb6fire_fw_ihex_init(fw, rec);
+@@ -280,8 +278,6 @@ static int usb6fire_fw_fpga_upload(
+
+ ret = request_firmware(&fw, fwname, &device->dev);
+ if (ret < 0) {
+- dev_err(&intf->dev, "unable to get fpga firmware %s.\n",
+- fwname);
+ kfree(buffer);
+ return -EIO;
+ }
diff --git a/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch b/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch
new file mode 100644
index 0000000000..092a744961
--- /dev/null
+++ b/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch
@@ -0,0 +1,83 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: firmware_class: Log every success and failure against given device
+Date: Sun, 09 Dec 2012 16:02:00 +0000
+Forwarded: no
+
+The hundreds of users of request_firmware() have nearly as many
+different log formats for reporting failures. They also have only the
+vaguest hint as to what went wrong; only firmware_class really knows
+that. Therefore, add specific log messages for the failure modes that
+aren't currently logged.
+
+In case of a driver that tries multiple names, this may result in the
+impression that it failed to initialise. Therefore, also log successes.
+
+This makes many error messages in drivers redundant, which will be
+removed in later patches.
+
+This does not cover the case where we fall back to a user-mode helper
+(which is no longer enabled in Debian).
+
+NOTE: hw-detect will depend on the "firmware: failed to load %s (%d)\n"
+format to detect missing firmware.
+---
+ drivers/base/firmware_loader/fallback.c | 2 +-
+ drivers/base/firmware_loader/main.c | 17 ++++++++---------
+ 2 files changed, 9 insertions(+), 10 deletions(-)
+
+--- a/drivers/base/firmware_loader/fallback.c
++++ b/drivers/base/firmware_loader/fallback.c
+@@ -558,7 +558,7 @@ static int fw_load_from_user_helper(stru
+ if (opt_flags & FW_OPT_NOWAIT) {
+ timeout = usermodehelper_read_lock_wait(timeout);
+ if (!timeout) {
+- dev_dbg(device, "firmware: %s loading timed out\n",
++ dev_err(device, "firmware: %s loading timed out\n",
+ name);
+ return -EBUSY;
+ }
+--- a/drivers/base/firmware_loader/main.c
++++ b/drivers/base/firmware_loader/main.c
+@@ -535,18 +535,15 @@ fw_get_filesystem_firmware(struct device
+ file_size_ptr,
+ READING_FIRMWARE);
+ if (rc < 0) {
+- if (rc != -ENOENT)
+- dev_warn(device, "loading %s failed with error %d\n",
+- path, rc);
+- else
+- dev_dbg(device, "loading %s failed for no such file or directory.\n",
+- path);
++ dev_dbg(device, "loading %s failed with error %d\n",
++ path, rc);
+ continue;
+ }
+ size = rc;
+ rc = 0;
+
+- dev_dbg(device, "Loading firmware from %s\n", path);
++ dev_info(device, "firmware: direct-loading firmware %s\n",
++ fw_priv->fw_name);
+ if (decompress) {
+ dev_dbg(device, "f/w decompressing %s\n",
+ fw_priv->fw_name);
+@@ -559,8 +556,6 @@ fw_get_filesystem_firmware(struct device
+ continue;
+ }
+ } else {
+- dev_dbg(device, "direct-loading %s\n",
+- fw_priv->fw_name);
+ if (!fw_priv->data)
+ fw_priv->data = buffer;
+ fw_priv->size = size;
+@@ -570,6 +565,10 @@ fw_get_filesystem_firmware(struct device
+ }
+ __putname(path);
+
++ if (rc)
++ dev_err(device, "firmware: failed to load %s (%d)\n",
++ fw_priv->fw_name, rc);
++
+ return rc;
+ }
+
diff --git a/debian/patches/bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch b/debian/patches/bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch
new file mode 100644
index 0000000000..91fd2fb9bd
--- /dev/null
+++ b/debian/patches/bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch
@@ -0,0 +1,61 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 13 Apr 2016 21:48:06 +0100
+Subject: fs: Add MODULE_SOFTDEP declarations for hard-coded crypto drivers
+Bug-Debian: https://bugs.debian.org/819725
+Forwarded: https://lore.kernel.org/all/20160517133631.GF7555@decadent.org.uk/
+
+This helps initramfs builders and other tools to find the full
+dependencies of a module.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+[Lukas Wunner: Forward-ported to 4.11: drop parts applied upstream]
+---
+ fs/btrfs/super.c | 2 +-
+ fs/ext4/super.c | 2 +-
+ fs/f2fs/super.c | 1 +
+ fs/jbd2/journal.c | 1 +
+ fs/nfsd/nfsctl.c | 3 +++
+ 5 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -2549,7 +2549,7 @@
+ module_exit(exit_btrfs_fs)
+
+ MODULE_LICENSE("GPL");
+-MODULE_SOFTDEP("pre: crc32c");
++MODULE_SOFTDEP("pre: crypto-crc32c");
+ MODULE_SOFTDEP("pre: xxhash64");
+ MODULE_SOFTDEP("pre: sha256");
+ MODULE_SOFTDEP("pre: blake2b-256");
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -7420,6 +7420,6 @@
+ MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
+ MODULE_DESCRIPTION("Fourth Extended Filesystem");
+ MODULE_LICENSE("GPL");
+-MODULE_SOFTDEP("pre: crc32c");
++MODULE_SOFTDEP("pre: crypto-crc32c");
+ module_init(ext4_init_fs)
+ module_exit(ext4_exit_fs)
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -3168,6 +3168,7 @@
+ }
+
+ MODULE_LICENSE("GPL");
++MODULE_SOFTDEP("pre: crypto-crc32c");
+ module_init(journal_init);
+ module_exit(journal_exit);
+
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1629,5 +1629,8 @@
+ MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
+ MODULE_DESCRIPTION("In-kernel NFS server");
+ MODULE_LICENSE("GPL");
++#ifdef CONFIG_NFSD_V4
++MODULE_SOFTDEP("pre: crypto-md5");
++#endif
+ module_init(init_nfsd)
+ module_exit(exit_nfsd)
diff --git a/debian/patches/bugfix/all/kbuild-fix-recordmcount-dependency.patch b/debian/patches/bugfix/all/kbuild-fix-recordmcount-dependency.patch
new file mode 100644
index 0000000000..8f9c21f56c
--- /dev/null
+++ b/debian/patches/bugfix/all/kbuild-fix-recordmcount-dependency.patch
@@ -0,0 +1,23 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: kbuild: Fix recordmcount dependency for OOT modules
+Date: Mon, 08 Sep 2014 18:31:24 +0100
+Forwarded: no
+
+We never rebuild anything in-tree when building an out-of-tree
+modules, so external modules should not depend on the recordmcount
+sources.
+
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -210,6 +210,11 @@ cmd_record_mcount = $(if $(findstring $(
+ $(sub_cmd_record_mcount))
+ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
+
++# Don't require recordmcount source for an OOT build.
++ifdef KBUILD_EXTMOD
++recordmcount_source :=
++endif
++
+ # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
+ # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
+ # 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
diff --git a/debian/patches/bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch b/debian/patches/bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch
new file mode 100644
index 0000000000..0412b83aa5
--- /dev/null
+++ b/debian/patches/bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch
@@ -0,0 +1,18 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Sat, 15 Jan 2022 22:30:49 +0100
+Subject: libapi: Define _FORTIFY_SOURCE as 2, not empty
+Forwarded: https://lore.kernel.org/lkml/20230424102049.58338-1-ukleinek@debian.org/
+
+Signed-off-by: Ben Hutchings <benh@debian.org>
+---
+--- a/tools/lib/api/Makefile
++++ b/tools/lib/api/Makefile
+@@ -29,7 +29,7 @@ endif
+ endif
+
+ ifeq ($(DEBUG),0)
+- CFLAGS += -D_FORTIFY_SOURCE
++ CFLAGS += -D_FORTIFY_SOURCE=2
+ endif
+
+ # Treat warnings as errors unless directed not to
diff --git a/debian/patches/bugfix/all/module-disable-matching-missing-version-crc.patch b/debian/patches/bugfix/all/module-disable-matching-missing-version-crc.patch
new file mode 100644
index 0000000000..8e0a7ee76d
--- /dev/null
+++ b/debian/patches/bugfix/all/module-disable-matching-missing-version-crc.patch
@@ -0,0 +1,23 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 02 Dec 2016 23:06:18 +0000
+Subject: module: Disable matching missing version CRC
+Forwarded: not-needed
+
+This partly reverts commit cd3caefb4663e3811d37cc2afad3cce642d60061.
+We want to fail closed if a symbol version CRC is missing, as the
+alternative may allow subverting module signing.
+---
+--- a/kernel/module/version.c
++++ b/kernel/module/version.c
+@@ -46,9 +46,8 @@ int check_version(const struct load_info
+ goto bad_version;
+ }
+
+- /* Broken toolchain. Warn once, then let it go.. */
+- pr_warn_once("%s: no symbol version for %s\n", info->name, symname);
+- return 1;
++ pr_warn("%s: no symbol version for %s\n", info->name, symname);
++ return 0;
+
+ bad_version:
+ pr_warn("%s: disagrees about version of symbol %s\n", info->name, symname);
diff --git a/debian/patches/bugfix/all/perf-tools-support-extra-cxxflags.patch b/debian/patches/bugfix/all/perf-tools-support-extra-cxxflags.patch
new file mode 100644
index 0000000000..a3169e3818
--- /dev/null
+++ b/debian/patches/bugfix/all/perf-tools-support-extra-cxxflags.patch
@@ -0,0 +1,30 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Mon, 15 May 2023 15:58:39 +0200
+Subject: perf tools: Support EXTRA_CXXFLAGS
+
+Add support for an EXTRA_CXXFLAGS variable, used similarly to
+EXTRA_CFLAGS.
+
+Signed-off-by: Ben Hutchings <benh@debian.org>
+---
+--- a/tools/perf/Makefile.config
++++ b/tools/perf/Makefile.config
+@@ -18,6 +18,7 @@ detected_var = $(shell echo "$(1)=$($(1)
+
+ CFLAGS := $(EXTRA_CFLAGS) $(filter-out -Wnested-externs,$(EXTRA_WARNINGS))
+ HOSTCFLAGS := $(filter-out -Wnested-externs,$(EXTRA_WARNINGS))
++CXXFLAGS := $(EXTRA_CXXFLAGS)
+
+ # Enabled Wthread-safety analysis for clang builds.
+ ifeq ($(CC_NO_CLANG), 0)
+--- a/tools/perf/Makefile.perf
++++ b/tools/perf/Makefile.perf
+@@ -33,7 +33,7 @@ include ../scripts/utilities.mak
+ #
+ # Define LDFLAGS=-static to build a static binary.
+ #
+-# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
++# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds, and similarly EXTRA_CXXFLAGS.
+ #
+ # Define EXCLUDE_EXTLIBS=-lmylib to exclude libmylib from the auto-generated
+ # EXTLIBS.
diff --git a/debian/patches/bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch b/debian/patches/bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch
new file mode 100644
index 0000000000..9f4d914fee
--- /dev/null
+++ b/debian/patches/bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch
@@ -0,0 +1,88 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: radeon, amdgpu: Firmware is required for DRM and KMS on R600 onward
+Date: Tue, 08 Jan 2013 03:25:52 +0000
+Bug-Debian: https://bugs.debian.org/607194
+Bug-Debian: https://bugs.debian.org/607471
+Bug-Debian: https://bugs.debian.org/610851
+Bug-Debian: https://bugs.debian.org/627497
+Bug-Debian: https://bugs.debian.org/632212
+Bug-Debian: https://bugs.debian.org/637943
+Bug-Debian: https://bugs.debian.org/649448
+Bug-Debian: https://bugs.debian.org/697229
+Bug-Debian: https://bugs.debian.org/1053764
+Forwarded: no
+Last-Update: 2023-11-08
+
+radeon requires firmware/microcode for the GPU in all chips, but for
+newer chips (apparently R600 'Evergreen' onward) it also expects
+firmware for the memory controller and other sub-blocks.
+
+radeon attempts to gracefully fall back and disable some features if
+the firmware is not available, but becomes unstable - the framebuffer
+and/or system memory may be corrupted, or the display may stay black.
+
+Therefore, perform a basic check for the existence of
+/lib/firmware/radeon when a device is probed, and abort if it
+is missing, except for the pre-R600 case.
+
+Update 2023-11-08:
+In bug 1053764 Mario Limonciello <mario.limonciello@amd.com> states
+that the patch isn't needed anymore for amdgpu, so remove that part
+of the patch
+---
+ drivers/gpu/drm/radeon/radeon_drv.c | 30 +++++++++++++++++++++++++
+ 1 files changed, 30 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/radeon_drv.c
++++ b/drivers/gpu/drm/radeon/radeon_drv.c
+@@ -32,6 +32,8 @@
+
+ #include <linux/compat.h>
+ #include <linux/module.h>
++#include <linux/namei.h>
++#include <linux/path.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/vga_switcheroo.h>
+ #include <linux/mmu_notifier.h>
+@@ -255,6 +257,28 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
+
+ static const struct drm_driver kms_driver;
+
++/* Test that /lib/firmware/radeon is a directory (or symlink to a
++ * directory). We could try to match the udev search path, but let's
++ * keep it simple.
++ */
++static bool radeon_firmware_installed(void)
++{
++#if IS_BUILTIN(CONFIG_DRM_RADEON)
++ /* It may be too early to tell. Assume it's there. */
++ return true;
++#else
++ struct path path;
++
++ if (kern_path("/lib/firmware/radeon", LOOKUP_DIRECTORY | LOOKUP_FOLLOW,
++ &path) == 0) {
++ path_put(&path);
++ return true;
++ }
++
++ return false;
++#endif
++}
++
+ static int radeon_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+@@ -295,6 +319,12 @@ static int radeon_pci_probe(struct pci_d
+ if (vga_switcheroo_client_probe_defer(pdev))
+ return -EPROBE_DEFER;
+
++ if ((ent->driver_data & RADEON_FAMILY_MASK) >= CHIP_R600 &&
++ !radeon_firmware_installed()) {
++ DRM_ERROR("radeon kernel modesetting for R600 or later requires firmware installed\n");
++ return -ENODEV;
++ }
++
+ /* Get rid of things like offb */
+ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &kms_driver);
+ if (ret)
diff --git a/debian/patches/bugfix/all/tools-build-remove-bpf-run-time-check-at-build-time.patch b/debian/patches/bugfix/all/tools-build-remove-bpf-run-time-check-at-build-time.patch
new file mode 100644
index 0000000000..3818dbb172
--- /dev/null
+++ b/debian/patches/bugfix/all/tools-build-remove-bpf-run-time-check-at-build-time.patch
@@ -0,0 +1,27 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 21 Feb 2016 15:33:15 +0000
+Subject: tools/build: Remove bpf() run-time check at build time
+Forwarded: no
+
+It is not correct to test that a syscall works on the build system's
+kernel. We might be building on an earlier kernel version or with
+security restrictions that block bpf().
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/tools/build/feature/test-bpf.c
++++ b/tools/build/feature/test-bpf.c
+@@ -35,8 +35,10 @@ int main(void)
+ attr.prog_flags = 0;
+
+ /*
+- * Test existence of __NR_bpf and BPF_PROG_LOAD.
+- * This call should fail if we run the testcase.
++ * bwh: Don't use the bpf() syscall as we might be building on a
++ * much older kernel. Do "use" the attr structure here to avoid
++ * a "set but not used" warning.
+ */
+- return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
++ (void)&attr;
++ return 0;
+ }
diff --git a/debian/patches/bugfix/all/tools-perf-fix-missing-ldflags-for-some-programs.patch b/debian/patches/bugfix/all/tools-perf-fix-missing-ldflags-for-some-programs.patch
new file mode 100644
index 0000000000..2d8f29d25c
--- /dev/null
+++ b/debian/patches/bugfix/all/tools-perf-fix-missing-ldflags-for-some-programs.patch
@@ -0,0 +1,17 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Sat, 15 Jan 2022 22:59:11 +0100
+Subject: tools/perf: Fix missing LDFLAGS for some programs
+
+Signed-off-by: Ben Hutchings <benh@debian.org>
+---
+--- a/tools/perf/Makefile.perf
++++ b/tools/perf/Makefile.perf
+@@ -785,7 +785,7 @@ $(OUTPUT)dlfilters/%.o: dlfilters/%.c in
+ .SECONDARY: $(DLFILTERS:.so=.o)
+
+ $(OUTPUT)dlfilters/%.so: $(OUTPUT)dlfilters/%.o
+- $(QUIET_LINK)$(CC) $(EXTRA_CFLAGS) -shared -o $@ $<
++ $(QUIET_LINK)$(CC) $(EXTRA_CFLAGS) $(LDFLAGS) -shared -o $@ $<
+
+ ifndef NO_JVMTI
+ LIBJVMTI_IN := $(OUTPUT)jvmti/jvmti-in.o
diff --git a/debian/patches/bugfix/all/tools-perf-man-date.patch b/debian/patches/bugfix/all/tools-perf-man-date.patch
new file mode 100644
index 0000000000..1ba6488cad
--- /dev/null
+++ b/debian/patches/bugfix/all/tools-perf-man-date.patch
@@ -0,0 +1,44 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 13 Jul 2015 20:29:20 +0100
+Subject: perf tools: Use $KBUILD_BUILD_TIMESTAMP as man page date
+Forwarded: https://lore.kernel.org/all/20160517132809.GE7555@decadent.org.uk/
+
+This allows man pages to be built reproducibly.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ tools/perf/Documentation/Makefile | 3 +++
+ tools/perf/Documentation/asciidoc.conf | 3 +++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
+index adc5a7e44b98..2161b2e838b7 100644
+--- a/tools/perf/Documentation/Makefile
++++ b/tools/perf/Documentation/Makefile
+@@ -132,6 +132,9 @@ endif
+ ifdef DOCBOOK_SUPPRESS_SP
+ XMLTO_EXTRA += -m manpage-suppress-sp.xsl
+ endif
++ifdef KBUILD_BUILD_TIMESTAMP
++ASCIIDOC_EXTRA += -a revdate=$(shell date -u -d '$(KBUILD_BUILD_TIMESTAMP)' +%Y-%m-%d)
++endif
+
+ SHELL_PATH ?= $(SHELL)
+ # Shell quote;
+diff --git a/tools/perf/Documentation/asciidoc.conf b/tools/perf/Documentation/asciidoc.conf
+index 2b62ba1e72b7..82d3060177ba 100644
+--- a/tools/perf/Documentation/asciidoc.conf
++++ b/tools/perf/Documentation/asciidoc.conf
+@@ -71,6 +71,9 @@ ifdef::backend-docbook[]
+ [header]
+ template::[header-declarations]
+ <refentry>
++<refentryinfo>
++template::[docinfo]
++</refentryinfo>
+ ifdef::perf_date[]
+ <refentryinfo><date>{perf_date}</date></refentryinfo>
+ endif::perf_date[]
+--
+2.23.0
+
diff --git a/debian/patches/bugfix/all/tools-perf-remove-shebangs.patch b/debian/patches/bugfix/all/tools-perf-remove-shebangs.patch
new file mode 100644
index 0000000000..9766e0e4a5
--- /dev/null
+++ b/debian/patches/bugfix/all/tools-perf-remove-shebangs.patch
@@ -0,0 +1,39 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 25 Sep 2015 20:09:23 +0100
+Subject: tools/perf: Remove shebang lines from perf scripts
+Forwarded: no
+
+perf scripts need to be invoked through perf, not directly through
+perl (or other language interpreter). So including shebang lines in
+them is useless and possibly misleading.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/tools/perf/scripts/perl/rw-by-file.pl
++++ b/tools/perf/scripts/perl/rw-by-file.pl
+@@ -1,4 +1,3 @@
+-#!/usr/bin/perl -w
+ # SPDX-License-Identifier: GPL-2.0-only
+ # (c) 2009, Tom Zanussi <tzanussi@gmail.com>
+
+--- a/tools/perf/scripts/perl/rw-by-pid.pl
++++ b/tools/perf/scripts/perl/rw-by-pid.pl
+@@ -1,4 +1,3 @@
+-#!/usr/bin/perl -w
+ # SPDX-License-Identifier: GPL-2.0-only
+ # (c) 2009, Tom Zanussi <tzanussi@gmail.com>
+
+--- a/tools/perf/scripts/perl/rwtop.pl
++++ b/tools/perf/scripts/perl/rwtop.pl
+@@ -1,4 +1,3 @@
+-#!/usr/bin/perl -w
+ # SPDX-License-Identifier: GPL-2.0-only
+ # (c) 2010, Tom Zanussi <tzanussi@gmail.com>
+
+--- a/tools/perf/scripts/perl/wakeup-latency.pl
++++ b/tools/perf/scripts/perl/wakeup-latency.pl
+@@ -1,4 +1,3 @@
+-#!/usr/bin/perl -w
+ # SPDX-License-Identifier: GPL-2.0-only
+ # (c) 2009, Tom Zanussi <tzanussi@gmail.com>
+
diff --git a/debian/patches/bugfix/all/tools_lib_symbol_use_d_fortify_source_2_for_non_debug_builds.patch b/debian/patches/bugfix/all/tools_lib_symbol_use_d_fortify_source_2_for_non_debug_builds.patch
new file mode 100644
index 0000000000..9662520417
--- /dev/null
+++ b/debian/patches/bugfix/all/tools_lib_symbol_use_d_fortify_source_2_for_non_debug_builds.patch
@@ -0,0 +1,31 @@
+From: Uwe Kleine-König <ukleinek@debian.org>
+Subject: tools lib symbol: Use -D_FORTIFY_SOURCE=2 for non-debug builds
+Date: Mon, 24 Apr 2023 12:28:27 +0200
+Forwarded: https://lore.kernel.org/all/20230424102827.58707-1-ukleinek@debian.org/
+
+Commit 160be157eaba ("tool lib symbol: Add Makefile/Build") failed to
+define _FORTIFY_SOURCE to 2, probabaly this was cut&pasted from other
+Makefiles with the same problem.
+
+Fixes: 160be157eaba ("tool lib symbol: Add Makefile/Build")
+Signed-off-by: Uwe Kleine-König <ukleinek@debian.org>
+Acked-by: Ian Rogers <irogers@google.com>
+---
+ tools/lib/symbol/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lib/symbol/Makefile b/tools/lib/symbol/Makefile
+index 13d43c6f92b4..4a08cc4e19f2 100644
+--- a/tools/lib/symbol/Makefile
++++ b/tools/lib/symbol/Makefile
+@@ -39,7 +39,7 @@ endif
+ endif
+
+ ifeq ($(DEBUG),0)
+- CFLAGS += -D_FORTIFY_SOURCE
++ CFLAGS += -D_FORTIFY_SOURCE=2
+ endif
+
+ # Treat warnings as errors unless directed not to
+--
+2.39.2
diff --git a/debian/patches/bugfix/all/usbip-document-tcp-wrappers.patch b/debian/patches/bugfix/all/usbip-document-tcp-wrappers.patch
new file mode 100644
index 0000000000..d9d7b301dd
--- /dev/null
+++ b/debian/patches/bugfix/all/usbip-document-tcp-wrappers.patch
@@ -0,0 +1,29 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 24 Jun 2012 02:51:39 +0100
+Subject: usbip: Document TCP wrappers
+Forwarded: no
+
+Add references to TCP wrappers configuration in the manual page.
+
+--- a/tools/usb/usbip/doc/usbipd.8
++++ b/tools/usb/usbip/doc/usbipd.8
+@@ -14,7 +14,8 @@ Devices have to explicitly be exported u
+ before usbipd makes them available to other hosts.
+
+ The daemon accepts connections from USB/IP clients
+-on TCP port 3240 by default.
++on TCP port 3240 by default. The clients authorised to connect may be
++configured as documented in hosts_access(5).
+
+ .SH OPTIONS
+ .HP
+@@ -69,7 +70,8 @@ Show version.
+
+ .B usbipd
+ offers no authentication or authorization for USB/IP. Any
+-USB/IP client can connect and use exported devices.
++USB/IP client running on an authorised host can connect and
++use exported devices.
+
+ .SH EXAMPLES
+
diff --git a/debian/patches/bugfix/alpha/alpha-fix-missing-symbol-versions-for-str-n-cat-cpy.patch b/debian/patches/bugfix/alpha/alpha-fix-missing-symbol-versions-for-str-n-cat-cpy.patch
new file mode 100644
index 0000000000..3da69882e8
--- /dev/null
+++ b/debian/patches/bugfix/alpha/alpha-fix-missing-symbol-versions-for-str-n-cat-cpy.patch
@@ -0,0 +1,75 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 5 Jan 2023 17:04:40 +0100
+Subject: alpha: Fix missing symbol versions for str{,n}{cat,cpy}
+Origin: https://marc.info/?l=linux-alpha&m=167364720725291&w=2
+
+Now that modpost extracts symbol versions from *.cmd files, it can't
+find the versions for these 4 symbols. This is due to the way we link
+their objects together ahead of the full vmlinux link. genksyms puts
+their symbol CRCs in .str{,n}{cat,cpy}.o.cmd, but modpost only reads
+the .sty{,n}cpy.o.cmd files.
+
+Add assembly sources that bring the appropriate routines together with
+include directives instead of using the linker for this.
+
+Reported-by: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
+Fixes: f292d875d0dc ("modpost: extract symbol versions from *.cmd files")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/alpha/lib/Makefile | 14 --------------
+ arch/alpha/lib/stycpy.S | 8 ++++++++
+ arch/alpha/lib/styncpy.S | 8 ++++++++
+ 3 files changed, 16 insertions(+), 14 deletions(-)
+ create mode 100644 arch/alpha/lib/stycpy.S
+ create mode 100644 arch/alpha/lib/styncpy.S
+
+diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
+index 1cc74f7b50ef..8f1c32a25a40 100644
+--- a/arch/alpha/lib/Makefile
++++ b/arch/alpha/lib/Makefile
+@@ -45,17 +45,3 @@ AFLAGS___remlu.o = -DREM -DINTSIZE
+ $(addprefix $(obj)/,__divqu.o __remqu.o __divlu.o __remlu.o): \
+ $(src)/$(ev6-y)divide.S FORCE
+ $(call if_changed_rule,as_o_S)
+-
+-# There are direct branches between {str*cpy,str*cat} and stx*cpy.
+-# Ensure the branches are within range by merging these objects.
+-
+-LDFLAGS_stycpy.o := -r
+-LDFLAGS_styncpy.o := -r
+-
+-$(obj)/stycpy.o: $(obj)/strcpy.o $(obj)/$(ev67-y)strcat.o \
+- $(obj)/$(ev6-y)stxcpy.o FORCE
+- $(call if_changed,ld)
+-
+-$(obj)/styncpy.o: $(obj)/strncpy.o $(obj)/$(ev67-y)strncat.o \
+- $(obj)/$(ev6-y)stxncpy.o FORCE
+- $(call if_changed,ld)
+diff --git a/arch/alpha/lib/stycpy.S b/arch/alpha/lib/stycpy.S
+new file mode 100644
+index 000000000000..b4376834c91f
+--- /dev/null
++++ b/arch/alpha/lib/stycpy.S
+@@ -0,0 +1,8 @@
++#include "strcpy.S"
++#ifdef CONFIG_ALPHA_EV6
++#include "ev6-strcat.S"
++#include "ev6-stxcpy.S"
++#else
++#include "strcat.S"
++#include "stxcpy.S"
++#endif
+diff --git a/arch/alpha/lib/styncpy.S b/arch/alpha/lib/styncpy.S
+new file mode 100644
+index 000000000000..c393f816ff98
+--- /dev/null
++++ b/arch/alpha/lib/styncpy.S
+@@ -0,0 +1,8 @@
++#include "strncpy.S"
++#ifdef CONFIG_ALPHA_EV6
++#include "ev6-strncat.S"
++#include "ev6-stxncpy.S"
++#else
++#include "strncat.S"
++#include "stxncpy.S"
++#endif
diff --git a/debian/patches/bugfix/arm/arm-dts-kirkwood-fix-sata-pinmux-ing-for-ts419.patch b/debian/patches/bugfix/arm/arm-dts-kirkwood-fix-sata-pinmux-ing-for-ts419.patch
new file mode 100644
index 0000000000..52acb9fb56
--- /dev/null
+++ b/debian/patches/bugfix/arm/arm-dts-kirkwood-fix-sata-pinmux-ing-for-ts419.patch
@@ -0,0 +1,35 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 17 Feb 2017 01:30:30 +0000
+Subject: ARM: dts: kirkwood: Fix SATA pinmux-ing for TS419
+Forwarded: https://lore.kernel.org/all/20170218003251.GC4152@decadent.org.uk/
+Bug-Debian: https://bugs.debian.org/855017
+
+The old board code for the TS419 assigns MPP pins 15 and 16 as SATA
+activity signals (and none as SATA presence signals). Currently the
+device tree assigns the SoC's default pinmux groups for SATA, which
+conflict with the second Ethernet port.
+
+Reported-by: gmbh@gazeta.pl
+Tested-by: gmbh@gazeta.pl
+References: https://bugs.debian.org/855017
+Cc: stable@vger.kernel.org # 3.15+
+Fixes: 934b524b3f49 ("ARM: Kirkwood: Add DT description of QNAP 419")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi
++++ b/arch/arm/boot/dts/marvell/kirkwood-ts419.dtsi
+@@ -69,3 +69,11 @@
+ phy-handle = <&ethphy1>;
+ };
+ };
++
++&pmx_sata0 {
++ marvell,pins = "mpp15";
++};
++
++&pmx_sata1 {
++ marvell,pins = "mpp16";
++};
diff --git a/debian/patches/bugfix/arm/arm-mm-export-__sync_icache_dcache-for-xen-privcmd.patch b/debian/patches/bugfix/arm/arm-mm-export-__sync_icache_dcache-for-xen-privcmd.patch
new file mode 100644
index 0000000000..cd5b36fa17
--- /dev/null
+++ b/debian/patches/bugfix/arm/arm-mm-export-__sync_icache_dcache-for-xen-privcmd.patch
@@ -0,0 +1,31 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 11 Jul 2018 23:40:55 +0100
+Subject: ARM: mm: Export __sync_icache_dcache() for xen-privcmd
+Forwarded: https://lore.kernel.org/all/20180711225013.GF14131@decadent.org.uk/
+
+The xen-privcmd driver, which can be modular, calls set_pte_at()
+which in turn may call __sync_icache_dcache().
+
+The call to __sync_icache_dcache() may be optimised out because it is
+conditional on !pte_special(), and xen-privcmd calls pte_mkspecial().
+However, in a non-LPAE configuration there is no "special" bit and the
+call is really unconditional.
+
+Fixes: 3ad0876554ca ("xen/privcmd: add IOCTL_PRIVCMD_MMAP_RESOURCE")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/arm/mm/flush.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+Index: debian-kernel/arch/arm/mm/flush.c
+===================================================================
+--- debian-kernel.orig/arch/arm/mm/flush.c
++++ debian-kernel/arch/arm/mm/flush.c
+@@ -292,6 +292,7 @@ void __sync_icache_dcache(pte_t pteval)
+ if (pte_exec(pteval))
+ __flush_icache_all();
+ }
++EXPORT_SYMBOL_GPL(__sync_icache_dcache);
+ #endif
+
+ /*
diff --git a/debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch b/debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch
new file mode 100644
index 0000000000..7a866fdc35
--- /dev/null
+++ b/debian/patches/bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch
@@ -0,0 +1,92 @@
+From: Geoff Levand <geoff@infradead.org>
+Date: Wed, 13 Jun 2018 10:56:08 -0700
+Subject: arm64/acpi: Add fixup for HPE m400 quirks
+Forwarded: https://lore.kernel.org/all/51d3d738-cdf5-2992-bba5-c3e1f34096c2@infradead.org/
+
+Adds a new ACPI init routine acpi_fixup_m400_quirks that adds
+a work-around for HPE ProLiant m400 APEI firmware problems.
+
+The work-around disables APEI when CONFIG_ACPI_APEI is set and
+m400 firmware is detected. Without this fixup m400 systems
+experience errors like these on startup:
+
+ [Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+ [Hardware Error]: event severity: fatal
+ [Hardware Error]: Error 0, type: fatal
+ [Hardware Error]: section_type: memory error
+ [Hardware Error]: error_status: 0x0000000000001300
+ [Hardware Error]: error_type: 10, invalid address
+ Kernel panic - not syncing: Fatal hardware error!
+
+Signed-off-by: Geoff Levand <geoff@infradead.org>
+[bwh: Adjust context to apply to Linux 4.19]
+---
+ arch/arm64/kernel/acpi.c | 40 ++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 36 insertions(+), 4 deletions(-)
+
+Index: linux/arch/arm64/kernel/acpi.c
+===================================================================
+--- linux.orig/arch/arm64/kernel/acpi.c
++++ linux/arch/arm64/kernel/acpi.c
+@@ -32,6 +32,8 @@
+ #include <asm/daifflags.h>
+ #include <asm/smp_plat.h>
+
++#include <acpi/apei.h>
++
+ int acpi_noirq = 1; /* skip ACPI IRQ initialization */
+ int acpi_disabled = 1;
+ EXPORT_SYMBOL(acpi_disabled);
+@@ -178,6 +180,33 @@ out:
+ }
+
+ /*
++ * acpi_fixup_m400_quirks - Work-around for HPE ProLiant m400 APEI firmware
++ * problems.
++ */
++static void __init acpi_fixup_m400_quirks(void)
++{
++ acpi_status status;
++ struct acpi_table_header *header;
++#if !defined(CONFIG_ACPI_APEI)
++ int hest_disable = HEST_DISABLED;
++#endif
++
++ if (!IS_ENABLED(CONFIG_ACPI_APEI) || hest_disable != HEST_ENABLED)
++ return;
++
++ status = acpi_get_table(ACPI_SIG_HEST, 0, &header);
++
++ if (ACPI_SUCCESS(status) && !strncmp(header->oem_id, "HPE ", 6) &&
++ !strncmp(header->oem_table_id, "ProLiant", 8) &&
++ MIDR_IMPLEMENTOR(read_cpuid_id()) == ARM_CPU_IMP_APM) {
++ hest_disable = HEST_DISABLED;
++ pr_info("Disabled APEI for m400.\n");
++ }
++
++ acpi_put_table(header);
++}
++
++/*
+ * acpi_boot_table_init() called from setup_arch(), always.
+ * 1. find RSDP and get its address, and then find XSDT
+ * 2. extract all tables and checksums them all
+@@ -232,11 +261,14 @@ done:
+ if (acpi_disabled) {
+ if (earlycon_acpi_spcr_enable)
+ early_init_dt_scan_chosen_stdout();
+- } else {
+- acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
+- if (IS_ENABLED(CONFIG_ACPI_BGRT))
+- acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
++ return;
+ }
++
++ acpi_parse_spcr(earlycon_acpi_spcr_enable, true);
++ if (IS_ENABLED(CONFIG_ACPI_BGRT))
++ acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);
++
++ acpi_fixup_m400_quirks();
+ }
+
+ static pgprot_t __acpi_get_writethrough_mem_attribute(void)
diff --git a/debian/patches/bugfix/powerpc/fbdev-offb-Update-expected-device-name.patch b/debian/patches/bugfix/powerpc/fbdev-offb-Update-expected-device-name.patch
new file mode 100644
index 0000000000..d090356914
--- /dev/null
+++ b/debian/patches/bugfix/powerpc/fbdev-offb-Update-expected-device-name.patch
@@ -0,0 +1,46 @@
+From: Cyril Brulebois <cyril@debamax.com>
+Date: Wed, 12 Apr 2023 11:55:08 +0200
+Subject: fbdev/offb: Update expected device name
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git/commit?id=27c74ea74be805ccba1bc1a0a03cc79c51dca6ea
+
+Since commit 241d2fb56a18 ("of: Make OF framebuffer device names unique"),
+as spotted by Frédéric Bonnard, the historical "of-display" device is
+gone: the updated logic creates "of-display.0" instead, then as many
+"of-display.N" as required.
+
+This means that offb no longer finds the expected device, which prevents
+the Debian Installer from setting up its interface, at least on ppc64el.
+
+It might be better to iterate on all possible nodes, but updating the
+hardcoded device from "of-display" to "of-display.0" is confirmed to fix
+the Debian Installer at the very least.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=217328
+Link: https://bugs.debian.org/1033058
+Fixes: 241d2fb56a18 ("of: Make OF framebuffer device names unique")
+Cc: stable@vger.kernel.org
+Signed-off-by: Cyril Brulebois <cyril@debamax.com>
+Signed-off-by: Helge Deller <deller@gmx.de>
+---
+ drivers/video/fbdev/offb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c
+index 0065a77b6dbc8..b5fdef2b74359 100644
+--- a/drivers/video/fbdev/offb.c
++++ b/drivers/video/fbdev/offb.c
+@@ -696,7 +696,7 @@ MODULE_DEVICE_TABLE(of, offb_of_match_display);
+
+ static struct platform_driver offb_driver_display = {
+ .driver = {
+- .name = "of-display",
++ .name = "of-display.0",
+ .of_match_table = offb_of_match_display,
+ },
+ .probe = offb_probe_display,
+--
+2.30.2
+
diff --git a/debian/patches/bugfix/powerpc/powerpc-boot-fix-missing-crc32poly.h-when-building-with-kernel_xz.patch b/debian/patches/bugfix/powerpc/powerpc-boot-fix-missing-crc32poly.h-when-building-with-kernel_xz.patch
new file mode 100644
index 0000000000..a00a2a485c
--- /dev/null
+++ b/debian/patches/bugfix/powerpc/powerpc-boot-fix-missing-crc32poly.h-when-building-with-kernel_xz.patch
@@ -0,0 +1,39 @@
+From: Krzysztof Kozlowski <krzk@kernel.org>
+Date: Wed, 29 Aug 2018 09:32:23 +0200
+Subject: powerpc/boot: Fix missing crc32poly.h when building with KERNEL_XZ
+Origin: https://patchwork.ozlabs.org/patch/963258/
+
+After commit faa16bc404d7 ("lib: Use existing define with
+polynomial") the lib/xz/xz_crc32.c includes a header from include/linux
+directory thus any other user of this code should define proper include
+path.
+
+This fixes the build error on powerpc with CONFIG_KERNEL_XZ:
+
+ In file included from ../arch/powerpc/boot/../../../lib/decompress_unxz.c:233:0,
+ from ../arch/powerpc/boot/decompress.c:42:
+ ../arch/powerpc/boot/../../../lib/xz/xz_crc32.c:18:29: fatal error: linux/crc32poly.h: No such file or directory
+
+Reported-by: Michal Kubecek <mkubecek@suse.cz>
+Fixes: faa16bc404d7 ("lib: Use existing define with polynomial")
+Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
+Reported-by: kbuild test robot <lkp@intel.com>
+Reported-by: Meelis Roos <mroos@linux.ee>
+Tested-by: Michal Kubecek <mkubecek@suse.cz>
+---
+ arch/powerpc/boot/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: linux/arch/powerpc/boot/Makefile
+===================================================================
+--- linux.orig/arch/powerpc/boot/Makefile
++++ linux/arch/powerpc/boot/Makefile
+@@ -70,7 +70,7 @@ BOOTCFLAGS += -fno-stack-protector
+ endif
+
+ BOOTCFLAGS += -include $(srctree)/include/linux/compiler_attributes.h
+-BOOTCFLAGS += -I$(objtree)/$(obj) -I$(srctree)/$(obj)
++BOOTCFLAGS += -I$(objtree)/$(obj) -I$(srctree)/$(obj) -I$(srctree)/include
+
+ DTC_FLAGS ?= -p 1024
+
diff --git a/debian/patches/bugfix/sh/sh-boot-do-not-use-hyphen-in-exported-variable-name.patch b/debian/patches/bugfix/sh/sh-boot-do-not-use-hyphen-in-exported-variable-name.patch
new file mode 100644
index 0000000000..31eb2eb5d2
--- /dev/null
+++ b/debian/patches/bugfix/sh/sh-boot-do-not-use-hyphen-in-exported-variable-name.patch
@@ -0,0 +1,95 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 07 Feb 2022 00:00:26 +0100
+Subject: sh: Do not use hyphen in exported variable names
+
+arch/sh/Makefile defines and exports ld-bfd to be used by
+arch/sh/boot/Makefile and arch/sh/boot/compressed/Makefile. However
+some shells, including dash, will not pass through environment
+variables whose name includes a hyphen. Usually GNU make does not use
+a shell to recurse, but if e.g. $(srctree) contains '~' it will use a
+shell here.
+
+Rename the variable to ld_bfd.
+
+(Another instance of this problem was fixed upstream by commit
+82977af93a0d "sh: rename suffix-y to suffix_y".)
+
+References: https://buildd.debian.org/status/fetch.php?pkg=linux&arch=sh4&ver=4.13%7Erc5-1%7Eexp1&stamp=1502943967&raw=0
+Fixes: ef9b542fce00 ("sh: bzip2/lzma uImage support.")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/sh/Makefile | 10 +++++-----
+ arch/sh/boot/compressed/Makefile | 4 ++--
+ arch/sh/boot/romimage/Makefile | 4 ++--
+ 3 files changed, 9 insertions(+), 9 deletions(-)
+
+Index: linux/arch/sh/Makefile
+===================================================================
+--- linux.orig/arch/sh/Makefile
++++ linux/arch/sh/Makefile
+@@ -102,16 +102,16 @@ UTS_MACHINE := sh
+ LDFLAGS_vmlinux += -e _stext
+
+ ifdef CONFIG_CPU_LITTLE_ENDIAN
+-ld-bfd := elf32-sh-linux
+-LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld-bfd)
++ld_bfd := elf32-sh-linux
++LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld_bfd)
+ KBUILD_LDFLAGS += -EL
+ else
+-ld-bfd := elf32-shbig-linux
+-LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld-bfd)
++ld_bfd := elf32-shbig-linux
++LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld_bfd)
+ KBUILD_LDFLAGS += -EB
+ endif
+
+-export ld-bfd
++export ld_bfd
+
+ # Mach groups
+ machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se
+Index: linux/arch/sh/boot/compressed/Makefile
+===================================================================
+--- linux.orig/arch/sh/boot/compressed/Makefile
++++ linux/arch/sh/boot/compressed/Makefile
+@@ -36,7 +36,7 @@ endif
+
+ ccflags-remove-$(CONFIG_MCOUNT) += -pg
+
+-LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \
++LDFLAGS_vmlinux := --oformat $(ld_bfd) -Ttext $(IMAGE_OFFSET) -e startup \
+ -T $(obj)/../../kernel/vmlinux.lds
+
+ KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
+@@ -60,7 +60,7 @@ $(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.b
+
+ OBJCOPYFLAGS += -R .empty_zero_page
+
+-LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
++LDFLAGS_piggy.o := -r --format binary --oformat $(ld_bfd) -T
+
+ $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE
+ $(call if_changed,ld)
+Index: linux/arch/sh/boot/romimage/Makefile
+===================================================================
+--- linux.orig/arch/sh/boot/romimage/Makefile
++++ linux/arch/sh/boot/romimage/Makefile
+@@ -13,7 +13,7 @@ mmcif-obj-$(CONFIG_CPU_SUBTYPE_SH7724) :
+ load-$(CONFIG_ROMIMAGE_MMCIF) := $(mmcif-load-y)
+ obj-$(CONFIG_ROMIMAGE_MMCIF) := $(mmcif-obj-y)
+
+-LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(load-y) -e romstart \
++LDFLAGS_vmlinux := --oformat $(ld_bfd) -Ttext $(load-y) -e romstart \
+ -T $(obj)/../../kernel/vmlinux.lds
+
+ $(obj)/vmlinux: $(obj)/head.o $(obj-y) $(obj)/piggy.o FORCE
+@@ -24,7 +24,7 @@ OBJCOPYFLAGS += -j .empty_zero_page
+ $(obj)/zeropage.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+-LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T
++LDFLAGS_piggy.o := -r --format binary --oformat $(ld_bfd) -T
+
+ $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/zeropage.bin arch/sh/boot/zImage FORCE
+ $(call if_changed,ld)
diff --git a/debian/patches/bugfix/x86/perf-tools-fix-unwind-build-on-i386.patch b/debian/patches/bugfix/x86/perf-tools-fix-unwind-build-on-i386.patch
new file mode 100644
index 0000000000..f9baa7bd3c
--- /dev/null
+++ b/debian/patches/bugfix/x86/perf-tools-fix-unwind-build-on-i386.patch
@@ -0,0 +1,35 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 22 Jul 2017 17:37:33 +0100
+Subject: perf tools: Fix unwind build on i386
+Forwarded: no
+
+EINVAL may not be defined when building unwind-libunwind.c with
+REMOTE_UNWIND_LIBUNWIND, resulting in a compiler error in
+LIBUNWIND__ARCH_REG_ID(). Its only caller, access_reg(), only checks
+for a negative return value and doesn't care what it is. So change
+-EINVAL to -1.
+
+Fixes: 52ffe0ff02fc ("Support x86(32-bit) cross platform callchain unwind.")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+
+--- a/tools/perf/arch/x86/util/unwind-libunwind.c
++++ b/tools/perf/arch/x86/util/unwind-libunwind.c
+@@ -66,7 +66,7 @@ int LIBUNWIND__ARCH_REG_ID(int regnum)
+ break;
+ default:
+ pr_err("unwind: invalid reg id %d\n", regnum);
+- return -EINVAL;
++ return -1;
+ }
+
+ return id;
+@@ -106,7 +106,7 @@ int LIBUNWIND__ARCH_REG_ID(int regnum)
+ break;
+ default:
+ pr_err("unwind: invalid reg id %d\n", regnum);
+- return -EINVAL;
++ return -1;
+ }
+
+ return id;
diff --git a/debian/patches/bugfix/x86/revert-perf-build-fix-libunwind-feature-detection-on.patch b/debian/patches/bugfix/x86/revert-perf-build-fix-libunwind-feature-detection-on.patch
new file mode 100644
index 0000000000..cfbf98e824
--- /dev/null
+++ b/debian/patches/bugfix/x86/revert-perf-build-fix-libunwind-feature-detection-on.patch
@@ -0,0 +1,22 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 25 Sep 2015 22:50:50 +0100
+Subject: Revert "perf build: Fix libunwind feature detection on 32-bit x86"
+Forwarded: no
+
+This reverts commit 05b41775e2edd69a83f592e3534930c934d4038e.
+It broke feature detection that was working just fine for us.
+---
+ tools/perf/Makefile.config | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/perf/Makefile.config
++++ b/tools/perf/Makefile.config
+@@ -38,7 +38,7 @@ ifeq ($(SRCARCH),x86)
+ LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma
+ $(call detected,CONFIG_X86_64)
+ else
+- LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind
++ LIBUNWIND_LIBS = -lunwind -lunwind-x86
+ endif
+ NO_PERF_REGS := 0
+ endif
diff --git a/debian/patches/bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch b/debian/patches/bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch
new file mode 100644
index 0000000000..62b4eb7dec
--- /dev/null
+++ b/debian/patches/bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch
@@ -0,0 +1,34 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 20 Apr 2013 15:52:02 +0100
+Subject: viafb: Autoload on OLPC XO 1.5 only
+Bug-Debian: https://bugs.debian.org/705788
+Forwarded: no
+
+It appears that viafb won't work automatically on all the boards for
+which it has a PCI device ID match. Currently, it is blacklisted by
+udev along with most other framebuffer drivers, so this doesn't matter
+much.
+
+However, this driver is required for console support on the XO 1.5.
+We need to allow it to be autoloaded on this model only, and then
+un-blacklist it in udev.
+
+---
+--- a/drivers/video/fbdev/via/via-core.c
++++ b/drivers/video/fbdev/via/via-core.c
+@@ -695,7 +695,14 @@ static const struct pci_device_id via_pc
+ .driver_data = UNICHROME_VX900 },
+ { }
+ };
+-MODULE_DEVICE_TABLE(pci, via_pci_table);
++
++static const struct pci_device_id via_pci_autoload_table[] __initconst = {
++ /* OLPC XO 1.5 */
++ { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
++ .subvendor = 0x152d, .subdevice = 0x0833 },
++ { }
++};
++MODULE_DEVICE_TABLE(pci, via_pci_autoload_table);
+
+ static const struct dev_pm_ops via_pm_ops = {
+ #ifdef CONFIG_PM_SLEEP
diff --git a/debian/patches/debian/Revert-docs-kernel_feat.py-fix-potential-command-inj.patch b/debian/patches/debian/Revert-docs-kernel_feat.py-fix-potential-command-inj.patch
new file mode 100644
index 0000000000..7bfaf99b47
--- /dev/null
+++ b/debian/patches/debian/Revert-docs-kernel_feat.py-fix-potential-command-inj.patch
@@ -0,0 +1,295 @@
+From 4f86519c560fd00b2ab58721cf2943e07107437d Mon Sep 17 00:00:00 2001
+From: Salvatore Bonaccorso <carnil@debian.org>
+Date: Sun, 4 Feb 2024 21:02:11 +0100
+Subject: [PATCH 2/2] Revert "docs: kernel_feat.py: fix potential command
+ injection"
+
+This reverts commit e961f8c6966abbd486ff87549e29e53f3c69b685.
+---
+ Documentation/admin-guide/features.rst | 2 +-
+ Documentation/arch/arc/features.rst | 2 +-
+ Documentation/arch/arm/features.rst | 2 +-
+ Documentation/arch/arm64/features.rst | 2 +-
+ Documentation/arch/loongarch/features.rst | 2 +-
+ Documentation/arch/m68k/features.rst | 2 +-
+ Documentation/arch/mips/features.rst | 2 +-
+ Documentation/arch/nios2/features.rst | 2 +-
+ Documentation/arch/openrisc/features.rst | 2 +-
+ Documentation/arch/parisc/features.rst | 2 +-
+ Documentation/arch/s390/features.rst | 2 +-
+ Documentation/arch/sh/features.rst | 2 +-
+ Documentation/arch/sparc/features.rst | 2 +-
+ Documentation/arch/x86/features.rst | 2 +-
+ Documentation/arch/xtensa/features.rst | 2 +-
+ Documentation/powerpc/features.rst | 2 +-
+ Documentation/riscv/features.rst | 2 +-
+ Documentation/sphinx/kernel_feat.py | 55 +++++++++++++++----
+ .../zh_CN/arch/loongarch/features.rst | 2 +-
+ .../translations/zh_CN/arch/mips/features.rst | 2 +-
+ 20 files changed, 63 insertions(+), 30 deletions(-)
+
+diff --git a/Documentation/admin-guide/features.rst b/Documentation/admin-guide/features.rst
+index 7651eca38227..8c167082a84f 100644
+--- a/Documentation/admin-guide/features.rst
++++ b/Documentation/admin-guide/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features
++.. kernel-feat:: $srctree/Documentation/features
+diff --git a/Documentation/arch/arc/features.rst b/Documentation/arch/arc/features.rst
+index 49ff446ff744..b793583d688a 100644
+--- a/Documentation/arch/arc/features.rst
++++ b/Documentation/arch/arc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features arc
++.. kernel-feat:: $srctree/Documentation/features arc
+diff --git a/Documentation/arch/arm/features.rst b/Documentation/arch/arm/features.rst
+index 0e76aaf68eca..7414ec03dd15 100644
+--- a/Documentation/arch/arm/features.rst
++++ b/Documentation/arch/arm/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features arm
++.. kernel-feat:: $srctree/Documentation/features arm
+diff --git a/Documentation/arch/arm64/features.rst b/Documentation/arch/arm64/features.rst
+index 03321f4309d0..dfa4cb3cd3ef 100644
+--- a/Documentation/arch/arm64/features.rst
++++ b/Documentation/arch/arm64/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features arm64
++.. kernel-feat:: $srctree/Documentation/features arm64
+diff --git a/Documentation/arch/loongarch/features.rst b/Documentation/arch/loongarch/features.rst
+index 009f44c7951f..ebacade3ea45 100644
+--- a/Documentation/arch/loongarch/features.rst
++++ b/Documentation/arch/loongarch/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features loongarch
++.. kernel-feat:: $srctree/Documentation/features loongarch
+diff --git a/Documentation/arch/m68k/features.rst b/Documentation/arch/m68k/features.rst
+index de7f0ccf7fc8..5107a2119472 100644
+--- a/Documentation/arch/m68k/features.rst
++++ b/Documentation/arch/m68k/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features m68k
++.. kernel-feat:: $srctree/Documentation/features m68k
+diff --git a/Documentation/arch/mips/features.rst b/Documentation/arch/mips/features.rst
+index 6e0ffe3e7354..1973d729b29a 100644
+--- a/Documentation/arch/mips/features.rst
++++ b/Documentation/arch/mips/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features mips
++.. kernel-feat:: $srctree/Documentation/features mips
+diff --git a/Documentation/arch/nios2/features.rst b/Documentation/arch/nios2/features.rst
+index 89913810ccb5..8449e63f69b2 100644
+--- a/Documentation/arch/nios2/features.rst
++++ b/Documentation/arch/nios2/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features nios2
++.. kernel-feat:: $srctree/Documentation/features nios2
+diff --git a/Documentation/arch/openrisc/features.rst b/Documentation/arch/openrisc/features.rst
+index bae2e25adfd6..3f7c40d219f2 100644
+--- a/Documentation/arch/openrisc/features.rst
++++ b/Documentation/arch/openrisc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features openrisc
++.. kernel-feat:: $srctree/Documentation/features openrisc
+diff --git a/Documentation/arch/parisc/features.rst b/Documentation/arch/parisc/features.rst
+index b3aa4d243b93..501d7c450037 100644
+--- a/Documentation/arch/parisc/features.rst
++++ b/Documentation/arch/parisc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features parisc
++.. kernel-feat:: $srctree/Documentation/features parisc
+diff --git a/Documentation/arch/s390/features.rst b/Documentation/arch/s390/features.rst
+index 2883dc950681..57c296a9d8f3 100644
+--- a/Documentation/arch/s390/features.rst
++++ b/Documentation/arch/s390/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features s390
++.. kernel-feat:: $srctree/Documentation/features s390
+diff --git a/Documentation/arch/sh/features.rst b/Documentation/arch/sh/features.rst
+index fae48fe81e9b..f722af3b6c99 100644
+--- a/Documentation/arch/sh/features.rst
++++ b/Documentation/arch/sh/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features sh
++.. kernel-feat:: $srctree/Documentation/features sh
+diff --git a/Documentation/arch/sparc/features.rst b/Documentation/arch/sparc/features.rst
+index 96835b6d598a..c0c92468b0fe 100644
+--- a/Documentation/arch/sparc/features.rst
++++ b/Documentation/arch/sparc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features sparc
++.. kernel-feat:: $srctree/Documentation/features sparc
+diff --git a/Documentation/arch/x86/features.rst b/Documentation/arch/x86/features.rst
+index a33616346a38..b663f15053ce 100644
+--- a/Documentation/arch/x86/features.rst
++++ b/Documentation/arch/x86/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features x86
++.. kernel-feat:: $srctree/Documentation/features x86
+diff --git a/Documentation/arch/xtensa/features.rst b/Documentation/arch/xtensa/features.rst
+index 28dcce1759be..6b92c7bfa19d 100644
+--- a/Documentation/arch/xtensa/features.rst
++++ b/Documentation/arch/xtensa/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features xtensa
++.. kernel-feat:: $srctree/Documentation/features xtensa
+diff --git a/Documentation/powerpc/features.rst b/Documentation/powerpc/features.rst
+index ee4b95e04202..aeae73df86b0 100644
+--- a/Documentation/powerpc/features.rst
++++ b/Documentation/powerpc/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features powerpc
++.. kernel-feat:: $srctree/Documentation/features powerpc
+diff --git a/Documentation/riscv/features.rst b/Documentation/riscv/features.rst
+index 36e90144adab..c70ef6ac2368 100644
+--- a/Documentation/riscv/features.rst
++++ b/Documentation/riscv/features.rst
+@@ -1,3 +1,3 @@
+ .. SPDX-License-Identifier: GPL-2.0
+
+-.. kernel-feat:: features riscv
++.. kernel-feat:: $srctree/Documentation/features riscv
+diff --git a/Documentation/sphinx/kernel_feat.py b/Documentation/sphinx/kernel_feat.py
+index bdfaa3e4b202..27b701ed3681 100644
+--- a/Documentation/sphinx/kernel_feat.py
++++ b/Documentation/sphinx/kernel_feat.py
+@@ -37,6 +37,8 @@ import re
+ import subprocess
+ import sys
+
++from os import path
++
+ from docutils import nodes, statemachine
+ from docutils.statemachine import ViewList
+ from docutils.parsers.rst import directives, Directive
+@@ -74,26 +76,33 @@ class KernelFeat(Directive):
+ self.state.document.settings.env.app.warn(message, prefix="")
+
+ def run(self):
++
+ doc = self.state.document
+ if not doc.settings.file_insertion_enabled:
+ raise self.warning("docutils: file insertion disabled")
+
+ env = doc.settings.env
++ cwd = path.dirname(doc.current_source)
++ cmd = "get_feat.pl rest --enable-fname --dir "
++ cmd += self.arguments[0]
++
++ if len(self.arguments) > 1:
++ cmd += " --arch " + self.arguments[1]
+
+- srctree = os.path.abspath(os.environ["srctree"])
++ srctree = path.abspath(os.environ["srctree"])
+
+- args = [
+- os.path.join(srctree, 'scripts/get_feat.pl'),
+- 'rest',
+- '--enable-fname',
+- '--dir',
+- os.path.join(srctree, 'Documentation', self.arguments[0]),
+- ]
++ fname = cmd
+
+- if len(self.arguments) > 1:
+- args.extend(['--arch', self.arguments[1]])
++ # extend PATH with $(srctree)/scripts
++ path_env = os.pathsep.join([
++ srctree + os.sep + "scripts",
++ os.environ["PATH"]
++ ])
++ shell_env = os.environ.copy()
++ shell_env["PATH"] = path_env
++ shell_env["srctree"] = srctree
+
+- lines = subprocess.check_output(args, cwd=os.path.dirname(doc.current_source)).decode('utf-8')
++ lines = self.runCmd(cmd, shell=True, cwd=cwd, env=shell_env)
+
+ line_regex = re.compile("^\.\. FILE (\S+)$")
+
+@@ -112,6 +121,30 @@ class KernelFeat(Directive):
+ nodeList = self.nestedParse(out_lines, fname)
+ return nodeList
+
++ def runCmd(self, cmd, **kwargs):
++ u"""Run command ``cmd`` and return its stdout as unicode."""
++
++ try:
++ proc = subprocess.Popen(
++ cmd
++ , stdout = subprocess.PIPE
++ , stderr = subprocess.PIPE
++ , **kwargs
++ )
++ out, err = proc.communicate()
++
++ out, err = codecs.decode(out, 'utf-8'), codecs.decode(err, 'utf-8')
++
++ if proc.returncode != 0:
++ raise self.severe(
++ u"command '%s' failed with return code %d"
++ % (cmd, proc.returncode)
++ )
++ except OSError as exc:
++ raise self.severe(u"problems with '%s' directive: %s."
++ % (self.name, ErrorString(exc)))
++ return out
++
+ def nestedParse(self, lines, fname):
+ content = ViewList()
+ node = nodes.section()
+diff --git a/Documentation/translations/zh_CN/arch/loongarch/features.rst b/Documentation/translations/zh_CN/arch/loongarch/features.rst
+index cec38dda8298..82bfac180bdc 100644
+--- a/Documentation/translations/zh_CN/arch/loongarch/features.rst
++++ b/Documentation/translations/zh_CN/arch/loongarch/features.rst
+@@ -5,4 +5,4 @@
+ :Original: Documentation/arch/loongarch/features.rst
+ :Translator: Huacai Chen <chenhuacai@loongson.cn>
+
+-.. kernel-feat:: features loongarch
++.. kernel-feat:: $srctree/Documentation/features loongarch
+diff --git a/Documentation/translations/zh_CN/arch/mips/features.rst b/Documentation/translations/zh_CN/arch/mips/features.rst
+index 0d6df97db069..da1b956e4a40 100644
+--- a/Documentation/translations/zh_CN/arch/mips/features.rst
++++ b/Documentation/translations/zh_CN/arch/mips/features.rst
+@@ -10,4 +10,4 @@
+
+ .. _cn_features:
+
+-.. kernel-feat:: features mips
++.. kernel-feat:: $srctree/Documentation/features mips
+--
+2.43.0
+
diff --git a/debian/patches/debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch b/debian/patches/debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch
new file mode 100644
index 0000000000..205510d6bf
--- /dev/null
+++ b/debian/patches/debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch
@@ -0,0 +1,101 @@
+From: Serge Hallyn <serge.hallyn@canonical.com>
+Date: Fri, 31 May 2013 19:12:12 +0000 (+0100)
+Subject: add sysctl to disallow unprivileged CLONE_NEWUSER by default
+Origin: http://kernel.ubuntu.com/git?p=serge%2Fubuntu-saucy.git;a=commit;h=5c847404dcb2e3195ad0057877e1422ae90892b8
+
+add sysctl to disallow unprivileged CLONE_NEWUSER by default
+
+This is a short-term patch. Unprivileged use of CLONE_NEWUSER
+is certainly an intended feature of user namespaces. However
+for at least saucy we want to make sure that, if any security
+issues are found, we have a fail-safe.
+
+Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
+[bwh: Remove unneeded binary sysctl bits]
+[bwh: Keep this sysctl, but change the default to enabled]
+---
+Index: linux/kernel/fork.c
+===================================================================
+--- linux.orig/kernel/fork.c
++++ linux/kernel/fork.c
+@@ -108,6 +108,11 @@
+
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/task.h>
++#ifdef CONFIG_USER_NS
++extern int unprivileged_userns_clone;
++#else
++#define unprivileged_userns_clone 0
++#endif
+
+ /*
+ * Minimum number of threads to boot the kernel
+@@ -2008,6 +2013,10 @@ static __latent_entropy struct task_stru
+ if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
+ return ERR_PTR(-EINVAL);
+
++ if ((clone_flags & CLONE_NEWUSER) && !unprivileged_userns_clone)
++ if (!capable(CAP_SYS_ADMIN))
++ return ERR_PTR(-EPERM);
++
+ /*
+ * Thread groups must share signals as well, and detached threads
+ * can only be started up within the thread group.
+@@ -3166,6 +3175,12 @@ int ksys_unshare(unsigned long unshare_f
+ if (unshare_flags & CLONE_NEWNS)
+ unshare_flags |= CLONE_FS;
+
++ if ((unshare_flags & CLONE_NEWUSER) && !unprivileged_userns_clone) {
++ err = -EPERM;
++ if (!capable(CAP_SYS_ADMIN))
++ goto bad_unshare_out;
++ }
++
+ err = check_unshare_flags(unshare_flags);
+ if (err)
+ goto bad_unshare_out;
+Index: linux/kernel/sysctl.c
+===================================================================
+--- linux.orig/kernel/sysctl.c
++++ linux/kernel/sysctl.c
+@@ -136,6 +136,10 @@ static enum sysctl_writes_mode sysctl_wr
+ int sysctl_legacy_va_layout;
+ #endif
+
++#ifdef CONFIG_USER_NS
++extern int unprivileged_userns_clone;
++#endif
++
+ #endif /* CONFIG_SYSCTL */
+
+ /*
+@@ -1659,6 +1663,15 @@ static struct ctl_table kern_table[] = {
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
++#ifdef CONFIG_USER_NS
++ {
++ .procname = "unprivileged_userns_clone",
++ .data = &unprivileged_userns_clone,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec,
++ },
++#endif
+ #ifdef CONFIG_PROC_SYSCTL
+ {
+ .procname = "tainted",
+Index: linux/kernel/user_namespace.c
+===================================================================
+--- linux.orig/kernel/user_namespace.c
++++ linux/kernel/user_namespace.c
+@@ -22,6 +22,9 @@
+ #include <linux/bsearch.h>
+ #include <linux/sort.h>
+
++/* sysctl */
++int unprivileged_userns_clone = 1;
++
+ static struct kmem_cache *user_ns_cachep __read_mostly;
+ static DEFINE_MUTEX(userns_state_mutex);
+
diff --git a/debian/patches/debian/af_802154-Disable-auto-loading-as-mitigation-against.patch b/debian/patches/debian/af_802154-Disable-auto-loading-as-mitigation-against.patch
new file mode 100644
index 0000000000..3b33f845ab
--- /dev/null
+++ b/debian/patches/debian/af_802154-Disable-auto-loading-as-mitigation-against.patch
@@ -0,0 +1,29 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 19 Nov 2010 02:12:48 +0000
+Subject: [PATCH 2/3] af_802154: Disable auto-loading as mitigation against local exploits
+Forwarded: not-needed
+
+Recent review has revealed several bugs in obscure protocol
+implementations that can be exploited by local users for denial of
+service or privilege escalation. We can mitigate the effect of any
+remaining vulnerabilities in such protocols by preventing unprivileged
+users from loading the modules, so that they are only exploitable on
+systems where the administrator has chosen to load the protocol.
+
+The 'af_802154' (IEEE 802.15.4) protocol is not widely used, was
+not present in the 'lenny' kernel, and seems to receive only sporadic
+maintenance. Therefore disable auto-loading.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ net/ieee802154/socket.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+--- a/net/ieee802154/socket.c
++++ b/net/ieee802154/socket.c
+@@ -1122,4 +1122,4 @@ module_init(af_ieee802154_init);
+ module_exit(af_ieee802154_remove);
+
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_NETPROTO(PF_IEEE802154);
++/* MODULE_ALIAS_NETPROTO(PF_IEEE802154); */
diff --git a/debian/patches/debian/android-enable-building-ashmem-and-binder-as-modules.patch b/debian/patches/debian/android-enable-building-ashmem-and-binder-as-modules.patch
new file mode 100644
index 0000000000..8a565c6c0d
--- /dev/null
+++ b/debian/patches/debian/android-enable-building-ashmem-and-binder-as-modules.patch
@@ -0,0 +1,62 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 22 Jun 2018 17:27:00 +0100
+Subject: android: Enable building ashmem and binder as modules
+Bug-Debian: https://bugs.debian.org/901492
+
+We want to enable use of the Android ashmem and binder drivers to
+support Anbox, but they should not be built-in as that would waste
+resources and increase security attack surface on systems that don't
+need them.
+
+- Add a MODULE_LICENSE declaration to ashmem
+- Change the Makefiles to build each driver as an object with the
+ "_linux" suffix (which is what Anbox expects)
+- Change config symbol types to tristate
+
+Update:
+In upstream commit 721412ed3d titled "staging: remove ashmem" the ashmem
+driver was removed entirely. Secondary commit message:
+"The mainline replacement for ashmem is memfd, so remove the legacy
+code from drivers/staging/"
+Consequently, the ashmem part of this patch has been removed.
+---
+ drivers/android/Kconfig | 2 +-
+ drivers/android/Makefile | 7 ++++---
+ drivers/android/binder_alloc.c | 2 +-
+ 3 files changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/android/Kconfig
++++ b/drivers/android/Kconfig
+@@ -2,7 +2,7 @@
+ menu "Android"
+
+ config ANDROID_BINDER_IPC
+- bool "Android Binder IPC Driver"
++ tristate "Android Binder IPC Driver"
+ depends on MMU
+ default n
+ help
+--- a/drivers/android/Makefile
++++ b/drivers/android/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ ccflags-y += -I$(src) # needed for trace events
+
+-obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
+-obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o
+-obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
++obj-$(CONFIG_ANDROID_BINDER_IPC) += binder_linux.o
++binder_linux-y := binder.o binder_alloc.o
++binder_linux-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
++binder_linux-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+--- a/drivers/android/binder_alloc.c
++++ b/drivers/android/binder_alloc.c
+@@ -38,7 +38,7 @@ enum {
+ };
+ static uint32_t binder_alloc_debug_mask = BINDER_DEBUG_USER_ERROR;
+
+-module_param_named(debug_mask, binder_alloc_debug_mask,
++module_param_named(alloc_debug_mask, binder_alloc_debug_mask,
+ uint, 0644);
+
+ #define binder_alloc_debug(mask, x...) \
diff --git a/debian/patches/debian/arch-sh4-fix-uimage-build.patch b/debian/patches/debian/arch-sh4-fix-uimage-build.patch
new file mode 100644
index 0000000000..89e626b6b8
--- /dev/null
+++ b/debian/patches/debian/arch-sh4-fix-uimage-build.patch
@@ -0,0 +1,26 @@
+From: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+Subject: [sh4] Fix uImage build
+Bug-Debian: https://bugs.debian.org/569034
+Forwarded: not-needed
+
+[bwh: This was added without a description, but I think it is done
+ only to avoid a build-dependency on u-boot-tools.]
+---
+ arch/sh/Makefile | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/arch/sh/Makefile b/arch/sh/Makefile
+index da9cf952f33c..974bbd9dcfcf 100644
+--- a/arch/sh/Makefile
++++ b/arch/sh/Makefile
+@@ -85,7 +85,6 @@ OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment \
+
+ # Give the various platforms the opportunity to set default image types
+ defaultimage-y := zImage
+-defaultimage-$(CONFIG_SH_SH7785LCR) := uImage
+ defaultimage-$(CONFIG_SH_RSK) := uImage
+ defaultimage-$(CONFIG_SH_URQUELL) := uImage
+ defaultimage-$(CONFIG_SH_MIGOR) := uImage
+--
+2.27.0
+
diff --git a/debian/patches/debian/btrfs-warn-about-raid5-6-being-experimental-at-mount.patch b/debian/patches/debian/btrfs-warn-about-raid5-6-being-experimental-at-mount.patch
new file mode 100644
index 0000000000..abc4cc2bd0
--- /dev/null
+++ b/debian/patches/debian/btrfs-warn-about-raid5-6-being-experimental-at-mount.patch
@@ -0,0 +1,37 @@
+From: Adam Borowski <kilobyte@angband.pl>
+Date: Tue, 28 Mar 2017 16:55:05 +0200
+Subject: btrfs: warn about RAID5/6 being experimental at mount time
+Bug-Debian: https://bugs.debian.org/863290
+Origin: https://bugs.debian.org/863290#5
+
+Too many people come complaining about losing their data -- and indeed,
+there's no warning outside a wiki and the mailing list tribal knowledge.
+Message severity chosen for consistency with XFS -- "alert" makes dmesg
+produce nice red background which should get the point across.
+
+Signed-off-by: Adam Borowski <kilobyte@angband.pl>
+[bwh: Also add_taint() so this is flagged in bug reports]
+[2023-01-10: still accurate according to btrfs-progs own manpage:
+https://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git/commit/?id=922797e15590b836e377d6dc47b828356cafc2a9]
+---
+ fs/btrfs/disk-io.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -3832,6 +3832,15 @@ int __cold open_ctree(struct super_block *sb,
+ btrfs_set_and_info(fs_info, SSD, "enabling ssd optimizations");
+ }
+
++ if ((fs_info->avail_data_alloc_bits |
++ fs_info->avail_metadata_alloc_bits |
++ fs_info->avail_system_alloc_bits) &
++ BTRFS_BLOCK_GROUP_RAID56_MASK) {
++ btrfs_alert(fs_info,
++ "btrfs RAID5/6 is EXPERIMENTAL and has known data-loss bugs");
++ add_taint(TAINT_AUX, LOCKDEP_STILL_OK);
++ }
++
+ /*
+ * For devices supporting discard turn on discard=async automatically,
+ * unless it's already set or disabled. This could be turned off by
diff --git a/debian/patches/debian/cdc_ncm-cdc_mbim-use-ncm-by-default.patch b/debian/patches/debian/cdc_ncm-cdc_mbim-use-ncm-by-default.patch
new file mode 100644
index 0000000000..70b4468601
--- /dev/null
+++ b/debian/patches/debian/cdc_ncm-cdc_mbim-use-ncm-by-default.patch
@@ -0,0 +1,27 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: cdc_ncm,cdc_mbim: Use NCM by default
+Date: Sun, 31 Mar 2013 03:58:04 +0100
+Forwarded: not-needed
+
+Devices that support both NCM and MBIM modes should be kept in NCM
+mode unless there is userland support for MBIM.
+
+Set the default value of cdc_ncm.prefer_mbim to false and leave it to
+userland (modem-manager) to override this with a modprobe.conf file
+once it's ready to speak MBIM.
+
+---
+--- a/drivers/net/usb/cdc_ncm.c
++++ b/drivers/net/usb/cdc_ncm.c
+@@ -53,11 +53,7 @@
+ #include <linux/usb/cdc.h>
+ #include <linux/usb/cdc_ncm.h>
+
+-#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+-static bool prefer_mbim = true;
+-#else
+ static bool prefer_mbim;
+-#endif
+ module_param(prefer_mbim, bool, 0644);
+ MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions");
+
diff --git a/debian/patches/debian/dccp-disable-auto-loading-as-mitigation-against-local-exploits.patch b/debian/patches/debian/dccp-disable-auto-loading-as-mitigation-against-local-exploits.patch
new file mode 100644
index 0000000000..83583184e4
--- /dev/null
+++ b/debian/patches/debian/dccp-disable-auto-loading-as-mitigation-against-local-exploits.patch
@@ -0,0 +1,41 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 16 Feb 2017 19:09:17 +0000
+Subject: dccp: Disable auto-loading as mitigation against local exploits
+Forwarded: not-needed
+
+We can mitigate the effect of vulnerabilities in obscure protocols by
+preventing unprivileged users from loading the modules, so that they
+are only exploitable on systems where the administrator has chosen to
+load the protocol.
+
+The 'dccp' protocol is not actively maintained or widely used.
+Therefore disable auto-loading.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/net/dccp/ipv4.c
++++ b/net/dccp/ipv4.c
+@@ -1071,8 +1071,8 @@ module_exit(dccp_v4_exit);
+ * values directly, Also cover the case where the protocol is not specified,
+ * i.e. net-pf-PF_INET-proto-0-type-SOCK_DCCP
+ */
+-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6);
+-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6);
++/* MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 33, 6); */
++/* MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 0, 6); */
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
+ MODULE_DESCRIPTION("DCCP - Datagram Congestion Controlled Protocol");
+--- a/net/dccp/ipv6.c
++++ b/net/dccp/ipv6.c
+@@ -1125,8 +1125,8 @@ module_exit(dccp_v6_exit);
+ * values directly, Also cover the case where the protocol is not specified,
+ * i.e. net-pf-PF_INET6-proto-0-type-SOCK_DCCP
+ */
+-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6);
+-MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6);
++/* MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 33, 6); */
++/* MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 0, 6); */
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Arnaldo Carvalho de Melo <acme@mandriva.com>");
+ MODULE_DESCRIPTION("DCCPv6 - Datagram Congestion Controlled Protocol");
diff --git a/debian/patches/debian/dfsg/arch-powerpc-platforms-8xx-ucode-disable.patch b/debian/patches/debian/dfsg/arch-powerpc-platforms-8xx-ucode-disable.patch
new file mode 100644
index 0000000000..0e5176908a
--- /dev/null
+++ b/debian/patches/debian/dfsg/arch-powerpc-platforms-8xx-ucode-disable.patch
@@ -0,0 +1,29 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 13 Apr 2009 17:34:00 +0100
+Subject: Remove microcode patches for mgsuvd (not enabled in Debian configs)
+Forwarded: not-needed
+
+diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
+index 48a920a..81570b6 100644
+--- a/arch/powerpc/platforms/8xx/Kconfig
++++ b/arch/powerpc/platforms/8xx/Kconfig
+@@ -160,16 +160,19 @@ config NO_UCODE_PATCH
+
+ config USB_SOF_UCODE_PATCH
+ bool "USB SOF patch"
++ depends on BROKEN
+ help
+ Help not implemented yet, coming soon.
+
+ config I2C_SPI_UCODE_PATCH
+ bool "I2C/SPI relocation patch"
++ depends on BROKEN
+ help
+ Help not implemented yet, coming soon.
+
+ config I2C_SPI_SMC1_UCODE_PATCH
+ bool "I2C/SPI/SMC1 relocation patch"
++ depends on BROKEN
+ help
+ Help not implemented yet, coming soon.
+
diff --git a/debian/patches/debian/dfsg/documentation-fix-broken-link-to-cipso-draft.patch b/debian/patches/debian/dfsg/documentation-fix-broken-link-to-cipso-draft.patch
new file mode 100644
index 0000000000..840cf24d72
--- /dev/null
+++ b/debian/patches/debian/dfsg/documentation-fix-broken-link-to-cipso-draft.patch
@@ -0,0 +1,18 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 24 Aug 2019 19:00:41 +0100
+Subject: Documentation: Fix broken link to CIPSO draft
+Forwarded: not-needed
+
+We exclude the CIPSO draft text as its licence is not DFSG compliant.
+Link to the IETF's online version instead.
+
+---
+--- a/Documentation/netlabel/draft_ietf.rst
++++ b/Documentation/netlabel/draft_ietf.rst
+@@ -1,5 +1,4 @@
+ Draft IETF CIPSO IP Security
+ ----------------------------
+
+- .. include:: draft-ietf-cipso-ipsecurity-01.txt
+- :literal:
++https://tools.ietf.org/html/draft-ietf-cipso-ipsecurity-01
diff --git a/debian/patches/debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch b/debian/patches/debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch
new file mode 100644
index 0000000000..4e42da9a9b
--- /dev/null
+++ b/debian/patches/debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch
@@ -0,0 +1,15 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 17 Aug 2009 02:45:41 +0100
+Subject: dvb-usb-af9005: mark as broken
+Forwarded: not-needed
+
+--- a/drivers/media/usb/dvb-usb/Kconfig
++++ b/drivers/media/usb/dvb-usb/Kconfig
+@@ -227,6 +227,7 @@ config DVB_USB_OPERA1
+
+ config DVB_USB_AF9005
+ tristate "Afatech AF9005 DVB-T USB1.1 support"
++ depends on BROKEN
+ depends on DVB_USB
+ select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/debian/patches/debian/dfsg/drivers-net-appletalk-cops.patch b/debian/patches/debian/dfsg/drivers-net-appletalk-cops.patch
new file mode 100644
index 0000000000..3bf7ca6b33
--- /dev/null
+++ b/debian/patches/debian/dfsg/drivers-net-appletalk-cops.patch
@@ -0,0 +1,55 @@
+From: Frederik Schüler <fs@debian.org>
+Date: Fri, 05 Jan 2007 15:55:24 +0000
+Subject: Add removal patches for: 3c359, smctr, keyspan, cops
+Forwarded: not-needed
+
+---
+ drivers/net/appletalk/Kconfig | 26 --------------------------
+ drivers/net/appletalk/Makefile | 1 -
+ 2 files changed, 27 deletions(-)
+
+--- a/drivers/net/appletalk/Kconfig
++++ b/drivers/net/appletalk/Kconfig
+@@ -39,35 +39,6 @@ config DEV_APPLETALK
+ connect to the AppleTalk network, say Y.
+
+
+-config COPS
+- tristate "COPS LocalTalk PC support"
+- depends on DEV_APPLETALK && ISA
+- depends on NETDEVICES
+- select NETDEV_LEGACY_INIT
+- help
+- This allows you to use COPS AppleTalk cards to connect to LocalTalk
+- networks. You also need version 1.3.3 or later of the netatalk
+- package. This driver is experimental, which means that it may not
+- work. This driver will only work if you choose "AppleTalk DDP"
+- networking support, above.
+- Please read the file
+- <file:Documentation/networking/device_drivers/appletalk/cops.rst>.
+-
+-config COPS_DAYNA
+- bool "Dayna firmware support"
+- depends on COPS
+- help
+- Support COPS compatible cards with Dayna style firmware (Dayna
+- DL2000/ Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC
+- III, Farallon PhoneNET PC II).
+-
+-config COPS_TANGENT
+- bool "Tangent firmware support"
+- depends on COPS
+- help
+- Support COPS compatible cards with Tangent style firmware (Tangent
+- ATB_II, Novell NL-1000, Daystar Digital LT-200.
+-
+ config IPDDP
+ tristate "Appletalk-IP driver support"
+ depends on DEV_APPLETALK && ATALK
+--- a/drivers/net/appletalk/Makefile
++++ b/drivers/net/appletalk/Makefile
+@@ -4,4 +4,3 @@
+ #
+
+ obj-$(CONFIG_IPDDP) += ipddp.o
+-obj-$(CONFIG_COPS) += cops.o
diff --git a/debian/patches/debian/dfsg/video-remove-nvidiafb-and-rivafb.patch b/debian/patches/debian/dfsg/video-remove-nvidiafb-and-rivafb.patch
new file mode 100644
index 0000000000..cbef215c16
--- /dev/null
+++ b/debian/patches/debian/dfsg/video-remove-nvidiafb-and-rivafb.patch
@@ -0,0 +1,130 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 2 Jun 2012 19:53:38 +0100
+Subject: video: Remove nvidiafb and rivafb
+Bug-Debian: https://bugs.debian.org/383481
+Forwarded: no
+
+These drivers contain register programming code provided by the
+hardware vendor that appears to have been deliberately obfuscated.
+This is arguably not the preferred form for modification.
+
+These drivers are also largely redundant with nouveau. The RIVA 128
+(NV3) is not supported by nouveau but is about 15 years old and
+probably discontinued 10 years ago.
+
+---
+--- a/drivers/video/fbdev/Kconfig
++++ b/drivers/video/fbdev/Kconfig
+@@ -882,101 +882,6 @@ config FB_ATMEL
+ help
+ This enables support for the AT91 LCD Controller.
+
+-config FB_NVIDIA
+- tristate "nVidia Framebuffer Support"
+- depends on FB && PCI
+- select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
+- select FB_MODE_HELPERS
+- select FB_CFB_FILLRECT
+- select FB_CFB_COPYAREA
+- select FB_CFB_IMAGEBLIT
+- select BITREVERSE
+- select VGASTATE
+- select VIDEO_NOMODESET
+- help
+- This driver supports graphics boards with the nVidia chips, TNT
+- and newer. For very old chipsets, such as the RIVA128, then use
+- the rivafb.
+- Say Y if you have such a graphics board.
+-
+- To compile this driver as a module, choose M here: the
+- module will be called nvidiafb.
+-
+-config FB_NVIDIA_I2C
+- bool "Enable DDC Support"
+- depends on FB_NVIDIA
+- select FB_DDC
+- help
+- This enables I2C support for nVidia Chipsets. This is used
+- only for getting EDID information from the attached display
+- allowing for robust video mode handling and switching.
+-
+- Because fbdev-2.6 requires that drivers must be able to
+- independently validate video mode parameters, you should say Y
+- here.
+-
+-config FB_NVIDIA_DEBUG
+- bool "Lots of debug output"
+- depends on FB_NVIDIA
+- help
+- Say Y here if you want the nVidia driver to output all sorts
+- of debugging information to provide to the maintainer when
+- something goes wrong.
+-
+-config FB_NVIDIA_BACKLIGHT
+- bool "Support for backlight control"
+- depends on FB_NVIDIA
+- default y
+- help
+- Say Y here if you want to control the backlight of your display.
+-
+-config FB_RIVA
+- tristate "nVidia Riva support"
+- depends on FB && PCI
+- select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
+- select FB_MODE_HELPERS
+- select FB_CFB_FILLRECT
+- select FB_CFB_COPYAREA
+- select FB_CFB_IMAGEBLIT
+- select BITREVERSE
+- select VGASTATE
+- select VIDEO_NOMODESET
+- help
+- This driver supports graphics boards with the nVidia Riva/Geforce
+- chips.
+- Say Y if you have such a graphics board.
+-
+- To compile this driver as a module, choose M here: the
+- module will be called rivafb.
+-
+-config FB_RIVA_I2C
+- bool "Enable DDC Support"
+- depends on FB_RIVA
+- select FB_DDC
+- help
+- This enables I2C support for nVidia Chipsets. This is used
+- only for getting EDID information from the attached display
+- allowing for robust video mode handling and switching.
+-
+- Because fbdev-2.6 requires that drivers must be able to
+- independently validate video mode parameters, you should say Y
+- here.
+-
+-config FB_RIVA_DEBUG
+- bool "Lots of debug output"
+- depends on FB_RIVA
+- help
+- Say Y here if you want the Riva driver to output all sorts
+- of debugging information to provide to the maintainer when
+- something goes wrong.
+-
+-config FB_RIVA_BACKLIGHT
+- bool "Support for backlight control"
+- depends on FB_RIVA
+- default y
+- help
+- Say Y here if you want to control the backlight of your display.
+-
+ config FB_I740
+ tristate "Intel740 support"
+ depends on FB && PCI
+--- a/drivers/video/fbdev/Makefile
++++ b/drivers/video/fbdev/Makefile
+@@ -21,8 +21,6 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o
+
+ obj-$(CONFIG_FB_I740) += i740fb.o
+ obj-$(CONFIG_FB_MATROX) += matrox/
+-obj-$(CONFIG_FB_RIVA) += riva/
+-obj-$(CONFIG_FB_NVIDIA) += nvidia/
+ obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
+ obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
+ obj-$(CONFIG_FB_RADEON) += aty/
diff --git a/debian/patches/debian/documentation-drop-sphinx-version-check.patch b/debian/patches/debian/documentation-drop-sphinx-version-check.patch
new file mode 100644
index 0000000000..7e1260c93c
--- /dev/null
+++ b/debian/patches/debian/documentation-drop-sphinx-version-check.patch
@@ -0,0 +1,56 @@
+From 252aa79fdbd4ac2da09d9b98f81bf11f5e3e1870 Mon Sep 17 00:00:00 2001
+From: Bastian Blank <waldi@debian.org>
+Date: Tue, 4 Aug 2020 09:44:19 +0000
+Subject: [PATCH 1/2] Documentation: Drop sphinx version check
+Forwarded: not-needed
+
+---
+ Documentation/Makefile | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/Documentation/Makefile
++++ b/Documentation/Makefile
+@@ -98,7 +98,6 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
+ fi
+
+ htmldocs:
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
+
+ # If Rust support is available and .config exists, add rustdoc generated contents.
+@@ -112,7 +111,6 @@ endif
+ endif
+
+ texinfodocs:
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,texinfo,$(var),texinfo,$(var)))
+
+ # Note: the 'info' Make target is generated by sphinx itself when
+@@ -124,7 +122,6 @@ linkcheckdocs:
+ @$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
+
+ latexdocs:
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
+
+ ifeq ($(HAVE_PDFLATEX),0)
+@@ -136,7 +133,6 @@ pdfdocs:
+ else # HAVE_PDFLATEX
+
+ pdfdocs: latexdocs
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ $(foreach var,$(SPHINXDIRS), \
+ $(MAKE) PDFLATEX="$(PDFLATEX)" LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex || exit; \
+ mkdir -p $(BUILDDIR)/$(var)/pdf; \
+@@ -146,11 +142,9 @@ pdfdocs: latexdocs
+ endif # HAVE_PDFLATEX
+
+ epubdocs:
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var)))
+
+ xmldocs:
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var)))
+
+ endif # HAVE_SPHINX
diff --git a/debian/patches/debian/export-symbols-needed-by-android-drivers.patch b/debian/patches/debian/export-symbols-needed-by-android-drivers.patch
new file mode 100644
index 0000000000..4e4238c314
--- /dev/null
+++ b/debian/patches/debian/export-symbols-needed-by-android-drivers.patch
@@ -0,0 +1,116 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 07 Sep 2020 02:51:53 +0100
+Subject: Export symbols needed by Android drivers
+Bug-Debian: https://bugs.debian.org/901492
+
+We want to enable use of the Android ashmem and binder drivers to
+support Anbox, but they should not be built-in as that would waste
+resources and increase security attack surface on systems that don't
+need them.
+
+Export the currently un-exported symbols they depend on.
+
+---
+ fs/file.c | 1 +
+ kernel/sched/core.c | 1 +
+ kernel/sched/wait.c | 1 +
+ kernel/task_work.c | 1 +
+ mm/memory.c | 1 +
+ mm/shmem.c | 1 +
+ security/security.c | 4 ++++
+ 7 files changed, 10 insertions(+)
+
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -816,6 +816,7 @@ struct file *close_fd_get_file(unsigned
+
+ return file;
+ }
++EXPORT_SYMBOL_GPL(close_fd_get_file);
+
+ void do_close_on_exec(struct files_struct *files)
+ {
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -7253,6 +7253,7 @@ static bool is_nice_reduction(const stru
+
+ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE));
+ }
++EXPORT_SYMBOL_GPL(can_nice);
+
+ /*
+ * can_nice - check if a task can reduce its nice value
+--- a/kernel/sched/wait.c
++++ b/kernel/sched/wait.c
+@@ -252,6 +252,7 @@ void __wake_up_pollfree(struct wait_queu
+ /* POLLFREE must have cleared the queue. */
+ WARN_ON_ONCE(waitqueue_active(wq_head));
+ }
++EXPORT_SYMBOL_GPL(__wake_up_pollfree);
+
+ /*
+ * Note: we use "set_current_state()" _after_ the wait-queue add,
+--- a/kernel/task_work.c
++++ b/kernel/task_work.c
+@@ -73,6 +73,7 @@ int task_work_add(struct task_struct *ta
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(task_work_add);
+
+ /**
+ * task_work_cancel_match - cancel a pending work added by task_work_add()
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -1770,6 +1770,7 @@ void zap_page_range_single(struct vm_area_struc
+ tlb_finish_mmu(&tlb);
+ hugetlb_zap_end(vma, details);
+ }
++EXPORT_SYMBOL_GPL(zap_page_range_single);
+
+ /**
+ * zap_vma_ptes - remove ptes mapping the vma
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -4871,6 +4871,7 @@ int shmem_zero_setup(struct vm_area_stru
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(shmem_zero_setup);
+
+ /**
+ * shmem_read_folio_gfp - read into page cache, using specified page allocation flags.
+--- a/security/security.c
++++ b/security/security.c
+@@ -799,6 +799,7 @@ int security_binder_set_context_mgr(const struct cred *mgr)
+ {
+ return call_int_hook(binder_set_context_mgr, 0, mgr);
+ }
++EXPORT_SYMBOL_GPL(security_binder_set_context_mgr);
+
+ /**
+ * security_binder_transaction() - Check if a binder transaction is allowed
+@@ -814,6 +815,7 @@ int security_binder_transaction(const struct cred *from,
+ {
+ return call_int_hook(binder_transaction, 0, from, to);
+ }
++EXPORT_SYMBOL_GPL(security_binder_transaction);
+
+ /**
+ * security_binder_transfer_binder() - Check if a binder transfer is allowed
+@@ -829,6 +831,7 @@ int security_binder_transfer_binder(const struct cred *from,
+ {
+ return call_int_hook(binder_transfer_binder, 0, from, to);
+ }
++EXPORT_SYMBOL_GPL(security_binder_transfer_binder);
+
+ /**
+ * security_binder_transfer_file() - Check if a binder file xfer is allowed
+@@ -845,6 +848,7 @@ int security_binder_transfer_file(const struct cred *from,
+ {
+ return call_int_hook(binder_transfer_file, 0, from, to, file);
+ }
++EXPORT_SYMBOL_GPL(security_binder_transfer_file);
+
+ /**
+ * security_ptrace_access_check() - Check if tracing is allowed
diff --git a/debian/patches/debian/fanotify-taint-on-use-of-fanotify_access_permissions.patch b/debian/patches/debian/fanotify-taint-on-use-of-fanotify_access_permissions.patch
new file mode 100644
index 0000000000..88a2b15b3d
--- /dev/null
+++ b/debian/patches/debian/fanotify-taint-on-use-of-fanotify_access_permissions.patch
@@ -0,0 +1,29 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: fanotify: Taint on use of FANOTIFY_ACCESS_PERMISSIONS
+Date: Wed, 13 Jul 2016 01:37:22 +0100
+Forwarded: not-needed
+
+Various free and proprietary AV products use this feature and users
+apparently want it. But punting access checks to userland seems like
+an easy way to deadlock the system, and there will be nothing we can
+do about that. So warn and taint the kernel if this feature is
+actually used.
+
+---
+--- a/fs/notify/fanotify/fanotify_user.c
++++ b/fs/notify/fanotify/fanotify_user.c
+@@ -1661,6 +1661,14 @@ static int do_fanotify_mark(int fanotify
+ umask = FANOTIFY_EVENT_FLAGS;
+ }
+
++#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
++ if (mask & FANOTIFY_PERM_EVENTS) {
++ pr_warn_once("%s (%d): Using fanotify permission checks may lead to deadlock; tainting kernel\n",
++ current->comm, current->pid);
++ add_taint(TAINT_AUX, LOCKDEP_STILL_OK);
++ }
++#endif
++
+ f = fdget(fanotify_fd);
+ if (unlikely(!f.file))
+ return -EBADF;
diff --git a/debian/patches/debian/firmware_class-refer-to-debian-wiki-firmware-page.patch b/debian/patches/debian/firmware_class-refer-to-debian-wiki-firmware-page.patch
new file mode 100644
index 0000000000..208eb1e788
--- /dev/null
+++ b/debian/patches/debian/firmware_class-refer-to-debian-wiki-firmware-page.patch
@@ -0,0 +1,48 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 12 Mar 2018 01:14:03 +0000
+Subject: firmware_class: Refer to Debian wiki page when logging missing firmware
+Bug-Debian: https://bugs.debian.org/888405
+Bug-Debian: https://bugs.debian.org/1053764
+Forwarded: not-needed
+Last-Update: 2023-11-08
+
+If firmware loading fails due to a missing file, log a second error
+message referring to our wiki page about firmware. This will explain
+why some firmware is in non-free, or can't be packaged at all. Only
+do this once per boot.
+
+Do something similar in the radeon drivers, where we have an early
+check to avoid failing at a point where we cannot display anything.
+
+Update 2023-11-08:
+In bug 1053764 Mario Limonciello <mario.limonciello@amd.com> states
+that the patch isn't needed anymore for amdgpu, so remove that part
+of the patch
+
+---
+--- a/drivers/base/firmware_loader/main.c
++++ b/drivers/base/firmware_loader/main.c
+@@ -580,9 +580,12 @@ fw_get_filesystem_firmware(struct device
+ }
+ __putname(path);
+
+- if (rc)
++ if (rc) {
+ dev_err(device, "firmware: failed to load %s (%d)\n",
+ fw_priv->fw_name, rc);
++ if (rc == -ENOENT)
++ pr_err_once("See https://wiki.debian.org/Firmware for information about missing firmware\n");
++ }
+
+ return rc;
+ }
+--- a/drivers/gpu/drm/radeon/radeon_drv.c
++++ b/drivers/gpu/drm/radeon/radeon_drv.c
+@@ -322,6 +322,7 @@ static int radeon_pci_probe(struct pci_d
+ if ((ent->driver_data & RADEON_FAMILY_MASK) >= CHIP_R600 &&
+ !radeon_firmware_installed()) {
+ DRM_ERROR("radeon kernel modesetting for R600 or later requires firmware installed\n");
++ pr_err_once("See https://wiki.debian.org/Firmware for information about missing firmware\n");
+ return -ENODEV;
+ }
+
diff --git a/debian/patches/debian/fixdep-allow-overriding-hostcc-and-hostld.patch b/debian/patches/debian/fixdep-allow-overriding-hostcc-and-hostld.patch
new file mode 100644
index 0000000000..f1d856e0a1
--- /dev/null
+++ b/debian/patches/debian/fixdep-allow-overriding-hostcc-and-hostld.patch
@@ -0,0 +1,23 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Sat, 13 May 2023 13:03:26 +0200
+Subject: fixdep: Allow overriding HOSTCC and HOSTLD
+Forwarded: not-needed
+
+objtool always uses HOSTCC, HOSTLD, and HOSTAR, so we need to override
+these on the command line for cross-builds of linux-kbuild. But it
+also builds fixdep which still needs to be native in a cross-build.
+Add support for REALHOSTCC and REALHOSTLD variables which, if set,
+override HOSTCC and HOSTLD for fixdep only.
+
+---
+--- a/tools/build/Makefile.include
++++ b/tools/build/Makefile.include
+@@ -2,7 +2,7 @@
+ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
+
+ fixdep:
+- $(Q)$(MAKE) -C $(srctree)/tools/build CFLAGS= LDFLAGS= $(OUTPUT)fixdep
++ $(Q)$(MAKE) -C $(srctree)/tools/build HOSTCC=$(or $(REALHOSTCC),$(HOSTCC)) HOSTLD=$(or $(REALHOSTLD),$(HOSTLD)) CFLAGS= LDFLAGS= $(OUTPUT)fixdep
+
+ fixdep-clean:
+ $(Q)$(MAKE) -C $(srctree)/tools/build clean
diff --git a/debian/patches/debian/fjes-disable-autoload.patch b/debian/patches/debian/fjes-disable-autoload.patch
new file mode 100644
index 0000000000..873c6906e2
--- /dev/null
+++ b/debian/patches/debian/fjes-disable-autoload.patch
@@ -0,0 +1,26 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Mar 2017 20:47:58 +0000
+Subject: fjes: Disable auto-loading
+Bug-Debian: https://bugs.debian.org/853976
+Forwarded: no
+
+fjes matches a generic ACPI device ID, and relies on its probe
+function to distinguish whether that really corresponds to a supported
+device. Very few system will need the driver and it wastes memory on
+all the other systems where the same device ID appears, so disable
+auto-loading.
+
+---
+Index: linux/drivers/net/fjes/fjes_main.c
+===================================================================
+--- linux.orig/drivers/net/fjes/fjes_main.c
++++ linux/drivers/net/fjes/fjes_main.c
+@@ -36,7 +36,7 @@ static const struct acpi_device_id fjes_
+ {ACPI_MOTHERBOARD_RESOURCE_HID, 0},
+ {"", 0},
+ };
+-MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids);
++/* MODULE_DEVICE_TABLE(acpi, fjes_acpi_ids); */
+
+ static bool is_extended_socket_device(struct acpi_device *device)
+ {
diff --git a/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch b/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch
new file mode 100644
index 0000000000..eab0e78eef
--- /dev/null
+++ b/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch
@@ -0,0 +1,22 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: fs: Enable link security restrictions by default
+Date: Fri, 02 Nov 2012 05:32:06 +0000
+Bug-Debian: https://bugs.debian.org/609455
+Forwarded: not-needed
+
+This reverts commit 561ec64ae67ef25cac8d72bb9c4bfc955edfd415
+('VFS: don't do protected {sym,hard}links by default').
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1020,8 +1020,8 @@ static inline void put_link(struct namei
+ path_put(&last->link);
+ }
+
+-static int sysctl_protected_symlinks __read_mostly;
+-static int sysctl_protected_hardlinks __read_mostly;
++static int sysctl_protected_symlinks __read_mostly = 1;
++static int sysctl_protected_hardlinks __read_mostly = 1;
+ static int sysctl_protected_fifos __read_mostly;
+ static int sysctl_protected_regular __read_mostly;
+
diff --git a/debian/patches/debian/gitignore.patch b/debian/patches/debian/gitignore.patch
new file mode 100644
index 0000000000..4be8009d88
--- /dev/null
+++ b/debian/patches/debian/gitignore.patch
@@ -0,0 +1,53 @@
+From: Ian Campbell <ijc@hellion.org.uk>
+Date: Thu, 17 Jan 2013 08:55:21 +0000
+Subject: Tweak gitignore for Debian pkg-kernel using git
+Forwarded: not-needed
+
+[bwh: Tweak further for pure git]
+
+Index: linux/.gitignore
+===================================================================
+--- linux.orig/.gitignore
++++ linux/.gitignore
+@@ -77,11 +77,6 @@ modules.order
+ /kernel.spec
+ /rpmbuild/
+
+-#
+-# Debian directory (make deb-pkg)
+-#
+-/debian/
+-
+ #
+ # Snap directory (make snap-pkg)
+ #
+@@ -92,18 +87,6 @@ modules.order
+ #
+ /tar-install/
+
+-#
+-# We don't want to ignore the following even if they are dot-files
+-#
+-!.clang-format
+-!.cocciconfig
+-!.get_maintainer.ignore
+-!.gitattributes
+-!.gitignore
+-!.kunitconfig
+-!.mailmap
+-!.rustfmt.toml
+-
+ #
+ # Generated include files
+ #
+@@ -170,3 +153,10 @@ sphinx_*/
+
+ # Rust analyzer configuration
+ /rust-project.json
++
++#
++# Debian packaging: ignore everything at the top level, since it isn't
++# included in our repository
++#
++/*
++!/debian/
diff --git a/debian/patches/debian/hamradio-disable-auto-loading-as-mitigation-against-local-exploits.patch b/debian/patches/debian/hamradio-disable-auto-loading-as-mitigation-against-local-exploits.patch
new file mode 100644
index 0000000000..b532d00549
--- /dev/null
+++ b/debian/patches/debian/hamradio-disable-auto-loading-as-mitigation-against-local-exploits.patch
@@ -0,0 +1,48 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 05 Aug 2019 00:29:11 +0100
+Subject: hamradio: Disable auto-loading as mitigation against local exploits
+Forwarded: not-needed
+
+We can mitigate the effect of vulnerabilities in obscure protocols by
+preventing unprivileged users from loading the modules, so that they
+are only exploitable on systems where the administrator has chosen to
+load the protocol.
+
+The 'ham' radio protocols (ax25, netrom, rose) are not actively
+maintained or widely used. Therefore disable auto-loading.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -1986,7 +1986,7 @@ module_init(ax25_init);
+ MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
+ MODULE_DESCRIPTION("The amateur radio AX.25 link layer protocol");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_NETPROTO(PF_AX25);
++/* MODULE_ALIAS_NETPROTO(PF_AX25); */
+
+ static void __exit ax25_exit(void)
+ {
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -1486,7 +1486,7 @@ MODULE_PARM_DESC(nr_ndevs, "number of NE
+ MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
+ MODULE_DESCRIPTION("The amateur radio NET/ROM network and transport layer protocol");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_NETPROTO(PF_NETROM);
++/* MODULE_ALIAS_NETPROTO(PF_NETROM); */
+
+ static void __exit nr_exit(void)
+ {
+--- a/net/rose/af_rose.c
++++ b/net/rose/af_rose.c
+@@ -1577,7 +1577,7 @@ MODULE_PARM_DESC(rose_ndevs, "number of
+ MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
+ MODULE_DESCRIPTION("The amateur radio ROSE network layer protocol");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS_NETPROTO(PF_ROSE);
++/* MODULE_ALIAS_NETPROTO(PF_ROSE); */
+
+ static void __exit rose_exit(void)
+ {
diff --git a/debian/patches/debian/i386-686-pae-pci-set-pci-nobios-by-default.patch b/debian/patches/debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
new file mode 100644
index 0000000000..1b216d0d1c
--- /dev/null
+++ b/debian/patches/debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
@@ -0,0 +1,27 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 16 Feb 2016 02:45:42 +0000
+Subject: [i386/686-pae] PCI: Set pci=nobios by default
+Forwarded: not-needed
+
+CONFIG_PCI_GOBIOS results in physical addresses 640KB-1MB being mapped
+W+X, which is undesirable for security reasons and will result in a
+warning at boot now that we enable CONFIG_DEBUG_WX.
+
+This can be overridden using the kernel parameter "pci=nobios", but we
+want to disable W+X by default. Disable PCI BIOS probing by default;
+it can still be enabled using "pci=bios".
+
+---
+--- a/arch/x86/pci/common.c
++++ b/arch/x86/pci/common.c
+@@ -21,8 +21,8 @@
+ #include <asm/setup.h>
+ #include <asm/irqdomain.h>
+
+-unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
+- PCI_PROBE_MMCONF;
++unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF |
++ (IS_ENABLED(CONFIG_X86_64) || IS_ENABLED(CONFIG_X86_PAE) ? 0 : PCI_PROBE_BIOS);
+
+ static int pci_bf_sort;
+ int pci_routeirq;
diff --git a/debian/patches/debian/ia64-hardcode-arch-script-output.patch b/debian/patches/debian/ia64-hardcode-arch-script-output.patch
new file mode 100644
index 0000000000..79356c4900
--- /dev/null
+++ b/debian/patches/debian/ia64-hardcode-arch-script-output.patch
@@ -0,0 +1,71 @@
+From: dann frazier <dannf@debian.org>
+Subject: Hardcode arch script output
+Date: Mon, 26 Mar 2007 16:30:51 -0600
+Bug-Debian: https://bugs.debian.org/392592
+Forwarded: not-needed
+
+Here's a patch that simply uses hardcoded definitions instead of
+doing the dynamic tests that require architecture-specific scripts.
+
+I don't particularly like this approach because it restricts
+portability and diverts from upstream. But, it is simpler, and this
+really needs to be fixed somehow before etch (along with a rebuild of
+linux-modules-extra-2.6), so I'm willing to live with it if my other
+patch is deemed unacceptable.
+
+My primary concern is that, in the future, the output of these scripts
+will change and we (or our successors) will either not notice or
+forget to update the hardcoded values.
+
+Including the scripts in linux-kbuild will avoid this manual step
+altogether, and allow for the possibility of other archs to provide
+their own scripts in the future.
+---
+ arch/ia64/Makefile | 17 ++---------------
+ 1 file changed, 2 insertions(+), 15 deletions(-)
+
+--- a/arch/ia64/Makefile
++++ b/arch/ia64/Makefile
+@@ -26,16 +26,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -
+ -frename-registers -fno-optimize-sibling-calls
+ KBUILD_CFLAGS_KERNEL := -mconstant-gp
+
+-GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
+-KBUILD_CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
+-
+-ifeq ($(GAS_STATUS),buggy)
+-$(error Sorry, you need a newer version of the assember, one that is built from \
+- a source-tree that post-dates 18-Dec-2002. You can find a pre-compiled \
+- static binary of such an assembler at: \
+- \
+- ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
+-endif
++KBUILD_CPPFLAGS += -DHAVE_WORKING_TEXT_ALIGN -DHAVE_MODEL_SMALL_ATTRIBUTE -DHAVE_SERIALIZE_DIRECTIVE
+
+ quiet_cmd_gzip = GZIP $@
+ cmd_gzip = cat $(real-prereqs) | $(KGZIP) -n -f -9 > $@
+@@ -52,7 +42,7 @@ drivers-y += arch/ia64/pci/ arch/ia64/
+
+ PHONY += compressed check
+
+-all: compressed unwcheck
++all: compressed
+
+ compressed: vmlinux.gz
+
+@@ -64,9 +54,6 @@ vmlinux.gz: vmlinux.bin FORCE
+ vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+-unwcheck: vmlinux
+- -$(Q)READELF=$(READELF) $(PYTHON3) $(srctree)/arch/ia64/scripts/unwcheck.py $<
+-
+ archheaders:
+ $(Q)$(MAKE) $(build)=arch/ia64/kernel/syscalls all
+
+@@ -78,5 +66,4 @@ install: vmlinux.gz
+ define archhelp
+ echo '* compressed - Build compressed kernel image'
+ echo ' install - Install compressed kernel image'
+- echo '* unwcheck - Check vmlinux for invalid unwind info'
+ endef
diff --git a/debian/patches/debian/iwlwifi-do-not-request-unreleased-firmware.patch b/debian/patches/debian/iwlwifi-do-not-request-unreleased-firmware.patch
new file mode 100644
index 0000000000..c8061436d0
--- /dev/null
+++ b/debian/patches/debian/iwlwifi-do-not-request-unreleased-firmware.patch
@@ -0,0 +1,26 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: iwlwifi: Do not request unreleased firmware for IWL6000
+Bug-Debian: https://bugs.debian.org/689416
+Forwarded: not-needed
+
+The iwlwifi driver currently supports firmware API versions 4-6 for
+these devices. It will request the file for the latest supported
+version and then fall back to earlier versions. However, the latest
+version that has actually been released is 4, so we expect the
+requests for versions 6 and then 5 to fail.
+
+The installer appears to report any failed request, and it is probably
+not easy to detect that this particular failure is harmless. So stop
+requesting the unreleased firmware.
+
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+@@ -31,7 +31,7 @@
+ #include "dvm/commands.h" /* needed for BT for now */
+
+ /* Highest firmware API version supported */
+-#define IWL6000_UCODE_API_MAX 6
++#define IWL6000_UCODE_API_MAX 4 /* v5-6 are supported but not released */
+ #define IWL6050_UCODE_API_MAX 5
+ #define IWL6000G2_UCODE_API_MAX 6
+ #define IWL6035_UCODE_API_MAX 6
diff --git a/debian/patches/debian/kbuild-abort-build-if-subdirs-used.patch b/debian/patches/debian/kbuild-abort-build-if-subdirs-used.patch
new file mode 100644
index 0000000000..ec23040d83
--- /dev/null
+++ b/debian/patches/debian/kbuild-abort-build-if-subdirs-used.patch
@@ -0,0 +1,37 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Mon, 26 Apr 2021 18:27:16 +0200
+Subject: kbuild: Abort build if SUBDIRS used
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/987575
+
+DKMS and module-assistant both build OOT modules as root. If they
+build an old OOT module that still use SUBDIRS this causes Kbuild
+to try building a full kernel, which obviously fails but not before
+deleting files from the installed headers package.
+
+To avoid such mishaps, detect this situation and abort the build.
+
+The error message is based on that used in commit 0126be38d988
+"kbuild: announce removal of SUBDIRS if used".
+---
+--- a/Makefile
++++ b/Makefile
+@@ -218,6 +218,18 @@ ifeq ("$(origin M)", "command line")
+ KBUILD_EXTMOD := $(M)
+ endif
+
++# Old syntax make ... SUBDIRS=$PWD should be rejected to avoid mishaps
++# (see Debian bugs #982334, #987575)
++ifndef KBUILD_EXTMOD
++ ifdef SUBDIRS
++ $(warning =============== ERROR ==============)
++ $(warning 'SUBDIRS' was removed in Linux 5.3)
++ $(warning Use 'M=' or 'KBUILD_EXTMOD=' instead)
++ $(warning ====================================)
++ $(error .)
++ endif
++endif
++
+ $(if $(word 2, $(KBUILD_EXTMOD)), \
+ $(error building multiple external modules is not supported))
+
diff --git a/debian/patches/debian/kbuild-look-for-module.lds-under-arch-directory-too.patch b/debian/patches/debian/kbuild-look-for-module.lds-under-arch-directory-too.patch
new file mode 100644
index 0000000000..eea69e4558
--- /dev/null
+++ b/debian/patches/debian/kbuild-look-for-module.lds-under-arch-directory-too.patch
@@ -0,0 +1,52 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Thu, 10 Dec 2020 17:31:39 +0100
+Subject: kbuild: Look for module.lds under arch directory too
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/975571
+
+The module.lds linker script is now built under the scripts directory,
+where previously it was under arch/$(SRCARCH).
+
+However, we package the scripts directory as linux-kbuild, which is
+meant to be able to do support native and cross-builds. That means it
+shouldn't contain files for a specific target architecture without a
+wrapper to select between them, and it doesn't appear that linker
+scripts are powerful enough to implement such a wrapper.
+
+Building module.lds in a different location would require relatively
+large changes. Moving it in the package build rules can work, but we
+need to support custom kernel builds from the same source so we can't
+assume it's moved.
+
+Therefore, we move module.lds under the arch build directory in
+rules.real and change Makefile.modfinal to look for it in both places.
+
+---
+Index: linux/scripts/Makefile.modfinal
+===================================================================
+--- linux.orig/scripts/Makefile.modfinal
++++ linux/scripts/Makefile.modfinal
+@@ -29,12 +29,13 @@ quiet_cmd_cc_o_c = CC [M] $@
+ $(call if_changed_dep,cc_o_c)
+
+ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
++ARCH_MODULE_LDS := $(word 1,$(wildcard scripts/module.lds arch/$(SRCARCH)/module.lds))
+
+ quiet_cmd_ld_ko_o = LD [M] $@
+ cmd_ld_ko_o += \
+ $(LD) -r $(KBUILD_LDFLAGS) \
+ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
+- -T scripts/module.lds -o $@ $(filter %.o, $^); \
++ -T $(ARCH_MODULE_LDS) -o $@ $(filter %.o, $^); \
+ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+
+ quiet_cmd_btf_ko = BTF [M] $@
+@@ -57,7 +58,7 @@ if_changed_except = $(if $(call newer_pr
+ printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
+
+ # Re-generate module BTFs if either module's .ko or vmlinux changed
+-%.ko: %.o %.mod.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE
++%.ko: %.o %.mod.o $(ARCH_MODULE_LDS) $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE
+ +$(call if_changed_except,ld_ko_o,vmlinux)
+ ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+ +$(if $(newer-prereqs),$(call cmd,btf_ko))
diff --git a/debian/patches/debian/kernelvariables.patch b/debian/patches/debian/kernelvariables.patch
new file mode 100644
index 0000000000..ef427ab195
--- /dev/null
+++ b/debian/patches/debian/kernelvariables.patch
@@ -0,0 +1,92 @@
+From: Bastian Blank <waldi@debian.org>
+Subject: kbuild: Make the toolchain variables easily overwritable
+Date: Sun, 22 Feb 2009 15:39:35 +0100
+Forwarded: not-needed
+
+Allow make variables to be overridden for each flavour by a file in
+the build tree, .kernelvariables.
+
+We currently use this for ARCH, KERNELRELEASE, CC, and in some cases
+also CROSS_COMPILE, KCFLAGS.
+
+This file can only be read after we establish the build tree, and all
+use of $(ARCH) needs to be moved after this.
+
+[bwh: Updated for 5.3: include .kernelvariables from current directory
+ rather than using undefined $(obj).]
+---
+--- a/Makefile
++++ b/Makefile
+@@ -406,36 +406,6 @@ include $(srctree)/scripts/subarch.inclu
+ # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
+ ARCH ?= $(SUBARCH)
+
+-# Architecture as present in compile.h
+-UTS_MACHINE := $(ARCH)
+-SRCARCH := $(ARCH)
+-
+-# Additional ARCH settings for x86
+-ifeq ($(ARCH),i386)
+- SRCARCH := x86
+-endif
+-ifeq ($(ARCH),x86_64)
+- SRCARCH := x86
+-endif
+-
+-# Additional ARCH settings for sparc
+-ifeq ($(ARCH),sparc32)
+- SRCARCH := sparc
+-endif
+-ifeq ($(ARCH),sparc64)
+- SRCARCH := sparc
+-endif
+-
+-# Additional ARCH settings for parisc
+-ifeq ($(ARCH),parisc64)
+- SRCARCH := parisc
+-endif
+-
+-export cross_compiling :=
+-ifneq ($(SRCARCH),$(SUBARCH))
+-cross_compiling := 1
+-endif
+-
+ KCONFIG_CONFIG ?= .config
+ export KCONFIG_CONFIG
+
+@@ -551,6 +521,35 @@ RUSTFLAGS_KERNEL =
+ AFLAGS_KERNEL =
+ LDFLAGS_vmlinux =
+
++-include .kernelvariables
++
++# Architecture as present in compile.h
++UTS_MACHINE := $(ARCH)
++SRCARCH := $(ARCH)
++
++# Additional ARCH settings for x86
++ifeq ($(ARCH),i386)
++ SRCARCH := x86
++endif
++ifeq ($(ARCH),x86_64)
++ SRCARCH := x86
++endif
++
++# Additional ARCH settings for sparc
++ifeq ($(ARCH),sparc64)
++ SRCARCH := sparc
++endif
++
++# Additional ARCH settings for parisc
++ifeq ($(ARCH),parisc64)
++ SRCARCH := parisc
++endif
++
++# Additional ARCH settings for sh
++ifeq ($(ARCH),sh64)
++ SRCARCH := sh
++endif
++
+ # Use USERINCLUDE when you must reference the UAPI directories only.
+ USERINCLUDE := \
+ -I$(srctree)/arch/$(SRCARCH)/include/uapi \
diff --git a/debian/patches/debian/makefile-make-compiler-version-comparison-optional.patch b/debian/patches/debian/makefile-make-compiler-version-comparison-optional.patch
new file mode 100644
index 0000000000..f0d5c80d7a
--- /dev/null
+++ b/debian/patches/debian/makefile-make-compiler-version-comparison-optional.patch
@@ -0,0 +1,31 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Thu, 15 Sep 2022 02:14:03 +0200
+Subject: Makefile: Make compiler version comparison optional
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/1019749
+
+The top-level Makefile warns if the compiler version string changes at
+all between the kernel build and an out-of-tree module build.
+
+We expect that major compiler version changes could introduce ABI
+changes, and override the CC variable in out-of-tree module builds to
+ensure that the same major compiler version is used. But minor
+version changes should not make a difference, so this exact version
+comparison produces false warnings.
+
+Since custom kernel packages don't have that, don't remove the version
+comparison. Instead, skip it if $(DEBIAN_KERNEL_NO_CC_VERSION_CHECK)
+is non-empty.
+
+---
+--- a/Makefile
++++ b/Makefile
+@@ -1753,7 +1753,7 @@ PHONY += prepare
+ # now expand this into a simple variable to reduce the cost of shell evaluations
+ prepare: CC_VERSION_TEXT := $(CC_VERSION_TEXT)
+ prepare:
+- @if [ "$(CC_VERSION_TEXT)" != "$(CONFIG_CC_VERSION_TEXT)" ]; then \
++ @if [ -z "$(DEBIAN_KERNEL_NO_CC_VERSION_CHECK)" ] && [ "$(CC_VERSION_TEXT)" != "$(CONFIG_CC_VERSION_TEXT)" ]; then \
+ echo >&2 "warning: the compiler differs from the one used to build the kernel"; \
+ echo >&2 " The kernel was built by: $(CONFIG_CC_VERSION_TEXT)"; \
+ echo >&2 " You are using: $(CC_VERSION_TEXT)"; \
diff --git a/debian/patches/debian/mips-boston-disable-its.patch b/debian/patches/debian/mips-boston-disable-its.patch
new file mode 100644
index 0000000000..ca4de2daa6
--- /dev/null
+++ b/debian/patches/debian/mips-boston-disable-its.patch
@@ -0,0 +1,22 @@
+From: YunQiang Su <syq@debian.org>
+Date: Mon, 14 May 2018 16:16:18 +0800
+Subject: Disable uImage generation for mips generic
+Forwarded: not-needed
+
+MIPS generic trys to generate uImage when build, which then ask for
+u-boot-tools.
+
+[bwh: Updated for 5.17:
+ - zload-y is no longer assigned here and appears to default to empty
+ - Adjust context]
+
+--- a/arch/mips/generic/Platform
++++ b/arch/mips/generic/Platform
+@@ -13,7 +13,6 @@ cflags-$(CONFIG_MACH_INGENIC_SOC) += -I$
+ cflags-$(CONFIG_MIPS_GENERIC) += -I$(srctree)/arch/mips/include/asm/mach-generic
+
+ load-$(CONFIG_MIPS_GENERIC) += 0xffffffff80100000
+-all-$(CONFIG_MIPS_GENERIC) += vmlinux.gz.itb
+
+ its-y := vmlinux.its.S
+ its-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += board-boston.its.S
diff --git a/debian/patches/debian/mips-disable-werror.patch b/debian/patches/debian/mips-disable-werror.patch
new file mode 100644
index 0000000000..52231cc447
--- /dev/null
+++ b/debian/patches/debian/mips-disable-werror.patch
@@ -0,0 +1,23 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 13 Sep 2010 02:16:18 +0100
+Subject: [PATCH] Partially revert "MIPS: Add -Werror to arch/mips/Kbuild"
+Forwarded: not-needed
+
+This reverts commits 66f9ba101f54bda63ab1db97f9e9e94763d0651b and
+5373633cc9253ba82547473e899cab141c54133e.
+
+We really don't want to add -Werror anywhere.
+---
+--- a/arch/mips/Kbuild
++++ b/arch/mips/Kbuild
+@@ -1,10 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0
+-# Fail on warnings - also for files referenced in subdirs
+-# -Werror can be disabled for specific files using:
+-# CFLAGS_<file.o> := -Wno-error
+-ifeq ($(W),)
+-subdir-ccflags-y := -Werror
+-endif
+
+ # platform specific definitions
+ include $(srctree)/arch/mips/Kbuild.platforms
diff --git a/debian/patches/debian/mips-ieee754-relaxed.patch b/debian/patches/debian/mips-ieee754-relaxed.patch
new file mode 100644
index 0000000000..20dff251c7
--- /dev/null
+++ b/debian/patches/debian/mips-ieee754-relaxed.patch
@@ -0,0 +1,32 @@
+From: YunQiang Su <syq@debian.org>
+Date: Mon 16 Nov 2020 09:11:00 +0800
+Subject: Use RELAXED ieee754 mode for Loongson-3 as 3A 4000 is 2008-only
+Forwarded: not-needed
+
+There are 2 mode of value of IEEE NaN hardcoded by CPU.
+Currently, our mipsel/mips64el port is in so-called lagacy mode.
+Loongson 3A 4000 is set as the so-called 2008 mode.
+
+To make Debian workable on Loongson 3A 4000, we need set the kerenl in
+RELAXED mode.
+
+https://web.archive.org/web/20180830093617/https://dmz-portal.mips.com/wiki/MIPS_ABI_-_NaN_Interlinking
+
+diff --git a/arch/mips/kernel/fpu-probe.c b/arch/mips/kernel/fpu-probe.c
+index e689d6a83..667226f94 100644
+--- a/arch/mips/kernel/fpu-probe.c
++++ b/arch/mips/kernel/fpu-probe.c
+@@ -144,7 +144,12 @@ static void cpu_set_fpu_2008(struct cpuinfo_mips *c)
+ * IEEE 754 conformance mode to use. Affects the NaN encoding and the
+ * ABS.fmt/NEG.fmt execution mode.
+ */
+-static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
++enum ieee754_mode { STRICT, LEGACY, STD2008, RELAXED };
++#ifdef CONFIG_CPU_LOONGSON64
++static enum ieee754_mode ieee754 = RELAXED;
++#else
++static enum ieee754_mode ieee754 = STRICT;
++#endif
+
+ /*
+ * Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes
diff --git a/debian/patches/debian/module-avoid-abi-changes-when-debug-info-is-disabled.patch b/debian/patches/debian/module-avoid-abi-changes-when-debug-info-is-disabled.patch
new file mode 100644
index 0000000000..3582f4ba33
--- /dev/null
+++ b/debian/patches/debian/module-avoid-abi-changes-when-debug-info-is-disabled.patch
@@ -0,0 +1,23 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Fri, 13 May 2022 21:08:08 +0200
+Subject: module: Avoid ABI changes when debug info is disabled
+Forwarded: not-needed
+
+CI builds are done with debug info disabled, but this removes some
+members from struct module. This causes builds to fail if there is an
+ABI reference for the current ABI.
+
+Define these members unconditionally, so that there is no ABI change.
+
+---
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -471,7 +471,7 @@ struct module {
+ unsigned int num_bpf_raw_events;
+ struct bpf_raw_event_map *bpf_raw_events;
+ #endif
+-#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
++#if 1
+ unsigned int btf_data_size;
+ void *btf_data;
+ #endif
diff --git a/debian/patches/debian/ntfs-mark-it-as-broken.patch b/debian/patches/debian/ntfs-mark-it-as-broken.patch
new file mode 100644
index 0000000000..0f59a9f44f
--- /dev/null
+++ b/debian/patches/debian/ntfs-mark-it-as-broken.patch
@@ -0,0 +1,23 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 25 Apr 2019 15:31:33 +0100
+Subject: ntfs: mark it as broken
+Forwarded: not-needed
+
+NTFS has unfixed issues CVE-2018-12929, CVE-2018-12930, and
+CVE-2018-12931. ntfs-3g is a better supported alternative.
+
+Make sure it can't be enabled even in custom kernels.
+
+---
+Index: debian-kernel/fs/ntfs/Kconfig
+===================================================================
+--- debian-kernel.orig/fs/ntfs/Kconfig
++++ debian-kernel/fs/ntfs/Kconfig
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ config NTFS_FS
+ tristate "NTFS file system support"
++ depends on BROKEN
+ select BUFFER_HEAD
+ select NLS
+ help
diff --git a/debian/patches/debian/perf-traceevent-support-asciidoctor-for-documentatio.patch b/debian/patches/debian/perf-traceevent-support-asciidoctor-for-documentatio.patch
new file mode 100644
index 0000000000..a1cbb2c0bd
--- /dev/null
+++ b/debian/patches/debian/perf-traceevent-support-asciidoctor-for-documentatio.patch
@@ -0,0 +1,40 @@
+From cd02fc78859ef9aefd7c92406f9523622da0b472 Mon Sep 17 00:00:00 2001
+From: Bastian Blank <waldi@debian.org>
+Date: Tue, 4 Aug 2020 09:44:37 +0000
+Subject: [PATCH 2/2] perf/traceevent: Support asciidoctor for documentation
+Forwarded: not-needed
+
+---
+ tools/lib/perf/Documentation/Makefile | 2 +-
+ tools/perf/Documentation/Makefile | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/lib/perf/Documentation/Makefile b/tools/lib/perf/Documentation/Makefile
+index 972754082a85..272d06173a3e 100644
+--- a/tools/lib/perf/Documentation/Makefile
++++ b/tools/lib/perf/Documentation/Makefile
+@@ -35,7 +35,7 @@ htmldir = $(docdir)/html
+ exdir = $(docdir)/examples
+
+ ASCIIDOC = asciidoc
+-ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf
++ASCIIDOC_EXTRA =
+ ASCIIDOC_HTML = xhtml11
+ MANPAGE_XSL = manpage-normal.xsl
+ XMLTO_EXTRA =
+diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
+index 6e54979c2124..7bfa6ae971ab 100644
+--- a/tools/perf/Documentation/Makefile
++++ b/tools/perf/Documentation/Makefile
+@@ -48,7 +48,7 @@ man5dir=$(mandir)/man5
+ man7dir=$(mandir)/man7
+
+ ASCIIDOC=asciidoc
+-ASCIIDOC_EXTRA += --unsafe -f asciidoc.conf
++ASCIIDOC_EXTRA +=
+ ASCIIDOC_HTML = xhtml11
+ MANPAGE_XSL = manpage-normal.xsl
+ XMLTO_EXTRA =
+--
+2.28.0
+
diff --git a/debian/patches/debian/rds-Disable-auto-loading-as-mitigation-against-local.patch b/debian/patches/debian/rds-Disable-auto-loading-as-mitigation-against-local.patch
new file mode 100644
index 0000000000..3343aecace
--- /dev/null
+++ b/debian/patches/debian/rds-Disable-auto-loading-as-mitigation-against-local.patch
@@ -0,0 +1,34 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 19 Nov 2010 02:12:48 +0000
+Subject: [PATCH 1/3] rds: Disable auto-loading as mitigation against local exploits
+Forwarded: not-needed
+
+Recent review has revealed several bugs in obscure protocol
+implementations that can be exploited by local users for denial of
+service or privilege escalation. We can mitigate the effect of any
+remaining vulnerabilities in such protocols by preventing unprivileged
+users from loading the modules, so that they are only exploitable on
+systems where the administrator has chosen to load the protocol.
+
+The 'rds' protocol is one such protocol that has been found to be
+vulnerable, and which was not present in the 'lenny' kernel.
+Therefore disable auto-loading.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ net/rds/af_rds.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
+index 98e0538..d8d4525 100644
+--- a/net/rds/af_rds.c
++++ b/net/rds/af_rds.c
+@@ -574,4 +574,4 @@ MODULE_DESCRIPTION("RDS: Reliable Datagram Sockets"
+ " v" DRV_VERSION " (" DRV_RELDATE ")");
+ MODULE_VERSION(DRV_VERSION);
+ MODULE_LICENSE("Dual BSD/GPL");
+-MODULE_ALIAS_NETPROTO(PF_RDS);
++/* MODULE_ALIAS_NETPROTO(PF_RDS); */
+--
+1.7.2.3
+
diff --git a/debian/patches/debian/sched-autogroup-disabled.patch b/debian/patches/debian/sched-autogroup-disabled.patch
new file mode 100644
index 0000000000..c616fa46ef
--- /dev/null
+++ b/debian/patches/debian/sched-autogroup-disabled.patch
@@ -0,0 +1,19 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: sched: Do not enable autogrouping by default
+Date: Wed, 16 Mar 2011 03:17:06 +0000
+Forwarded: not-needed
+
+We want to provide the option of autogrouping but without enabling
+it by default yet.
+
+--- a/kernel/sched/autogroup.c
++++ b/kernel/sched/autogroup.c
+@@ -4,7 +4,7 @@
+ * Auto-group scheduling implementation:
+ */
+
+-unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
++unsigned int __read_mostly sysctl_sched_autogroup_enabled = 0;
+ static struct autogroup autogroup_default;
+ static atomic_t autogroup_seq_nr;
+
diff --git a/debian/patches/debian/snd-pcsp-disable-autoload.patch b/debian/patches/debian/snd-pcsp-disable-autoload.patch
new file mode 100644
index 0000000000..e593f51446
--- /dev/null
+++ b/debian/patches/debian/snd-pcsp-disable-autoload.patch
@@ -0,0 +1,30 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 05 Feb 2014 23:01:30 +0000
+Subject: snd-pcsp: Disable autoload
+Forwarded: not-needed
+Bug-Debian: https://bugs.debian.org/697709
+
+There are two drivers claiming the platform:pcspkr device:
+- pcspkr creates an input(!) device that can only beep
+- snd-pcsp creates an equivalent input device plus a PCM device that can
+ play barely recognisable renditions of sampled sound
+
+snd-pcsp is blacklisted by the alsa-base package, but not everyone
+installs that. On PCs where no sound is wanted at all, both drivers
+will still be loaded and one or other will complain that it couldn't
+claim the relevant I/O range.
+
+In case anyone finds snd-pcsp useful, we continue to build it. But
+remove the alias, to ensure it's not loaded where it's not wanted.
+
+--- a/sound/drivers/pcsp/pcsp.c
++++ b/sound/drivers/pcsp/pcsp.c
+@@ -22,7 +22,7 @@
+ MODULE_AUTHOR("Stas Sergeev <stsp@users.sourceforge.net>");
+ MODULE_DESCRIPTION("PC-Speaker driver");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:pcspkr");
++/*MODULE_ALIAS("platform:pcspkr");*/
+
+ static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
+ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
diff --git a/debian/patches/debian/tools-perf-install-python-bindings.patch b/debian/patches/debian/tools-perf-install-python-bindings.patch
new file mode 100644
index 0000000000..c3f1747414
--- /dev/null
+++ b/debian/patches/debian/tools-perf-install-python-bindings.patch
@@ -0,0 +1,26 @@
+From: Adriaan Schmidt <adriaan.schmidt@siemens.com>
+Date: Mon, 4 Apr 2022 13:38:33 +0200
+Subject: tools: install perf python bindings
+Bug-Debian: http://bugs.debian.org/860957
+Forwarded: not-needed
+
+---
+ tools/perf/Makefile.perf | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
+index 80522bcfafe0..b011c7aae742 100644
+--- a/tools/perf/Makefile.perf
++++ b/tools/perf/Makefile.perf
+@@ -1026,7 +1026,7 @@ install-bin: install-tools install-tests install-traceevent-plugins
+ install: install-bin try-install-man
+
+ install-python_ext:
+- $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
++ $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' --install-layout=deb
+
+ # 'make install-doc' should call 'make -C Documentation install'
+ $(INSTALL_DOC_TARGETS):
+--
+2.30.2
+
diff --git a/debian/patches/debian/tools-perf-perf-read-vdso-in-libexec.patch b/debian/patches/debian/tools-perf-perf-read-vdso-in-libexec.patch
new file mode 100644
index 0000000000..044f584697
--- /dev/null
+++ b/debian/patches/debian/tools-perf-perf-read-vdso-in-libexec.patch
@@ -0,0 +1,32 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Mon, 11 May 2015 02:51:07 +0000
+Subject: linux-tools: Install perf-read-vdso{,x}32 in directory under /usr/lib
+
+--- a/tools/perf/Makefile.perf
++++ b/tools/perf/Makefile.perf
+@@ -943,21 +943,21 @@ install-tools: all install-gtk
+ $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'; \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(includedir_SQ)/perf'; \
+ $(INSTALL) -m 644 include/perf/perf_dlfilter.h -t '$(DESTDIR_SQ)$(includedir_SQ)/perf'
++ $(call QUIET_INSTALL, libexec) \
++ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+ ifndef NO_PERF_READ_VDSO32
+ $(call QUIET_INSTALL, perf-read-vdso32) \
+- $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)';
++ $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)';
+ endif
+ ifndef NO_PERF_READ_VDSOX32
+ $(call QUIET_INSTALL, perf-read-vdsox32) \
+- $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
++ $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)';
+ endif
+ ifndef NO_JVMTI
+ $(call QUIET_INSTALL, $(LIBJVMTI)) \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
+ $(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
+ endif
+- $(call QUIET_INSTALL, libexec) \
+- $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+ $(call QUIET_INSTALL, perf-archive) \
+ $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+ $(call QUIET_INSTALL, perf-iostat) \
diff --git a/debian/patches/debian/uname-version-timestamp.patch b/debian/patches/debian/uname-version-timestamp.patch
new file mode 100644
index 0000000000..4be158e09c
--- /dev/null
+++ b/debian/patches/debian/uname-version-timestamp.patch
@@ -0,0 +1,26 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: Make mkcompile_h accept an alternate timestamp string
+Date: Tue, 12 May 2015 19:29:22 +0100
+Forwarded: not-needed
+
+We want to include the Debian version in the utsname::version string
+instead of a full timestamp string. However, we still need to provide
+a standard timestamp string for gen_initramfs_list.sh to make the
+kernel image reproducible.
+
+Make mkcompile_h use $KBUILD_BUILD_VERSION_TIMESTAMP in preference to
+$KBUILD_BUILD_TIMESTAMP.
+
+Index: linux/init/Makefile
+===================================================================
+--- linux.orig/init/Makefile
++++ linux/init/Makefile
+@@ -29,7 +29,7 @@ preempt-flag-$(CONFIG_PREEMPT_DYNAMIC) :
+ preempt-flag-$(CONFIG_PREEMPT_RT) := PREEMPT_RT
+
+ build-version = $(or $(KBUILD_BUILD_VERSION), $(build-version-auto))
+-build-timestamp = $(or $(KBUILD_BUILD_TIMESTAMP), $(build-timestamp-auto))
++build-timestamp = $(or $(KBUILD_BUILD_VERSION_TIMESTAMP), $(KBUILD_BUILD_TIMESTAMP), $(build-timestamp-auto))
+
+ # Maximum length of UTS_VERSION is 64 chars
+ filechk_uts_version = \
diff --git a/debian/patches/debian/version.patch b/debian/patches/debian/version.patch
new file mode 100644
index 0000000000..7f80a9dd0a
--- /dev/null
+++ b/debian/patches/debian/version.patch
@@ -0,0 +1,174 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: Include package version along with kernel release in stack traces
+Date: Tue, 24 Jul 2012 03:13:10 +0100
+Forwarded: not-needed
+
+For distribution binary packages we assume
+$DISTRIBUTION_OFFICIAL_BUILD, $DISTRIBUTOR and $DISTRIBUTION_VERSION
+are set.
+---
+ Makefile | 15 ++++++++++++++-
+ arch/ia64/kernel/process.c | 5 +++--
+ arch/powerpc/kernel/process.c | 6 ++++--
+ arch/x86/um/sysrq_64.c | 6 ++++--
+ kernel/hung_task.c | 6 ++++--
+ lib/dump_stack.c | 6 ++++--
+ 6 files changed, 33 insertions(+), 11 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -1268,7 +1268,8 @@ PHONY += prepare archprepare
+
+ archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
+ asm-generic $(version_h) include/generated/utsrelease.h \
+- include/generated/compile.h include/generated/autoconf.h remove-stale-files
++ include/generated/compile.h include/generated/autoconf.h \
++ include/generated/package.h remove-stale-files
+
+ prepare0: archprepare
+ $(Q)$(MAKE) $(build)=scripts/mod
+@@ -1326,6 +1327,16 @@ define filechk_version.h
+ echo \#define LINUX_VERSION_SUBLEVEL $(SUBLEVEL)
+ endef
+
++ifneq ($(DISTRIBUTION_OFFICIAL_BUILD),)
++define filechk_package.h
++ echo \#define LINUX_PACKAGE_ID \" $(DISTRIBUTOR) $(DISTRIBUTION_VERSION)\"
++endef
++else
++define filechk_package.h
++ echo \#define LINUX_PACKAGE_ID \"\"
++endef
++endif
++
+ $(version_h): PATCHLEVEL := $(or $(PATCHLEVEL), 0)
+ $(version_h): SUBLEVEL := $(or $(SUBLEVEL), 0)
+ $(version_h): FORCE
+@@ -1340,6 +1351,9 @@ filechk_compile.h = $(srctree)/scripts/m
+ include/generated/compile.h: FORCE
+ $(call filechk,compile.h)
+
++include/generated/package.h: $(srctree)/Makefile FORCE
++ $(call filechk,package.h)
++
+ PHONY += headerdep
+ headerdep:
+ $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \
+--- a/arch/ia64/kernel/process.c
++++ b/arch/ia64/kernel/process.c
+@@ -35,6 +35,7 @@
+ #include <linux/utsname.h>
+ #include <linux/resume_user_mode.h>
+ #include <linux/rcupdate.h>
++#include <generated/package.h>
+
+ #include <asm/cpu.h>
+ #include <asm/delay.h>
+@@ -102,9 +103,9 @@ show_regs (struct pt_regs *regs)
+ print_modules();
+ printk("\n");
+ show_regs_print_info(KERN_DEFAULT);
+- printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n",
++ printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s%s)\n",
+ regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(),
+- init_utsname()->release);
++ init_utsname()->release, LINUX_PACKAGE_ID);
+ printk("ip is at %pS\n", (void *)ip);
+ printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
+ regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
+--- a/arch/powerpc/kernel/process.c
++++ b/arch/powerpc/kernel/process.c
+@@ -38,6 +38,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/pkeys.h>
+ #include <linux/seq_buf.h>
++#include <generated/package.h>
+
+ #include <asm/interrupt.h>
+ #include <asm/io.h>
+@@ -1555,8 +1556,9 @@ static void __show_regs(struct pt_regs *
+
+ printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
+ regs->nip, regs->link, regs->ctr);
+- printk("REGS: %px TRAP: %04lx %s (%s)\n",
+- regs, regs->trap, print_tainted(), init_utsname()->release);
++ printk("REGS: %px TRAP: %04lx %s (%s%s)\n",
++ regs, regs->trap, print_tainted(), init_utsname()->release,
++ LINUX_PACKAGE_ID);
+ printk("MSR: "REG" ", regs->msr);
+ print_msr_bits(regs->msr);
+ pr_cont(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
+--- a/arch/x86/um/sysrq_64.c
++++ b/arch/x86/um/sysrq_64.c
+@@ -9,6 +9,7 @@
+ #include <linux/sched.h>
+ #include <linux/sched/debug.h>
+ #include <linux/utsname.h>
++#include <generated/package.h>
+ #include <asm/current.h>
+ #include <asm/ptrace.h>
+ #include <asm/sysrq.h>
+@@ -17,8 +18,9 @@ void show_regs(struct pt_regs *regs)
+ {
+ printk("\n");
+ print_modules();
+- printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+- current->comm, print_tainted(), init_utsname()->release);
++ printk(KERN_INFO "Pid: %d, comm: %.20s %s %s%s\n", task_pid_nr(current),
++ current->comm, print_tainted(), init_utsname()->release,
++ LINUX_PACKAGE_ID);
+ printk(KERN_INFO "RIP: %04lx:%pS\n", PT_REGS_CS(regs) & 0xffff,
+ (void *)PT_REGS_IP(regs));
+ printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs),
+--- a/kernel/hung_task.c
++++ b/kernel/hung_task.c
+@@ -24,6 +24,7 @@
+ #include <linux/sched/sysctl.h>
+
+ #include <trace/events/sched.h>
++#include <generated/package.h>
+
+ /*
+ * The number of tasks checked:
+@@ -131,10 +132,11 @@ static void check_hung_task(struct task_
+ sysctl_hung_task_warnings--;
+ pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
+ t->comm, t->pid, (jiffies - t->last_switch_time) / HZ);
+- pr_err(" %s %s %.*s\n",
++ pr_err(" %s %s %.*s%s\n",
+ print_tainted(), init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+- init_utsname()->version);
++ init_utsname()->version,
++ LINUX_PACKAGE_ID);
+ pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
+ " disables this message.\n");
+ sched_show_task(t);
+--- a/lib/dump_stack.c
++++ b/lib/dump_stack.c
+@@ -14,6 +14,7 @@
+ #include <linux/kexec.h>
+ #include <linux/utsname.h>
+ #include <linux/stop_machine.h>
++#include <generated/package.h>
+
+ static char dump_stack_arch_desc_str[128];
+
+@@ -54,13 +55,15 @@ void __init dump_stack_set_arch_desc(con
+ */
+ void dump_stack_print_info(const char *log_lvl)
+ {
+- printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s" BUILD_ID_FMT "\n",
++ printk("%sCPU: %d PID: %d Comm: %.20s %s%s %s %.*s %s" BUILD_ID_FMT "\n",
+ log_lvl, raw_smp_processor_id(), current->pid, current->comm,
+ kexec_crash_loaded() ? "Kdump: loaded " : "",
+ print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+- init_utsname()->version, BUILD_ID_VAL);
++ init_utsname()->version,
++ LINUX_PACKAGE_ID,
++ BUILD_ID_VAL);
+
+ if (dump_stack_arch_desc_str[0] != '\0')
+ printk("%sHardware name: %s\n",
diff --git a/debian/patches/debian/wireless-add-debian-wireless-regdb-certificates.patch b/debian/patches/debian/wireless-add-debian-wireless-regdb-certificates.patch
new file mode 100644
index 0000000000..edbf8657f4
--- /dev/null
+++ b/debian/patches/debian/wireless-add-debian-wireless-regdb-certificates.patch
@@ -0,0 +1,1452 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 13 Apr 2018 20:10:28 +0100
+Subject: wireless: Add Debian wireless-regdb certificates
+Forwarded: not-needed
+
+This hex dump is generated using:
+
+{
+ for cert in debian/certs/wireless-regdb-*.pem; do
+ openssl x509 -in $cert -outform der;
+ done
+} | hexdump -v -e '1/1 "0x%.2x," "\n"' > net/wireless/certs/debian.hex
+---
+ net/wireless/certs/debian.hex | 1426 +++++++++++++++++++++++++++++++++
+ 1 file changed, 1426 insertions(+)
+ create mode 100644 net/wireless/certs/debian.hex
+
+diff --git a/net/wireless/certs/debian.hex b/net/wireless/certs/debian.hex
+new file mode 100644
+index 000000000000..c5ab03f8c500
+--- /dev/null
++++ b/net/wireless/certs/debian.hex
+@@ -0,0 +1,1426 @@
++0x30,
++0x82,
++0x02,
++0xbd,
++0x30,
++0x82,
++0x01,
++0xa5,
++0x02,
++0x14,
++0x57,
++0x7e,
++0x02,
++0x1c,
++0xb9,
++0x80,
++0xe0,
++0xe8,
++0x20,
++0x82,
++0x1b,
++0xa7,
++0xb5,
++0x4b,
++0x49,
++0x61,
++0xb8,
++0xb4,
++0xfa,
++0xdf,
++0x30,
++0x0d,
++0x06,
++0x09,
++0x2a,
++0x86,
++0x48,
++0x86,
++0xf7,
++0x0d,
++0x01,
++0x01,
++0x0b,
++0x05,
++0x00,
++0x30,
++0x1a,
++0x31,
++0x18,
++0x30,
++0x16,
++0x06,
++0x03,
++0x55,
++0x04,
++0x03,
++0x0c,
++0x0f,
++0x62,
++0x65,
++0x6e,
++0x68,
++0x40,
++0x64,
++0x65,
++0x62,
++0x69,
++0x61,
++0x6e,
++0x2e,
++0x6f,
++0x72,
++0x67,
++0x30,
++0x20,
++0x17,
++0x0d,
++0x32,
++0x30,
++0x30,
++0x31,
++0x33,
++0x30,
++0x31,
++0x33,
++0x32,
++0x36,
++0x31,
++0x33,
++0x5a,
++0x18,
++0x0f,
++0x32,
++0x31,
++0x32,
++0x30,
++0x30,
++0x31,
++0x30,
++0x36,
++0x31,
++0x33,
++0x32,
++0x36,
++0x31,
++0x33,
++0x5a,
++0x30,
++0x1a,
++0x31,
++0x18,
++0x30,
++0x16,
++0x06,
++0x03,
++0x55,
++0x04,
++0x03,
++0x0c,
++0x0f,
++0x62,
++0x65,
++0x6e,
++0x68,
++0x40,
++0x64,
++0x65,
++0x62,
++0x69,
++0x61,
++0x6e,
++0x2e,
++0x6f,
++0x72,
++0x67,
++0x30,
++0x82,
++0x01,
++0x22,
++0x30,
++0x0d,
++0x06,
++0x09,
++0x2a,
++0x86,
++0x48,
++0x86,
++0xf7,
++0x0d,
++0x01,
++0x01,
++0x01,
++0x05,
++0x00,
++0x03,
++0x82,
++0x01,
++0x0f,
++0x00,
++0x30,
++0x82,
++0x01,
++0x0a,
++0x02,
++0x82,
++0x01,
++0x01,
++0x00,
++0x9d,
++0xe1,
++0x77,
++0xa0,
++0x24,
++0xa0,
++0xd5,
++0x79,
++0x65,
++0x3a,
++0x07,
++0x90,
++0xc9,
++0xf6,
++0xa5,
++0xa6,
++0x1f,
++0x84,
++0x1c,
++0x23,
++0x07,
++0x4b,
++0x4f,
++0xa5,
++0x03,
++0xc6,
++0x0f,
++0xf7,
++0x54,
++0xd5,
++0x8b,
++0x7e,
++0x79,
++0x81,
++0x00,
++0xd2,
++0xe9,
++0x3d,
++0xf4,
++0x97,
++0xfe,
++0x84,
++0xcd,
++0x55,
++0xbd,
++0xc9,
++0x8f,
++0x21,
++0x57,
++0x88,
++0x06,
++0x39,
++0x90,
++0x66,
++0x41,
++0x26,
++0x79,
++0x2c,
++0xca,
++0x3f,
++0x95,
++0x87,
++0x01,
++0x11,
++0x2f,
++0x2f,
++0xb0,
++0xe1,
++0x0b,
++0x43,
++0xfc,
++0x5f,
++0x2f,
++0x4f,
++0x67,
++0x04,
++0xdb,
++0x4d,
++0xb7,
++0x72,
++0x4d,
++0xd1,
++0xc5,
++0x76,
++0x73,
++0x4d,
++0x91,
++0x69,
++0xb0,
++0x71,
++0x17,
++0x36,
++0xea,
++0xab,
++0x0a,
++0x3a,
++0xcd,
++0x95,
++0x9b,
++0x76,
++0x1b,
++0x8e,
++0x21,
++0x17,
++0x8f,
++0xc5,
++0x02,
++0xbf,
++0x24,
++0xc7,
++0xc0,
++0x40,
++0xb1,
++0x3b,
++0xc4,
++0x80,
++0x7c,
++0x71,
++0xa5,
++0x51,
++0xdc,
++0xf7,
++0x3a,
++0x58,
++0x7f,
++0xb1,
++0x07,
++0x81,
++0x8a,
++0x10,
++0xd1,
++0xf6,
++0x93,
++0x17,
++0x71,
++0xe0,
++0xfa,
++0x51,
++0x79,
++0x15,
++0xd4,
++0xd7,
++0x8f,
++0xad,
++0xbd,
++0x6f,
++0x38,
++0xe1,
++0x26,
++0x7d,
++0xbc,
++0xf0,
++0x3e,
++0x80,
++0x89,
++0xb4,
++0xec,
++0x8e,
++0x69,
++0x90,
++0xdb,
++0x97,
++0x8a,
++0xf0,
++0x23,
++0x23,
++0x83,
++0x82,
++0x3b,
++0x6a,
++0xb1,
++0xac,
++0xeb,
++0xe7,
++0x99,
++0x74,
++0x2a,
++0x35,
++0x8e,
++0xa9,
++0x64,
++0xfd,
++0x46,
++0x9e,
++0xe8,
++0xe5,
++0x48,
++0x61,
++0x31,
++0x6e,
++0xe6,
++0xfc,
++0x19,
++0x18,
++0x54,
++0xc3,
++0x1b,
++0x4f,
++0xd6,
++0x00,
++0x44,
++0x87,
++0x1c,
++0x37,
++0x45,
++0xea,
++0xf5,
++0xc9,
++0xcb,
++0x0f,
++0x0c,
++0x55,
++0xec,
++0xcf,
++0x6a,
++0xc2,
++0x45,
++0x26,
++0x23,
++0xa2,
++0x31,
++0x52,
++0x4d,
++0xee,
++0x21,
++0x7d,
++0xfd,
++0x58,
++0x72,
++0xc2,
++0x28,
++0xc5,
++0x8e,
++0xa9,
++0xd0,
++0xee,
++0x01,
++0x77,
++0x08,
++0xa5,
++0xf0,
++0x22,
++0x2b,
++0x47,
++0x79,
++0x2b,
++0xcf,
++0x9a,
++0x46,
++0xb5,
++0x8f,
++0xfd,
++0x64,
++0xa2,
++0xb5,
++0xed,
++0x02,
++0x03,
++0x01,
++0x00,
++0x01,
++0x30,
++0x0d,
++0x06,
++0x09,
++0x2a,
++0x86,
++0x48,
++0x86,
++0xf7,
++0x0d,
++0x01,
++0x01,
++0x0b,
++0x05,
++0x00,
++0x03,
++0x82,
++0x01,
++0x01,
++0x00,
++0x20,
++0x44,
++0xfe,
++0xa9,
++0x9e,
++0xdd,
++0x9b,
++0xea,
++0xce,
++0x25,
++0x75,
++0x08,
++0xf0,
++0x2b,
++0x53,
++0xf7,
++0x5a,
++0x36,
++0x1c,
++0x4a,
++0x23,
++0x7f,
++0xd0,
++0x41,
++0x3c,
++0x12,
++0x2b,
++0xb9,
++0x80,
++0x4e,
++0x8a,
++0x15,
++0x5d,
++0x1f,
++0x40,
++0xa7,
++0x26,
++0x28,
++0x32,
++0xc3,
++0x5b,
++0x06,
++0x28,
++0x2d,
++0x3d,
++0x08,
++0x09,
++0x1e,
++0x01,
++0xe9,
++0x67,
++0xe3,
++0x33,
++0xe6,
++0x15,
++0x45,
++0x39,
++0xee,
++0x17,
++0x83,
++0xdb,
++0x42,
++0xff,
++0x7f,
++0x35,
++0xf4,
++0xac,
++0x16,
++0xdb,
++0xba,
++0xb8,
++0x1a,
++0x20,
++0x21,
++0x41,
++0xff,
++0xf3,
++0x92,
++0xff,
++0x65,
++0x6e,
++0x29,
++0x16,
++0xd0,
++0xbf,
++0x8d,
++0xdf,
++0x48,
++0x2c,
++0x73,
++0x36,
++0x7f,
++0x22,
++0xe6,
++0xee,
++0x78,
++0xb4,
++0x63,
++0x83,
++0x0e,
++0x39,
++0xeb,
++0xaf,
++0x10,
++0x2a,
++0x90,
++0xd3,
++0xfc,
++0xe6,
++0xc3,
++0x8f,
++0x97,
++0x5b,
++0x76,
++0xbf,
++0x9b,
++0xf5,
++0x98,
++0xd2,
++0x53,
++0x06,
++0x8b,
++0xf8,
++0xa4,
++0x04,
++0x9b,
++0x1b,
++0x62,
++0x6a,
++0x9d,
++0xac,
++0xe6,
++0x4b,
++0x0d,
++0xc9,
++0xd7,
++0x56,
++0x63,
++0x15,
++0x01,
++0x38,
++0x8c,
++0xbe,
++0xf1,
++0x44,
++0xc4,
++0x38,
++0x27,
++0xe0,
++0xcf,
++0x72,
++0xd6,
++0x3d,
++0xe4,
++0xf7,
++0x4b,
++0x3b,
++0xd2,
++0xb1,
++0x0c,
++0xd5,
++0x83,
++0x6d,
++0x1e,
++0x10,
++0x04,
++0x69,
++0x29,
++0x88,
++0x69,
++0xe0,
++0x7d,
++0xd7,
++0xdb,
++0xb4,
++0x59,
++0x72,
++0x8d,
++0x9d,
++0x3c,
++0x43,
++0xaf,
++0xc6,
++0x7d,
++0xb7,
++0x21,
++0x15,
++0x52,
++0x8a,
++0xe9,
++0x9b,
++0x6b,
++0x2e,
++0xe8,
++0x27,
++0x3c,
++0x3f,
++0x2d,
++0x84,
++0xfb,
++0x9a,
++0x22,
++0x0a,
++0x9f,
++0x6a,
++0x25,
++0xe6,
++0x39,
++0xe4,
++0x74,
++0x73,
++0xb6,
++0x2a,
++0x70,
++0xaa,
++0x1d,
++0xcb,
++0xcc,
++0xd4,
++0xa0,
++0x1b,
++0x26,
++0x71,
++0x63,
++0x04,
++0xc5,
++0x12,
++0x21,
++0x48,
++0xba,
++0x92,
++0x27,
++0x06,
++0xa8,
++0x3e,
++0x6d,
++0xa1,
++0x43,
++0xa5,
++0xd2,
++0x2a,
++0xf7,
++0xca,
++0xc4,
++0x26,
++0xe8,
++0x5b,
++0x1f,
++0xe4,
++0xdc,
++0x89,
++0xdc,
++0x1f,
++0x04,
++0x79,
++0x3f,
++0x30,
++0x82,
++0x02,
++0xcd,
++0x30,
++0x82,
++0x01,
++0xb5,
++0x02,
++0x14,
++0x3a,
++0xbb,
++0xc6,
++0xec,
++0x14,
++0x6e,
++0x09,
++0xd1,
++0xb6,
++0x01,
++0x6a,
++0xb9,
++0xd6,
++0xcf,
++0x71,
++0xdd,
++0x23,
++0x3f,
++0x03,
++0x28,
++0x30,
++0x0d,
++0x06,
++0x09,
++0x2a,
++0x86,
++0x48,
++0x86,
++0xf7,
++0x0d,
++0x01,
++0x01,
++0x0b,
++0x05,
++0x00,
++0x30,
++0x22,
++0x31,
++0x20,
++0x30,
++0x1e,
++0x06,
++0x03,
++0x55,
++0x04,
++0x03,
++0x0c,
++0x17,
++0x72,
++0x6f,
++0x6d,
++0x61,
++0x69,
++0x6e,
++0x2e,
++0x70,
++0x65,
++0x72,
++0x69,
++0x65,
++0x72,
++0x40,
++0x67,
++0x6d,
++0x61,
++0x69,
++0x6c,
++0x2e,
++0x63,
++0x6f,
++0x6d,
++0x30,
++0x20,
++0x17,
++0x0d,
++0x32,
++0x30,
++0x30,
++0x32,
++0x32,
++0x34,
++0x31,
++0x39,
++0x30,
++0x31,
++0x34,
++0x34,
++0x5a,
++0x18,
++0x0f,
++0x32,
++0x31,
++0x32,
++0x30,
++0x30,
++0x31,
++0x33,
++0x31,
++0x31,
++0x39,
++0x30,
++0x31,
++0x34,
++0x34,
++0x5a,
++0x30,
++0x22,
++0x31,
++0x20,
++0x30,
++0x1e,
++0x06,
++0x03,
++0x55,
++0x04,
++0x03,
++0x0c,
++0x17,
++0x72,
++0x6f,
++0x6d,
++0x61,
++0x69,
++0x6e,
++0x2e,
++0x70,
++0x65,
++0x72,
++0x69,
++0x65,
++0x72,
++0x40,
++0x67,
++0x6d,
++0x61,
++0x69,
++0x6c,
++0x2e,
++0x63,
++0x6f,
++0x6d,
++0x30,
++0x82,
++0x01,
++0x22,
++0x30,
++0x0d,
++0x06,
++0x09,
++0x2a,
++0x86,
++0x48,
++0x86,
++0xf7,
++0x0d,
++0x01,
++0x01,
++0x01,
++0x05,
++0x00,
++0x03,
++0x82,
++0x01,
++0x0f,
++0x00,
++0x30,
++0x82,
++0x01,
++0x0a,
++0x02,
++0x82,
++0x01,
++0x01,
++0x00,
++0xf0,
++0xb8,
++0x4f,
++0x3f,
++0x70,
++0x78,
++0xf8,
++0x74,
++0x45,
++0xa2,
++0x28,
++0xaf,
++0x04,
++0x75,
++0x04,
++0xa3,
++0xf3,
++0xa7,
++0xc7,
++0x04,
++0xac,
++0xb6,
++0xe1,
++0xfc,
++0xe1,
++0xc0,
++0x3d,
++0xe0,
++0x26,
++0x90,
++0x8a,
++0x45,
++0x60,
++0xc4,
++0x75,
++0xf3,
++0x1a,
++0x33,
++0x37,
++0x56,
++0x7d,
++0x30,
++0x07,
++0x75,
++0x0e,
++0xa6,
++0x79,
++0x06,
++0x95,
++0x9d,
++0x17,
++0x3c,
++0x09,
++0xa9,
++0x7f,
++0xab,
++0x95,
++0x5d,
++0xed,
++0xe0,
++0x75,
++0x26,
++0x2f,
++0x65,
++0x65,
++0xcd,
++0x61,
++0xb1,
++0x33,
++0x27,
++0x67,
++0x41,
++0xa1,
++0x01,
++0x13,
++0xe9,
++0x13,
++0x6a,
++0x6d,
++0x4e,
++0x98,
++0xe1,
++0x9e,
++0x7b,
++0x0b,
++0x5b,
++0x44,
++0xef,
++0x68,
++0x5a,
++0x6f,
++0x7d,
++0x97,
++0xa1,
++0x33,
++0x22,
++0x97,
++0x12,
++0x21,
++0x09,
++0x8f,
++0x90,
++0xe0,
++0x25,
++0x94,
++0xdd,
++0x8a,
++0x3a,
++0xf7,
++0x4a,
++0x60,
++0x04,
++0x26,
++0x6d,
++0x00,
++0x82,
++0xe4,
++0xcf,
++0x64,
++0x1c,
++0x79,
++0x15,
++0x24,
++0xf2,
++0x42,
++0x86,
++0xf5,
++0x10,
++0x86,
++0xac,
++0x20,
++0x88,
++0x90,
++0x87,
++0xdf,
++0x8c,
++0x37,
++0x7c,
++0xbf,
++0x35,
++0xd5,
++0x6f,
++0x9f,
++0x77,
++0xc3,
++0xcd,
++0x69,
++0x25,
++0x06,
++0xc2,
++0x65,
++0x51,
++0x71,
++0x89,
++0x7f,
++0x6e,
++0x4d,
++0xe5,
++0xd5,
++0x8a,
++0x36,
++0x1a,
++0xad,
++0xc1,
++0x18,
++0xd6,
++0x14,
++0x42,
++0x87,
++0xf0,
++0x93,
++0x83,
++0xf1,
++0x99,
++0x74,
++0xc4,
++0x13,
++0xaa,
++0x3b,
++0x66,
++0x85,
++0x6f,
++0xe0,
++0xbc,
++0x5f,
++0xb6,
++0x40,
++0xa6,
++0x41,
++0x06,
++0x0a,
++0xba,
++0x0e,
++0xe9,
++0x32,
++0x44,
++0x10,
++0x39,
++0x53,
++0xcd,
++0xbf,
++0xf3,
++0xd3,
++0x26,
++0xf6,
++0xb6,
++0x2b,
++0x40,
++0x2e,
++0xb9,
++0x88,
++0xc1,
++0xf4,
++0xe3,
++0xa0,
++0x28,
++0x77,
++0x4f,
++0xba,
++0xa8,
++0xca,
++0x9c,
++0x05,
++0xba,
++0x88,
++0x96,
++0x99,
++0x54,
++0x89,
++0xa2,
++0x8d,
++0xf3,
++0x73,
++0xa1,
++0x8c,
++0x4a,
++0xa8,
++0x71,
++0xee,
++0x2e,
++0xd2,
++0x83,
++0x14,
++0x48,
++0xbd,
++0x98,
++0xc6,
++0xce,
++0xdc,
++0xa8,
++0xa3,
++0x97,
++0x2e,
++0x40,
++0x16,
++0x2f,
++0x02,
++0x03,
++0x01,
++0x00,
++0x01,
++0x30,
++0x0d,
++0x06,
++0x09,
++0x2a,
++0x86,
++0x48,
++0x86,
++0xf7,
++0x0d,
++0x01,
++0x01,
++0x0b,
++0x05,
++0x00,
++0x03,
++0x82,
++0x01,
++0x01,
++0x00,
++0x76,
++0x5d,
++0x03,
++0x3d,
++0xb6,
++0x96,
++0x00,
++0x1b,
++0x6e,
++0x0c,
++0xdd,
++0xbb,
++0xc8,
++0xdf,
++0xbc,
++0xeb,
++0x6c,
++0x01,
++0x40,
++0x1a,
++0x2b,
++0x07,
++0x60,
++0xa1,
++0x1a,
++0xe1,
++0x43,
++0x57,
++0xfa,
++0xbe,
++0xde,
++0xbb,
++0x8f,
++0x73,
++0xf3,
++0x92,
++0xa2,
++0xaa,
++0x83,
++0x01,
++0xc1,
++0x17,
++0xe4,
++0x9d,
++0x09,
++0x41,
++0xe0,
++0x32,
++0x33,
++0x97,
++0x4b,
++0xf2,
++0xdc,
++0x0f,
++0x8b,
++0xa8,
++0xb8,
++0x5a,
++0x04,
++0x86,
++0xf6,
++0x71,
++0xa1,
++0x97,
++0xd0,
++0x54,
++0x56,
++0x10,
++0x8e,
++0x54,
++0x99,
++0x0d,
++0x2a,
++0xa9,
++0xaf,
++0x1b,
++0x55,
++0x59,
++0x06,
++0x2b,
++0xa4,
++0x5f,
++0xb1,
++0x54,
++0xa6,
++0xec,
++0xc7,
++0xd6,
++0x43,
++0xee,
++0x86,
++0x2c,
++0x9b,
++0x18,
++0x9d,
++0x8f,
++0x00,
++0x82,
++0xc1,
++0x88,
++0x61,
++0x16,
++0x85,
++0x3c,
++0x17,
++0x56,
++0xfe,
++0x6a,
++0xa0,
++0x7a,
++0x68,
++0xc5,
++0x7b,
++0x3d,
++0x3c,
++0xb6,
++0x13,
++0x18,
++0x99,
++0x6d,
++0x74,
++0x65,
++0x13,
++0x67,
++0xb7,
++0xfc,
++0x5a,
++0x44,
++0x48,
++0x72,
++0xa0,
++0x73,
++0xb8,
++0xff,
++0x02,
++0x9d,
++0x7c,
++0x5b,
++0xf9,
++0x7c,
++0x75,
++0x0a,
++0x3c,
++0x81,
++0x80,
++0x3c,
++0x41,
++0xf2,
++0xd5,
++0xfa,
++0x3d,
++0x1f,
++0xe3,
++0xda,
++0x8c,
++0xa5,
++0x17,
++0x1f,
++0x53,
++0x1a,
++0x75,
++0xad,
++0x4e,
++0x11,
++0x1c,
++0x07,
++0xec,
++0x0a,
++0x69,
++0xfd,
++0x33,
++0xfa,
++0x32,
++0x7e,
++0x66,
++0xf5,
++0x29,
++0xe8,
++0x4d,
++0x8a,
++0xfa,
++0x0d,
++0x4b,
++0x68,
++0xc3,
++0x95,
++0x11,
++0xba,
++0x6f,
++0x1e,
++0x07,
++0x8c,
++0x85,
++0xc7,
++0xc7,
++0xc9,
++0xc1,
++0x30,
++0xa3,
++0x70,
++0xb0,
++0xa1,
++0xe0,
++0xd5,
++0x85,
++0x15,
++0x94,
++0x77,
++0xc1,
++0x1c,
++0x91,
++0xf1,
++0x5f,
++0x50,
++0xcd,
++0x2c,
++0x57,
++0x4b,
++0x22,
++0x4f,
++0xee,
++0x95,
++0xd7,
++0xa7,
++0xa4,
++0x59,
++0x62,
++0xae,
++0xb9,
++0xbf,
++0xd7,
++0x63,
++0x5a,
++0x04,
++0xfc,
++0x24,
++0x11,
++0xae,
++0x34,
++0x4b,
++0xf4,
++0x0c,
++0x9f,
++0x0b,
++0x59,
++0x7d,
++0x27,
++0x39,
++0x54,
++0x69,
++0x4f,
++0xfd,
++0x6e,
++0x44,
++0x9f,
++0x21,
+--
+2.25.1
+
diff --git a/debian/patches/debian/yama-disable-by-default.patch b/debian/patches/debian/yama-disable-by-default.patch
new file mode 100644
index 0000000000..c33ac0c9d6
--- /dev/null
+++ b/debian/patches/debian/yama-disable-by-default.patch
@@ -0,0 +1,32 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Subject: yama: Disable by default
+Date: Wed, 19 Jun 2013 04:35:28 +0100
+Bug-Debian: https://bugs.debian.org/712740
+Forwarded: not-needed
+
+---
+ security/yama/yama_lsm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
+index efac68556b45..95ff3e778a17 100644
+--- a/security/yama/yama_lsm.c
++++ b/security/yama/yama_lsm.c
+@@ -28,7 +28,7 @@
+ #define YAMA_SCOPE_CAPABILITY 2
+ #define YAMA_SCOPE_NO_ATTACH 3
+
+-static int ptrace_scope = YAMA_SCOPE_RELATIONAL;
++static int ptrace_scope = YAMA_SCOPE_DISABLED;
+
+ /* describe a ptrace relationship for potential exception */
+ struct ptrace_relation {
+@@ -481,7 +481,7 @@ static inline void yama_init_sysctl(void) { }
+
+ static int __init yama_init(void)
+ {
+- pr_info("Yama: becoming mindful.\n");
++ pr_info("Yama: disabled by default; enable with sysctl kernel.yama.*\n");
+ security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
+ yama_init_sysctl();
+ return 0;
diff --git a/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch b/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch
new file mode 100644
index 0000000000..f2278ce63e
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch
@@ -0,0 +1,130 @@
+From: "Lee, Chun-Yi" <joeyli.kernel@gmail.com>
+Date: Tue, 13 Mar 2018 18:38:02 +0800
+Subject: [PATCH 3/4] MODSIGN: checking the blacklisted hash before loading a
+ kernel module
+Origin: https://lore.kernel.org/patchwork/patch/933175/
+
+This patch adds the logic for checking the kernel module's hash
+base on blacklist. The hash must be generated by sha256 and enrolled
+to dbx/mokx.
+
+For example:
+ sha256sum sample.ko
+ mokutil --mokx --import-hash $HASH_RESULT
+
+Whether the signature on ko file is stripped or not, the hash can be
+compared by kernel.
+
+Cc: David Howells <dhowells@redhat.com>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: "Lee, Chun-Yi" <jlee@suse.com>
+[Rebased by Luca Boccassi]
+[bwh: Forward-ported to 5.19:
+ - The type parameter to is_hash_blacklisted() is now an enumeration
+ rather than a string
+ - Adjust filename, context]
+---
+ kernel/module/signing.c | 59 +++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 57 insertions(+), 2 deletions(-)
+
+--- a/kernel/module/signing.c
++++ b/kernel/module/signing.c
+@@ -13,6 +13,8 @@
+ #include <linux/verification.h>
+ #include <linux/security.h>
+ #include <crypto/public_key.h>
++#include <crypto/hash.h>
++#include <keys/system_keyring.h>
+ #include <uapi/linux/module.h>
+ #include "internal.h"
+
+@@ -37,13 +39,60 @@
+ sig_enforce = true;
+ }
+
++static int mod_is_hash_blacklisted(const void *mod, size_t verifylen)
++{
++ struct crypto_shash *tfm;
++ struct shash_desc *desc;
++ size_t digest_size, desc_size;
++ u8 *digest;
++ int ret;
++
++ tfm = crypto_alloc_shash("sha256", 0, 0);
++ if (IS_ERR(tfm)) {
++ ret = PTR_ERR(tfm);
++ goto error_return;
++ }
++
++ desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
++ digest_size = crypto_shash_digestsize(tfm);
++ digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
++ if (!digest) {
++ pr_err("digest memory buffer allocate fail\n");
++ ret = -ENOMEM;
++ goto error_digest;
++ }
++ desc = (void *)digest + digest_size;
++ desc->tfm = tfm;
++ ret = crypto_shash_init(desc);
++ if (ret < 0)
++ goto error_shash;
++
++ ret = crypto_shash_finup(desc, mod, verifylen, digest);
++ if (ret < 0)
++ goto error_shash;
++
++ pr_debug("%ld digest: %*phN\n", verifylen, (int) digest_size, digest);
++
++ ret = is_hash_blacklisted(digest, digest_size, BLACKLIST_HASH_BINARY);
++ if (ret == -EKEYREJECTED)
++ pr_err("Module hash %*phN is blacklisted\n",
++ (int) digest_size, digest);
++
++error_shash:
++ kfree(digest);
++error_digest:
++ crypto_free_shash(tfm);
++error_return:
++ return ret;
++}
++
+ /*
+ * Verify the signature on a module.
+ */
+ int mod_verify_sig(const void *mod, struct load_info *info)
+ {
+ struct module_signature ms;
+- size_t sig_len, modlen = info->len;
++ size_t sig_len, modlen = info->len, wholelen;
+ int ret;
+
+ pr_devel("==>%s(,%zu)\n", __func__, modlen);
+@@ -51,6 +100,7 @@
+ if (modlen <= sizeof(ms))
+ return -EBADMSG;
+
++ wholelen = modlen + sizeof(MODULE_SIG_STRING) - 1;
+ memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
+
+ ret = mod_check_sig(&ms, modlen, "module");
+@@ -61,10 +111,17 @@
+ modlen -= sig_len + sizeof(ms);
+ info->len = modlen;
+
+- return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
++ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
+ VERIFY_USE_SECONDARY_KEYRING,
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
++ pr_devel("verify_pkcs7_signature() = %d\n", ret);
++
++ /* checking hash of module is in blacklist */
++ if (!ret)
++ ret = mod_is_hash_blacklisted(mod, wholelen);
++
++ return ret;
+ }
+
+ int module_sig_check(struct load_info *info, int flags)
diff --git a/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch b/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
new file mode 100644
index 0000000000..e46aefe4d0
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
@@ -0,0 +1,33 @@
+From: Robert Holmes <robeholmes@gmail.com>
+Date: Tue, 23 Apr 2019 07:39:29 +0000
+Subject: [PATCH] KEYS: Make use of platform keyring for module signature
+ verify
+Bug-Debian: https://bugs.debian.org/935945
+Bug-Debian: https://bugs.debian.org/1030200
+Origin: https://src.fedoraproject.org/rpms/kernel/raw/master/f/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
+Forwarded: https://lore.kernel.org/linux-modules/qvgp2il2co4iyxkzxvcs4p2bpyilqsbfgcprtpfrsajwae2etc@3z2s2o52i3xg/t/#u
+
+This allows a cert in DB to be used to sign modules,
+in addition to certs in the MoK and built-in keyrings.
+
+Signed-off-by: Robert Holmes <robeholmes@gmail.com>
+Signed-off-by: Jeremy Cline <jcline@redhat.com>
+[bwh: Forward-ported to 5.19: adjust filename]
+[наб: reinstate for 6.1, re-write description]
+---
+--- a/kernel/module/signing.c
++++ b/kernel/module/signing.c
+@@ -116,6 +116,13 @@ int mod_verify_sig(const void *mod, stru
+ VERIFYING_MODULE_SIGNATURE,
+ NULL, NULL);
+ pr_devel("verify_pkcs7_signature() = %d\n", ret);
++ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING)) {
++ ret = verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
++ VERIFY_USE_PLATFORM_KEYRING,
++ VERIFYING_MODULE_SIGNATURE,
++ NULL, NULL);
++ pr_devel("verify_pkcs7_signature() = %d\n", ret);
++ }
+
+ /* checking hash of module is in blacklist */
+ if (!ret)
diff --git a/debian/patches/features/all/db-mok-keyring/trust-machine-keyring-by-default.patch b/debian/patches/features/all/db-mok-keyring/trust-machine-keyring-by-default.patch
new file mode 100644
index 0000000000..c814c6d7f1
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/trust-machine-keyring-by-default.patch
@@ -0,0 +1,29 @@
+From 585cbcb982bffc4a8cee2f3d8d099fc64f9a74b9 Mon Sep 17 00:00:00 2001
+From: Luca Boccassi <bluca@debian.org>
+Date: Fri, 14 Oct 2022 00:22:06 +0200
+Subject: [PATCH] trust machine keyring (MoK) by default
+Forwarded: not-needed
+
+Debian always trusted keys in MoK by default. Upstream made it
+conditional on a new EFI variable being set.
+To keep backward compatibility skip this check.
+---
+ security/integrity/platform_certs/machine_keyring.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/security/integrity/platform_certs/machine_keyring.c b/security/integrity/platform_certs/machine_keyring.c
+index a401640a63cd..0627f14eacbe 100644
+--- a/security/integrity/platform_certs/machine_keyring.c
++++ b/security/integrity/platform_certs/machine_keyring.c
+@@ -68,10 +68,7 @@ static bool __init trust_moklist(void)
+
+ if (!initialized) {
+ initialized = true;
+- trust_mok = false;
+-
+- if (uefi_check_trust_mok_keys())
+- trust_mok = true;
++ trust_mok = true;
+ }
+
+ return trust_mok;
diff --git a/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch
new file mode 100644
index 0000000000..a24ba17ef9
--- /dev/null
+++ b/debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch
@@ -0,0 +1,149 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 24 Aug 2009 23:19:58 +0100
+Subject: af9005: Use request_firmware() to load register init script
+Forwarded: no
+
+Read the register init script from the Windows driver. This is sick
+but should avoid the potential copyright infringement in distributing
+a version of the script which is directly derived from the driver.
+---
+ drivers/media/dvb/dvb-usb/Kconfig | 2 +-
+ drivers/media/dvb/dvb-usb/af9005-fe.c | 66 ++++++++++++++++++++++++++------
+ 2 files changed, 54 insertions(+), 14 deletions(-)
+
+Index: debian-kernel/drivers/media/usb/dvb-usb/Kconfig
+===================================================================
+--- debian-kernel.orig/drivers/media/usb/dvb-usb/Kconfig
++++ debian-kernel/drivers/media/usb/dvb-usb/Kconfig
+@@ -260,10 +260,10 @@ config DVB_USB_OPERA1
+
+ config DVB_USB_AF9005
+ tristate "Afatech AF9005 DVB-T USB1.1 support"
+- depends on BROKEN
+ depends on DVB_USB
+ select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
++ select FW_LOADER
+ help
+ Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
+ and the TerraTec Cinergy T USB XE (Rev.1)
+Index: debian-kernel/drivers/media/usb/dvb-usb/af9005-fe.c
+===================================================================
+--- debian-kernel.orig/drivers/media/usb/dvb-usb/af9005-fe.c
++++ debian-kernel/drivers/media/usb/dvb-usb/af9005-fe.c
+@@ -9,10 +9,26 @@
+ * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
+ */
+ #include "af9005.h"
+-#include "af9005-script.h"
+ #include "mt2060.h"
+ #include "qt1010.h"
+ #include <asm/div64.h>
++#include <linux/firmware.h>
++
++/* Register initialisation script to be extracted from the Windows driver */
++
++typedef struct {
++ __le16 reg;
++ u8 pos;
++ u8 len;
++ u8 val;
++ u8 pad;
++} __packed RegDesc;
++
++#define WIN_DRV_NAME "AF05BDA.sys"
++#define WIN_DRV_VERSION "6.3.2.1"
++#define WIN_DRV_SIZE 133504
++#define WIN_DRV_SCRIPT_OFFSET 88316
++#define WIN_DRV_SCRIPT_SIZE 1110
+
+ struct af9005_fe_state {
+ struct dvb_usb_device *d;
+@@ -804,6 +820,8 @@ static int af9005_fe_init(struct dvb_fro
+ {
+ struct af9005_fe_state *state = fe->demodulator_priv;
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
++ const struct firmware *fw;
++ const RegDesc *script;
+ int ret, i, scriptlen;
+ u8 temp, temp0 = 0, temp1 = 0, temp2 = 0;
+ u8 buf[2];
+@@ -956,37 +974,55 @@ static int af9005_fe_init(struct dvb_fro
+ if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01)))
+ return ret;
+
+- /* load init script */
+- deb_info("load init script\n");
+- scriptlen = sizeof(script) / sizeof(RegDesc);
++ /* load and validate init script */
++ deb_info("load init script from Windows driver\n");
++ ret = request_firmware(&fw, WIN_DRV_NAME, &state->d->udev->dev);
++ if (ret)
++ return ret;
++ BUILD_BUG_ON(sizeof(RegDesc) != 6);
++ if (fw->size != WIN_DRV_SIZE ||
++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET,
++ "\x80\xa1\x00\x08\x0a\x00", 6) ||
++ memcmp(fw->data + WIN_DRV_SCRIPT_OFFSET + WIN_DRV_SCRIPT_SIZE - 6,
++ "\x49\xa3\x00\x06\x02\x00", 6)) {
++ err("%s is invalid - should be version %s, size %u bytes\n",
++ WIN_DRV_NAME, WIN_DRV_VERSION, WIN_DRV_SIZE);
++ ret = -EINVAL;
++ goto fail_release;
++ }
++
++ script = (const RegDesc *)(fw->data + WIN_DRV_SCRIPT_OFFSET);
++ scriptlen = WIN_DRV_SCRIPT_SIZE / sizeof(RegDesc);
+ for (i = 0; i < scriptlen; i++) {
++ u16 reg = le16_to_cpu(script[i].reg);
+ if ((ret =
+- af9005_write_register_bits(state->d, script[i].reg,
++ af9005_write_register_bits(state->d, reg,
+ script[i].pos,
+ script[i].len, script[i].val)))
+- return ret;
++ goto fail_release;
+ /* save 3 bytes of original fcw */
+- if (script[i].reg == 0xae18)
++ if (reg == 0xae18)
+ temp2 = script[i].val;
+- if (script[i].reg == 0xae19)
++ if (reg == 0xae19)
+ temp1 = script[i].val;
+- if (script[i].reg == 0xae1a)
++ if (reg == 0xae1a)
+ temp0 = script[i].val;
+
+ /* save original unplug threshold */
+- if (script[i].reg == xd_p_reg_unplug_th)
++ if (reg == xd_p_reg_unplug_th)
+ state->original_if_unplug_th = script[i].val;
+- if (script[i].reg == xd_p_reg_unplug_rf_gain_th)
++ if (reg == xd_p_reg_unplug_rf_gain_th)
+ state->original_rf_unplug_th = script[i].val;
+- if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th)
++ if (reg == xd_p_reg_unplug_dtop_if_gain_th)
+ state->original_dtop_if_unplug_th = script[i].val;
+- if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th)
++ if (reg == xd_p_reg_unplug_dtop_rf_gain_th)
+ state->original_dtop_rf_unplug_th = script[i].val;
+
+ }
+ state->original_fcw =
+ ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0;
+
++ release_firmware(fw);
+
+ /* save original TOPs */
+ deb_info("save original TOPs\n");
+@@ -1066,6 +1102,10 @@ static int af9005_fe_init(struct dvb_fro
+
+ deb_info("profit!\n");
+ return 0;
++
++fail_release:
++ release_firmware(fw);
++ return ret;
+ }
+
+ static int af9005_fe_sleep(struct dvb_frontend *fe)
diff --git a/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch b/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch
new file mode 100644
index 0000000000..6f1ba8e5a6
--- /dev/null
+++ b/debian/patches/features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch
@@ -0,0 +1,153 @@
+From: Linn Crosetto <linn@hpe.com>
+Date: Tue, 30 Aug 2016 11:54:38 -0600
+Subject: arm64: add kernel config option to lock down when in Secure Boot mode
+Bug-Debian: https://bugs.debian.org/831827
+Forwarded: no
+
+Add a kernel configuration option to lock down the kernel, to restrict
+userspace's ability to modify the running kernel when UEFI Secure Boot is
+enabled. Based on the x86 patch by Matthew Garrett.
+
+Determine the state of Secure Boot in the EFI stub and pass this to the
+kernel using the FDT.
+
+Signed-off-by: Linn Crosetto <linn@hpe.com>
+[bwh: Forward-ported to 4.10: adjust context]
+[Lukas Wunner: Forward-ported to 4.11: drop parts applied upstream]
+[bwh: Forward-ported to 4.15 and lockdown patch set:
+ - Pass result of efi_get_secureboot() in stub through to
+ efi_set_secure_boot() in main kernel
+ - Use lockdown API and naming]
+[bwh: Forward-ported to 4.19.3: adjust context in update_fdt()]
+[dannf: Moved init_lockdown() call after uefi_init(), fixing SB detection]
+[bwh: Drop call to init_lockdown(), as efi_set_secure_boot() now calls this]
+[bwh: Forward-ported to 5.6: efi_get_secureboot() no longer takes a
+ sys_table parameter]
+[bwh: Forward-ported to 5.7: EFI initialisation from FDT was rewritten, so:
+ - Add Secure Boot mode to the parameter enumeration in fdtparams.c
+ - Add a parameter to efi_get_fdt_params() to return the Secure Boot mode
+ - Since Xen does not have a property name defined for Secure Boot mode,
+ change efi_get_fdt_prop() to handle a missing property name by clearing
+ the output variable]
+[Salvatore Bonaccorso: Forward-ported to 5.10: f30f242fb131 ("efi: Rename
+arm-init to efi-init common for all arch") renamed arm-init.c to efi-init.c]
+---
+ drivers/firmware/efi/efi-init.c | 5 ++++-
+ drivers/firmware/efi/fdtparams.c | 12 +++++++++++-
+ drivers/firmware/efi/libstub/fdt.c | 6 ++++++
+ include/linux/efi.h | 3 ++-
+ 4 files changed, 23 insertions(+), 3 deletions(-)
+
+--- a/drivers/firmware/efi/efi-init.c
++++ b/drivers/firmware/efi/efi-init.c
+@@ -210,9 +210,10 @@ void __init efi_init(void)
+ {
+ struct efi_memory_map_data data;
+ u64 efi_system_table;
++ u32 secure_boot;
+
+ /* Grab UEFI information placed in FDT by stub */
+- efi_system_table = efi_get_fdt_params(&data);
++ efi_system_table = efi_get_fdt_params(&data, &secure_boot);
+ if (!efi_system_table)
+ return;
+
+@@ -234,6 +235,8 @@ void __init efi_init(void)
+ return;
+ }
+
++ efi_set_secure_boot(secure_boot);
++
+ reserve_regions();
+ /*
+ * For memblock manipulation, the cap should come after the memblock_add().
+--- a/drivers/firmware/efi/fdtparams.c
++++ b/drivers/firmware/efi/fdtparams.c
+@@ -16,6 +16,7 @@ enum {
+ MMSIZE,
+ DCSIZE,
+ DCVERS,
++ SBMODE,
+
+ PARAMCOUNT
+ };
+@@ -26,6 +27,7 @@ static __initconst const char name[][22]
+ [MMSIZE] = "MemMap Size ",
+ [DCSIZE] = "MemMap Desc. Size ",
+ [DCVERS] = "MemMap Desc. Version ",
++ [SBMODE] = "Secure Boot Enabled ",
+ };
+
+ static __initconst const struct {
+@@ -41,6 +43,7 @@ static __initconst const struct {
+ [MMSIZE] = "xen,uefi-mmap-size",
+ [DCSIZE] = "xen,uefi-mmap-desc-size",
+ [DCVERS] = "xen,uefi-mmap-desc-ver",
++ [SBMODE] = "",
+ }
+ }, {
+ #endif
+@@ -51,6 +54,7 @@ static __initconst const struct {
+ [MMSIZE] = "linux,uefi-mmap-size",
+ [DCSIZE] = "linux,uefi-mmap-desc-size",
+ [DCVERS] = "linux,uefi-mmap-desc-ver",
++ [SBMODE] = "linux,uefi-secure-boot",
+ }
+ }
+ };
+@@ -62,6 +66,11 @@ static int __init efi_get_fdt_prop(const
+ int len;
+ u64 val;
+
++ if (!pname[0]) {
++ memset(var, 0, size);
++ return 0;
++ }
++
+ prop = fdt_getprop(fdt, node, pname, &len);
+ if (!prop)
+ return 1;
+@@ -79,7 +88,7 @@ static int __init efi_get_fdt_prop(const
+ return 0;
+ }
+
+-u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
++u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm, u32 *secure_boot)
+ {
+ const void *fdt = initial_boot_params;
+ unsigned long systab;
+@@ -93,6 +102,7 @@ u64 __init efi_get_fdt_params(struct efi
+ [MMSIZE] = { &mm->size, sizeof(mm->size) },
+ [DCSIZE] = { &mm->desc_size, sizeof(mm->desc_size) },
+ [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) },
++ [SBMODE] = { secure_boot, sizeof(*secure_boot) },
+ };
+
+ BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
+--- a/drivers/firmware/efi/libstub/fdt.c
++++ b/drivers/firmware/efi/libstub/fdt.c
+@@ -148,6 +148,12 @@ static efi_status_t update_fdt(void *ori
+ }
+ }
+
++ fdt_val32 = cpu_to_fdt32(efi_get_secureboot());
++ status = fdt_setprop(fdt, node, "linux,uefi-secure-boot",
++ &fdt_val32, sizeof(fdt_val32));
++ if (status)
++ goto fdt_set_fail;
++
+ /* Shrink the FDT back to its minimum size: */
+ fdt_pack(fdt);
+
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -662,7 +662,8 @@ extern void efi_mem_reserve(phys_addr_t
+ extern int efi_mem_reserve_persistent(phys_addr_t addr, u64 size);
+ extern void efi_initialize_iomem_resources(struct resource *code_resource,
+ struct resource *data_resource, struct resource *bss_resource);
+-extern u64 efi_get_fdt_params(struct efi_memory_map_data *data);
++extern u64 efi_get_fdt_params(struct efi_memory_map_data *data,
++ u32 *secure_boot);
+ extern struct kobject *efi_kobj;
+
+ extern int efi_reboot_quirk_mode;
diff --git a/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch b/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch
new file mode 100644
index 0000000000..822beab21c
--- /dev/null
+++ b/debian/patches/features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch
@@ -0,0 +1,153 @@
+From: David Howells <dhowells@redhat.com>
+Date: Mon, 18 Feb 2019 12:45:03 +0000
+Subject: [28/30] efi: Add an EFI_SECURE_BOOT flag to indicate secure boot mode
+Origin: https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/commit?id=a5d70c55c603233c192b375f72116a395909da28
+
+UEFI machines can be booted in Secure Boot mode. Add an EFI_SECURE_BOOT
+flag that can be passed to efi_enabled() to find out whether secure boot is
+enabled.
+
+Move the switch-statement in x86's setup_arch() that inteprets the
+secure_boot boot parameter to generic code and set the bit there.
+
+Suggested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
+cc: linux-efi@vger.kernel.org
+[rperier: Forward-ported to 5.5:
+ - Use pr_warn()
+ - Adjust context]
+[bwh: Forward-ported to 5.6: adjust context]
+[bwh: Forward-ported to 5.7:
+ - Use the next available bit in efi.flags
+ - Adjust context]
+---
+ arch/x86/kernel/setup.c | 14 +----------
+ drivers/firmware/efi/Makefile | 1 +
+ drivers/firmware/efi/secureboot.c | 39 +++++++++++++++++++++++++++++++
+ include/linux/efi.h | 16 ++++++++-----
+ 4 files changed, 51 insertions(+), 19 deletions(-)
+ create mode 100644 drivers/firmware/efi/secureboot.c
+
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1193,19 +1193,7 @@ void __init setup_arch(char **cmdline_p)
+ /* Allocate bigger log buffer */
+ setup_log_buf(1);
+
+- if (efi_enabled(EFI_BOOT)) {
+- switch (boot_params.secure_boot) {
+- case efi_secureboot_mode_disabled:
+- pr_info("Secure boot disabled\n");
+- break;
+- case efi_secureboot_mode_enabled:
+- pr_info("Secure boot enabled\n");
+- break;
+- default:
+- pr_info("Secure boot could not be determined\n");
+- break;
+- }
+- }
++ efi_set_secure_boot(boot_params.secure_boot);
+
+ reserve_initrd();
+
+--- a/drivers/firmware/efi/Makefile
++++ b/drivers/firmware/efi/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_m
+ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o
+ obj-$(CONFIG_EFI_TEST) += test/
+ obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
++obj-$(CONFIG_EFI) += secureboot.o
+ obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o
+ obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o
+ obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
+--- /dev/null
++++ b/drivers/firmware/efi/secureboot.c
+@@ -0,0 +1,39 @@
++
++/* Core kernel secure boot support.
++ *
++ * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public Licence
++ * as published by the Free Software Foundation; either version
++ * 2 of the Licence, or (at your option) any later version.
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/efi.h>
++#include <linux/kernel.h>
++#include <linux/printk.h>
++
++/*
++ * Decide what to do when UEFI secure boot mode is enabled.
++ */
++void __init efi_set_secure_boot(enum efi_secureboot_mode mode)
++{
++ if (efi_enabled(EFI_BOOT)) {
++ switch (mode) {
++ case efi_secureboot_mode_disabled:
++ pr_info("Secure boot disabled\n");
++ break;
++ case efi_secureboot_mode_enabled:
++ set_bit(EFI_SECURE_BOOT, &efi.flags);
++ pr_info("Secure boot enabled\n");
++ break;
++ default:
++ pr_warn("Secure boot could not be determined (mode %u)\n",
++ mode);
++ break;
++ }
++ }
++}
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -871,6 +871,14 @@ extern int __init efi_setup_pcdp_console
+ #define EFI_MEM_ATTR 10 /* Did firmware publish an EFI_MEMORY_ATTRIBUTES table? */
+ #define EFI_MEM_NO_SOFT_RESERVE 11 /* Is the kernel configured to ignore soft reservations? */
+ #define EFI_PRESERVE_BS_REGIONS 12 /* Are EFI boot-services memory segments available? */
++#define EFI_SECURE_BOOT 13 /* Are we in Secure Boot mode? */
++
++enum efi_secureboot_mode {
++ efi_secureboot_mode_unset,
++ efi_secureboot_mode_unknown,
++ efi_secureboot_mode_disabled,
++ efi_secureboot_mode_enabled,
++};
+
+ #ifdef CONFIG_EFI
+ /*
+@@ -895,6 +903,7 @@ static inline bool efi_rt_services_suppo
+ return (efi.runtime_supported_mask & mask) == mask;
+ }
+ extern void efi_find_mirror(void);
++extern void __init efi_set_secure_boot(enum efi_secureboot_mode mode);
+ #else
+ static inline bool efi_enabled(int feature)
+ {
+@@ -914,6 +923,7 @@ static inline bool efi_rt_services_suppo
+ }
+
+ static inline void efi_find_mirror(void) {}
++static inline void efi_set_secure_boot(enum efi_secureboot_mode mode) {}
+ #endif
+
+ extern int efi_status_to_err(efi_status_t status);
+@@ -1133,13 +1143,6 @@ static inline bool efi_runtime_disabled(
+ extern void efi_call_virt_check_flags(unsigned long flags, const void *caller);
+ extern unsigned long efi_call_virt_save_flags(void);
+
+-enum efi_secureboot_mode {
+- efi_secureboot_mode_unset,
+- efi_secureboot_mode_unknown,
+- efi_secureboot_mode_disabled,
+- efi_secureboot_mode_enabled,
+-};
+-
+ static inline
+ enum efi_secureboot_mode efi_get_secureboot_mode(efi_get_variable_t *get_var)
+ {
diff --git a/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch
new file mode 100644
index 0000000000..3d8bdf0664
--- /dev/null
+++ b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch
@@ -0,0 +1,121 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Tue, 10 Sep 2019 11:54:28 +0100
+Subject: efi: Lock down the kernel if booted in secure boot mode
+
+Based on an earlier patch by David Howells, who wrote the following
+description:
+
+> UEFI Secure Boot provides a mechanism for ensuring that the firmware will
+> only load signed bootloaders and kernels. Certain use cases may also
+> require that all kernel modules also be signed. Add a configuration option
+> that to lock down the kernel - which includes requiring validly signed
+> modules - if the kernel is secure-booted.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+[Salvatore Bonaccorso: After fixing https://bugs.debian.org/956197 the
+help text for LOCK_DOWN_IN_EFI_SECURE_BOOT was adjusted to mention that
+lockdown is triggered in integrity mode (https://bugs.debian.org/1025417)]
+Signed-off-by: Salvatore Bonaccorso <carnil@debian.org>
+---
+ arch/x86/kernel/setup.c | 4 ++--
+ drivers/firmware/efi/secureboot.c | 3 +++
+ include/linux/security.h | 6 ++++++
+ security/lockdown/Kconfig | 15 +++++++++++++++
+ security/lockdown/lockdown.c | 2 +-
+ 5 files changed, 27 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -1031,6 +1031,8 @@ void __init setup_arch(char **cmdline_p)
+ if (efi_enabled(EFI_BOOT))
+ efi_init();
+
++ efi_set_secure_boot(boot_params.secure_boot);
++
+ reserve_ibft_region();
+ dmi_setup();
+
+@@ -1192,8 +1194,6 @@ void __init setup_arch(char **cmdline_p)
+ /* Allocate bigger log buffer */
+ setup_log_buf(1);
+
+- efi_set_secure_boot(boot_params.secure_boot);
+-
+ reserve_initrd();
+
+ acpi_table_upgrade();
+--- a/drivers/firmware/efi/secureboot.c
++++ b/drivers/firmware/efi/secureboot.c
+@@ -15,6 +15,7 @@
+ #include <linux/efi.h>
+ #include <linux/kernel.h>
+ #include <linux/printk.h>
++#include <linux/security.h>
+
+ /*
+ * Decide what to do when UEFI secure boot mode is enabled.
+@@ -28,6 +29,10 @@ void __init efi_set_secure_boot(enum efi
+ break;
+ case efi_secureboot_mode_enabled:
+ set_bit(EFI_SECURE_BOOT, &efi.flags);
++#ifdef CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT
++ lock_kernel_down("EFI Secure Boot",
++ LOCKDOWN_INTEGRITY_MAX);
++#endif
+ pr_info("Secure boot enabled\n");
+ break;
+ default:
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -482,6 +482,7 @@ int security_inode_notifysecctx(struct i
+ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
+ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+ int security_locked_down(enum lockdown_reason what);
++int lock_kernel_down(const char *where, enum lockdown_reason level);
+ #else /* CONFIG_SECURITY */
+
+ static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
+@@ -1388,6 +1389,11 @@ static inline int security_locked_down(e
+ {
+ return 0;
+ }
++static inline int
++lock_kernel_down(const char *where, enum lockdown_reason level)
++{
++ return -EOPNOTSUPP;
++}
+ #endif /* CONFIG_SECURITY */
+
+ #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
+--- a/security/lockdown/Kconfig
++++ b/security/lockdown/Kconfig
+@@ -45,3 +45,18 @@ config LOCK_DOWN_KERNEL_FORCE_CONFIDENTI
+ disabled.
+
+ endchoice
++
++config LOCK_DOWN_IN_EFI_SECURE_BOOT
++ bool "Lock down the kernel in EFI Secure Boot mode"
++ default n
++ depends on SECURITY_LOCKDOWN_LSM
++ depends on EFI
++ select SECURITY_LOCKDOWN_LSM_EARLY
++ help
++ UEFI Secure Boot provides a mechanism for ensuring that the firmware
++ will only load signed bootloaders and kernels. Secure boot mode may
++ be determined from EFI variables provided by the system firmware if
++ not indicated by the boot parameters.
++
++ Enabling this option results in kernel lockdown being
++ triggered in integrity mode if EFI Secure Boot is set.
+--- a/security/lockdown/lockdown.c
++++ b/security/lockdown/lockdown.c
+@@ -23,7 +23,7 @@ static const enum lockdown_reason lockdo
+ /*
+ * Put the kernel into lock-down mode.
+ */
+-static int lock_kernel_down(const char *where, enum lockdown_reason level)
++int lock_kernel_down(const char *where, enum lockdown_reason level)
+ {
+ if (kernel_locked_down >= level)
+ return -EPERM;
diff --git a/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch b/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch
new file mode 100644
index 0000000000..c718e7e2f0
--- /dev/null
+++ b/debian/patches/features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch
@@ -0,0 +1,75 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Fri, 30 Aug 2019 15:54:24 +0100
+Subject: mtd: phram,slram: Disable when the kernel is locked down
+Forwarded: https://lore.kernel.org/linux-security-module/20190830154720.eekfjt6c4jzvlbfz@decadent.org.uk/
+
+These drivers allow mapping arbitrary memory ranges as MTD devices.
+This should be disabled to preserve the kernel's integrity when it is
+locked down.
+
+* Add the HWPARAM flag to the module parameters
+* When slram is built-in, it uses __setup() to read kernel parameters,
+ so add an explicit check security_locked_down() check
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Matthew Garrett <mjg59@google.com>
+Cc: David Howells <dhowells@redhat.com>
+Cc: Joern Engel <joern@lazybastard.org>
+Cc: linux-mtd@lists.infradead.org
+---
+ drivers/mtd/devices/phram.c | 6 +++++-
+ drivers/mtd/devices/slram.c | 9 ++++++++-
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/devices/phram.c
++++ b/drivers/mtd/devices/phram.c
+@@ -364,7 +364,11 @@ static int phram_param_call(const char *
+ #endif
+ }
+
+-module_param_call(phram, phram_param_call, NULL, NULL, 0200);
++static const struct kernel_param_ops phram_param_ops = {
++ .set = phram_param_call
++};
++__module_param_call(MODULE_PARAM_PREFIX, phram, &phram_param_ops, NULL,
++ 0200, -1, KERNEL_PARAM_FL_HWPARAM | hwparam_iomem);
+ MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>[,<erasesize>]\"");
+
+ #ifdef CONFIG_OF
+--- a/drivers/mtd/devices/slram.c
++++ b/drivers/mtd/devices/slram.c
+@@ -43,6 +43,7 @@
+ #include <linux/ioctl.h>
+ #include <linux/init.h>
+ #include <linux/io.h>
++#include <linux/security.h>
+
+ #include <linux/mtd/mtd.h>
+
+@@ -65,7 +66,7 @@ typedef struct slram_mtd_list {
+ #ifdef MODULE
+ static char *map[SLRAM_MAX_DEVICES_PARAMS];
+
+-module_param_array(map, charp, NULL, 0);
++module_param_hw_array(map, charp, iomem, NULL, 0);
+ MODULE_PARM_DESC(map, "List of memory regions to map. \"map=<name>, <start>, <length / end>\"");
+ #else
+ static char *map;
+@@ -281,11 +282,17 @@ static int __init init_slram(void)
+ #ifndef MODULE
+ char *devstart;
+ char *devlength;
++ int ret;
+
+ if (!map) {
+ E("slram: not enough parameters.\n");
+ return(-EINVAL);
+ }
++
++ ret = security_locked_down(LOCKDOWN_MODULE_PARAMETERS);
++ if (ret)
++ return ret;
++
+ while (map) {
+ devname = devstart = devlength = NULL;
+
diff --git a/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch b/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch
new file mode 100644
index 0000000000..9ca7803757
--- /dev/null
+++ b/debian/patches/features/all/security-perf-allow-further-restriction-of-perf_event_open.patch
@@ -0,0 +1,80 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 11 Jan 2016 15:23:55 +0000
+Subject: security,perf: Allow further restriction of perf_event_open
+Forwarded: https://lore.kernel.org/all/20160111152355.GS28542@decadent.org.uk/
+
+When kernel.perf_event_open is set to 3 (or greater), disallow all
+access to performance events by users without CAP_SYS_ADMIN.
+Add a Kconfig symbol CONFIG_SECURITY_PERF_EVENTS_RESTRICT that
+makes this value the default.
+
+This is based on a similar feature in grsecurity
+(CONFIG_GRKERNSEC_PERF_HARDEN). This version doesn't include making
+the variable read-only. It also allows enabling further restriction
+at run-time regardless of whether the default is changed.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ include/linux/perf_event.h | 5 +++++
+ kernel/events/core.c | 8 ++++++++
+ security/Kconfig | 9 +++++++++
+ 3 files changed, 22 insertions(+)
+
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1387,6 +1387,11 @@ int perf_cpu_time_max_percent_handler(st
+ int perf_event_max_stack_handler(struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos);
+
++static inline bool perf_paranoid_any(void)
++{
++ return sysctl_perf_event_paranoid > 2;
++}
++
+ /* Access to perf_event_open(2) syscall. */
+ #define PERF_SECURITY_OPEN 0
+
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -415,8 +415,13 @@ static struct kmem_cache *perf_event_cac
+ * 0 - disallow raw tracepoint access for unpriv
+ * 1 - disallow cpu events for unpriv
+ * 2 - disallow kernel profiling for unpriv
++ * 3 - disallow all unpriv perf event use
+ */
++#ifdef CONFIG_SECURITY_PERF_EVENTS_RESTRICT
++int sysctl_perf_event_paranoid __read_mostly = 3;
++#else
+ int sysctl_perf_event_paranoid __read_mostly = 2;
++#endif
+
+ /* Minimum for 512 kiB + 1 user control page */
+ int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
+@@ -12325,6 +12330,9 @@ SYSCALL_DEFINE5(perf_event_open,
+ if (err)
+ return err;
+
++ if (perf_paranoid_any() && !capable(CAP_SYS_ADMIN))
++ return -EACCES;
++
+ /* Do we allow access to perf_event_open(2) ? */
+ err = security_perf_event_open(&attr, PERF_SECURITY_OPEN);
+ if (err)
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -19,6 +19,15 @@ config SECURITY_DMESG_RESTRICT
+
+ If you are unsure how to answer this question, answer N.
+
++config SECURITY_PERF_EVENTS_RESTRICT
++ bool "Restrict unprivileged use of performance events"
++ depends on PERF_EVENTS
++ help
++ If you say Y here, the kernel.perf_event_paranoid sysctl
++ will be set to 3 by default, and no unprivileged use of the
++ perf_event_open syscall will be permitted unless it is
++ changed.
++
+ config SECURITY
+ bool "Enable different security models"
+ depends on SYSFS
diff --git a/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch b/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch
new file mode 100644
index 0000000000..16cac663c1
--- /dev/null
+++ b/debian/patches/features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch
@@ -0,0 +1,76 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 21 Aug 2019 00:32:16 +0100
+Subject: intel-iommu: Add Kconfig option to exclude iGPU by default
+Bug-Debian: https://bugs.debian.org/935270
+Bug-Kali: https://bugs.kali.org/view.php?id=5644
+
+There is still laptop firmware that touches the integrated GPU behind
+the operating system's back, and doesn't say so in the RMRR table.
+Enabling the IOMMU for all devices causes breakage.
+
+Replace CONFIG_INTEL_IOMMU_DEFAULT_ON with a 3-way choice
+corresponding to "on", "off", and "on,intgpu_off".
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/drivers/iommu/intel/Kconfig
++++ b/drivers/iommu/intel/Kconfig
+@@ -56,14 +56,25 @@ config INTEL_IOMMU_SVM
+ to access DMA resources through process address space by
+ means of a Process Address Space ID (PASID).
+
+-config INTEL_IOMMU_DEFAULT_ON
+- bool "Enable Intel DMA Remapping Devices by default"
+- default y
++choice
++ prompt "Default state of Intel DMA Remapping Devices"
++ default INTEL_IOMMU_DEFAULT_ON
+ help
+- Selecting this option will enable a DMAR device at boot time if
+- one is found. If this option is not selected, DMAR support can
+- be enabled by passing intel_iommu=on to the kernel.
++ Choose whether Intel DMA Remapping Devices should be enabled
++ by default. This can be overridden at boot time using the
++ intel_iommu= kernel parameter.
++
++config INTEL_IOMMU_DEFAULT_ON
++ bool "Enable"
++
++config INTEL_IOMMU_DEFAULT_ON_INTGPU_OFF
++ bool "Enable, excluding integrated GPU"
++
++config INTEL_IOMMU_DEFAULT_OFF
++ bool "Disable"
+
++endchoice
++
+ config INTEL_IOMMU_BROKEN_GFX_WA
+ bool "Workaround broken graphics drivers (going away soon)"
+ depends on BROKEN && X86
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -283,14 +283,14 @@ static LIST_HEAD(dmar_satc_units);
+ static void device_block_translation(struct device *dev);
+ static void intel_iommu_domain_free(struct iommu_domain *domain);
+
+-int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
++int dmar_disabled = IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_OFF);
+ int intel_iommu_sm = IS_ENABLED(CONFIG_INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON);
+
+ int intel_iommu_enabled = 0;
+ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+
+ static int dmar_map_gfx = 1;
+-static int dmar_map_intgpu = 1;
++static int dmar_map_intgpu = IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
+ static int intel_iommu_superpage = 1;
+ static int iommu_identity_mapping;
+ static int iommu_skip_te_disable;
+@@ -328,6 +328,7 @@ static int __init intel_iommu_setup(char
+ while (*str) {
+ if (!strncmp(str, "on", 2)) {
+ dmar_disabled = 0;
++ dmar_map_intgpu = 1;
+ pr_info("IOMMU enabled\n");
+ } else if (!strncmp(str, "off", 3)) {
+ dmar_disabled = 1;
diff --git a/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch b/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch
new file mode 100644
index 0000000000..a3543d90e9
--- /dev/null
+++ b/debian/patches/features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch
@@ -0,0 +1,90 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 21 Aug 2019 00:05:30 +0100
+Subject: intel-iommu: Add option to exclude integrated GPU only
+Bug-Debian: https://bugs.debian.org/935270
+Bug-Kali: https://bugs.kali.org/view.php?id=5644
+
+There is still laptop firmware that touches the integrated GPU behind
+the operating system's back, and doesn't say so in the RMRR table.
+Enabling the IOMMU for all devices causes breakage, but turning it off
+for all graphics devices seems like a major weakness.
+
+Add an option, intel_iommu=intgpu_off, to exclude only integrated GPUs
+from remapping. This is a narrower exclusion than igfx_off: it only
+affects Intel devices on the root bus. Devices attached through an
+external port (Thunderbolt or ExpressCard) won't be on the root bus.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ Documentation/admin-guide/kernel-parameters.txt | 2 ++
+ drivers/iommu/intel/iommu.c | 14 ++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -2053,6 +2053,8 @@
+ bypassed by not enabling DMAR with this option. In
+ this case, gfx device will use physical address for
+ DMA.
++ intgpu_off [Default Off]
++ Bypass the DMAR unit for an integrated GPU only.
+ strict [Default Off]
+ Deprecated, equivalent to iommu.strict=1.
+ sp_off [Default Off]
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -35,6 +35,9 @@
+ #define CONTEXT_SIZE VTD_PAGE_SIZE
+
+ #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
++#define IS_INTGPU_DEVICE(pdev) (IS_GFX_DEVICE(pdev) && \
++ (pdev)->vendor == 0x8086 && \
++ pci_is_root_bus((pdev)->bus))
+ #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+ #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+ #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
+@@ -293,12 +296,14 @@ int intel_iommu_enabled = 0;
+ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+
+ static int dmar_map_gfx = 1;
++static int dmar_map_intgpu = 1;
+ static int intel_iommu_superpage = 1;
+ static int iommu_identity_mapping;
+ static int iommu_skip_te_disable;
+
+ #define IDENTMAP_GFX 2
+ #define IDENTMAP_AZALIA 4
++#define IDENTMAP_INTGPU 8
+
+ const struct iommu_ops intel_iommu_ops;
+
+@@ -337,6 +342,9 @@ static int __init intel_iommu_setup(char
+ } else if (!strncmp(str, "igfx_off", 8)) {
+ dmar_map_gfx = 0;
+ pr_info("Disable GFX device mapping\n");
++ } else if (!strncmp(str, "intgpu_off", 10)) {
++ dmar_map_intgpu = 0;
++ pr_info("Disable integrated GPU device mapping\n");
+ } else if (!strncmp(str, "forcedac", 8)) {
+ pr_warn("intel_iommu=forcedac deprecated; use iommu.forcedac instead\n");
+ iommu_dma_forcedac = true;
+@@ -2582,6 +2590,9 @@ static int device_def_domain_type(struct
+
+ if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
+ return IOMMU_DOMAIN_IDENTITY;
++
++ if ((iommu_identity_mapping & IDENTMAP_INTGPU) && IS_INTGPU_DEVICE(pdev))
++ return IOMMU_DOMAIN_IDENTITY;
+ }
+
+ return 0;
+@@ -2985,6 +2996,9 @@ static int __init init_dmars(void)
+ if (!dmar_map_gfx)
+ iommu_identity_mapping |= IDENTMAP_GFX;
+
++ if (!dmar_map_intgpu)
++ iommu_identity_mapping |= IDENTMAP_INTGPU;
++
+ check_tylersburg_isoch();
+
+ ret = si_domain_init(hw_pass_through);
diff --git a/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch
new file mode 100644
index 0000000000..010fa59105
--- /dev/null
+++ b/debian/patches/features/x86/x86-make-x32-syscall-support-conditional.patch
@@ -0,0 +1,180 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 12 Feb 2018 23:59:26 +0000
+Subject: x86: Make x32 syscall support conditional on a kernel parameter
+Bug-Debian: https://bugs.debian.org/708070
+Forwarded: https://lore.kernel.org/lkml/1415245982.3398.53.camel@decadent.org.uk/T/#u
+
+Enabling x32 in the standard amd64 kernel would increase its attack
+surface while provide no benefit to the vast majority of its users.
+No-one seems interested in regularly checking for vulnerabilities
+specific to x32 (at least no-one with a white hat).
+
+Still, adding another flavour just to turn on x32 seems wasteful. And
+the only differences on syscall entry are a few instructions that mask
+out the x32 flag and compare the syscall number.
+
+Use a static key to control whether x32 syscalls are really enabled, a
+Kconfig parameter to set its default value and a kernel parameter
+"syscall.x32" to change it at boot time.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ .../admin-guide/kernel-parameters.txt | 4 ++
+ arch/x86/Kconfig | 8 ++++
+ arch/x86/entry/common.c | 3 +-
+ arch/x86/entry/syscall_64.c | 46 +++++++++++++++++++
+ arch/x86/include/asm/elf.h | 6 ++-
+ arch/x86/include/asm/syscall.h | 13 ++++++
+ 6 files changed, 78 insertions(+), 2 deletions(-)
+
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -6172,6 +6172,10 @@
+ later by a loaded module cannot be set this way.
+ Example: sysctl.vm.swappiness=40
+
++ syscall.x32= [KNL,x86_64] Enable/disable use of x32 syscalls on
++ an x86_64 kernel where CONFIG_X86_X32 is enabled.
++ Default depends on CONFIG_X86_X32_DISABLED.
++
+ sysrq_always_enabled
+ [KNL]
+ Ignore sysrq setting - this boot parameter will
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -3058,6 +3058,14 @@ config COMPAT_32
+ select HAVE_UID16
+ select OLD_SIGSUSPEND3
+
++config X86_X32_DISABLED
++ bool "x32 ABI disabled by default"
++ depends on X86_X32_ABI
++ default n
++ help
++ Disable the x32 ABI unless explicitly enabled using the
++ kernel paramter "syscall.x32=y".
++
+ config COMPAT
+ def_bool y
+ depends on IA32_EMULATION || X86_X32_ABI
+--- a/arch/x86/entry/common.c
++++ b/arch/x86/entry/common.c
+@@ -62,7 +62,7 @@ static __always_inline bool do_syscall_x
+ */
+ unsigned int xnr = nr - __X32_SYSCALL_BIT;
+
+- if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(xnr < X32_NR_syscalls)) {
++ if (IS_ENABLED(CONFIG_X86_X32_ABI) && unlikely(x32_enabled) && likely(xnr < X32_NR_syscalls)) {
+ xnr = array_index_nospec(xnr, X32_NR_syscalls);
+ regs->ax = x32_sys_call_table[xnr](regs);
+ return true;
+--- a/arch/x86/entry/syscall_x32.c
++++ b/arch/x86/entry/syscall_x32.c
+@@ -4,6 +4,9 @@
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+ #include <linux/cache.h>
++#include <linux/moduleparam.h>
++#undef MODULE_PARAM_PREFIX
++#define MODULE_PARAM_PREFIX "syscall."
+ #include <linux/syscalls.h>
+ #include <asm/syscall.h>
+
+@@ -16,3 +19,46 @@
+ asmlinkage const sys_call_ptr_t x32_sys_call_table[] = {
+ #include <asm/syscalls_x32.h>
+ };
++
++/* Maybe enable x32 syscalls */
++
++#if defined(CONFIG_X86_X32_DISABLED)
++DEFINE_STATIC_KEY_FALSE(x32_enabled_skey);
++#else
++DEFINE_STATIC_KEY_TRUE(x32_enabled_skey);
++#endif
++
++static int __init x32_param_set(const char *val, const struct kernel_param *p)
++{
++ bool enabled;
++ int ret;
++
++ ret = kstrtobool(val, &enabled);
++ if (ret)
++ return ret;
++ if (IS_ENABLED(CONFIG_X86_X32_DISABLED)) {
++ if (enabled) {
++ static_key_enable(&x32_enabled_skey.key);
++ pr_info("Enabled x32 syscalls\n");
++ }
++ } else {
++ if (!enabled) {
++ static_key_disable(&x32_enabled_skey.key);
++ pr_info("Disabled x32 syscalls\n");
++ }
++ }
++ return 0;
++}
++
++static int x32_param_get(char *buffer, const struct kernel_param *p)
++{
++ return sprintf(buffer, "%c\n",
++ static_key_enabled(&x32_enabled_skey) ? 'Y' : 'N');
++}
++
++static const struct kernel_param_ops x32_param_ops = {
++ .set = x32_param_set,
++ .get = x32_param_get,
++};
++
++arch_param_cb(x32, &x32_param_ops, NULL, 0444);
+--- a/arch/x86/include/asm/elf.h
++++ b/arch/x86/include/asm/elf.h
+@@ -11,6 +11,9 @@
+ #include <asm/user.h>
+ #include <asm/auxvec.h>
+ #include <asm/fsgsbase.h>
++#ifndef COMPILE_OFFSETS /* avoid a circular dependency on asm-offsets.h */
++#include <asm/syscall.h>
++#endif
+
+ typedef unsigned long elf_greg_t;
+
+@@ -150,7 +153,8 @@ do { \
+
+ #define compat_elf_check_arch(x) \
+ (elf_check_arch_ia32(x) || \
+- (IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64))
++ (IS_ENABLED(CONFIG_X86_X32_ABI) && x32_enabled && \
++ (x)->e_machine == EM_X86_64))
+
+ static inline void elf_common_init(struct thread_struct *t,
+ struct pt_regs *regs, const u16 ds)
+--- a/arch/x86/include/asm/syscall.h
++++ b/arch/x86/include/asm/syscall.h
+@@ -13,6 +13,7 @@
+ #include <uapi/linux/audit.h>
+ #include <linux/sched.h>
+ #include <linux/err.h>
++#include <linux/jump_label.h>
+ #include <asm/thread_info.h> /* for TS_COMPAT */
+ #include <asm/unistd.h>
+
+@@ -30,6 +31,18 @@ extern const sys_call_ptr_t ia32_sys_cal
+ extern const sys_call_ptr_t x32_sys_call_table[];
+ #endif
+
++#if defined(CONFIG_X86_X32_ABI)
++#if defined(CONFIG_X86_X32_DISABLED)
++DECLARE_STATIC_KEY_FALSE(x32_enabled_skey);
++#define x32_enabled static_branch_unlikely(&x32_enabled_skey)
++#else
++DECLARE_STATIC_KEY_TRUE(x32_enabled_skey);
++#define x32_enabled static_branch_likely(&x32_enabled_skey)
++#endif
++#else
++#define x32_enabled 0
++#endif
++
+ /*
+ * Only the low 32 bits of orig_ax are meaningful, so we return int.
+ * This importantly ignores the high bits on 64-bit, so comparisons
diff --git a/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch b/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
new file mode 100644
index 0000000000..e8bc1b0495
--- /dev/null
+++ b/debian/patches/features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
@@ -0,0 +1,28 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Mon, 5 Dec 2011 04:00:58 +0000
+Subject: x86: memtest: WARN if bad RAM found
+Bug-Debian: https://bugs.debian.org/613321
+Forwarded: https://lore.kernel.org/all/20120402150522.GA4980@burratino/
+
+Since this is not a particularly thorough test, if we find any bad
+bits of RAM then there is a fair chance that there are other bad bits
+we fail to detect.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ mm/memtest.c | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+--- a/mm/memtest.c
++++ b/mm/memtest.c
+@@ -26,6 +26,10 @@ static u64 patterns[] __initdata = {
+
+ static void __init reserve_bad_mem(u64 pattern, phys_addr_t start_bad, phys_addr_t end_bad)
+ {
++#ifdef CONFIG_X86
++ WARN_ONCE(1, "Bad RAM detected. Use memtest86+ to perform a thorough test\n"
++ "and the memmap= parameter to reserve the bad areas.");
++#endif
+ pr_info(" %016llx bad mem addr %pa - %pa reserved\n",
+ cpu_to_be64(pattern), &start_bad, &end_bad);
+ memblock_reserve(start_bad, end_bad - start_bad);
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000000..9401d26da0
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,119 @@
+debian/gitignore.patch
+
+# Disable features broken by exclusion of upstream files
+debian/dfsg/arch-powerpc-platforms-8xx-ucode-disable.patch
+debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch
+debian/dfsg/drivers-net-appletalk-cops.patch
+debian/dfsg/video-remove-nvidiafb-and-rivafb.patch
+debian/dfsg/documentation-fix-broken-link-to-cipso-draft.patch
+
+# Changes to support package build system
+debian/version.patch
+debian/uname-version-timestamp.patch
+debian/kernelvariables.patch
+debian/ia64-hardcode-arch-script-output.patch
+debian/mips-disable-werror.patch
+debian/mips-boston-disable-its.patch
+debian/mips-ieee754-relaxed.patch
+debian/arch-sh4-fix-uimage-build.patch
+debian/tools-perf-perf-read-vdso-in-libexec.patch
+debian/tools-perf-install-python-bindings.patch
+debian/wireless-add-debian-wireless-regdb-certificates.patch
+debian/export-symbols-needed-by-android-drivers.patch
+debian/android-enable-building-ashmem-and-binder-as-modules.patch
+debian/documentation-drop-sphinx-version-check.patch
+debian/perf-traceevent-support-asciidoctor-for-documentatio.patch
+debian/kbuild-look-for-module.lds-under-arch-directory-too.patch
+debian/kbuild-abort-build-if-subdirs-used.patch
+debian/module-avoid-abi-changes-when-debug-info-is-disabled.patch
+debian/makefile-make-compiler-version-comparison-optional.patch
+debian/fixdep-allow-overriding-hostcc-and-hostld.patch
+
+# Fixes/improvements to firmware loading
+features/all/drivers-media-dvb-usb-af9005-request_firmware.patch
+debian/iwlwifi-do-not-request-unreleased-firmware.patch
+bugfix/all/firmware_class-log-every-success-and-failure.patch
+bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch
+bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch
+debian/firmware_class-refer-to-debian-wiki-firmware-page.patch
+
+# Change some defaults for security reasons
+debian/af_802154-Disable-auto-loading-as-mitigation-against.patch
+debian/rds-Disable-auto-loading-as-mitigation-against-local.patch
+debian/dccp-disable-auto-loading-as-mitigation-against-local-exploits.patch
+debian/hamradio-disable-auto-loading-as-mitigation-against-local-exploits.patch
+debian/fs-enable-link-security-restrictions-by-default.patch
+
+# Set various features runtime-disabled by default
+debian/sched-autogroup-disabled.patch
+debian/yama-disable-by-default.patch
+debian/add-sysctl-to-disallow-unprivileged-CLONE_NEWUSER-by-default.patch
+features/all/security-perf-allow-further-restriction-of-perf_event_open.patch
+features/x86/intel-iommu-add-option-to-exclude-integrated-gpu-only.patch
+features/x86/intel-iommu-add-kconfig-option-to-exclude-igpu-by-default.patch
+
+# Disable autoloading/probing of various drivers by default
+debian/cdc_ncm-cdc_mbim-use-ncm-by-default.patch
+debian/snd-pcsp-disable-autoload.patch
+bugfix/x86/viafb-autoload-on-olpc-xo1.5-only.patch
+debian/fjes-disable-autoload.patch
+
+# Taint if dangerous features are used
+debian/fanotify-taint-on-use-of-fanotify_access_permissions.patch
+debian/btrfs-warn-about-raid5-6-being-experimental-at-mount.patch
+
+# Arch bug fixes
+bugfix/arm/arm-dts-kirkwood-fix-sata-pinmux-ing-for-ts419.patch
+bugfix/x86/perf-tools-fix-unwind-build-on-i386.patch
+bugfix/sh/sh-boot-do-not-use-hyphen-in-exported-variable-name.patch
+bugfix/arm/arm-mm-export-__sync_icache_dcache-for-xen-privcmd.patch
+bugfix/powerpc/powerpc-boot-fix-missing-crc32poly.h-when-building-with-kernel_xz.patch
+bugfix/arm64/arm64-acpi-Add-fixup-for-HPE-m400-quirks.patch
+bugfix/alpha/alpha-fix-missing-symbol-versions-for-str-n-cat-cpy.patch
+
+# Arch features
+features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
+features/x86/x86-make-x32-syscall-support-conditional.patch
+
+# Miscellaneous bug fixes
+bugfix/all/disable-some-marvell-phys.patch
+bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.patch
+debian/Revert-docs-kernel_feat.py-fix-potential-command-inj.patch
+
+# Miscellaneous features
+
+# Lockdown missing pieces
+features/all/lockdown/efi-add-an-efi_secure_boot-flag-to-indicate-secure-b.patch
+features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch
+features/all/lockdown/mtd-disable-slram-and-phram-when-locked-down.patch
+features/all/lockdown/arm64-add-kernel-config-option-to-lock-down-when.patch
+
+# Improve integrity platform keyring for kernel modules verification
+features/all/db-mok-keyring/0003-MODSIGN-checking-the-blacklisted-hash-before-loading-a-kernel-module.patch
+features/all/db-mok-keyring/KEYS-Make-use-of-platform-keyring-for-module-signature.patch
+features/all/db-mok-keyring/trust-machine-keyring-by-default.patch
+
+# Security fixes
+debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
+debian/ntfs-mark-it-as-broken.patch
+
+# Fix exported symbol versions
+bugfix/all/module-disable-matching-missing-version-crc.patch
+
+# Tools bug fixes
+bugfix/all/usbip-document-tcp-wrappers.patch
+bugfix/all/kbuild-fix-recordmcount-dependency.patch
+bugfix/all/tools-perf-man-date.patch
+bugfix/all/tools-perf-remove-shebangs.patch
+bugfix/x86/revert-perf-build-fix-libunwind-feature-detection-on.patch
+bugfix/all/tools-build-remove-bpf-run-time-check-at-build-time.patch
+bugfix/all/cpupower-fix-checks-for-cpu-existence.patch
+bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch
+bugfix/all/tools-perf-fix-missing-ldflags-for-some-programs.patch
+bugfix/all/tools_lib_symbol_use_d_fortify_source_2_for_non_debug_builds.patch
+bugfix/all/perf-tools-support-extra-cxxflags.patch
+
+# debian-installer fixes
+bugfix/powerpc/fbdev-offb-Update-expected-device-name.patch
+
+# ABI maintenance