summaryrefslogtreecommitdiffstats
path: root/debian/patches
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:49:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:49:59 +0000
commit01997497f915e8f79871f3f2acb55ac465051d24 (patch)
tree1ce1afd7246e1014199e15cbf854bf7924458e5d /debian/patches
parentAdding upstream version 6.1.76. (diff)
downloadlinux-debian/6.1.76-1.tar.xz
linux-debian/6.1.76-1.zip
Adding debian version 6.1.76-1.debian/6.1.76-1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--debian/patches-rt/0001-vduse-Remove-include-of-rwlock.h.patch33
-rw-r--r--debian/patches-rt/0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch66
-rw-r--r--debian/patches-rt/0003-sched-Consider-task_struct-saved_state-in-wait_task_.patch152
-rw-r--r--debian/patches-rt/0004-spi-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch40
-rw-r--r--debian/patches-rt/0005-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch2087
-rw-r--r--debian/patches-rt/0006-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-n.patch393
-rw-r--r--debian/patches-rt/0007-bpf-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch51
-rw-r--r--debian/patches-rt/0008-u64_stat-Remove-the-obsolete-fetch_irq-variants.patch42
-rw-r--r--debian/patches-rt/0009-net-Avoid-the-IPI-to-free-the.patch125
-rw-r--r--debian/patches-rt/0010-x86-Allow-to-enable-RT.patch29
-rw-r--r--debian/patches-rt/0011-x86-Enable-RT-also-on-32bit.patch35
-rw-r--r--debian/patches-rt/0012-softirq-Use-a-dedicated-thread-for-timer-wakeups.patch234
-rw-r--r--debian/patches-rt/0013-rcutorture-Also-force-sched-priority-to-timersd-on-b.patch81
-rw-r--r--debian/patches-rt/0014-tick-Fix-timer-storm-since-introduction-of-timersd.patch116
-rw-r--r--debian/patches-rt/0015-softirq-Wake-ktimers-thread-also-in-softirq.patch50
-rw-r--r--debian/patches-rt/0016-tpm_tis-fix-stall-after-iowrite-s.patch82
-rw-r--r--debian/patches-rt/0017-zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch100
-rw-r--r--debian/patches-rt/0018-locking-lockdep-Remove-lockdep_init_map_crosslock.patch34
-rw-r--r--debian/patches-rt/0019-printk-Bring-back-the-RT-bits.patch1234
-rw-r--r--debian/patches-rt/0020-printk-add-infrastucture-for-atomic-consoles.patch608
-rw-r--r--debian/patches-rt/0021-serial-8250-implement-write_atomic.patch938
-rw-r--r--debian/patches-rt/0022-printk-avoid-preempt_disable-for-PREEMPT_RT.patch96
-rw-r--r--debian/patches-rt/0023-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch62
-rw-r--r--debian/patches-rt/0024-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch91
-rw-r--r--debian/patches-rt/0025-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch36
-rw-r--r--debian/patches-rt/0026-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch51
-rw-r--r--debian/patches-rt/0027-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch35
-rw-r--r--debian/patches-rt/0028-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch48
-rw-r--r--debian/patches-rt/0029-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch95
-rw-r--r--debian/patches-rt/0030-drm-i915-Drop-the-irqs_disabled-check.patch45
-rw-r--r--debian/patches-rt/0031-Revert-drm-i915-Depend-on-PREEMPT_RT.patch29
-rw-r--r--debian/patches-rt/0032-sched-Add-support-for-lazy-preemption.patch714
-rw-r--r--debian/patches-rt/0033-x86-entry-Use-should_resched-in-idtentry_exit_cond_r.patch36
-rw-r--r--debian/patches-rt/0034-x86-Support-for-lazy-preemption.patch158
-rw-r--r--debian/patches-rt/0035-entry-Fix-the-preempt-lazy-fallout.patch49
-rw-r--r--debian/patches-rt/0036-arm-Add-support-for-lazy-preemption.patch137
-rw-r--r--debian/patches-rt/0037-powerpc-Add-support-for-lazy-preemption.patch118
-rw-r--r--debian/patches-rt/0038-arch-arm64-Add-lazy-preempt-support.patch146
-rw-r--r--debian/patches-rt/0039-arm-Disable-jump-label-on-PREEMPT_RT.patch42
-rw-r--r--debian/patches-rt/0040-ARM-enable-irq-in-translation-section-permission-fau.patch97
-rw-r--r--debian/patches-rt/0041-tty-serial-omap-Make-the-locking-RT-aware.patch49
-rw-r--r--debian/patches-rt/0042-tty-serial-pl011-Make-the-locking-work-on-RT.patch60
-rw-r--r--debian/patches-rt/0043-ARM-Allow-to-enable-RT.patch37
-rw-r--r--debian/patches-rt/0044-ARM64-Allow-to-enable-RT.patch29
-rw-r--r--debian/patches-rt/0045-powerpc-traps-Use-PREEMPT_RT.patch40
-rw-r--r--debian/patches-rt/0046-powerpc-pseries-iommu-Use-a-locallock-instead-local_.patch118
-rw-r--r--debian/patches-rt/0047-powerpc-kvm-Disable-in-kernel-MPIC-emulation-for-PRE.patch46
-rw-r--r--debian/patches-rt/0048-powerpc-stackprotector-work-around-stack-guard-init-.patch37
-rw-r--r--debian/patches-rt/0049-POWERPC-Allow-to-enable-RT.patch37
-rw-r--r--debian/patches-rt/0050-sysfs-Add-sys-kernel-realtime-entry.patch55
-rw-r--r--debian/patches-rt/0051-Add-localversion-for-RT-release.patch22
-rw-r--r--debian/patches-rt/0052-Linux-6.1.46-rt13-REBASE.patch21
-rw-r--r--debian/patches-rt/0053-io-mapping-don-t-disable-preempt-on-RT-in-io_mapping.patch93
-rw-r--r--debian/patches-rt/0054-locking-rwbase-Mitigate-indefinite-writer-starvation.patch63
-rw-r--r--debian/patches-rt/0055-revert-softirq-Let-ksoftirqd-do-its-job.patch108
-rw-r--r--debian/patches-rt/0056-debugobjects-locking-Annotate-debug_object_fill_pool.patch177
-rw-r--r--debian/patches-rt/0057-sched-avoid-false-lockdep-splat-in-put_task_struct.patch52
-rw-r--r--debian/patches-rt/0058-mm-page_alloc-Use-write_seqlock_irqsave-instead-writ.patch97
-rw-r--r--debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch120
-rw-r--r--debian/patches-rt/0060-posix-timers-Ensure-timer-ID-search-loop-limit-is-va.patch115
-rw-r--r--debian/patches-rt/0061-drm-i915-Do-not-disable-preemption-for-resets.patch110
-rw-r--r--debian/patches-rt/0062-Linux-6.1.69-rt21-REBASE.patch21
-rw-r--r--debian/patches-rt/series62
-rw-r--r--debian/patches/bugfix/all/cpupower-bump-soname-version.patch27
-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.patch2716
-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.patch17
-rw-r--r--debian/patches/bugfix/all/module-disable-matching-missing-version-crc.patch23
-rw-r--r--debian/patches/bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch135
-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-pmu-events-fix-reproducibility.patch26
-rw-r--r--debian/patches/bugfix/all/tools-perf-remove-shebangs.patch39
-rw-r--r--debian/patches/bugfix/all/usbip-document-tcp-wrappers.patch29
-rw-r--r--debian/patches/bugfix/all/wifi-mt76-do-not-run-mt76_unregister_device-on-unregistered-hw.patch78
-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.patch37
-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/arm64/arm64-dts-rockchip-fix-spdif-fe460000-ordering-on-rk.patch63
-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/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.patch35
-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.patch128
-rw-r--r--debian/patches/debian/dfsg/vs6624-disable.patch19
-rw-r--r--debian/patches/debian/documentation-drop-sphinx-version-check.patch47
-rw-r--r--debian/patches/debian/export-symbols-needed-by-android-drivers.patch113
-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.patch52
-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.patch52
-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.patch22
-rw-r--r--debian/patches/debian/perf-traceevent-support-asciidoctor-for-documentatio.patch54
-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.patch186
-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.patch16
-rw-r--r--debian/patches/features/all/drivers-media-dvb-usb-af9005-request_firmware.patch149
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0001-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch89
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0002-net-mana-Assign-interrupts-to-CPUs-based-on-NUMA-nod.patch114
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0003-net-mana-Add-support-for-auxiliary-device.patch178
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0004-net-mana-Record-the-physical-address-for-doorbell-pa.patch63
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0005-net-mana-Handle-vport-sharing-between-devices.patch150
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0006-net-mana-Set-the-DMA-device-max-segment-size.patch40
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0007-net-mana-Export-Work-Queue-functions-for-use-by-RDMA.patch100
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0008-net-mana-Record-port-number-in-netdev.patch34
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0009-net-mana-Move-header-files-to-a-common-location.patch152
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0010-net-mana-Define-max-values-for-SGL-entries.patch79
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0011-net-mana-Define-and-process-GDMA-response-code-GDMA_.patch52
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0012-net-mana-Define-data-structures-for-protection-domai.patch353
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0013-net-mana-Fix-return-type-of-mana_start_xmit.patch66
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0014-net-mana-Fix-accessing-freed-irq-affinity_hint.patch135
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0015-net-mana-Add-new-MANA-VF-performance-counters-for-ea.patch334
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0016-net-mana-Remove-redundant-pci_clear_master.patch54
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0017-net-mana-Use-napi_build_skb-in-RX-path.patch33
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0018-net-mana-Refactor-RX-buffer-allocation-code-to-prepa.patch289
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0019-net-mana-Enable-RX-path-to-handle-various-MTU-sizes.patch147
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0020-net-mana-Add-support-for-jumbo-frame.patch423
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0021-net-mana-Check-if-netdev-napi_alloc_frag-returns-sin.patch54
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0022-net-mana-Fix-perf-regression-remove-rx_cqes-tx_cqes-.patch121
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0023-net-mana-Add-support-for-vlan-tagging.patch67
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0024-RDMA-mana_ib-Use-v2-version-of-cfg_rx_steer_req-to-e.patch78
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0025-net-mana-use-vmalloc_array-and-vcalloc.patch75
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0026-net-mana-Batch-ringing-RX-queue-doorbell-on-receivin.patch62
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0027-net-mana-Use-the-correct-WQE-count-for-ringing-RQ-do.patch41
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0028-net-mana-Configure-hwc-timeout-from-hardware.patch217
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0029-net-mana-Rename-mana_refill_rxoob-and-remove-some-em.patch67
-rw-r--r--debian/patches/features/all/ethernet-microsoft/0030-net-mana-Add-gdma-stats-to-ethtool-output-for-mana.patch232
-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.patch131
-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/arm64/arm64-dts-rockchip-Add-Hardkernel-ODROID-M1-board.patch454
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-IR-receiver-node-to-ODROID-M1.patch51
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-NOR-flash-to-ODROID-M1.patch100
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-PCIEe-v3-nodes-to-ODROID-M1.patch77
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-SATA-support-to-ODROID-M1.patch45
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Add-analog-audio-on-ODROID-M1.patch99
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Enable-HDMI-audio-on-ODROID-M1.patch45
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-GPU-on-ODROID-M1.patch34
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-2.0-ports-on-ODROI.patch108
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-3.0-ports-on-ODROI.patch111
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-Enable-vop2-and-hdmi-tx-on-ODROID.patch94
-rw-r--r--debian/patches/features/arm64/arm64-dts-rockchip-add-thermal-support-to-ODROID-M1.patch35
-rw-r--r--debian/patches/features/arm64/dt-bindings-rockchip-Add-Hardkernel-ODROID-M1-board.patch37
-rw-r--r--debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-Model-A-baseboard.patch279
-rw-r--r--debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-blade-board.patch242
-rw-r--r--debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-HDMI-sound-on-SOQuartz.patch44
-rw-r--r--debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-PCIe-2-on-SOQuartz-CM4IO.patch82
-rw-r--r--debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-video-output-and-HDMI-on-S.patch94
-rw-r--r--debian/patches/features/arm64/quartz64/arm64-dts-rockchip-RK356x-Add-I2S2-device-node.patch50
-rw-r--r--debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Blade.patch39
-rw-r--r--debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Model-A.patch39
-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/series175
199 files changed, 25088 insertions, 0 deletions
diff --git a/debian/patches-rt/0001-vduse-Remove-include-of-rwlock.h.patch b/debian/patches-rt/0001-vduse-Remove-include-of-rwlock.h.patch
new file mode 100644
index 000000000..891081a3a
--- /dev/null
+++ b/debian/patches-rt/0001-vduse-Remove-include-of-rwlock.h.patch
@@ -0,0 +1,33 @@
+From 52072a197524e62baa4ac9a5f33d15cd8b27fb17 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 16 Aug 2022 09:45:22 +0200
+Subject: [PATCH 01/62] vduse: Remove include of rwlock.h
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+rwlock.h should not be included directly. Instead linux/splinlock.h
+should be included. Including it directly will break the RT build.
+
+Remove the rwlock.h include.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Link: https://lkml.kernel.org/r/20221026134407.711768-1-bigeasy@linutronix.de
+---
+ drivers/vdpa/vdpa_user/iova_domain.h | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/vdpa/vdpa_user/iova_domain.h b/drivers/vdpa/vdpa_user/iova_domain.h
+index 4e0e50e7ac15..173e979b84a9 100644
+--- a/drivers/vdpa/vdpa_user/iova_domain.h
++++ b/drivers/vdpa/vdpa_user/iova_domain.h
+@@ -14,7 +14,6 @@
+ #include <linux/iova.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/vhost_iotlb.h>
+-#include <linux/rwlock.h>
+
+ #define IOVA_START_PFN 1
+
+--
+2.43.0
+
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 000000000..05ec116ad
--- /dev/null
+++ b/debian/patches-rt/0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch
@@ -0,0 +1,66 @@
+From d5541b6ef4eccee650abfe3095b9e7365773494c Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 22 Jun 2022 11:36:17 +0200
+Subject: [PATCH 02/62] signal: Don't disable preemption in ptrace_stop() on
+ PREEMPT_RT.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Commit
+ 53da1d9456fe7 ("fix ptrace slowness")
+
+is just band aid around the problem.
+The invocation of do_notify_parent_cldstop() wakes the parent and makes
+it runnable. The scheduler then wants to replace this still running task
+with the parent. With the read_lock() acquired this is not possible
+because preemption is disabled and so this is deferred until read_unlock().
+This scheduling point is undesired and is avoided by disabling preemption
+around the unlock operation enabled again before the schedule() invocation
+without a preemption point.
+This is only undesired because the parent sleeps a cycle in
+wait_task_inactive() until the traced task leaves the run-queue in
+schedule(). It is not a correctness issue, it is just band aid to avoid the
+visbile delay which sums up over multiple invocations.
+The task can still be preempted if an interrupt occurs between
+preempt_enable_no_resched() and freezable_schedule() because on the IRQ-exit
+path of the interrupt scheduling _will_ happen. This is ignored since it does
+not happen very often.
+
+On PREEMPT_RT keeping preemption disabled during the invocation of
+cgroup_enter_frozen() becomes 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.
+
+Don't disable preemption on PREEMPT_RT. Remove the TODO regarding adding
+read_unlock_no_resched() as there is no need for it and will cause harm.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lkml.kernel.org/r/20220720154435.232749-2-bigeasy@linutronix.de
+---
+ kernel/signal.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/signal.c b/kernel/signal.c
+index 5d45f5da2b36..58e919c7c936 100644
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -2302,13 +2302,13 @@ static int ptrace_stop(int exit_code, int why, unsigned long message,
+ /*
+ * Don't want to allow preemption here, because
+ * sys_ptrace() needs this task to be inactive.
+- *
+- * XXX: implement read_unlock_no_resched().
+ */
+- 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);
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0003-sched-Consider-task_struct-saved_state-in-wait_task_.patch b/debian/patches-rt/0003-sched-Consider-task_struct-saved_state-in-wait_task_.patch
new file mode 100644
index 000000000..933385ab9
--- /dev/null
+++ b/debian/patches-rt/0003-sched-Consider-task_struct-saved_state-in-wait_task_.patch
@@ -0,0 +1,152 @@
+From e4742fc784660e012dc23090a72614bf1f9a0ca1 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 22 Jun 2022 12:27:05 +0200
+Subject: [PATCH 03/62] sched: Consider task_struct::saved_state in
+ wait_task_inactive().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Ptrace is using wait_task_inactive() to wait for the tracee to reach a
+certain task state. On PREEMPT_RT that state may be stored in
+task_struct::saved_state while the tracee blocks on a sleeping lock and
+task_struct::__state is set to TASK_RTLOCK_WAIT.
+It is not possible to check only for TASK_RTLOCK_WAIT to be sure that the task
+is blocked on a sleeping lock because during wake up (after the sleeping lock
+has been acquired) the task state is set TASK_RUNNING. After the task in on CPU
+and acquired the pi_lock it will reset the state accordingly but until then
+TASK_RUNNING will be observed (with the desired state saved in saved_state).
+
+Check also for task_struct::saved_state if the desired match was not found in
+task_struct::__state on PREEMPT_RT. If the state was found in saved_state, wait
+until the task is idle and state is visible in task_struct::__state.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Valentin Schneider <vschneid@redhat.com>
+Link: https://lkml.kernel.org/r/Yt%2FpQAFQ1xKNK0RY@linutronix.de
+---
+ kernel/sched/core.c | 81 ++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 76 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 18a4f8f28a25..6bd06122850a 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -3281,6 +3281,76 @@ int migrate_swap(struct task_struct *cur, struct task_struct *p,
+ }
+ #endif /* CONFIG_NUMA_BALANCING */
+
++#ifdef CONFIG_PREEMPT_RT
++
++/*
++ * Consider:
++ *
++ * set_special_state(X);
++ *
++ * do_things()
++ * // Somewhere in there is an rtlock that can be contended:
++ * current_save_and_set_rtlock_wait_state();
++ * [...]
++ * schedule_rtlock(); (A)
++ * [...]
++ * current_restore_rtlock_saved_state();
++ *
++ * schedule(); (B)
++ *
++ * If p->saved_state is anything else than TASK_RUNNING, then p blocked on an
++ * rtlock (A) *before* voluntarily calling into schedule() (B) after setting its
++ * state to X. For things like ptrace (X=TASK_TRACED), the task could have more
++ * work to do upon acquiring the lock in do_things() before whoever called
++ * wait_task_inactive() should return. IOW, we have to wait for:
++ *
++ * p.saved_state = TASK_RUNNING
++ * p.__state = X
++ *
++ * which implies the task isn't blocked on an RT lock and got to schedule() (B).
++ *
++ * Also see comments in ttwu_state_match().
++ */
++
++static __always_inline bool state_mismatch(struct task_struct *p, unsigned int match_state)
++{
++ unsigned long flags;
++ bool mismatch;
++
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ if (READ_ONCE(p->__state) & match_state)
++ mismatch = false;
++ else if (READ_ONCE(p->saved_state) & match_state)
++ mismatch = false;
++ else
++ mismatch = true;
++
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++ return mismatch;
++}
++static __always_inline bool state_match(struct task_struct *p, unsigned int match_state,
++ bool *wait)
++{
++ if (READ_ONCE(p->__state) & match_state)
++ return true;
++ if (READ_ONCE(p->saved_state) & match_state) {
++ *wait = true;
++ return true;
++ }
++ return false;
++}
++#else
++static __always_inline bool state_mismatch(struct task_struct *p, unsigned int match_state)
++{
++ return !(READ_ONCE(p->__state) & match_state);
++}
++static __always_inline bool state_match(struct task_struct *p, unsigned int match_state,
++ bool *wait)
++{
++ return (READ_ONCE(p->__state) & match_state);
++}
++#endif
++
+ /*
+ * wait_task_inactive - wait for a thread to unschedule.
+ *
+@@ -3299,7 +3369,7 @@ int migrate_swap(struct task_struct *cur, struct task_struct *p,
+ */
+ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state)
+ {
+- int running, queued;
++ bool running, wait;
+ struct rq_flags rf;
+ unsigned long ncsw;
+ struct rq *rq;
+@@ -3325,7 +3395,7 @@ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state
+ * is actually now running somewhere else!
+ */
+ while (task_on_cpu(rq, p)) {
+- if (!(READ_ONCE(p->__state) & match_state))
++ if (state_mismatch(p, match_state))
+ return 0;
+ cpu_relax();
+ }
+@@ -3338,9 +3408,10 @@ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state
+ rq = task_rq_lock(p, &rf);
+ trace_sched_wait_task(p);
+ running = task_on_cpu(rq, p);
+- queued = task_on_rq_queued(p);
++ wait = task_on_rq_queued(p);
+ ncsw = 0;
+- if (READ_ONCE(p->__state) & match_state)
++
++ if (state_match(p, match_state, &wait))
+ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
+ task_rq_unlock(rq, p, &rf);
+
+@@ -3370,7 +3441,7 @@ unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state
+ * running right now), it's preempted, and we should
+ * yield - it could be a while.
+ */
+- if (unlikely(queued)) {
++ if (unlikely(wait)) {
+ ktime_t to = NSEC_PER_SEC / HZ;
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+--
+2.43.0
+
diff --git a/debian/patches-rt/0004-spi-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch b/debian/patches-rt/0004-spi-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch
new file mode 100644
index 000000000..0f1b0f221
--- /dev/null
+++ b/debian/patches-rt/0004-spi-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch
@@ -0,0 +1,40 @@
+From 638117350cb3452dd5043156c7e394befe7d6eb9 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 25 Aug 2022 16:15:32 +0200
+Subject: [PATCH 04/62] spi: Remove the obsolte u64_stats_fetch_*_irq() users.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Now that the 32bit UP oddity is gone and 32bit uses always a sequence
+count, there is no need for the fetch_irq() variants anymore.
+
+Convert to the regular interface.
+
+Cc: Mark Brown <broonie@kernel.org>
+Cc: linux-spi@vger.kernel.org
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+---
+ drivers/spi/spi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 5d046be8b2dd..716e6d6ecf98 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -127,10 +127,10 @@ do { \
+ unsigned int start; \
+ pcpu_stats = per_cpu_ptr(in, i); \
+ do { \
+- start = u64_stats_fetch_begin_irq( \
++ start = u64_stats_fetch_begin( \
+ &pcpu_stats->syncp); \
+ inc = u64_stats_read(&pcpu_stats->field); \
+- } while (u64_stats_fetch_retry_irq( \
++ } while (u64_stats_fetch_retry( \
+ &pcpu_stats->syncp, start)); \
+ ret += inc; \
+ } \
+--
+2.43.0
+
diff --git a/debian/patches-rt/0005-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch b/debian/patches-rt/0005-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch
new file mode 100644
index 000000000..a4d96ec61
--- /dev/null
+++ b/debian/patches-rt/0005-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch
@@ -0,0 +1,2087 @@
+From d1c3fb886c8b630c3a70f2f7192d53f545798283 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 25 Aug 2022 16:15:44 +0200
+Subject: [PATCH 05/62] net: Remove the obsolte u64_stats_fetch_*_irq() users
+ (drivers).
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Now that the 32bit UP oddity is gone and 32bit uses always a sequence
+count, there is no need for the fetch_irq() variants anymore.
+
+Convert to the regular interface.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+---
+ drivers/net/ethernet/alacritech/slic.h | 12 +++----
+ drivers/net/ethernet/amazon/ena/ena_ethtool.c | 4 +--
+ drivers/net/ethernet/amazon/ena/ena_netdev.c | 12 +++----
+ .../net/ethernet/aquantia/atlantic/aq_ring.c | 8 ++---
+ drivers/net/ethernet/asix/ax88796c_main.c | 4 +--
+ drivers/net/ethernet/broadcom/b44.c | 8 ++---
+ drivers/net/ethernet/broadcom/bcmsysport.c | 12 +++----
+ drivers/net/ethernet/cortina/gemini.c | 24 +++++++-------
+ .../net/ethernet/emulex/benet/be_ethtool.c | 12 +++----
+ drivers/net/ethernet/emulex/benet/be_main.c | 16 +++++-----
+ .../ethernet/fungible/funeth/funeth_txrx.h | 4 +--
+ drivers/net/ethernet/google/gve/gve_ethtool.c | 16 +++++-----
+ drivers/net/ethernet/google/gve/gve_main.c | 12 +++----
+ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 4 +--
+ drivers/net/ethernet/huawei/hinic/hinic_rx.c | 4 +--
+ drivers/net/ethernet/huawei/hinic/hinic_tx.c | 4 +--
+ .../net/ethernet/intel/fm10k/fm10k_netdev.c | 8 ++---
+ .../net/ethernet/intel/i40e/i40e_ethtool.c | 8 ++---
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 20 ++++++------
+ .../net/ethernet/intel/iavf/iavf_ethtool.c | 8 ++---
+ drivers/net/ethernet/intel/ice/ice_main.c | 4 +--
+ drivers/net/ethernet/intel/igb/igb_ethtool.c | 12 +++----
+ drivers/net/ethernet/intel/igb/igb_main.c | 8 ++---
+ drivers/net/ethernet/intel/igc/igc_ethtool.c | 12 +++----
+ drivers/net/ethernet/intel/igc/igc_main.c | 8 ++---
+ .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 8 ++---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 8 ++---
+ drivers/net/ethernet/intel/ixgbevf/ethtool.c | 12 +++----
+ .../net/ethernet/intel/ixgbevf/ixgbevf_main.c | 8 ++---
+ drivers/net/ethernet/marvell/mvneta.c | 8 ++---
+ .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 8 ++---
+ drivers/net/ethernet/marvell/sky2.c | 8 ++---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++---
+ .../net/ethernet/mellanox/mlxsw/spectrum.c | 4 +--
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 8 ++---
+ .../ethernet/microsoft/mana/mana_ethtool.c | 8 ++---
+ .../ethernet/netronome/nfp/nfp_net_common.c | 8 ++---
+ .../ethernet/netronome/nfp/nfp_net_ethtool.c | 8 ++---
+ .../net/ethernet/netronome/nfp/nfp_net_repr.c | 4 +--
+ drivers/net/ethernet/nvidia/forcedeth.c | 8 ++---
+ .../net/ethernet/qualcomm/rmnet/rmnet_vnd.c | 4 +--
+ drivers/net/ethernet/realtek/8139too.c | 8 ++---
+ drivers/net/ethernet/socionext/sni_ave.c | 8 ++---
+ drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +--
+ drivers/net/ethernet/ti/netcp_core.c | 8 ++---
+ drivers/net/ethernet/via/via-rhine.c | 8 ++---
+ .../net/ethernet/xilinx/xilinx_axienet_main.c | 8 ++---
+ drivers/net/hyperv/netvsc_drv.c | 32 +++++++++----------
+ drivers/net/ifb.c | 12 +++----
+ drivers/net/ipvlan/ipvlan_main.c | 4 +--
+ drivers/net/loopback.c | 4 +--
+ drivers/net/macsec.c | 12 +++----
+ drivers/net/macvlan.c | 4 +--
+ drivers/net/mhi_net.c | 8 ++---
+ drivers/net/netdevsim/netdev.c | 4 +--
+ drivers/net/team/team.c | 4 +--
+ drivers/net/team/team_mode_loadbalance.c | 4 +--
+ drivers/net/veth.c | 12 +++----
+ drivers/net/virtio_net.c | 16 +++++-----
+ drivers/net/vrf.c | 4 +--
+ drivers/net/vxlan/vxlan_vnifilter.c | 4 +--
+ drivers/net/wwan/mhi_wwan_mbim.c | 8 ++---
+ drivers/net/xen-netfront.c | 8 ++---
+ 63 files changed, 274 insertions(+), 274 deletions(-)
+
+diff --git a/drivers/net/ethernet/alacritech/slic.h b/drivers/net/ethernet/alacritech/slic.h
+index 4eecbdfff3ff..82071d0e5f7f 100644
+--- a/drivers/net/ethernet/alacritech/slic.h
++++ b/drivers/net/ethernet/alacritech/slic.h
+@@ -288,13 +288,13 @@ do { \
+ u64_stats_update_end(&(st)->syncp); \
+ } while (0)
+
+-#define SLIC_GET_STATS_COUNTER(newst, st, counter) \
+-{ \
+- unsigned int start; \
++#define SLIC_GET_STATS_COUNTER(newst, st, counter) \
++{ \
++ unsigned int start; \
+ do { \
+- start = u64_stats_fetch_begin_irq(&(st)->syncp); \
+- newst = (st)->counter; \
+- } while (u64_stats_fetch_retry_irq(&(st)->syncp, start)); \
++ start = u64_stats_fetch_begin(&(st)->syncp); \
++ newst = (st)->counter; \
++ } while (u64_stats_fetch_retry(&(st)->syncp, start)); \
+ }
+
+ struct slic_upr {
+diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
+index 444ccef76da2..8da79eedc057 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c
++++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
+@@ -118,9 +118,9 @@ static void ena_safe_update_stat(u64 *src, u64 *dst,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(syncp);
++ start = u64_stats_fetch_begin(syncp);
+ *(dst) = *src;
+- } while (u64_stats_fetch_retry_irq(syncp, start));
++ } while (u64_stats_fetch_retry(syncp, start));
+ }
+
+ static void ena_queue_stats(struct ena_adapter *adapter, u64 **data)
+diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+index 044b8afde69a..e296546f03cd 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+@@ -3312,10 +3312,10 @@ static void ena_get_stats64(struct net_device *netdev,
+ tx_ring = &adapter->tx_ring[i];
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_ring->syncp);
++ start = u64_stats_fetch_begin(&tx_ring->syncp);
+ packets = tx_ring->tx_stats.cnt;
+ bytes = tx_ring->tx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&tx_ring->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_ring->syncp, start));
+
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+@@ -3323,20 +3323,20 @@ static void ena_get_stats64(struct net_device *netdev,
+ rx_ring = &adapter->rx_ring[i];
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_ring->syncp);
++ start = u64_stats_fetch_begin(&rx_ring->syncp);
+ packets = rx_ring->rx_stats.cnt;
+ bytes = rx_ring->rx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&rx_ring->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_ring->syncp, start));
+
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&adapter->syncp);
++ start = u64_stats_fetch_begin(&adapter->syncp);
+ rx_drops = adapter->dev_stats.rx_drops;
+ tx_drops = adapter->dev_stats.tx_drops;
+- } while (u64_stats_fetch_retry_irq(&adapter->syncp, start));
++ } while (u64_stats_fetch_retry(&adapter->syncp, start));
+
+ stats->rx_dropped = rx_drops;
+ stats->tx_dropped = tx_drops;
+diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+index 4d9d7d1edb9b..697ce83eeae1 100644
+--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
++++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+@@ -957,7 +957,7 @@ unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)
+ /* This data should mimic aq_ethtool_queue_rx_stat_names structure */
+ do {
+ count = 0;
+- start = u64_stats_fetch_begin_irq(&self->stats.rx.syncp);
++ start = u64_stats_fetch_begin(&self->stats.rx.syncp);
+ data[count] = self->stats.rx.packets;
+ data[++count] = self->stats.rx.jumbo_packets;
+ data[++count] = self->stats.rx.lro_packets;
+@@ -974,15 +974,15 @@ unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)
+ data[++count] = self->stats.rx.xdp_tx;
+ data[++count] = self->stats.rx.xdp_invalid;
+ data[++count] = self->stats.rx.xdp_redirect;
+- } while (u64_stats_fetch_retry_irq(&self->stats.rx.syncp, start));
++ } while (u64_stats_fetch_retry(&self->stats.rx.syncp, start));
+ } else {
+ /* This data should mimic aq_ethtool_queue_tx_stat_names structure */
+ do {
+ count = 0;
+- start = u64_stats_fetch_begin_irq(&self->stats.tx.syncp);
++ start = u64_stats_fetch_begin(&self->stats.tx.syncp);
+ data[count] = self->stats.tx.packets;
+ data[++count] = self->stats.tx.queue_restarts;
+- } while (u64_stats_fetch_retry_irq(&self->stats.tx.syncp, start));
++ } while (u64_stats_fetch_retry(&self->stats.tx.syncp, start));
+ }
+
+ return ++count;
+diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c
+index 8b7cdf015a16..21376c79f671 100644
+--- a/drivers/net/ethernet/asix/ax88796c_main.c
++++ b/drivers/net/ethernet/asix/ax88796c_main.c
+@@ -662,12 +662,12 @@ static void ax88796c_get_stats64(struct net_device *ndev,
+ s = per_cpu_ptr(ax_local->stats, cpu);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&s->syncp);
++ start = u64_stats_fetch_begin(&s->syncp);
+ rx_packets = u64_stats_read(&s->rx_packets);
+ rx_bytes = u64_stats_read(&s->rx_bytes);
+ tx_packets = u64_stats_read(&s->tx_packets);
+ tx_bytes = u64_stats_read(&s->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&s->syncp, start));
++ } while (u64_stats_fetch_retry(&s->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
+index 7f876721596c..b751dc8486dc 100644
+--- a/drivers/net/ethernet/broadcom/b44.c
++++ b/drivers/net/ethernet/broadcom/b44.c
+@@ -1680,7 +1680,7 @@ static void b44_get_stats64(struct net_device *dev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&hwstat->syncp);
++ start = u64_stats_fetch_begin(&hwstat->syncp);
+
+ /* Convert HW stats into rtnl_link_stats64 stats. */
+ nstat->rx_packets = hwstat->rx_pkts;
+@@ -1714,7 +1714,7 @@ static void b44_get_stats64(struct net_device *dev,
+ /* Carrier lost counter seems to be broken for some devices */
+ nstat->tx_carrier_errors = hwstat->tx_carrier_lost;
+ #endif
+- } while (u64_stats_fetch_retry_irq(&hwstat->syncp, start));
++ } while (u64_stats_fetch_retry(&hwstat->syncp, start));
+
+ }
+
+@@ -2082,12 +2082,12 @@ static void b44_get_ethtool_stats(struct net_device *dev,
+ do {
+ data_src = &hwstat->tx_good_octets;
+ data_dst = data;
+- start = u64_stats_fetch_begin_irq(&hwstat->syncp);
++ start = u64_stats_fetch_begin(&hwstat->syncp);
+
+ for (i = 0; i < ARRAY_SIZE(b44_gstrings); i++)
+ *data_dst++ = *data_src++;
+
+- } while (u64_stats_fetch_retry_irq(&hwstat->syncp, start));
++ } while (u64_stats_fetch_retry(&hwstat->syncp, start));
+ }
+
+ static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
+index 425d6ccd5413..f8b1adc389b3 100644
+--- a/drivers/net/ethernet/broadcom/bcmsysport.c
++++ b/drivers/net/ethernet/broadcom/bcmsysport.c
+@@ -457,10 +457,10 @@ static void bcm_sysport_update_tx_stats(struct bcm_sysport_priv *priv,
+ for (q = 0; q < priv->netdev->num_tx_queues; q++) {
+ ring = &priv->tx_rings[q];
+ do {
+- start = u64_stats_fetch_begin_irq(&priv->syncp);
++ start = u64_stats_fetch_begin(&priv->syncp);
+ bytes = ring->bytes;
+ packets = ring->packets;
+- } while (u64_stats_fetch_retry_irq(&priv->syncp, start));
++ } while (u64_stats_fetch_retry(&priv->syncp, start));
+
+ *tx_bytes += bytes;
+ *tx_packets += packets;
+@@ -504,9 +504,9 @@ static void bcm_sysport_get_stats(struct net_device *dev,
+ if (s->stat_sizeof == sizeof(u64) &&
+ s->type == BCM_SYSPORT_STAT_NETDEV64) {
+ do {
+- start = u64_stats_fetch_begin_irq(syncp);
++ start = u64_stats_fetch_begin(syncp);
+ data[i] = *(u64 *)p;
+- } while (u64_stats_fetch_retry_irq(syncp, start));
++ } while (u64_stats_fetch_retry(syncp, start));
+ } else
+ data[i] = *(u32 *)p;
+ j++;
+@@ -1878,10 +1878,10 @@ static void bcm_sysport_get_stats64(struct net_device *dev,
+ &stats->tx_packets);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&priv->syncp);
++ start = u64_stats_fetch_begin(&priv->syncp);
+ stats->rx_packets = stats64->rx_packets;
+ stats->rx_bytes = stats64->rx_bytes;
+- } while (u64_stats_fetch_retry_irq(&priv->syncp, start));
++ } while (u64_stats_fetch_retry(&priv->syncp, start));
+ }
+
+ static void bcm_sysport_netif_start(struct net_device *dev)
+diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
+index 7c0b0bc033c9..e7137b468f5b 100644
+--- a/drivers/net/ethernet/cortina/gemini.c
++++ b/drivers/net/ethernet/cortina/gemini.c
+@@ -1941,7 +1941,7 @@ static void gmac_get_stats64(struct net_device *netdev,
+
+ /* Racing with RX NAPI */
+ do {
+- start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
++ start = u64_stats_fetch_begin(&port->rx_stats_syncp);
+
+ stats->rx_packets = port->stats.rx_packets;
+ stats->rx_bytes = port->stats.rx_bytes;
+@@ -1953,11 +1953,11 @@ static void gmac_get_stats64(struct net_device *netdev,
+ stats->rx_crc_errors = port->stats.rx_crc_errors;
+ stats->rx_frame_errors = port->stats.rx_frame_errors;
+
+- } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
++ } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
+
+ /* Racing with MIB and TX completion interrupts */
+ do {
+- start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
++ start = u64_stats_fetch_begin(&port->ir_stats_syncp);
+
+ stats->tx_errors = port->stats.tx_errors;
+ stats->tx_packets = port->stats.tx_packets;
+@@ -1967,15 +1967,15 @@ static void gmac_get_stats64(struct net_device *netdev,
+ stats->rx_missed_errors = port->stats.rx_missed_errors;
+ stats->rx_fifo_errors = port->stats.rx_fifo_errors;
+
+- } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
++ } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
+
+ /* Racing with hard_start_xmit */
+ do {
+- start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
++ start = u64_stats_fetch_begin(&port->tx_stats_syncp);
+
+ stats->tx_dropped = port->stats.tx_dropped;
+
+- } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
++ } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
+
+ stats->rx_dropped += stats->rx_missed_errors;
+ }
+@@ -2044,18 +2044,18 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
+ /* Racing with MIB interrupt */
+ do {
+ p = values;
+- start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
++ start = u64_stats_fetch_begin(&port->ir_stats_syncp);
+
+ for (i = 0; i < RX_STATS_NUM; i++)
+ *p++ = port->hw_stats[i];
+
+- } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
++ } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
+ values = p;
+
+ /* Racing with RX NAPI */
+ do {
+ p = values;
+- start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
++ start = u64_stats_fetch_begin(&port->rx_stats_syncp);
+
+ for (i = 0; i < RX_STATUS_NUM; i++)
+ *p++ = port->rx_stats[i];
+@@ -2063,13 +2063,13 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
+ *p++ = port->rx_csum_stats[i];
+ *p++ = port->rx_napi_exits;
+
+- } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
++ } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
+ values = p;
+
+ /* Racing with TX start_xmit */
+ do {
+ p = values;
+- start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
++ start = u64_stats_fetch_begin(&port->tx_stats_syncp);
+
+ for (i = 0; i < TX_MAX_FRAGS; i++) {
+ *values++ = port->tx_frag_stats[i];
+@@ -2078,7 +2078,7 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
+ *values++ = port->tx_frags_linearized;
+ *values++ = port->tx_hw_csummed;
+
+- } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
++ } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
+ }
+
+ static int gmac_get_ksettings(struct net_device *netdev,
+diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
+index 77edc3d9b505..a29de29bdf23 100644
+--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
++++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
+@@ -389,10 +389,10 @@ static void be_get_ethtool_stats(struct net_device *netdev,
+ struct be_rx_stats *stats = rx_stats(rxo);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->sync);
++ start = u64_stats_fetch_begin(&stats->sync);
+ data[base] = stats->rx_bytes;
+ data[base + 1] = stats->rx_pkts;
+- } while (u64_stats_fetch_retry_irq(&stats->sync, start));
++ } while (u64_stats_fetch_retry(&stats->sync, start));
+
+ for (i = 2; i < ETHTOOL_RXSTATS_NUM; i++) {
+ p = (u8 *)stats + et_rx_stats[i].offset;
+@@ -405,19 +405,19 @@ static void be_get_ethtool_stats(struct net_device *netdev,
+ struct be_tx_stats *stats = tx_stats(txo);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->sync_compl);
++ start = u64_stats_fetch_begin(&stats->sync_compl);
+ data[base] = stats->tx_compl;
+- } while (u64_stats_fetch_retry_irq(&stats->sync_compl, start));
++ } while (u64_stats_fetch_retry(&stats->sync_compl, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->sync);
++ start = u64_stats_fetch_begin(&stats->sync);
+ for (i = 1; i < ETHTOOL_TXSTATS_NUM; i++) {
+ p = (u8 *)stats + et_tx_stats[i].offset;
+ data[base + i] =
+ (et_tx_stats[i].size == sizeof(u64)) ?
+ *(u64 *)p : *(u32 *)p;
+ }
+- } while (u64_stats_fetch_retry_irq(&stats->sync, start));
++ } while (u64_stats_fetch_retry(&stats->sync, start));
+ base += ETHTOOL_TXSTATS_NUM;
+ }
+ }
+diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
+index a9e4e6464a04..968fecfc03bd 100644
+--- a/drivers/net/ethernet/emulex/benet/be_main.c
++++ b/drivers/net/ethernet/emulex/benet/be_main.c
+@@ -665,10 +665,10 @@ static void be_get_stats64(struct net_device *netdev,
+ const struct be_rx_stats *rx_stats = rx_stats(rxo);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->sync);
++ start = u64_stats_fetch_begin(&rx_stats->sync);
+ pkts = rx_stats(rxo)->rx_pkts;
+ bytes = rx_stats(rxo)->rx_bytes;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->sync, start));
++ } while (u64_stats_fetch_retry(&rx_stats->sync, start));
+ stats->rx_packets += pkts;
+ stats->rx_bytes += bytes;
+ stats->multicast += rx_stats(rxo)->rx_mcast_pkts;
+@@ -680,10 +680,10 @@ static void be_get_stats64(struct net_device *netdev,
+ const struct be_tx_stats *tx_stats = tx_stats(txo);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->sync);
++ start = u64_stats_fetch_begin(&tx_stats->sync);
+ pkts = tx_stats(txo)->tx_pkts;
+ bytes = tx_stats(txo)->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->sync, start));
++ } while (u64_stats_fetch_retry(&tx_stats->sync, start));
+ stats->tx_packets += pkts;
+ stats->tx_bytes += bytes;
+ }
+@@ -2156,16 +2156,16 @@ static int be_get_new_eqd(struct be_eq_obj *eqo)
+
+ for_all_rx_queues_on_eq(adapter, eqo, rxo, i) {
+ do {
+- start = u64_stats_fetch_begin_irq(&rxo->stats.sync);
++ start = u64_stats_fetch_begin(&rxo->stats.sync);
+ rx_pkts += rxo->stats.rx_pkts;
+- } while (u64_stats_fetch_retry_irq(&rxo->stats.sync, start));
++ } while (u64_stats_fetch_retry(&rxo->stats.sync, start));
+ }
+
+ for_all_tx_queues_on_eq(adapter, eqo, txo, i) {
+ do {
+- start = u64_stats_fetch_begin_irq(&txo->stats.sync);
++ start = u64_stats_fetch_begin(&txo->stats.sync);
+ tx_pkts += txo->stats.tx_reqs;
+- } while (u64_stats_fetch_retry_irq(&txo->stats.sync, start));
++ } while (u64_stats_fetch_retry(&txo->stats.sync, start));
+ }
+
+ /* Skip, if wrapped around or first calculation */
+diff --git a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h
+index 671f51135c26..53b7e95213a8 100644
+--- a/drivers/net/ethernet/fungible/funeth/funeth_txrx.h
++++ b/drivers/net/ethernet/fungible/funeth/funeth_txrx.h
+@@ -206,9 +206,9 @@ struct funeth_rxq {
+
+ #define FUN_QSTAT_READ(q, seq, stats_copy) \
+ do { \
+- seq = u64_stats_fetch_begin_irq(&(q)->syncp); \
++ seq = u64_stats_fetch_begin(&(q)->syncp); \
+ stats_copy = (q)->stats; \
+- } while (u64_stats_fetch_retry_irq(&(q)->syncp, (seq)))
++ } while (u64_stats_fetch_retry(&(q)->syncp, (seq)))
+
+ #define FUN_INT_NAME_LEN (IFNAMSIZ + 16)
+
+diff --git a/drivers/net/ethernet/google/gve/gve_ethtool.c b/drivers/net/ethernet/google/gve/gve_ethtool.c
+index 033f17cb96be..0a5953089a24 100644
+--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
+@@ -177,14 +177,14 @@ gve_get_ethtool_stats(struct net_device *netdev,
+ struct gve_rx_ring *rx = &priv->rx[ring];
+
+ start =
+- u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
++ u64_stats_fetch_begin(&priv->rx[ring].statss);
+ tmp_rx_pkts = rx->rpackets;
+ tmp_rx_bytes = rx->rbytes;
+ tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
+ tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
+ tmp_rx_desc_err_dropped_pkt =
+ rx->rx_desc_err_dropped_pkt;
+- } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
++ } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+ start));
+ rx_pkts += tmp_rx_pkts;
+ rx_bytes += tmp_rx_bytes;
+@@ -198,10 +198,10 @@ gve_get_ethtool_stats(struct net_device *netdev,
+ if (priv->tx) {
+ do {
+ start =
+- u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
++ u64_stats_fetch_begin(&priv->tx[ring].statss);
+ tmp_tx_pkts = priv->tx[ring].pkt_done;
+ tmp_tx_bytes = priv->tx[ring].bytes_done;
+- } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
++ } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+ start));
+ tx_pkts += tmp_tx_pkts;
+ tx_bytes += tmp_tx_bytes;
+@@ -259,13 +259,13 @@ gve_get_ethtool_stats(struct net_device *netdev,
+ data[i++] = rx->fill_cnt - rx->cnt;
+ do {
+ start =
+- u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
++ u64_stats_fetch_begin(&priv->rx[ring].statss);
+ tmp_rx_bytes = rx->rbytes;
+ tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
+ tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
+ tmp_rx_desc_err_dropped_pkt =
+ rx->rx_desc_err_dropped_pkt;
+- } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
++ } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+ start));
+ data[i++] = tmp_rx_bytes;
+ data[i++] = rx->rx_cont_packet_cnt;
+@@ -331,9 +331,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
+ }
+ do {
+ start =
+- u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
++ u64_stats_fetch_begin(&priv->tx[ring].statss);
+ tmp_tx_bytes = tx->bytes_done;
+- } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
++ } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+ start));
+ data[i++] = tmp_tx_bytes;
+ data[i++] = tx->wake_queue;
+diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
+index d3f6ad586ba1..1c2cd3ee1956 100644
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -51,10 +51,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
+ for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
+ do {
+ start =
+- u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
++ u64_stats_fetch_begin(&priv->rx[ring].statss);
+ packets = priv->rx[ring].rpackets;
+ bytes = priv->rx[ring].rbytes;
+- } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
++ } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+ start));
+ s->rx_packets += packets;
+ s->rx_bytes += bytes;
+@@ -64,10 +64,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
+ for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
+ do {
+ start =
+- u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
++ u64_stats_fetch_begin(&priv->tx[ring].statss);
+ packets = priv->tx[ring].pkt_done;
+ bytes = priv->tx[ring].bytes_done;
+- } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
++ } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+ start));
+ s->tx_packets += packets;
+ s->tx_bytes += bytes;
+@@ -1260,9 +1260,9 @@ void gve_handle_report_stats(struct gve_priv *priv)
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&priv->tx[idx].statss);
++ start = u64_stats_fetch_begin(&priv->tx[idx].statss);
+ tx_bytes = priv->tx[idx].bytes_done;
+- } while (u64_stats_fetch_retry_irq(&priv->tx[idx].statss, start));
++ } while (u64_stats_fetch_retry(&priv->tx[idx].statss, start));
+ stats[stats_idx++] = (struct stats) {
+ .stat_name = cpu_to_be32(TX_WAKE_CNT),
+ .value = cpu_to_be64(priv->tx[idx].wake_queue),
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+index 78d6752fe051..5bf81dca14fa 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+@@ -2496,7 +2496,7 @@ static void hns3_fetch_stats(struct rtnl_link_stats64 *stats,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ if (is_tx) {
+ stats->tx_bytes += ring->stats.tx_bytes;
+ stats->tx_packets += ring->stats.tx_pkts;
+@@ -2530,7 +2530,7 @@ static void hns3_fetch_stats(struct rtnl_link_stats64 *stats,
+ stats->multicast += ring->stats.rx_multicast;
+ stats->rx_length_errors += ring->stats.err_pkt_len;
+ }
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ }
+
+ static void hns3_nic_get_stats64(struct net_device *netdev,
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+index d649c6e323c8..ceec8be2a73b 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+@@ -74,14 +74,14 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rxq_stats->syncp);
++ start = u64_stats_fetch_begin(&rxq_stats->syncp);
+ stats->pkts = rxq_stats->pkts;
+ stats->bytes = rxq_stats->bytes;
+ stats->errors = rxq_stats->csum_errors +
+ rxq_stats->other_errors;
+ stats->csum_errors = rxq_stats->csum_errors;
+ stats->other_errors = rxq_stats->other_errors;
+- } while (u64_stats_fetch_retry_irq(&rxq_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+index e91476c8ff8b..ad47ac51a139 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+@@ -99,14 +99,14 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&txq_stats->syncp);
++ start = u64_stats_fetch_begin(&txq_stats->syncp);
+ stats->pkts = txq_stats->pkts;
+ stats->bytes = txq_stats->bytes;
+ stats->tx_busy = txq_stats->tx_busy;
+ stats->tx_wake = txq_stats->tx_wake;
+ stats->tx_dropped = txq_stats->tx_dropped;
+ stats->big_frags_pkts = txq_stats->big_frags_pkts;
+- } while (u64_stats_fetch_retry_irq(&txq_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+index 2cca9e84e31e..34ab5ff9823b 100644
+--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
++++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+@@ -1229,10 +1229,10 @@ static void fm10k_get_stats64(struct net_device *netdev,
+ continue;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+@@ -1245,10 +1245,10 @@ static void fm10k_get_stats64(struct net_device *netdev,
+ continue;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+index 107bcca7db8c..8f36fe90180f 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+@@ -154,7 +154,7 @@ __i40e_add_ethtool_stats(u64 **data, void *pointer,
+ * @ring: the ring to copy
+ *
+ * Queue statistics must be copied while protected by
+- * u64_stats_fetch_begin_irq, so we can't directly use i40e_add_ethtool_stats.
++ * u64_stats_fetch_begin, so we can't directly use i40e_add_ethtool_stats.
+ * Assumes that queue stats are defined in i40e_gstrings_queue_stats. If the
+ * ring pointer is null, zero out the queue stat values and update the data
+ * pointer. Otherwise safely copy the stats from the ring into the supplied
+@@ -172,16 +172,16 @@ i40e_add_queue_stats(u64 **data, struct i40e_ring *ring)
+
+ /* To avoid invalid statistics values, ensure that we keep retrying
+ * the copy until we get a consistent value according to
+- * u64_stats_fetch_retry_irq. But first, make sure our ring is
++ * u64_stats_fetch_retry. But first, make sure our ring is
+ * non-null before attempting to access its syncp.
+ */
+ do {
+- start = !ring ? 0 : u64_stats_fetch_begin_irq(&ring->syncp);
++ start = !ring ? 0 : u64_stats_fetch_begin(&ring->syncp);
+ for (i = 0; i < size; i++) {
+ i40e_add_one_ethtool_stat(&(*data)[i], ring,
+ &stats[i]);
+ }
+- } while (ring && u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (ring && u64_stats_fetch_retry(&ring->syncp, start));
+
+ /* Once we successfully copy the stats in, update the data pointer */
+ *data += size;
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index b4157ff370a3..3b1f912c4c2b 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -419,10 +419,10 @@ static void i40e_get_netdev_stats_struct_tx(struct i40e_ring *ring,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+@@ -472,10 +472,10 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
+ if (!ring)
+ continue;
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+@@ -897,10 +897,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
+ continue;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ packets = p->stats.packets;
+ bytes = p->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+ tx_b += bytes;
+ tx_p += packets;
+ tx_restart += p->tx_stats.restart_queue;
+@@ -915,10 +915,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
+ continue;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ packets = p->stats.packets;
+ bytes = p->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+ rx_b += bytes;
+ rx_p += packets;
+ rx_buf += p->rx_stats.alloc_buff_failed;
+@@ -935,10 +935,10 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
+ continue;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ packets = p->stats.packets;
+ bytes = p->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+ tx_b += bytes;
+ tx_p += packets;
+ tx_restart += p->tx_stats.restart_queue;
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+index f4ac2b164b3e..892c6a4f03bb 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+@@ -147,7 +147,7 @@ __iavf_add_ethtool_stats(u64 **data, void *pointer,
+ * @ring: the ring to copy
+ *
+ * Queue statistics must be copied while protected by
+- * u64_stats_fetch_begin_irq, so we can't directly use iavf_add_ethtool_stats.
++ * u64_stats_fetch_begin, so we can't directly use iavf_add_ethtool_stats.
+ * Assumes that queue stats are defined in iavf_gstrings_queue_stats. If the
+ * ring pointer is null, zero out the queue stat values and update the data
+ * pointer. Otherwise safely copy the stats from the ring into the supplied
+@@ -165,14 +165,14 @@ iavf_add_queue_stats(u64 **data, struct iavf_ring *ring)
+
+ /* To avoid invalid statistics values, ensure that we keep retrying
+ * the copy until we get a consistent value according to
+- * u64_stats_fetch_retry_irq. But first, make sure our ring is
++ * u64_stats_fetch_retry. But first, make sure our ring is
+ * non-null before attempting to access its syncp.
+ */
+ do {
+- start = !ring ? 0 : u64_stats_fetch_begin_irq(&ring->syncp);
++ start = !ring ? 0 : u64_stats_fetch_begin(&ring->syncp);
+ for (i = 0; i < size; i++)
+ iavf_add_one_ethtool_stat(&(*data)[i], ring, &stats[i]);
+- } while (ring && u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (ring && u64_stats_fetch_retry(&ring->syncp, start));
+
+ /* Once we successfully copy the stats in, update the data pointer */
+ *data += size;
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index f0f39364819a..f8d722339e89 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -6419,10 +6419,10 @@ ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(syncp);
++ start = u64_stats_fetch_begin(syncp);
+ *pkts = stats.pkts;
+ *bytes = stats.bytes;
+- } while (u64_stats_fetch_retry_irq(syncp, start));
++ } while (u64_stats_fetch_retry(syncp, start));
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+index ceff537d9d22..4ee849985e2b 100644
+--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
++++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
+@@ -2316,15 +2316,15 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
+
+ ring = adapter->tx_ring[j];
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->tx_syncp);
++ start = u64_stats_fetch_begin(&ring->tx_syncp);
+ data[i] = ring->tx_stats.packets;
+ data[i+1] = ring->tx_stats.bytes;
+ data[i+2] = ring->tx_stats.restart_queue;
+- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->tx_syncp, start));
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->tx_syncp2);
++ start = u64_stats_fetch_begin(&ring->tx_syncp2);
+ restart2 = ring->tx_stats.restart_queue2;
+- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp2, start));
++ } while (u64_stats_fetch_retry(&ring->tx_syncp2, start));
+ data[i+2] += restart2;
+
+ i += IGB_TX_QUEUE_STATS_LEN;
+@@ -2332,13 +2332,13 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
+ for (j = 0; j < adapter->num_rx_queues; j++) {
+ ring = adapter->rx_ring[j];
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->rx_syncp);
++ start = u64_stats_fetch_begin(&ring->rx_syncp);
+ data[i] = ring->rx_stats.packets;
+ data[i+1] = ring->rx_stats.bytes;
+ data[i+2] = ring->rx_stats.drops;
+ data[i+3] = ring->rx_stats.csum_err;
+ data[i+4] = ring->rx_stats.alloc_failed;
+- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->rx_syncp, start));
+ i += IGB_RX_QUEUE_STATS_LEN;
+ }
+ spin_unlock(&adapter->stats64_lock);
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index 45ce4ed16146..9824f7cfaca4 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -6660,10 +6660,10 @@ void igb_update_stats(struct igb_adapter *adapter)
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->rx_syncp);
++ start = u64_stats_fetch_begin(&ring->rx_syncp);
+ _bytes = ring->rx_stats.bytes;
+ _packets = ring->rx_stats.packets;
+- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->rx_syncp, start));
+ bytes += _bytes;
+ packets += _packets;
+ }
+@@ -6676,10 +6676,10 @@ void igb_update_stats(struct igb_adapter *adapter)
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ struct igb_ring *ring = adapter->tx_ring[i];
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->tx_syncp);
++ start = u64_stats_fetch_begin(&ring->tx_syncp);
+ _bytes = ring->tx_stats.bytes;
+ _packets = ring->tx_stats.packets;
+- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->tx_syncp, start));
+ bytes += _bytes;
+ packets += _packets;
+ }
+diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
+index 81897f7a90a9..dd8a9d27a167 100644
+--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
++++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
+@@ -840,15 +840,15 @@ static void igc_ethtool_get_stats(struct net_device *netdev,
+
+ ring = adapter->tx_ring[j];
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->tx_syncp);
++ start = u64_stats_fetch_begin(&ring->tx_syncp);
+ data[i] = ring->tx_stats.packets;
+ data[i + 1] = ring->tx_stats.bytes;
+ data[i + 2] = ring->tx_stats.restart_queue;
+- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->tx_syncp, start));
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->tx_syncp2);
++ start = u64_stats_fetch_begin(&ring->tx_syncp2);
+ restart2 = ring->tx_stats.restart_queue2;
+- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp2, start));
++ } while (u64_stats_fetch_retry(&ring->tx_syncp2, start));
+ data[i + 2] += restart2;
+
+ i += IGC_TX_QUEUE_STATS_LEN;
+@@ -856,13 +856,13 @@ static void igc_ethtool_get_stats(struct net_device *netdev,
+ for (j = 0; j < adapter->num_rx_queues; j++) {
+ ring = adapter->rx_ring[j];
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->rx_syncp);
++ start = u64_stats_fetch_begin(&ring->rx_syncp);
+ data[i] = ring->rx_stats.packets;
+ data[i + 1] = ring->rx_stats.bytes;
+ data[i + 2] = ring->rx_stats.drops;
+ data[i + 3] = ring->rx_stats.csum_err;
+ data[i + 4] = ring->rx_stats.alloc_failed;
+- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->rx_syncp, start));
+ i += IGC_RX_QUEUE_STATS_LEN;
+ }
+ spin_unlock(&adapter->stats64_lock);
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index 4b6f882b380d..c8c5c9d96ba2 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -4868,10 +4868,10 @@ void igc_update_stats(struct igc_adapter *adapter)
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->rx_syncp);
++ start = u64_stats_fetch_begin(&ring->rx_syncp);
+ _bytes = ring->rx_stats.bytes;
+ _packets = ring->rx_stats.packets;
+- } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->rx_syncp, start));
+ bytes += _bytes;
+ packets += _packets;
+ }
+@@ -4885,10 +4885,10 @@ void igc_update_stats(struct igc_adapter *adapter)
+ struct igc_ring *ring = adapter->tx_ring[i];
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->tx_syncp);
++ start = u64_stats_fetch_begin(&ring->tx_syncp);
+ _bytes = ring->tx_stats.bytes;
+ _packets = ring->tx_stats.packets;
+- } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));
++ } while (u64_stats_fetch_retry(&ring->tx_syncp, start));
+ bytes += _bytes;
+ packets += _packets;
+ }
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+index 0051aa676e19..1c22ff2dba9b 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+@@ -1335,10 +1335,10 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i+1] = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ i += 2;
+ }
+ for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {
+@@ -1351,10 +1351,10 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i+1] = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ i += 2;
+ }
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index 9e0e13638c46..ec86b61a8db8 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -9051,10 +9051,10 @@ static void ixgbe_get_ring_stats64(struct rtnl_link_stats64 *stats,
+
+ if (ring) {
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+@@ -9074,10 +9074,10 @@ static void ixgbe_get_stats64(struct net_device *netdev,
+
+ if (ring) {
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ packets = ring->stats.packets;
+ bytes = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+ }
+diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+index ccfa6b91aac6..296915414a7c 100644
+--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
++++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+@@ -458,10 +458,10 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev,
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i + 1] = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ i += 2;
+ }
+
+@@ -475,10 +475,10 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev,
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i + 1] = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ i += 2;
+ }
+
+@@ -492,10 +492,10 @@ static void ixgbevf_get_ethtool_stats(struct net_device *netdev,
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ data[i] = ring->stats.packets;
+ data[i + 1] = ring->stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ i += 2;
+ }
+ }
+diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+index e338fa572793..a9479ddf68eb 100644
+--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
++++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+@@ -4350,10 +4350,10 @@ static void ixgbevf_get_tx_ring_stats(struct rtnl_link_stats64 *stats,
+
+ if (ring) {
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ bytes = ring->stats.bytes;
+ packets = ring->stats.packets;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ stats->tx_bytes += bytes;
+ stats->tx_packets += packets;
+ }
+@@ -4376,10 +4376,10 @@ static void ixgbevf_get_stats(struct net_device *netdev,
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ ring = adapter->rx_ring[i];
+ do {
+- start = u64_stats_fetch_begin_irq(&ring->syncp);
++ start = u64_stats_fetch_begin(&ring->syncp);
+ bytes = ring->stats.bytes;
+ packets = ring->stats.packets;
+- } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
++ } while (u64_stats_fetch_retry(&ring->syncp, start));
+ stats->rx_bytes += bytes;
+ stats->rx_packets += packets;
+ }
+diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
+index eb4ebaa1c92f..327f03f80836 100644
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -813,14 +813,14 @@ mvneta_get_stats64(struct net_device *dev,
+
+ cpu_stats = per_cpu_ptr(pp->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ rx_packets = cpu_stats->es.ps.rx_packets;
+ rx_bytes = cpu_stats->es.ps.rx_bytes;
+ rx_dropped = cpu_stats->rx_dropped;
+ rx_errors = cpu_stats->rx_errors;
+ tx_packets = cpu_stats->es.ps.tx_packets;
+ tx_bytes = cpu_stats->es.ps.tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+@@ -4765,7 +4765,7 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp,
+
+ stats = per_cpu_ptr(pp->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ skb_alloc_error = stats->es.skb_alloc_error;
+ refill_error = stats->es.refill_error;
+ xdp_redirect = stats->es.ps.xdp_redirect;
+@@ -4775,7 +4775,7 @@ mvneta_ethtool_update_pcpu_stats(struct mvneta_port *pp,
+ xdp_xmit_err = stats->es.ps.xdp_xmit_err;
+ xdp_tx = stats->es.ps.xdp_tx;
+ xdp_tx_err = stats->es.ps.xdp_tx_err;
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ es->skb_alloc_error += skb_alloc_error;
+ es->refill_error += refill_error;
+diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+index f936640cca4e..8c7470ab4985 100644
+--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+@@ -2008,7 +2008,7 @@ mvpp2_get_xdp_stats(struct mvpp2_port *port, struct mvpp2_pcpu_stats *xdp_stats)
+
+ cpu_stats = per_cpu_ptr(port->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ xdp_redirect = cpu_stats->xdp_redirect;
+ xdp_pass = cpu_stats->xdp_pass;
+ xdp_drop = cpu_stats->xdp_drop;
+@@ -2016,7 +2016,7 @@ mvpp2_get_xdp_stats(struct mvpp2_port *port, struct mvpp2_pcpu_stats *xdp_stats)
+ xdp_xmit_err = cpu_stats->xdp_xmit_err;
+ xdp_tx = cpu_stats->xdp_tx;
+ xdp_tx_err = cpu_stats->xdp_tx_err;
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ xdp_stats->xdp_redirect += xdp_redirect;
+ xdp_stats->xdp_pass += xdp_pass;
+@@ -5115,12 +5115,12 @@ mvpp2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+
+ cpu_stats = per_cpu_ptr(port->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ rx_packets = cpu_stats->rx_packets;
+ rx_bytes = cpu_stats->rx_bytes;
+ tx_packets = cpu_stats->tx_packets;
+ tx_bytes = cpu_stats->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
+index ab33ba1c3023..ff97b140886a 100644
+--- a/drivers/net/ethernet/marvell/sky2.c
++++ b/drivers/net/ethernet/marvell/sky2.c
+@@ -3894,19 +3894,19 @@ static void sky2_get_stats(struct net_device *dev,
+ u64 _bytes, _packets;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&sky2->rx_stats.syncp);
++ start = u64_stats_fetch_begin(&sky2->rx_stats.syncp);
+ _bytes = sky2->rx_stats.bytes;
+ _packets = sky2->rx_stats.packets;
+- } while (u64_stats_fetch_retry_irq(&sky2->rx_stats.syncp, start));
++ } while (u64_stats_fetch_retry(&sky2->rx_stats.syncp, start));
+
+ stats->rx_packets = _packets;
+ stats->rx_bytes = _bytes;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&sky2->tx_stats.syncp);
++ start = u64_stats_fetch_begin(&sky2->tx_stats.syncp);
+ _bytes = sky2->tx_stats.bytes;
+ _packets = sky2->tx_stats.packets;
+- } while (u64_stats_fetch_retry_irq(&sky2->tx_stats.syncp, start));
++ } while (u64_stats_fetch_retry(&sky2->tx_stats.syncp, start));
+
+ stats->tx_packets = _packets;
+ stats->tx_bytes = _bytes;
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index 17e6ac4445af..f737e2b9a29e 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -866,7 +866,7 @@ static void mtk_get_stats64(struct net_device *dev,
+ }
+
+ do {
+- start = u64_stats_fetch_begin_irq(&hw_stats->syncp);
++ start = u64_stats_fetch_begin(&hw_stats->syncp);
+ storage->rx_packets = hw_stats->rx_packets;
+ storage->tx_packets = hw_stats->tx_packets;
+ storage->rx_bytes = hw_stats->rx_bytes;
+@@ -878,7 +878,7 @@ static void mtk_get_stats64(struct net_device *dev,
+ storage->rx_crc_errors = hw_stats->rx_fcs_errors;
+ storage->rx_errors = hw_stats->rx_checksum_errors;
+ storage->tx_aborted_errors = hw_stats->tx_skip;
+- } while (u64_stats_fetch_retry_irq(&hw_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&hw_stats->syncp, start));
+
+ storage->tx_errors = dev->stats.tx_errors;
+ storage->rx_dropped = dev->stats.rx_dropped;
+@@ -3694,13 +3694,13 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
+
+ do {
+ data_dst = data;
+- start = u64_stats_fetch_begin_irq(&hwstats->syncp);
++ start = u64_stats_fetch_begin(&hwstats->syncp);
+
+ for (i = 0; i < ARRAY_SIZE(mtk_ethtool_stats); i++)
+ *data_dst++ = *(data_src + mtk_ethtool_stats[i].offset);
+ if (mtk_page_pool_enabled(mac->hw))
+ mtk_ethtool_pp_stats(mac->hw, data_dst);
+- } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start));
++ } while (u64_stats_fetch_retry(&hwstats->syncp, start));
+ }
+
+ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+index 67ecdb9e708f..8345499563a4 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+@@ -827,12 +827,12 @@ mlxsw_sp_port_get_sw_stats64(const struct net_device *dev,
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(mlxsw_sp_port->pcpu_stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ rx_packets = p->rx_packets;
+ rx_bytes = p->rx_bytes;
+ tx_packets = p->tx_packets;
+ tx_bytes = p->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+index 27f4786ace4f..a5ca5c4a7896 100644
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+@@ -1631,21 +1631,21 @@ static void nfp_net_stat64(struct net_device *netdev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&r_vec->rx_sync);
++ start = u64_stats_fetch_begin(&r_vec->rx_sync);
+ data[0] = r_vec->rx_pkts;
+ data[1] = r_vec->rx_bytes;
+ data[2] = r_vec->rx_drops;
+- } while (u64_stats_fetch_retry_irq(&r_vec->rx_sync, start));
++ } while (u64_stats_fetch_retry(&r_vec->rx_sync, start));
+ stats->rx_packets += data[0];
+ stats->rx_bytes += data[1];
+ stats->rx_dropped += data[2];
+
+ do {
+- start = u64_stats_fetch_begin_irq(&r_vec->tx_sync);
++ start = u64_stats_fetch_begin(&r_vec->tx_sync);
+ data[0] = r_vec->tx_pkts;
+ data[1] = r_vec->tx_bytes;
+ data[2] = r_vec->tx_errors;
+- } while (u64_stats_fetch_retry_irq(&r_vec->tx_sync, start));
++ } while (u64_stats_fetch_retry(&r_vec->tx_sync, start));
+ stats->tx_packets += data[0];
+ stats->tx_bytes += data[1];
+ stats->tx_errors += data[2];
+diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+index af376b900067..cc97b3d00414 100644
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+@@ -881,7 +881,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].rx_sync);
++ start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync);
+ data[0] = nn->r_vecs[i].rx_pkts;
+ tmp[0] = nn->r_vecs[i].hw_csum_rx_ok;
+ tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok;
+@@ -889,10 +889,10 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
+ tmp[3] = nn->r_vecs[i].hw_csum_rx_error;
+ tmp[4] = nn->r_vecs[i].rx_replace_buf_alloc_fail;
+ tmp[5] = nn->r_vecs[i].hw_tls_rx;
+- } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].rx_sync, start));
++ } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].tx_sync);
++ start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync);
+ data[1] = nn->r_vecs[i].tx_pkts;
+ data[2] = nn->r_vecs[i].tx_busy;
+ tmp[6] = nn->r_vecs[i].hw_csum_tx;
+@@ -902,7 +902,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
+ tmp[10] = nn->r_vecs[i].hw_tls_tx;
+ tmp[11] = nn->r_vecs[i].tls_tx_fallback;
+ tmp[12] = nn->r_vecs[i].tls_tx_no_fallback;
+- } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].tx_sync, start));
++ } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start));
+
+ data += NN_RVEC_PER_Q_STATS;
+
+diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+index 8b77582bdfa0..a6b6ca1fd55e 100644
+--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
++++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+@@ -134,13 +134,13 @@ nfp_repr_get_host_stats64(const struct net_device *netdev,
+
+ repr_stats = per_cpu_ptr(repr->stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&repr_stats->syncp);
++ start = u64_stats_fetch_begin(&repr_stats->syncp);
+ tbytes = repr_stats->tx_bytes;
+ tpkts = repr_stats->tx_packets;
+ tdrops = repr_stats->tx_drops;
+ rbytes = repr_stats->rx_bytes;
+ rpkts = repr_stats->rx_packets;
+- } while (u64_stats_fetch_retry_irq(&repr_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&repr_stats->syncp, start));
+
+ stats->tx_bytes += tbytes;
+ stats->tx_packets += tpkts;
+diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
+index 486cbc8ab224..7a549b834e97 100644
+--- a/drivers/net/ethernet/nvidia/forcedeth.c
++++ b/drivers/net/ethernet/nvidia/forcedeth.c
+@@ -1734,12 +1734,12 @@ static void nv_get_stats(int cpu, struct fe_priv *np,
+ u64 tx_packets, tx_bytes, tx_dropped;
+
+ do {
+- syncp_start = u64_stats_fetch_begin_irq(&np->swstats_rx_syncp);
++ syncp_start = u64_stats_fetch_begin(&np->swstats_rx_syncp);
+ rx_packets = src->stat_rx_packets;
+ rx_bytes = src->stat_rx_bytes;
+ rx_dropped = src->stat_rx_dropped;
+ rx_missed_errors = src->stat_rx_missed_errors;
+- } while (u64_stats_fetch_retry_irq(&np->swstats_rx_syncp, syncp_start));
++ } while (u64_stats_fetch_retry(&np->swstats_rx_syncp, syncp_start));
+
+ storage->rx_packets += rx_packets;
+ storage->rx_bytes += rx_bytes;
+@@ -1747,11 +1747,11 @@ static void nv_get_stats(int cpu, struct fe_priv *np,
+ storage->rx_missed_errors += rx_missed_errors;
+
+ do {
+- syncp_start = u64_stats_fetch_begin_irq(&np->swstats_tx_syncp);
++ syncp_start = u64_stats_fetch_begin(&np->swstats_tx_syncp);
+ tx_packets = src->stat_tx_packets;
+ tx_bytes = src->stat_tx_bytes;
+ tx_dropped = src->stat_tx_dropped;
+- } while (u64_stats_fetch_retry_irq(&np->swstats_tx_syncp, syncp_start));
++ } while (u64_stats_fetch_retry(&np->swstats_tx_syncp, syncp_start));
+
+ storage->tx_packets += tx_packets;
+ storage->tx_bytes += tx_bytes;
+diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+index 1b2119b1d48a..3f5e6572d20e 100644
+--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
++++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+@@ -135,9 +135,9 @@ static void rmnet_get_stats64(struct net_device *dev,
+ pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp);
++ start = u64_stats_fetch_begin(&pcpu_ptr->syncp);
+ snapshot = pcpu_ptr->stats; /* struct assignment */
+- } while (u64_stats_fetch_retry_irq(&pcpu_ptr->syncp, start));
++ } while (u64_stats_fetch_retry(&pcpu_ptr->syncp, start));
+
+ total_stats.rx_pkts += snapshot.rx_pkts;
+ total_stats.rx_bytes += snapshot.rx_bytes;
+diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c
+index 469e2e229c6e..9ce0e8a64ba8 100644
+--- a/drivers/net/ethernet/realtek/8139too.c
++++ b/drivers/net/ethernet/realtek/8139too.c
+@@ -2532,16 +2532,16 @@ rtl8139_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+ netdev_stats_to_stats64(stats, &dev->stats);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tp->rx_stats.syncp);
++ start = u64_stats_fetch_begin(&tp->rx_stats.syncp);
+ stats->rx_packets = tp->rx_stats.packets;
+ stats->rx_bytes = tp->rx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&tp->rx_stats.syncp, start));
++ } while (u64_stats_fetch_retry(&tp->rx_stats.syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tp->tx_stats.syncp);
++ start = u64_stats_fetch_begin(&tp->tx_stats.syncp);
+ stats->tx_packets = tp->tx_stats.packets;
+ stats->tx_bytes = tp->tx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&tp->tx_stats.syncp, start));
++ } while (u64_stats_fetch_retry(&tp->tx_stats.syncp, start));
+ }
+
+ /* Set or clear the multicast filter for this adaptor.
+diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c
+index d2c6a5dfdc0e..b7e24ae92525 100644
+--- a/drivers/net/ethernet/socionext/sni_ave.c
++++ b/drivers/net/ethernet/socionext/sni_ave.c
+@@ -1508,16 +1508,16 @@ static void ave_get_stats64(struct net_device *ndev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&priv->stats_rx.syncp);
++ start = u64_stats_fetch_begin(&priv->stats_rx.syncp);
+ stats->rx_packets = priv->stats_rx.packets;
+ stats->rx_bytes = priv->stats_rx.bytes;
+- } while (u64_stats_fetch_retry_irq(&priv->stats_rx.syncp, start));
++ } while (u64_stats_fetch_retry(&priv->stats_rx.syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&priv->stats_tx.syncp);
++ start = u64_stats_fetch_begin(&priv->stats_tx.syncp);
+ stats->tx_packets = priv->stats_tx.packets;
+ stats->tx_bytes = priv->stats_tx.bytes;
+- } while (u64_stats_fetch_retry_irq(&priv->stats_tx.syncp, start));
++ } while (u64_stats_fetch_retry(&priv->stats_tx.syncp, start));
+
+ stats->rx_errors = priv->stats_rx.errors;
+ stats->tx_errors = priv->stats_tx.errors;
+diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+index 9f2553799895..1085b0642c28 100644
+--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+@@ -1376,12 +1376,12 @@ static void am65_cpsw_nuss_ndo_get_stats(struct net_device *dev,
+
+ cpu_stats = per_cpu_ptr(ndev_priv->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ rx_packets = cpu_stats->rx_packets;
+ rx_bytes = cpu_stats->rx_bytes;
+ tx_packets = cpu_stats->tx_packets;
+ tx_bytes = cpu_stats->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
+index 9eb9eaff4dc9..1bb596a9d8a2 100644
+--- a/drivers/net/ethernet/ti/netcp_core.c
++++ b/drivers/net/ethernet/ti/netcp_core.c
+@@ -1916,16 +1916,16 @@ netcp_get_stats(struct net_device *ndev, struct rtnl_link_stats64 *stats)
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp_rx);
++ start = u64_stats_fetch_begin(&p->syncp_rx);
+ rxpackets = p->rx_packets;
+ rxbytes = p->rx_bytes;
+- } while (u64_stats_fetch_retry_irq(&p->syncp_rx, start));
++ } while (u64_stats_fetch_retry(&p->syncp_rx, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp_tx);
++ start = u64_stats_fetch_begin(&p->syncp_tx);
+ txpackets = p->tx_packets;
+ txbytes = p->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&p->syncp_tx, start));
++ } while (u64_stats_fetch_retry(&p->syncp_tx, start));
+
+ stats->rx_packets = rxpackets;
+ stats->rx_bytes = rxbytes;
+diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
+index 0fb15a17b547..d716e6fe26e1 100644
+--- a/drivers/net/ethernet/via/via-rhine.c
++++ b/drivers/net/ethernet/via/via-rhine.c
+@@ -2217,16 +2217,16 @@ rhine_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+ netdev_stats_to_stats64(stats, &dev->stats);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rp->rx_stats.syncp);
++ start = u64_stats_fetch_begin(&rp->rx_stats.syncp);
+ stats->rx_packets = rp->rx_stats.packets;
+ stats->rx_bytes = rp->rx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&rp->rx_stats.syncp, start));
++ } while (u64_stats_fetch_retry(&rp->rx_stats.syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rp->tx_stats.syncp);
++ start = u64_stats_fetch_begin(&rp->tx_stats.syncp);
+ stats->tx_packets = rp->tx_stats.packets;
+ stats->tx_bytes = rp->tx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&rp->tx_stats.syncp, start));
++ } while (u64_stats_fetch_retry(&rp->tx_stats.syncp, start));
+ }
+
+ static void rhine_set_rx_mode(struct net_device *dev)
+diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+index 5ea9dc251dd9..c678876a7826 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+@@ -1305,16 +1305,16 @@ axienet_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+ netdev_stats_to_stats64(stats, &dev->stats);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&lp->rx_stat_sync);
++ start = u64_stats_fetch_begin(&lp->rx_stat_sync);
+ stats->rx_packets = u64_stats_read(&lp->rx_packets);
+ stats->rx_bytes = u64_stats_read(&lp->rx_bytes);
+- } while (u64_stats_fetch_retry_irq(&lp->rx_stat_sync, start));
++ } while (u64_stats_fetch_retry(&lp->rx_stat_sync, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&lp->tx_stat_sync);
++ start = u64_stats_fetch_begin(&lp->tx_stat_sync);
+ stats->tx_packets = u64_stats_read(&lp->tx_packets);
+ stats->tx_bytes = u64_stats_read(&lp->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&lp->tx_stat_sync, start));
++ } while (u64_stats_fetch_retry(&lp->tx_stat_sync, start));
+ }
+
+ static const struct net_device_ops axienet_netdev_ops = {
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index 0285894c892a..cf87d7ed3779 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -1264,12 +1264,12 @@ static void netvsc_get_vf_stats(struct net_device *net,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ rx_packets = stats->rx_packets;
+ tx_packets = stats->tx_packets;
+ rx_bytes = stats->rx_bytes;
+ tx_bytes = stats->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+@@ -1294,12 +1294,12 @@ static void netvsc_get_pcpu_stats(struct net_device *net,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ this_tot->vf_rx_packets = stats->rx_packets;
+ this_tot->vf_tx_packets = stats->tx_packets;
+ this_tot->vf_rx_bytes = stats->rx_bytes;
+ this_tot->vf_tx_bytes = stats->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+ this_tot->rx_packets = this_tot->vf_rx_packets;
+ this_tot->tx_packets = this_tot->vf_tx_packets;
+ this_tot->rx_bytes = this_tot->vf_rx_bytes;
+@@ -1318,20 +1318,20 @@ static void netvsc_get_pcpu_stats(struct net_device *net,
+
+ tx_stats = &nvchan->tx_stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
++ start = u64_stats_fetch_begin(&tx_stats->syncp);
+ packets = tx_stats->packets;
+ bytes = tx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+ this_tot->tx_bytes += bytes;
+ this_tot->tx_packets += packets;
+
+ rx_stats = &nvchan->rx_stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
++ start = u64_stats_fetch_begin(&rx_stats->syncp);
+ packets = rx_stats->packets;
+ bytes = rx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+
+ this_tot->rx_bytes += bytes;
+ this_tot->rx_packets += packets;
+@@ -1370,21 +1370,21 @@ static void netvsc_get_stats64(struct net_device *net,
+
+ tx_stats = &nvchan->tx_stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
++ start = u64_stats_fetch_begin(&tx_stats->syncp);
+ packets = tx_stats->packets;
+ bytes = tx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+ t->tx_bytes += bytes;
+ t->tx_packets += packets;
+
+ rx_stats = &nvchan->rx_stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
++ start = u64_stats_fetch_begin(&rx_stats->syncp);
+ packets = rx_stats->packets;
+ bytes = rx_stats->bytes;
+ multicast = rx_stats->multicast + rx_stats->broadcast;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+
+ t->rx_bytes += bytes;
+ t->rx_packets += packets;
+@@ -1527,24 +1527,24 @@ static void netvsc_get_ethtool_stats(struct net_device *dev,
+ tx_stats = &nvdev->chan_table[j].tx_stats;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
++ start = u64_stats_fetch_begin(&tx_stats->syncp);
+ packets = tx_stats->packets;
+ bytes = tx_stats->bytes;
+ xdp_xmit = tx_stats->xdp_xmit;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+ data[i++] = packets;
+ data[i++] = bytes;
+ data[i++] = xdp_xmit;
+
+ rx_stats = &nvdev->chan_table[j].rx_stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
++ start = u64_stats_fetch_begin(&rx_stats->syncp);
+ packets = rx_stats->packets;
+ bytes = rx_stats->bytes;
+ xdp_drop = rx_stats->xdp_drop;
+ xdp_redirect = rx_stats->xdp_redirect;
+ xdp_tx = rx_stats->xdp_tx;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+ data[i++] = packets;
+ data[i++] = bytes;
+ data[i++] = xdp_drop;
+diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
+index 1c64d5347b8e..78253ad57b2e 100644
+--- a/drivers/net/ifb.c
++++ b/drivers/net/ifb.c
+@@ -162,18 +162,18 @@ static void ifb_stats64(struct net_device *dev,
+
+ for (i = 0; i < dev->num_tx_queues; i++,txp++) {
+ do {
+- start = u64_stats_fetch_begin_irq(&txp->rx_stats.sync);
++ start = u64_stats_fetch_begin(&txp->rx_stats.sync);
+ packets = txp->rx_stats.packets;
+ bytes = txp->rx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&txp->rx_stats.sync, start));
++ } while (u64_stats_fetch_retry(&txp->rx_stats.sync, start));
+ stats->rx_packets += packets;
+ stats->rx_bytes += bytes;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&txp->tx_stats.sync);
++ start = u64_stats_fetch_begin(&txp->tx_stats.sync);
+ packets = txp->tx_stats.packets;
+ bytes = txp->tx_stats.bytes;
+- } while (u64_stats_fetch_retry_irq(&txp->tx_stats.sync, start));
++ } while (u64_stats_fetch_retry(&txp->tx_stats.sync, start));
+ stats->tx_packets += packets;
+ stats->tx_bytes += bytes;
+ }
+@@ -245,12 +245,12 @@ static void ifb_fill_stats_data(u64 **data,
+ int j;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&q_stats->sync);
++ start = u64_stats_fetch_begin(&q_stats->sync);
+ for (j = 0; j < IFB_Q_STATS_LEN; j++) {
+ offset = ifb_q_stats_desc[j].offset;
+ (*data)[j] = *(u64 *)(stats_base + offset);
+ }
+- } while (u64_stats_fetch_retry_irq(&q_stats->sync, start));
++ } while (u64_stats_fetch_retry(&q_stats->sync, start));
+
+ *data += IFB_Q_STATS_LEN;
+ }
+diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
+index fbf2d5b67aaf..57c79f5f2991 100644
+--- a/drivers/net/ipvlan/ipvlan_main.c
++++ b/drivers/net/ipvlan/ipvlan_main.c
+@@ -301,13 +301,13 @@ static void ipvlan_get_stats64(struct net_device *dev,
+ for_each_possible_cpu(idx) {
+ pcptr = per_cpu_ptr(ipvlan->pcpu_stats, idx);
+ do {
+- strt= u64_stats_fetch_begin_irq(&pcptr->syncp);
++ strt = u64_stats_fetch_begin(&pcptr->syncp);
+ rx_pkts = u64_stats_read(&pcptr->rx_pkts);
+ rx_bytes = u64_stats_read(&pcptr->rx_bytes);
+ rx_mcast = u64_stats_read(&pcptr->rx_mcast);
+ tx_pkts = u64_stats_read(&pcptr->tx_pkts);
+ tx_bytes = u64_stats_read(&pcptr->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&pcptr->syncp,
++ } while (u64_stats_fetch_retry(&pcptr->syncp,
+ strt));
+
+ s->rx_packets += rx_pkts;
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index 2e9742952c4e..f6d53e63ef4e 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -106,10 +106,10 @@ void dev_lstats_read(struct net_device *dev, u64 *packets, u64 *bytes)
+
+ lb_stats = per_cpu_ptr(dev->lstats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&lb_stats->syncp);
++ start = u64_stats_fetch_begin(&lb_stats->syncp);
+ tpackets = u64_stats_read(&lb_stats->packets);
+ tbytes = u64_stats_read(&lb_stats->bytes);
+- } while (u64_stats_fetch_retry_irq(&lb_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&lb_stats->syncp, start));
+ *bytes += tbytes;
+ *packets += tpackets;
+ }
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index 209ee9f35275..f9f25b5f1745 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -2802,9 +2802,9 @@ static void get_rx_sc_stats(struct net_device *dev,
+
+ stats = per_cpu_ptr(rx_sc->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ memcpy(&tmp, &stats->stats, sizeof(tmp));
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ sum->InOctetsValidated += tmp.InOctetsValidated;
+ sum->InOctetsDecrypted += tmp.InOctetsDecrypted;
+@@ -2883,9 +2883,9 @@ static void get_tx_sc_stats(struct net_device *dev,
+
+ stats = per_cpu_ptr(macsec_priv(dev)->secy.tx_sc.stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ memcpy(&tmp, &stats->stats, sizeof(tmp));
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ sum->OutPktsProtected += tmp.OutPktsProtected;
+ sum->OutPktsEncrypted += tmp.OutPktsEncrypted;
+@@ -2939,9 +2939,9 @@ static void get_secy_stats(struct net_device *dev, struct macsec_dev_stats *sum)
+
+ stats = per_cpu_ptr(macsec_priv(dev)->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ memcpy(&tmp, &stats->stats, sizeof(tmp));
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ sum->OutPktsUntagged += tmp.OutPktsUntagged;
+ sum->InPktsUntagged += tmp.InPktsUntagged;
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index 012830d12fde..9bea3f1b0a8a 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -948,13 +948,13 @@ static void macvlan_dev_get_stats64(struct net_device *dev,
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(vlan->pcpu_stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ rx_packets = u64_stats_read(&p->rx_packets);
+ rx_bytes = u64_stats_read(&p->rx_bytes);
+ rx_multicast = u64_stats_read(&p->rx_multicast);
+ tx_packets = u64_stats_read(&p->tx_packets);
+ tx_bytes = u64_stats_read(&p->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+diff --git a/drivers/net/mhi_net.c b/drivers/net/mhi_net.c
+index 0b9d37979133..3d322ac4f6a5 100644
+--- a/drivers/net/mhi_net.c
++++ b/drivers/net/mhi_net.c
+@@ -104,19 +104,19 @@ static void mhi_ndo_get_stats64(struct net_device *ndev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&mhi_netdev->stats.rx_syncp);
++ start = u64_stats_fetch_begin(&mhi_netdev->stats.rx_syncp);
+ stats->rx_packets = u64_stats_read(&mhi_netdev->stats.rx_packets);
+ stats->rx_bytes = u64_stats_read(&mhi_netdev->stats.rx_bytes);
+ stats->rx_errors = u64_stats_read(&mhi_netdev->stats.rx_errors);
+- } while (u64_stats_fetch_retry_irq(&mhi_netdev->stats.rx_syncp, start));
++ } while (u64_stats_fetch_retry(&mhi_netdev->stats.rx_syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&mhi_netdev->stats.tx_syncp);
++ start = u64_stats_fetch_begin(&mhi_netdev->stats.tx_syncp);
+ stats->tx_packets = u64_stats_read(&mhi_netdev->stats.tx_packets);
+ stats->tx_bytes = u64_stats_read(&mhi_netdev->stats.tx_bytes);
+ stats->tx_errors = u64_stats_read(&mhi_netdev->stats.tx_errors);
+ stats->tx_dropped = u64_stats_read(&mhi_netdev->stats.tx_dropped);
+- } while (u64_stats_fetch_retry_irq(&mhi_netdev->stats.tx_syncp, start));
++ } while (u64_stats_fetch_retry(&mhi_netdev->stats.tx_syncp, start));
+ }
+
+ static const struct net_device_ops mhi_netdev_ops = {
+diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
+index 9a1a5b203624..e470e3398abc 100644
+--- a/drivers/net/netdevsim/netdev.c
++++ b/drivers/net/netdevsim/netdev.c
+@@ -67,10 +67,10 @@ nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&ns->syncp);
++ start = u64_stats_fetch_begin(&ns->syncp);
+ stats->tx_bytes = ns->tx_bytes;
+ stats->tx_packets = ns->tx_packets;
+- } while (u64_stats_fetch_retry_irq(&ns->syncp, start));
++ } while (u64_stats_fetch_retry(&ns->syncp, start));
+ }
+
+ static int
+diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
+index 293eaf6b3ec9..eccf9df0c88c 100644
+--- a/drivers/net/team/team.c
++++ b/drivers/net/team/team.c
+@@ -1868,13 +1868,13 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(team->pcpu_stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ rx_packets = u64_stats_read(&p->rx_packets);
+ rx_bytes = u64_stats_read(&p->rx_bytes);
+ rx_multicast = u64_stats_read(&p->rx_multicast);
+ tx_packets = u64_stats_read(&p->tx_packets);
+ tx_bytes = u64_stats_read(&p->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
+index b095a4b4957b..18d99fda997c 100644
+--- a/drivers/net/team/team_mode_loadbalance.c
++++ b/drivers/net/team/team_mode_loadbalance.c
+@@ -466,9 +466,9 @@ static void __lb_one_cpu_stats_add(struct lb_stats *acc_stats,
+ struct lb_stats tmp;
+
+ do {
+- start = u64_stats_fetch_begin_irq(syncp);
++ start = u64_stats_fetch_begin(syncp);
+ tmp.tx_bytes = cpu_stats->tx_bytes;
+- } while (u64_stats_fetch_retry_irq(syncp, start));
++ } while (u64_stats_fetch_retry(syncp, start));
+ acc_stats->tx_bytes += tmp.tx_bytes;
+ }
+
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index 36c5a41f84e4..605f511a886c 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -182,12 +182,12 @@ static void veth_get_ethtool_stats(struct net_device *dev,
+ size_t offset;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rq_stats->syncp);
++ start = u64_stats_fetch_begin(&rq_stats->syncp);
+ for (j = 0; j < VETH_RQ_STATS_LEN; j++) {
+ offset = veth_rq_stats_desc[j].offset;
+ data[idx + j] = *(u64 *)(stats_base + offset);
+ }
+- } while (u64_stats_fetch_retry_irq(&rq_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rq_stats->syncp, start));
+ idx += VETH_RQ_STATS_LEN;
+ }
+
+@@ -203,12 +203,12 @@ static void veth_get_ethtool_stats(struct net_device *dev,
+
+ tx_idx += (i % dev->real_num_tx_queues) * VETH_TQ_STATS_LEN;
+ do {
+- start = u64_stats_fetch_begin_irq(&rq_stats->syncp);
++ start = u64_stats_fetch_begin(&rq_stats->syncp);
+ for (j = 0; j < VETH_TQ_STATS_LEN; j++) {
+ offset = veth_tq_stats_desc[j].offset;
+ data[tx_idx + j] += *(u64 *)(base + offset);
+ }
+- } while (u64_stats_fetch_retry_irq(&rq_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rq_stats->syncp, start));
+ }
+ }
+
+@@ -381,13 +381,13 @@ static void veth_stats_rx(struct veth_stats *result, struct net_device *dev)
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ peer_tq_xdp_xmit_err = stats->vs.peer_tq_xdp_xmit_err;
+ xdp_tx_err = stats->vs.xdp_tx_err;
+ packets = stats->vs.xdp_packets;
+ bytes = stats->vs.xdp_bytes;
+ drops = stats->vs.rx_drops;
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+ result->peer_tq_xdp_xmit_err += peer_tq_xdp_xmit_err;
+ result->xdp_tx_err += xdp_tx_err;
+ result->xdp_packets += packets;
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 21d3461fb5d1..666622ae4b9d 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -2107,18 +2107,18 @@ static void virtnet_stats(struct net_device *dev,
+ struct send_queue *sq = &vi->sq[i];
+
+ do {
+- start = u64_stats_fetch_begin_irq(&sq->stats.syncp);
++ start = u64_stats_fetch_begin(&sq->stats.syncp);
+ tpackets = sq->stats.packets;
+ tbytes = sq->stats.bytes;
+ terrors = sq->stats.tx_timeouts;
+- } while (u64_stats_fetch_retry_irq(&sq->stats.syncp, start));
++ } while (u64_stats_fetch_retry(&sq->stats.syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rq->stats.syncp);
++ start = u64_stats_fetch_begin(&rq->stats.syncp);
+ rpackets = rq->stats.packets;
+ rbytes = rq->stats.bytes;
+ rdrops = rq->stats.drops;
+- } while (u64_stats_fetch_retry_irq(&rq->stats.syncp, start));
++ } while (u64_stats_fetch_retry(&rq->stats.syncp, start));
+
+ tot->rx_packets += rpackets;
+ tot->tx_packets += tpackets;
+@@ -2726,12 +2726,12 @@ static void virtnet_get_ethtool_stats(struct net_device *dev,
+
+ stats_base = (u8 *)&rq->stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&rq->stats.syncp);
++ start = u64_stats_fetch_begin(&rq->stats.syncp);
+ for (j = 0; j < VIRTNET_RQ_STATS_LEN; j++) {
+ offset = virtnet_rq_stats_desc[j].offset;
+ data[idx + j] = *(u64 *)(stats_base + offset);
+ }
+- } while (u64_stats_fetch_retry_irq(&rq->stats.syncp, start));
++ } while (u64_stats_fetch_retry(&rq->stats.syncp, start));
+ idx += VIRTNET_RQ_STATS_LEN;
+ }
+
+@@ -2740,12 +2740,12 @@ static void virtnet_get_ethtool_stats(struct net_device *dev,
+
+ stats_base = (u8 *)&sq->stats;
+ do {
+- start = u64_stats_fetch_begin_irq(&sq->stats.syncp);
++ start = u64_stats_fetch_begin(&sq->stats.syncp);
+ for (j = 0; j < VIRTNET_SQ_STATS_LEN; j++) {
+ offset = virtnet_sq_stats_desc[j].offset;
+ data[idx + j] = *(u64 *)(stats_base + offset);
+ }
+- } while (u64_stats_fetch_retry_irq(&sq->stats.syncp, start));
++ } while (u64_stats_fetch_retry(&sq->stats.syncp, start));
+ idx += VIRTNET_SQ_STATS_LEN;
+ }
+ }
+diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
+index 208df4d41939..6043e63b42f9 100644
+--- a/drivers/net/vrf.c
++++ b/drivers/net/vrf.c
+@@ -159,13 +159,13 @@ static void vrf_get_stats64(struct net_device *dev,
+
+ dstats = per_cpu_ptr(dev->dstats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&dstats->syncp);
++ start = u64_stats_fetch_begin(&dstats->syncp);
+ tbytes = dstats->tx_bytes;
+ tpkts = dstats->tx_pkts;
+ tdrops = dstats->tx_drps;
+ rbytes = dstats->rx_bytes;
+ rpkts = dstats->rx_pkts;
+- } while (u64_stats_fetch_retry_irq(&dstats->syncp, start));
++ } while (u64_stats_fetch_retry(&dstats->syncp, start));
+ stats->tx_bytes += tbytes;
+ stats->tx_packets += tpkts;
+ stats->tx_dropped += tdrops;
+diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
+index c5cf55030158..c3ff30ab782e 100644
+--- a/drivers/net/vxlan/vxlan_vnifilter.c
++++ b/drivers/net/vxlan/vxlan_vnifilter.c
+@@ -129,9 +129,9 @@ static void vxlan_vnifilter_stats_get(const struct vxlan_vni_node *vninode,
+
+ pstats = per_cpu_ptr(vninode->stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&pstats->syncp);
++ start = u64_stats_fetch_begin(&pstats->syncp);
+ memcpy(&temp, &pstats->stats, sizeof(temp));
+- } while (u64_stats_fetch_retry_irq(&pstats->syncp, start));
++ } while (u64_stats_fetch_retry(&pstats->syncp, start));
+
+ dest->rx_packets += temp.rx_packets;
+ dest->rx_bytes += temp.rx_bytes;
+diff --git a/drivers/net/wwan/mhi_wwan_mbim.c b/drivers/net/wwan/mhi_wwan_mbim.c
+index ef70bb7c88ad..3f72ae943b29 100644
+--- a/drivers/net/wwan/mhi_wwan_mbim.c
++++ b/drivers/net/wwan/mhi_wwan_mbim.c
+@@ -456,19 +456,19 @@ static void mhi_mbim_ndo_get_stats64(struct net_device *ndev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&link->rx_syncp);
++ start = u64_stats_fetch_begin(&link->rx_syncp);
+ stats->rx_packets = u64_stats_read(&link->rx_packets);
+ stats->rx_bytes = u64_stats_read(&link->rx_bytes);
+ stats->rx_errors = u64_stats_read(&link->rx_errors);
+- } while (u64_stats_fetch_retry_irq(&link->rx_syncp, start));
++ } while (u64_stats_fetch_retry(&link->rx_syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&link->tx_syncp);
++ start = u64_stats_fetch_begin(&link->tx_syncp);
+ stats->tx_packets = u64_stats_read(&link->tx_packets);
+ stats->tx_bytes = u64_stats_read(&link->tx_bytes);
+ stats->tx_errors = u64_stats_read(&link->tx_errors);
+ stats->tx_dropped = u64_stats_read(&link->tx_dropped);
+- } while (u64_stats_fetch_retry_irq(&link->tx_syncp, start));
++ } while (u64_stats_fetch_retry(&link->tx_syncp, start));
+ }
+
+ static void mhi_mbim_ul_callback(struct mhi_device *mhi_dev,
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index dc404e05970c..14aec417fa06 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -1392,16 +1392,16 @@ static void xennet_get_stats64(struct net_device *dev,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
++ start = u64_stats_fetch_begin(&tx_stats->syncp);
+ tx_packets = tx_stats->packets;
+ tx_bytes = tx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
++ start = u64_stats_fetch_begin(&rx_stats->syncp);
+ rx_packets = rx_stats->packets;
+ rx_bytes = rx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+--
+2.43.0
+
diff --git a/debian/patches-rt/0006-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-n.patch b/debian/patches-rt/0006-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-n.patch
new file mode 100644
index 000000000..ff493ddaf
--- /dev/null
+++ b/debian/patches-rt/0006-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-n.patch
@@ -0,0 +1,393 @@
+From a0c8ef7e6160582c71c0d8b1786d8e45dcc02132 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 25 Aug 2022 16:17:37 +0200
+Subject: [PATCH 06/62] net: Remove the obsolte u64_stats_fetch_*_irq() users
+ (net).
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Now that the 32bit UP oddity is gone and 32bit uses always a sequence
+count, there is no need for the fetch_irq() variants anymore.
+
+Convert to the regular interface.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+---
+ net/8021q/vlan_dev.c | 4 ++--
+ net/bridge/br_multicast.c | 4 ++--
+ net/bridge/br_vlan.c | 4 ++--
+ net/core/dev.c | 4 ++--
+ net/core/drop_monitor.c | 8 ++++----
+ net/core/gen_stats.c | 16 ++++++++--------
+ net/devlink/leftover.c | 4 ++--
+ net/dsa/slave.c | 4 ++--
+ net/ipv4/af_inet.c | 4 ++--
+ net/ipv6/seg6_local.c | 4 ++--
+ net/mac80211/sta_info.c | 8 ++++----
+ net/mpls/af_mpls.c | 4 ++--
+ net/netfilter/ipvs/ip_vs_ctl.c | 4 ++--
+ net/netfilter/nf_tables_api.c | 4 ++--
+ net/openvswitch/datapath.c | 4 ++--
+ net/openvswitch/flow_table.c | 9 ++++-----
+ 16 files changed, 44 insertions(+), 45 deletions(-)
+
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index d3e511e1eba8..0fa52bcc296b 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -712,13 +712,13 @@ static void vlan_dev_get_stats64(struct net_device *dev,
+
+ p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ rxpackets = u64_stats_read(&p->rx_packets);
+ rxbytes = u64_stats_read(&p->rx_bytes);
+ rxmulticast = u64_stats_read(&p->rx_multicast);
+ txpackets = u64_stats_read(&p->tx_packets);
+ txbytes = u64_stats_read(&p->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+
+ stats->rx_packets += rxpackets;
+ stats->rx_bytes += rxbytes;
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index db4f2641d1cd..7e2a9fb5786c 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -4899,9 +4899,9 @@ void br_multicast_get_stats(const struct net_bridge *br,
+ unsigned int start;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ memcpy(&temp, &cpu_stats->mstats, sizeof(temp));
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ mcast_stats_add_dir(tdst.igmp_v1queries, temp.igmp_v1queries);
+ mcast_stats_add_dir(tdst.igmp_v2queries, temp.igmp_v2queries);
+diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
+index 9ffd40b8270c..bc75fa1e4666 100644
+--- a/net/bridge/br_vlan.c
++++ b/net/bridge/br_vlan.c
+@@ -1389,12 +1389,12 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
+
+ cpu_stats = per_cpu_ptr(v->stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ rxpackets = u64_stats_read(&cpu_stats->rx_packets);
+ rxbytes = u64_stats_read(&cpu_stats->rx_bytes);
+ txbytes = u64_stats_read(&cpu_stats->tx_bytes);
+ txpackets = u64_stats_read(&cpu_stats->tx_packets);
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ u64_stats_add(&stats->rx_packets, rxpackets);
+ u64_stats_add(&stats->rx_bytes, rxbytes);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 0d5aa820fd83..070039f9296c 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -10505,12 +10505,12 @@ void dev_fetch_sw_netstats(struct rtnl_link_stats64 *s,
+
+ stats = per_cpu_ptr(netstats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ rx_packets = u64_stats_read(&stats->rx_packets);
+ rx_bytes = u64_stats_read(&stats->rx_bytes);
+ tx_packets = u64_stats_read(&stats->tx_packets);
+ tx_bytes = u64_stats_read(&stats->tx_bytes);
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ s->rx_packets += rx_packets;
+ s->rx_bytes += rx_bytes;
+diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
+index 8e0a90b45df2..4d5e8b317c47 100644
+--- a/net/core/drop_monitor.c
++++ b/net/core/drop_monitor.c
+@@ -1432,9 +1432,9 @@ static void net_dm_stats_read(struct net_dm_stats *stats)
+ u64 dropped;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ dropped = u64_stats_read(&cpu_stats->dropped);
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ u64_stats_add(&stats->dropped, dropped);
+ }
+@@ -1476,9 +1476,9 @@ static void net_dm_hw_stats_read(struct net_dm_stats *stats)
+ u64 dropped;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ dropped = u64_stats_read(&cpu_stats->dropped);
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ u64_stats_add(&stats->dropped, dropped);
+ }
+diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
+index c8d137ef5980..b71ccaec0991 100644
+--- a/net/core/gen_stats.c
++++ b/net/core/gen_stats.c
+@@ -135,10 +135,10 @@ static void gnet_stats_add_basic_cpu(struct gnet_stats_basic_sync *bstats,
+ u64 bytes, packets;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&bcpu->syncp);
++ start = u64_stats_fetch_begin(&bcpu->syncp);
+ bytes = u64_stats_read(&bcpu->bytes);
+ packets = u64_stats_read(&bcpu->packets);
+- } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start));
++ } while (u64_stats_fetch_retry(&bcpu->syncp, start));
+
+ t_bytes += bytes;
+ t_packets += packets;
+@@ -162,10 +162,10 @@ void gnet_stats_add_basic(struct gnet_stats_basic_sync *bstats,
+ }
+ do {
+ if (running)
+- start = u64_stats_fetch_begin_irq(&b->syncp);
++ start = u64_stats_fetch_begin(&b->syncp);
+ bytes = u64_stats_read(&b->bytes);
+ packets = u64_stats_read(&b->packets);
+- } while (running && u64_stats_fetch_retry_irq(&b->syncp, start));
++ } while (running && u64_stats_fetch_retry(&b->syncp, start));
+
+ _bstats_update(bstats, bytes, packets);
+ }
+@@ -187,10 +187,10 @@ static void gnet_stats_read_basic(u64 *ret_bytes, u64 *ret_packets,
+ u64 bytes, packets;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&bcpu->syncp);
++ start = u64_stats_fetch_begin(&bcpu->syncp);
+ bytes = u64_stats_read(&bcpu->bytes);
+ packets = u64_stats_read(&bcpu->packets);
+- } while (u64_stats_fetch_retry_irq(&bcpu->syncp, start));
++ } while (u64_stats_fetch_retry(&bcpu->syncp, start));
+
+ t_bytes += bytes;
+ t_packets += packets;
+@@ -201,10 +201,10 @@ static void gnet_stats_read_basic(u64 *ret_bytes, u64 *ret_packets,
+ }
+ do {
+ if (running)
+- start = u64_stats_fetch_begin_irq(&b->syncp);
++ start = u64_stats_fetch_begin(&b->syncp);
+ *ret_bytes = u64_stats_read(&b->bytes);
+ *ret_packets = u64_stats_read(&b->packets);
+- } while (running && u64_stats_fetch_retry_irq(&b->syncp, start));
++ } while (running && u64_stats_fetch_retry(&b->syncp, start));
+ }
+
+ static int
+diff --git a/net/devlink/leftover.c b/net/devlink/leftover.c
+index 032c7af065cd..94e8cc3de330 100644
+--- a/net/devlink/leftover.c
++++ b/net/devlink/leftover.c
+@@ -8307,10 +8307,10 @@ static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
+
+ cpu_stats = per_cpu_ptr(trap_stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ start = u64_stats_fetch_begin(&cpu_stats->syncp);
+ rx_packets = u64_stats_read(&cpu_stats->rx_packets);
+ rx_bytes = u64_stats_read(&cpu_stats->rx_bytes);
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+ u64_stats_add(&stats->rx_packets, rx_packets);
+ u64_stats_add(&stats->rx_bytes, rx_bytes);
+diff --git a/net/dsa/slave.c b/net/dsa/slave.c
+index 5fe075bf479e..28ee63ec1d1d 100644
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -976,12 +976,12 @@ static void dsa_slave_get_ethtool_stats(struct net_device *dev,
+
+ s = per_cpu_ptr(dev->tstats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&s->syncp);
++ start = u64_stats_fetch_begin(&s->syncp);
+ tx_packets = u64_stats_read(&s->tx_packets);
+ tx_bytes = u64_stats_read(&s->tx_bytes);
+ rx_packets = u64_stats_read(&s->rx_packets);
+ rx_bytes = u64_stats_read(&s->rx_bytes);
+- } while (u64_stats_fetch_retry_irq(&s->syncp, start));
++ } while (u64_stats_fetch_retry(&s->syncp, start));
+ data[0] += tx_packets;
+ data[1] += tx_bytes;
+ data[2] += rx_packets;
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 5d379df90c82..312c730b725f 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1708,9 +1708,9 @@ u64 snmp_get_cpu_field64(void __percpu *mib, int cpu, int offt,
+ bhptr = per_cpu_ptr(mib, cpu);
+ syncp = (struct u64_stats_sync *)(bhptr + syncp_offset);
+ do {
+- start = u64_stats_fetch_begin_irq(syncp);
++ start = u64_stats_fetch_begin(syncp);
+ v = *(((u64 *)bhptr) + offt);
+- } while (u64_stats_fetch_retry_irq(syncp, start));
++ } while (u64_stats_fetch_retry(syncp, start));
+
+ return v;
+ }
+diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
+index 8370726ae7bf..487f8e98deaa 100644
+--- a/net/ipv6/seg6_local.c
++++ b/net/ipv6/seg6_local.c
+@@ -1644,13 +1644,13 @@ static int put_nla_counters(struct sk_buff *skb, struct seg6_local_lwt *slwt)
+
+ pcounters = per_cpu_ptr(slwt->pcpu_counters, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&pcounters->syncp);
++ start = u64_stats_fetch_begin(&pcounters->syncp);
+
+ packets = u64_stats_read(&pcounters->packets);
+ bytes = u64_stats_read(&pcounters->bytes);
+ errors = u64_stats_read(&pcounters->errors);
+
+- } while (u64_stats_fetch_retry_irq(&pcounters->syncp, start));
++ } while (u64_stats_fetch_retry(&pcounters->syncp, start));
+
+ counters.packets += packets;
+ counters.bytes += bytes;
+diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
+index 49b71453dec3..c462e20ccc8d 100644
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -2397,9 +2397,9 @@ static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats,
+ u64 value;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rxstats->syncp);
++ start = u64_stats_fetch_begin(&rxstats->syncp);
+ value = rxstats->msdu[tid];
+- } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
++ } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+
+ return value;
+ }
+@@ -2465,9 +2465,9 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
+ u64 value;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rxstats->syncp);
++ start = u64_stats_fetch_begin(&rxstats->syncp);
+ value = rxstats->bytes;
+- } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
++ } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+
+ return value;
+ }
+diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
+index f1f43894efb8..dc5165d3eec4 100644
+--- a/net/mpls/af_mpls.c
++++ b/net/mpls/af_mpls.c
+@@ -1079,9 +1079,9 @@ static void mpls_get_stats(struct mpls_dev *mdev,
+
+ p = per_cpu_ptr(mdev->stats, i);
+ do {
+- start = u64_stats_fetch_begin_irq(&p->syncp);
++ start = u64_stats_fetch_begin(&p->syncp);
+ local = p->stats;
+- } while (u64_stats_fetch_retry_irq(&p->syncp, start));
++ } while (u64_stats_fetch_retry(&p->syncp, start));
+
+ stats->rx_packets += local.rx_packets;
+ stats->rx_bytes += local.rx_bytes;
+diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
+index 17a1b731a76b..2be696513629 100644
+--- a/net/netfilter/ipvs/ip_vs_ctl.c
++++ b/net/netfilter/ipvs/ip_vs_ctl.c
+@@ -2299,13 +2299,13 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v)
+ u64 conns, inpkts, outpkts, inbytes, outbytes;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&u->syncp);
++ start = u64_stats_fetch_begin(&u->syncp);
+ conns = u64_stats_read(&u->cnt.conns);
+ inpkts = u64_stats_read(&u->cnt.inpkts);
+ outpkts = u64_stats_read(&u->cnt.outpkts);
+ inbytes = u64_stats_read(&u->cnt.inbytes);
+ outbytes = u64_stats_read(&u->cnt.outbytes);
+- } while (u64_stats_fetch_retry_irq(&u->syncp, start));
++ } while (u64_stats_fetch_retry(&u->syncp, start));
+
+ seq_printf(seq, "%3X %8LX %8LX %8LX %16LX %16LX\n",
+ i, (u64)conns, (u64)inpkts,
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 05fa5141af51..ab1888991ae5 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1692,10 +1692,10 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
+ for_each_possible_cpu(cpu) {
+ cpu_stats = per_cpu_ptr(stats, cpu);
+ do {
+- seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
++ seq = u64_stats_fetch_begin(&cpu_stats->syncp);
+ pkts = cpu_stats->pkts;
+ bytes = cpu_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq));
++ } while (u64_stats_fetch_retry(&cpu_stats->syncp, seq));
+ total.pkts += pkts;
+ total.bytes += bytes;
+ }
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
+index 3c7b24535409..0953f531f984 100644
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -716,9 +716,9 @@ static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
+ percpu_stats = per_cpu_ptr(dp->stats_percpu, i);
+
+ do {
+- start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
++ start = u64_stats_fetch_begin(&percpu_stats->syncp);
+ local_stats = *percpu_stats;
+- } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&percpu_stats->syncp, start));
+
+ stats->n_hit += local_stats.n_hit;
+ stats->n_missed += local_stats.n_missed;
+diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
+index d4a2db0b2299..0a0e4c283f02 100644
+--- a/net/openvswitch/flow_table.c
++++ b/net/openvswitch/flow_table.c
+@@ -205,9 +205,9 @@ static void tbl_mask_array_reset_counters(struct mask_array *ma)
+
+ stats = per_cpu_ptr(ma->masks_usage_stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ counter = stats->usage_cntrs[i];
+- } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ ma->masks_usage_zero_cntr[i] += counter;
+ }
+@@ -1136,10 +1136,9 @@ void ovs_flow_masks_rebalance(struct flow_table *table)
+
+ stats = per_cpu_ptr(ma->masks_usage_stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&stats->syncp);
++ start = u64_stats_fetch_begin(&stats->syncp);
+ counter = stats->usage_cntrs[i];
+- } while (u64_stats_fetch_retry_irq(&stats->syncp,
+- start));
++ } while (u64_stats_fetch_retry(&stats->syncp, start));
+
+ masks_and_count[i].counter += counter;
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0007-bpf-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch b/debian/patches-rt/0007-bpf-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch
new file mode 100644
index 000000000..6b725886f
--- /dev/null
+++ b/debian/patches-rt/0007-bpf-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch
@@ -0,0 +1,51 @@
+From b8cff7d0320e3b39f098d9562373e1c16c54c46c Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 25 Aug 2022 16:17:57 +0200
+Subject: [PATCH 07/62] bpf: Remove the obsolte u64_stats_fetch_*_irq() users.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Now that the 32bit UP oddity is gone and 32bit uses always a sequence
+count, there is no need for the fetch_irq() variants anymore.
+
+Convert to the regular interface.
+
+Cc: Alexei Starovoitov <ast@kernel.org>
+Cc: Andrii Nakryiko <andrii@kernel.org>
+Cc: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Hao Luo <haoluo@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: John Fastabend <john.fastabend@gmail.com>
+Cc: KP Singh <kpsingh@kernel.org>
+Cc: Martin KaFai Lau <martin.lau@linux.dev>
+Cc: Song Liu <song@kernel.org>
+Cc: Stanislav Fomichev <sdf@google.com>
+Cc: Yonghong Song <yhs@fb.com>
+Cc: bpf@vger.kernel.org
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+---
+ kernel/bpf/syscall.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index 0c8b7733573e..c0915e2424f1 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -2115,11 +2115,11 @@ static void bpf_prog_get_stats(const struct bpf_prog *prog,
+
+ st = per_cpu_ptr(prog->stats, cpu);
+ do {
+- start = u64_stats_fetch_begin_irq(&st->syncp);
++ start = u64_stats_fetch_begin(&st->syncp);
+ tnsecs = u64_stats_read(&st->nsecs);
+ tcnt = u64_stats_read(&st->cnt);
+ tmisses = u64_stats_read(&st->misses);
+- } while (u64_stats_fetch_retry_irq(&st->syncp, start));
++ } while (u64_stats_fetch_retry(&st->syncp, start));
+ nsecs += tnsecs;
+ cnt += tcnt;
+ misses += tmisses;
+--
+2.43.0
+
diff --git a/debian/patches-rt/0008-u64_stat-Remove-the-obsolete-fetch_irq-variants.patch b/debian/patches-rt/0008-u64_stat-Remove-the-obsolete-fetch_irq-variants.patch
new file mode 100644
index 000000000..176dbf1e5
--- /dev/null
+++ b/debian/patches-rt/0008-u64_stat-Remove-the-obsolete-fetch_irq-variants.patch
@@ -0,0 +1,42 @@
+From b908a7b47d95003c498f2f575285f528148602d6 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 25 Aug 2022 16:43:46 +0200
+Subject: [PATCH 08/62] u64_stat: Remove the obsolete fetch_irq() variants.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Now that the 32bit UP oddity is gone and 32bit uses always a sequence
+count, there is no need for the fetch_irq() variants anymore.
+
+Delete the obsolete interfaces.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+---
+ include/linux/u64_stats_sync.h | 12 ------------
+ 1 file changed, 12 deletions(-)
+
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index 46040d66334a..ffe48e69b3f3 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -213,16 +213,4 @@ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ return __u64_stats_fetch_retry(syncp, start);
+ }
+
+-/* Obsolete interfaces */
+-static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp)
+-{
+- return u64_stats_fetch_begin(syncp);
+-}
+-
+-static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp,
+- unsigned int start)
+-{
+- return u64_stats_fetch_retry(syncp, start);
+-}
+-
+ #endif /* _LINUX_U64_STATS_SYNC_H */
+--
+2.43.0
+
diff --git a/debian/patches-rt/0009-net-Avoid-the-IPI-to-free-the.patch b/debian/patches-rt/0009-net-Avoid-the-IPI-to-free-the.patch
new file mode 100644
index 000000000..1f6687796
--- /dev/null
+++ b/debian/patches-rt/0009-net-Avoid-the-IPI-to-free-the.patch
@@ -0,0 +1,125 @@
+From c910f301d71266e18f63407ec6c65d19ae90e779 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 15 Aug 2022 17:29:50 +0200
+Subject: [PATCH 09/62] net: Avoid the IPI to free the
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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 | 37 ++++++++++++++++++++++++++++---------
+ net/core/skbuff.c | 7 ++++++-
+ 3 files changed, 38 insertions(+), 10 deletions(-)
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 0373e0935990..55d698367883 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -3169,7 +3169,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)
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 070039f9296c..a3caa23be3cf 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -4618,15 +4618,6 @@ static void rps_trigger_softirq(void *data)
+
+ #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);
+-}
+-
+ /*
+ * Check if this softnet_data structure is another cpu one
+ * If yes, queue it to our IPI list and return 1
+@@ -6684,6 +6675,30 @@ static void skb_defer_free_flush(struct softnet_data *sd)
+ }
+ }
+
++#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 __latent_entropy void net_rx_action(struct softirq_action *h)
+ {
+ struct softnet_data *sd = this_cpu_ptr(&softnet_data);
+@@ -11435,7 +11450,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);
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 73b1e0e53534..a457a3445469 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6680,6 +6680,11 @@ 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
++ }
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0010-x86-Allow-to-enable-RT.patch b/debian/patches-rt/0010-x86-Allow-to-enable-RT.patch
new file mode 100644
index 000000000..e7681047e
--- /dev/null
+++ b/debian/patches-rt/0010-x86-Allow-to-enable-RT.patch
@@ -0,0 +1,29 @@
+From ce04e41eb149fcd93a71b63a605423d7f18ec8b4 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 7 Aug 2019 18:15:38 +0200
+Subject: [PATCH 10/62] x86: Allow to enable RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 4c9bfc4be58d..f7f81e3012cc 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -27,6 +27,7 @@ config X86_64
+ # Options that are inherently 64-bit kernel only:
+ select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
++ select ARCH_SUPPORTS_RT
+ select ARCH_USE_CMPXCHG_LOCKREF
+ select HAVE_ARCH_SOFT_DIRTY
+ select MODULES_USE_ELF_RELA
+--
+2.43.0
+
diff --git a/debian/patches-rt/0011-x86-Enable-RT-also-on-32bit.patch b/debian/patches-rt/0011-x86-Enable-RT-also-on-32bit.patch
new file mode 100644
index 000000000..de093669b
--- /dev/null
+++ b/debian/patches-rt/0011-x86-Enable-RT-also-on-32bit.patch
@@ -0,0 +1,35 @@
+From 28dbe0fc30a2d3e519fac1ffe18fe7427f1f49b3 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 7 Nov 2019 17:49:20 +0100
+Subject: [PATCH 11/62] x86: Enable RT also on 32bit
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(-)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index f7f81e3012cc..c9bed9c69423 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -27,7 +27,6 @@ config X86_64
+ # Options that are inherently 64-bit kernel only:
+ select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
+- select ARCH_SUPPORTS_RT
+ select ARCH_USE_CMPXCHG_LOCKREF
+ select HAVE_ARCH_SOFT_DIRTY
+ select MODULES_USE_ELF_RELA
+@@ -114,6 +113,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
+--
+2.43.0
+
diff --git a/debian/patches-rt/0012-softirq-Use-a-dedicated-thread-for-timer-wakeups.patch b/debian/patches-rt/0012-softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
new file mode 100644
index 000000000..720116187
--- /dev/null
+++ b/debian/patches-rt/0012-softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
@@ -0,0 +1,234 @@
+From 454343a4f08e5de772024588aec2bd396177ee89 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 1 Dec 2021 17:41:09 +0100
+Subject: [PATCH 12/62] softirq: Use a dedicated thread for timer wakeups.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index 4a1dc88ddbff..0efba74a835c 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -609,6 +609,22 @@ extern void __raise_softirq_irqoff(unsigned int nr);
+ 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)
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index c8a6913c067d..ed6d7c41aa17 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -637,6 +637,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
+@@ -646,8 +669,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();
+ }
+@@ -976,12 +1004,70 @@ static struct smp_hotplug_thread softirq_threads = {
+ .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);
+diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
+index 5561dabc9b22..c5d480d5da15 100644
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -1805,7 +1805,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
+ 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);
+@@ -1918,7 +1918,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);
+diff --git a/kernel/time/timer.c b/kernel/time/timer.c
+index 717fcb9fb14a..e6219da89933 100644
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
+@@ -1822,7 +1822,7 @@ static void run_local_timers(void)
+ if (time_before(jiffies, base->next_expiry))
+ return;
+ }
+- raise_softirq(TIMER_SOFTIRQ);
++ raise_timer_softirq();
+ }
+
+ /*
+--
+2.43.0
+
diff --git a/debian/patches-rt/0013-rcutorture-Also-force-sched-priority-to-timersd-on-b.patch b/debian/patches-rt/0013-rcutorture-Also-force-sched-priority-to-timersd-on-b.patch
new file mode 100644
index 000000000..9e062b97c
--- /dev/null
+++ b/debian/patches-rt/0013-rcutorture-Also-force-sched-priority-to-timersd-on-b.patch
@@ -0,0 +1,81 @@
+From a10aa54ef224bbd46ca1777e4b9fe960360961cc Mon Sep 17 00:00:00 2001
+From: Frederic Weisbecker <frederic@kernel.org>
+Date: Tue, 5 Apr 2022 03:07:51 +0200
+Subject: [PATCH 13/62] rcutorture: Also force sched priority to timersd on
+ boosting test.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index 0efba74a835c..f459b0f27c94 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -610,6 +610,7 @@ extern void raise_softirq_irqoff(unsigned int nr);
+ 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);
+
+diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
+index 503c2aa845a4..dcd8c0e44c00 100644
+--- a/kernel/rcu/rcutorture.c
++++ b/kernel/rcu/rcutorture.c
+@@ -2363,6 +2363,12 @@ static int rcutorture_booster_init(unsigned int cpu)
+ 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. */
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index ed6d7c41aa17..1892af494cdd 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -638,7 +638,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)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0014-tick-Fix-timer-storm-since-introduction-of-timersd.patch b/debian/patches-rt/0014-tick-Fix-timer-storm-since-introduction-of-timersd.patch
new file mode 100644
index 000000000..11eeed939
--- /dev/null
+++ b/debian/patches-rt/0014-tick-Fix-timer-storm-since-introduction-of-timersd.patch
@@ -0,0 +1,116 @@
+From ae3e63c4320c0c2d3865ba8ecff64a6d03948ce7 Mon Sep 17 00:00:00 2001
+From: Frederic Weisbecker <frederic@kernel.org>
+Date: Tue, 5 Apr 2022 03:07:52 +0200
+Subject: [PATCH 14/62] tick: Fix timer storm since introduction of timersd
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index f459b0f27c94..a5091ac97fc6 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -611,9 +611,16 @@ extern void raise_softirq(unsigned int nr);
+
+ #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(void)
+ {
+ 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);
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 1892af494cdd..ab1fe34326ba 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -639,12 +639,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)
+ {
+diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
+index 798e1841d286..b52e1861b913 100644
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -800,7 +800,7 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
+
+ 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)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0015-softirq-Wake-ktimers-thread-also-in-softirq.patch b/debian/patches-rt/0015-softirq-Wake-ktimers-thread-also-in-softirq.patch
new file mode 100644
index 000000000..3b938739e
--- /dev/null
+++ b/debian/patches-rt/0015-softirq-Wake-ktimers-thread-also-in-softirq.patch
@@ -0,0 +1,50 @@
+From ca98adaa69af0a5f3bb28cccb6543ee3e0c4a23f Mon Sep 17 00:00:00 2001
+From: Junxiao Chang <junxiao.chang@intel.com>
+Date: Mon, 20 Feb 2023 09:12:20 +0100
+Subject: [PATCH 15/62] softirq: Wake ktimers thread also in softirq.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index ab1fe34326ba..82f3e68fbe22 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -664,13 +664,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();
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0016-tpm_tis-fix-stall-after-iowrite-s.patch b/debian/patches-rt/0016-tpm_tis-fix-stall-after-iowrite-s.patch
new file mode 100644
index 000000000..4004bbf47
--- /dev/null
+++ b/debian/patches-rt/0016-tpm_tis-fix-stall-after-iowrite-s.patch
@@ -0,0 +1,82 @@
+From 87e5c70f401b5230b5125dedc88e10f54909a37e Mon Sep 17 00:00:00 2001
+From: Haris Okanovic <haris.okanovic@ni.com>
+Date: Tue, 15 Aug 2017 15:13:08 -0500
+Subject: [PATCH 16/62] tpm_tis: fix stall after iowrite*()s
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+ioread8() operations to TPM MMIO addresses can stall the cpu when
+immediately following a sequence of iowrite*()'s to the same region.
+
+For example, cyclitest measures ~400us latency spikes when a non-RT
+usermode application communicates with an SPI-based TPM chip (Intel Atom
+E3940 system, PREEMPT_RT kernel). The spikes are caused by a
+stalling ioread8() operation following a sequence of 30+ iowrite8()s to
+the same address. I believe this happens because the write sequence is
+buffered (in cpu or somewhere along the bus), and gets flushed on the
+first LOAD instruction (ioread*()) that follows.
+
+The enclosed change appears to fix this issue: read the TPM chip's
+access register (status code) after every iowrite*() operation to
+amortize the cost of flushing data to chip across multiple instructions.
+
+Signed-off-by: Haris Okanovic <haris.okanovic@ni.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ drivers/char/tpm/tpm_tis.c | 29 +++++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 0d084d6652c4..5d620322bdc2 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -50,6 +50,31 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da
+ return container_of(data, struct tpm_tis_tcg_phy, priv);
+ }
+
++#ifdef CONFIG_PREEMPT_RT
++/*
++ * Flushes previous write operations to chip so that a subsequent
++ * ioread*()s won't stall a cpu.
++ */
++static inline void tpm_tis_flush(void __iomem *iobase)
++{
++ ioread8(iobase + TPM_ACCESS(0));
++}
++#else
++#define tpm_tis_flush(iobase) do { } while (0)
++#endif
++
++static inline void tpm_tis_iowrite8(u8 b, void __iomem *iobase, u32 addr)
++{
++ iowrite8(b, iobase + addr);
++ tpm_tis_flush(iobase);
++}
++
++static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr)
++{
++ iowrite32(b, iobase + addr);
++ tpm_tis_flush(iobase);
++}
++
+ static int interrupts = -1;
+ module_param(interrupts, int, 0444);
+ MODULE_PARM_DESC(interrupts, "Enable interrupts");
+@@ -202,12 +227,12 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
+ switch (io_mode) {
+ case TPM_TIS_PHYS_8:
+ while (len--)
+- iowrite8(*value++, phy->iobase + addr);
++ tpm_tis_iowrite8(*value++, phy->iobase, addr);
+ break;
+ case TPM_TIS_PHYS_16:
+ return -EINVAL;
+ case TPM_TIS_PHYS_32:
+- iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase + addr);
++ tpm_tis_iowrite32(le32_to_cpu(*((__le32 *)value)), phy->iobase, addr);
+ break;
+ }
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0017-zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch b/debian/patches-rt/0017-zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch
new file mode 100644
index 000000000..b3f1a71bc
--- /dev/null
+++ b/debian/patches-rt/0017-zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch
@@ -0,0 +1,100 @@
+From 8397109d43ef57d5e91d738354b9c30f49cb2f95 Mon Sep 17 00:00:00 2001
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Thu, 31 Mar 2016 04:08:28 +0200
+Subject: [PATCH 17/62] zram: Replace bit spinlocks with spinlock_t for
+ PREEMPT_RT.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+The bit spinlock disables preemption on PREEMPT_RT. With disabled preemption it
+is not allowed to acquire other sleeping locks which includes invoking
+zs_free().
+
+Use a spinlock_t on PREEMPT_RT for locking and set/ clear ZRAM_LOCK 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
+---
+ drivers/block/zram/zram_drv.c | 36 +++++++++++++++++++++++++++++++++++
+ drivers/block/zram/zram_drv.h | 3 +++
+ 2 files changed, 39 insertions(+)
+
+diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
+index 966aab902d19..ee69e4443691 100644
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -57,6 +57,40 @@ static void zram_free_page(struct zram *zram, size_t index);
+ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
+ u32 index, int offset, struct bio *bio);
+
++#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)
+ {
+@@ -72,6 +106,7 @@ static void zram_slot_unlock(struct zram *zram, u32 index)
+ {
+ bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags);
+ }
++#endif
+
+ static inline bool init_done(struct zram *zram)
+ {
+@@ -1187,6 +1222,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
+
+ if (!huge_class_size)
+ huge_class_size = zs_huge_class_size(zram->mem_pool);
++ zram_meta_init_table_locks(zram, num_pages);
+ return true;
+ }
+
+diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
+index a2bda53020fd..ae7950b26db5 100644
+--- a/drivers/block/zram/zram_drv.h
++++ b/drivers/block/zram/zram_drv.h
+@@ -62,6 +62,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
+--
+2.43.0
+
diff --git a/debian/patches-rt/0018-locking-lockdep-Remove-lockdep_init_map_crosslock.patch b/debian/patches-rt/0018-locking-lockdep-Remove-lockdep_init_map_crosslock.patch
new file mode 100644
index 000000000..3dcd8cb9b
--- /dev/null
+++ b/debian/patches-rt/0018-locking-lockdep-Remove-lockdep_init_map_crosslock.patch
@@ -0,0 +1,34 @@
+From dd162e2589601c792a81a3c19ef4a87510ed6ce5 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 11 Mar 2022 17:44:57 +0100
+Subject: [PATCH 18/62] locking/lockdep: Remove lockdep_init_map_crosslock.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+The cross-release bits have been removed, lockdep_init_map_crosslock() is
+a leftover.
+
+Remove lockdep_init_map_crosslock.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Waiman Long <longman@redhat.com>
+Link: https://lore.kernel.org/r/20220311164457.46461-1-bigeasy@linutronix.de
+Link: https://lore.kernel.org/r/YqITgY+2aPITu96z@linutronix.de
+---
+ include/linux/lockdep.h | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 1f1099dac3f0..1023f349af71 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -435,7 +435,6 @@ enum xhlock_context_t {
+ XHLOCK_CTX_NR,
+ };
+
+-#define lockdep_init_map_crosslock(m, n, k, s) do {} while (0)
+ /*
+ * To initialize a lockdep_map statically use this macro.
+ * Note that _name must not be NULL.
+--
+2.43.0
+
diff --git a/debian/patches-rt/0019-printk-Bring-back-the-RT-bits.patch b/debian/patches-rt/0019-printk-Bring-back-the-RT-bits.patch
new file mode 100644
index 000000000..969f44377
--- /dev/null
+++ b/debian/patches-rt/0019-printk-Bring-back-the-RT-bits.patch
@@ -0,0 +1,1234 @@
+From dd4e52ae061806da556008ca819481befcff0fd3 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 19 Jul 2022 20:08:01 +0200
+Subject: [PATCH 19/62] printk: Bring back the RT bits.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+This is a revert of the commits:
+| 07a22b61946f0 Revert "printk: add functions to prefer direct printing"
+| 5831788afb17b Revert "printk: add kthread console printers"
+| 2d9ef940f89e0 Revert "printk: extend console_lock for per-console locking"
+| 007eeab7e9f03 Revert "printk: remove @console_locked"
+| 05c96b3713aa2 Revert "printk: Block console kthreads when direct printing will be required"
+| 20fb0c8272bbb Revert "printk: Wait for the global console lock when the system is going down"
+
+which is needed for the atomic consoles which are used on PREEMPT_RT.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/sysrq.c | 2 +
+ include/linux/console.h | 17 ++
+ include/linux/printk.h | 15 +
+ kernel/hung_task.c | 11 +-
+ kernel/panic.c | 4 +
+ kernel/printk/internal.h | 2 +
+ kernel/printk/printk.c | 586 ++++++++++++++++++++++++++++++++----
+ kernel/printk/printk_safe.c | 32 ++
+ kernel/rcu/tree_stall.h | 2 +
+ kernel/reboot.c | 16 +-
+ kernel/watchdog.c | 4 +
+ kernel/watchdog_hld.c | 4 +
+ 12 files changed, 636 insertions(+), 59 deletions(-)
+
+diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
+index 248067197287..0db9dad8c99f 100644
+--- a/drivers/tty/sysrq.c
++++ b/drivers/tty/sysrq.c
+@@ -582,6 +582,7 @@ void __handle_sysrq(int key, bool check_mask)
+
+ rcu_sysrq_start();
+ rcu_read_lock();
++ printk_prefer_direct_enter();
+ /*
+ * Raise the apparent loglevel to maximum so that the sysrq header
+ * is shown to provide the user with positive feedback. We do not
+@@ -623,6 +624,7 @@ void __handle_sysrq(int key, bool check_mask)
+ pr_cont("\n");
+ console_loglevel = orig_log_level;
+ }
++ printk_prefer_direct_exit();
+ rcu_read_unlock();
+ rcu_sysrq_end();
+
+diff --git a/include/linux/console.h b/include/linux/console.h
+index 8c1686e2c233..143653090c48 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -16,6 +16,7 @@
+
+ #include <linux/atomic.h>
+ #include <linux/types.h>
++#include <linux/mutex.h>
+
+ struct vc_data;
+ struct console_font_op;
+@@ -153,6 +154,22 @@ struct console {
+ uint ospeed;
+ u64 seq;
+ unsigned long dropped;
++ struct task_struct *thread;
++ bool blocked;
++
++ /*
++ * The per-console lock is used by printing kthreads to synchronize
++ * this console with callers of console_lock(). This is necessary in
++ * order to allow printing kthreads to run in parallel to each other,
++ * while each safely accessing the @blocked field and synchronizing
++ * against direct printing via console_lock/console_unlock.
++ *
++ * Note: For synchronizing against direct printing via
++ * console_trylock/console_unlock, see the static global
++ * variable @console_kthreads_active.
++ */
++ struct mutex lock;
++
+ void *data;
+ struct console *next;
+ };
+diff --git a/include/linux/printk.h b/include/linux/printk.h
+index 8c81806c2e99..f8c4e4fa6d7d 100644
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -168,6 +168,9 @@ extern void __printk_safe_exit(void);
+ */
+ #define printk_deferred_enter __printk_safe_enter
+ #define printk_deferred_exit __printk_safe_exit
++extern void printk_prefer_direct_enter(void);
++extern void printk_prefer_direct_exit(void);
++extern void try_block_console_kthreads(int timeout_ms);
+
+ /*
+ * Please don't use printk_ratelimit(), because it shares ratelimiting state
+@@ -219,6 +222,18 @@ static inline void printk_deferred_exit(void)
+ {
+ }
+
++static inline void printk_prefer_direct_enter(void)
++{
++}
++
++static inline void printk_prefer_direct_exit(void)
++{
++}
++
++static inline void try_block_console_kthreads(int timeout_ms)
++{
++}
++
+ static inline int printk_ratelimit(void)
+ {
+ return 0;
+diff --git a/kernel/hung_task.c b/kernel/hung_task.c
+index c71889f3f3fc..e2d2344cb9f4 100644
+--- a/kernel/hung_task.c
++++ b/kernel/hung_task.c
+@@ -127,6 +127,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
+ * complain:
+ */
+ if (sysctl_hung_task_warnings) {
++ printk_prefer_direct_enter();
++
+ if (sysctl_hung_task_warnings > 0)
+ sysctl_hung_task_warnings--;
+ pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n",
+@@ -142,6 +144,8 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
+
+ if (sysctl_hung_task_all_cpu_backtrace)
+ hung_task_show_all_bt = true;
++
++ printk_prefer_direct_exit();
+ }
+
+ touch_nmi_watchdog();
+@@ -212,12 +216,17 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
+ }
+ unlock:
+ rcu_read_unlock();
+- if (hung_task_show_lock)
++ if (hung_task_show_lock) {
++ printk_prefer_direct_enter();
+ debug_show_all_locks();
++ printk_prefer_direct_exit();
++ }
+
+ if (hung_task_show_all_bt) {
+ hung_task_show_all_bt = false;
++ printk_prefer_direct_enter();
+ trigger_all_cpu_backtrace();
++ printk_prefer_direct_exit();
+ }
+
+ if (hung_task_call_panic)
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 63e94f3bd8dc..88cd873c7c30 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -653,6 +653,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
+ {
+ disable_trace_on_warning();
+
++ printk_prefer_direct_enter();
++
+ if (file)
+ pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n",
+ raw_smp_processor_id(), current->pid, file, line,
+@@ -681,6 +683,8 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
+
+ /* Just a warning, don't kill lockdep. */
+ add_taint(taint, LOCKDEP_STILL_OK);
++
++ printk_prefer_direct_exit();
+ }
+
+ #ifndef __WARN_FLAGS
+diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
+index d947ca6c84f9..e7d8578860ad 100644
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -20,6 +20,8 @@ enum printk_info_flags {
+ LOG_CONT = 8, /* text is a fragment of a continuation line */
+ };
+
++extern bool block_console_kthreads;
++
+ __printf(4, 0)
+ int vprintk_store(int facility, int level,
+ const struct dev_printk_info *dev_info,
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index cc53fb77f77c..e9f9b66608a0 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -220,6 +220,36 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
+ }
+ #endif /* CONFIG_PRINTK && CONFIG_SYSCTL */
+
++/*
++ * Used to synchronize printing kthreads against direct printing via
++ * console_trylock/console_unlock.
++ *
++ * Values:
++ * -1 = console kthreads atomically blocked (via global trylock)
++ * 0 = no kthread printing, console not locked (via trylock)
++ * >0 = kthread(s) actively printing
++ *
++ * Note: For synchronizing against direct printing via
++ * console_lock/console_unlock, see the @lock variable in
++ * struct console.
++ */
++static atomic_t console_kthreads_active = ATOMIC_INIT(0);
++
++#define console_kthreads_atomic_tryblock() \
++ (atomic_cmpxchg(&console_kthreads_active, 0, -1) == 0)
++#define console_kthreads_atomic_unblock() \
++ atomic_cmpxchg(&console_kthreads_active, -1, 0)
++#define console_kthreads_atomically_blocked() \
++ (atomic_read(&console_kthreads_active) == -1)
++
++#define console_kthread_printing_tryenter() \
++ atomic_inc_unless_negative(&console_kthreads_active)
++#define console_kthread_printing_exit() \
++ atomic_dec(&console_kthreads_active)
++
++/* Block console kthreads to avoid processing new messages. */
++bool block_console_kthreads;
++
+ /*
+ * Helper macros to handle lockdep when locking/unlocking console_sem. We use
+ * macros instead of functions so that _RET_IP_ contains useful information.
+@@ -268,14 +298,49 @@ static bool panic_in_progress(void)
+ }
+
+ /*
+- * This is used for debugging the mess that is the VT code by
+- * keeping track if we have the console semaphore held. It's
+- * definitely not the perfect debug tool (we don't know if _WE_
+- * hold it and are racing, but it helps tracking those weird code
+- * paths in the console code where we end up in places I want
+- * locked without the console semaphore held).
++ * Tracks whether kthread printers are all blocked. A value of true implies
++ * that the console is locked via console_lock() or the console is suspended.
++ * Writing to this variable requires holding @console_sem.
++ */
++static bool console_kthreads_blocked;
++
++/*
++ * Block all kthread printers from a schedulable context.
++ *
++ * Requires holding @console_sem.
++ */
++static void console_kthreads_block(void)
++{
++ struct console *con;
++
++ for_each_console(con) {
++ mutex_lock(&con->lock);
++ con->blocked = true;
++ mutex_unlock(&con->lock);
++ }
++
++ console_kthreads_blocked = true;
++}
++
++/*
++ * Unblock all kthread printers from a schedulable context.
++ *
++ * Requires holding @console_sem.
+ */
+-static int console_locked, console_suspended;
++static void console_kthreads_unblock(void)
++{
++ struct console *con;
++
++ for_each_console(con) {
++ mutex_lock(&con->lock);
++ con->blocked = false;
++ mutex_unlock(&con->lock);
++ }
++
++ console_kthreads_blocked = false;
++}
++
++static int console_suspended;
+
+ /*
+ * Array of consoles built from command line options (console=)
+@@ -358,7 +423,75 @@ static int console_msg_format = MSG_FORMAT_DEFAULT;
+ /* syslog_lock protects syslog_* variables and write access to clear_seq. */
+ static DEFINE_MUTEX(syslog_lock);
+
++/*
++ * A flag to signify if printk_activate_kthreads() has already started the
++ * kthread printers. If true, any later registered consoles must start their
++ * own kthread directly. The flag is write protected by the console_lock.
++ */
++static bool printk_kthreads_available;
++
+ #ifdef CONFIG_PRINTK
++static atomic_t printk_prefer_direct = ATOMIC_INIT(0);
++
++/**
++ * printk_prefer_direct_enter - cause printk() calls to attempt direct
++ * printing to all enabled consoles
++ *
++ * Since it is not possible to call into the console printing code from any
++ * context, there is no guarantee that direct printing will occur.
++ *
++ * This globally effects all printk() callers.
++ *
++ * Context: Any context.
++ */
++void printk_prefer_direct_enter(void)
++{
++ atomic_inc(&printk_prefer_direct);
++}
++
++/**
++ * printk_prefer_direct_exit - restore printk() behavior
++ *
++ * Context: Any context.
++ */
++void printk_prefer_direct_exit(void)
++{
++ WARN_ON(atomic_dec_if_positive(&printk_prefer_direct) < 0);
++}
++
++/*
++ * Calling printk() always wakes kthread printers so that they can
++ * flush the new message to their respective consoles. Also, if direct
++ * printing is allowed, printk() tries to flush the messages directly.
++ *
++ * Direct printing is allowed in situations when the kthreads
++ * are not available or the system is in a problematic state.
++ *
++ * See the implementation about possible races.
++ */
++static inline bool allow_direct_printing(void)
++{
++ /*
++ * Checking kthread availability is a possible race because the
++ * kthread printers can become permanently disabled during runtime.
++ * However, doing that requires holding the console_lock, so any
++ * pending messages will be direct printed by console_unlock().
++ */
++ if (!printk_kthreads_available)
++ return true;
++
++ /*
++ * Prefer direct printing when the system is in a problematic state.
++ * The context that sets this state will always see the updated value.
++ * The other contexts do not care. Anyway, direct printing is just a
++ * best effort. The direct output is only possible when console_lock
++ * is not already taken and no kthread printers are actively printing.
++ */
++ return (system_state > SYSTEM_RUNNING ||
++ oops_in_progress ||
++ atomic_read(&printk_prefer_direct));
++}
++
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+ /* All 3 protected by @syslog_lock. */
+ /* the next printk record to read by syslog(READ) or /proc/kmsg */
+@@ -2249,10 +2382,10 @@ asmlinkage int vprintk_emit(int facility, int level,
+ 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 && allow_direct_printing()) {
+ /*
+ * The caller may be holding system-critical or
+- * timing-sensitive locks. Disable preemption during
++ * timing-sensitive locks. Disable preemption during direct
+ * 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.
+@@ -2300,6 +2433,8 @@ 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 void printk_start_kthread(struct console *con);
++
+ #else /* CONFIG_PRINTK */
+
+ #define CONSOLE_LOG_MAX 0
+@@ -2334,6 +2469,8 @@ static void call_console_driver(struct console *con, const char *text, size_t le
+ 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; }
++static void printk_start_kthread(struct console *con) { }
++static bool allow_direct_printing(void) { return true; }
+
+ #endif /* CONFIG_PRINTK */
+
+@@ -2552,6 +2689,14 @@ static int console_cpu_notify(unsigned int cpu)
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
++ else {
++ /*
++ * If a new CPU comes online, the conditions for
++ * printer_should_wake() may have changed for some
++ * kthread printer with !CON_ANYTIME.
++ */
++ wake_up_klogd();
++ }
+ }
+ return 0;
+ }
+@@ -2594,7 +2739,7 @@ void console_lock(void)
+ down_console_sem();
+ if (console_suspended)
+ return;
+- console_locked = 1;
++ console_kthreads_block();
+ console_may_schedule = 1;
+ }
+ EXPORT_SYMBOL(console_lock);
+@@ -2618,15 +2763,30 @@ int console_trylock(void)
+ up_console_sem();
+ return 0;
+ }
+- console_locked = 1;
++ if (!console_kthreads_atomic_tryblock()) {
++ up_console_sem();
++ return 0;
++ }
+ console_may_schedule = 0;
+ return 1;
+ }
+ EXPORT_SYMBOL(console_trylock);
+
++/*
++ * This is used to help to make sure that certain paths within the VT code are
++ * running with the console lock held. It is definitely not the perfect debug
++ * tool (it is not known if the VT code is the task holding the console lock),
++ * but it helps tracking those weird code paths in the console code such as
++ * when the console is suspended: where the console is not locked but no
++ * console printing may occur.
++ *
++ * Note: This returns true when the console is suspended but is not locked.
++ * This is intentional because the VT code must consider that situation
++ * the same as if the console was locked.
++ */
+ int is_console_locked(void)
+ {
+- return console_locked;
++ return (console_kthreads_blocked || atomic_read(&console_kthreads_active));
+ }
+ EXPORT_SYMBOL(is_console_locked);
+
+@@ -2636,12 +2796,9 @@ EXPORT_SYMBOL(is_console_locked);
+ *
+ * Requires the console_lock.
+ */
+-static inline bool console_is_usable(struct console *con)
++static inline bool __console_is_usable(short flags)
+ {
+- if (!(con->flags & CON_ENABLED))
+- return false;
+-
+- if (!con->write)
++ if (!(flags & CON_ENABLED))
+ return false;
+
+ /*
+@@ -2650,15 +2807,43 @@ static inline bool console_is_usable(struct console *con)
+ * cope (CON_ANYTIME) don't call them until this CPU is officially up.
+ */
+ if (!cpu_online(raw_smp_processor_id()) &&
+- !(con->flags & CON_ANYTIME))
++ !(flags & CON_ANYTIME))
+ return false;
+
+ return true;
+ }
+
++/*
++ * Check if the given console is currently capable and allowed to print
++ * records.
++ *
++ * Requires holding the console_lock.
++ */
++static inline bool console_is_usable(struct console *con)
++{
++ if (!con->write)
++ return false;
++
++ return __console_is_usable(con->flags);
++}
++
+ static void __console_unlock(void)
+ {
+- console_locked = 0;
++ /*
++ * Depending on whether console_lock() or console_trylock() was used,
++ * appropriately allow the kthread printers to continue.
++ */
++ if (console_kthreads_blocked)
++ console_kthreads_unblock();
++ else
++ console_kthreads_atomic_unblock();
++
++ /*
++ * New records may have arrived while the console was locked.
++ * Wake the kthread printers to print them.
++ */
++ wake_up_klogd();
++
+ up_console_sem();
+ }
+
+@@ -2676,17 +2861,19 @@ static void __console_unlock(void)
+ *
+ * @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 the
+- * console_lock. Otherwise it is set to false.
++ * console_lock. Otherwise it is set to false. A NULL pointer may be provided
++ * to disable allowing the console_lock to be taken over by a printk waiter.
+ *
+ * Returns false if the given console has no next record to print, otherwise
+ * true.
+ *
+- * Requires the console_lock.
++ * Requires the console_lock if @handover is non-NULL.
++ * Requires con->lock otherwise.
+ */
+-static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
+- char *dropped_text, bool *handover)
++static bool __console_emit_next_record(struct console *con, char *text, char *ext_text,
++ char *dropped_text, bool *handover)
+ {
+- static int panic_console_dropped;
++ static atomic_t panic_console_dropped = ATOMIC_INIT(0);
+ struct printk_info info;
+ struct printk_record r;
+ unsigned long flags;
+@@ -2695,7 +2882,8 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_
+
+ prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX);
+
+- *handover = false;
++ if (handover)
++ *handover = false;
+
+ if (!prb_read_valid(prb, con->seq, &r))
+ return false;
+@@ -2703,7 +2891,8 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_
+ if (con->seq != r.info->seq) {
+ con->dropped += r.info->seq - con->seq;
+ con->seq = r.info->seq;
+- if (panic_in_progress() && panic_console_dropped++ > 10) {
++ if (panic_in_progress() &&
++ atomic_fetch_inc_relaxed(&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");
+ }
+@@ -2725,31 +2914,61 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_
+ len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
+ }
+
+- /*
+- * 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();
++ if (handover) {
++ /*
++ * 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();
++
++ /* don't trace irqsoff print latency */
++ stop_critical_timings();
++ }
+
+- stop_critical_timings(); /* don't trace print latency */
+ call_console_driver(con, write_text, len, dropped_text);
+- start_critical_timings();
+
+ con->seq++;
+
+- *handover = console_lock_spinning_disable_and_check();
+- printk_safe_exit_irqrestore(flags);
++ if (handover) {
++ start_critical_timings();
++ *handover = console_lock_spinning_disable_and_check();
++ printk_safe_exit_irqrestore(flags);
++ }
+ skip:
+ return true;
+ }
+
++/*
++ * Print a record for a given console, but allow another printk() caller to
++ * take over the console_lock and continue printing.
++ *
++ * Requires the console_lock, but depending on @handover after the call, the
++ * caller may no longer have the console_lock.
++ *
++ * See __console_emit_next_record() for argument and return details.
++ */
++static bool console_emit_next_record_transferable(struct console *con, char *text, char *ext_text,
++ char *dropped_text, bool *handover)
++{
++ /*
++ * Handovers are only supported if threaded printers are atomically
++ * blocked. The context taking over the console_lock may be atomic.
++ */
++ if (!console_kthreads_atomically_blocked()) {
++ *handover = false;
++ handover = NULL;
++ }
++
++ return __console_emit_next_record(con, text, ext_text, dropped_text, handover);
++}
++
+ /*
+ * Print out all remaining records to all consoles.
+ *
+@@ -2768,8 +2987,8 @@ static bool console_emit_next_record(struct console *con, char *text, char *ext_
+ * were flushed to all usable consoles. A returned false informs the caller
+ * that everything was not flushed (either there were no usable consoles or
+ * another context has taken over printing or it is a panic situation and this
+- * is not the panic CPU). Regardless the reason, the caller should assume it
+- * is not useful to immediately try again.
++ * is not the panic CPU or direct printing is not preferred). Regardless the
++ * reason, the caller should assume it is not useful to immediately try again.
+ *
+ * Requires the console_lock.
+ */
+@@ -2786,6 +3005,10 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
+ *handover = false;
+
+ do {
++ /* Let the kthread printers do the work if they can. */
++ if (!allow_direct_printing())
++ return false;
++
+ any_progress = false;
+
+ for_each_console(con) {
+@@ -2797,13 +3020,11 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
+
+ if (con->flags & CON_EXTENDED) {
+ /* Extended consoles do not print "dropped messages". */
+- progress = console_emit_next_record(con, &text[0],
+- &ext_text[0], NULL,
+- handover);
++ progress = console_emit_next_record_transferable(con, &text[0],
++ &ext_text[0], NULL, handover);
+ } else {
+- progress = console_emit_next_record(con, &text[0],
+- NULL, &dropped_text[0],
+- handover);
++ progress = console_emit_next_record_transferable(con, &text[0],
++ NULL, &dropped_text[0], handover);
+ }
+ if (*handover)
+ return false;
+@@ -2918,10 +3139,13 @@ void console_unblank(void)
+ if (oops_in_progress) {
+ if (down_trylock_console_sem() != 0)
+ return;
++ if (!console_kthreads_atomic_tryblock()) {
++ up_console_sem();
++ return;
++ }
+ } else
+ console_lock();
+
+- console_locked = 1;
+ console_may_schedule = 0;
+ for_each_console(c)
+ if ((c->flags & CON_ENABLED) && c->unblank)
+@@ -3197,6 +3421,10 @@ void register_console(struct console *newcon)
+ }
+
+ newcon->dropped = 0;
++ newcon->thread = NULL;
++ newcon->blocked = true;
++ mutex_init(&newcon->lock);
++
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /* Get a consistent copy of @syslog_seq. */
+ mutex_lock(&syslog_lock);
+@@ -3206,6 +3434,10 @@ void register_console(struct console *newcon)
+ /* Begin with next message. */
+ newcon->seq = prb_next_seq(prb);
+ }
++
++ if (printk_kthreads_available)
++ printk_start_kthread(newcon);
++
+ console_unlock();
+ console_sysfs_notify();
+
+@@ -3229,6 +3461,7 @@ EXPORT_SYMBOL(register_console);
+
+ int unregister_console(struct console *console)
+ {
++ struct task_struct *thd;
+ struct console *con;
+ int res;
+
+@@ -3266,7 +3499,20 @@ int unregister_console(struct console *console)
+ console_drivers->flags |= CON_CONSDEV;
+
+ console->flags &= ~CON_ENABLED;
++
++ /*
++ * console->thread can only be cleared under the console lock. But
++ * stopping the thread must be done without the console lock. The
++ * task that clears @thread is the task that stops the kthread.
++ */
++ thd = console->thread;
++ console->thread = NULL;
++
+ console_unlock();
++
++ if (thd)
++ kthread_stop(thd);
++
+ console_sysfs_notify();
+
+ if (console->exit)
+@@ -3362,6 +3608,20 @@ static int __init printk_late_init(void)
+ }
+ late_initcall(printk_late_init);
+
++static int __init printk_activate_kthreads(void)
++{
++ struct console *con;
++
++ console_lock();
++ printk_kthreads_available = true;
++ for_each_console(con)
++ printk_start_kthread(con);
++ console_unlock();
++
++ return 0;
++}
++early_initcall(printk_activate_kthreads);
++
+ #if defined CONFIG_PRINTK
+ /* 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)
+@@ -3444,11 +3704,208 @@ static bool pr_flush(int timeout_ms, bool reset_on_progress)
+ return __pr_flush(NULL, timeout_ms, reset_on_progress);
+ }
+
++static void __printk_fallback_preferred_direct(void)
++{
++ printk_prefer_direct_enter();
++ pr_err("falling back to preferred direct printing\n");
++ printk_kthreads_available = false;
++}
++
++/*
++ * Enter preferred direct printing, but never exit. Mark console threads as
++ * unavailable. The system is then forever in preferred direct printing and
++ * any printing threads will exit.
++ *
++ * Must *not* be called under console_lock. Use
++ * __printk_fallback_preferred_direct() if already holding console_lock.
++ */
++static void printk_fallback_preferred_direct(void)
++{
++ console_lock();
++ __printk_fallback_preferred_direct();
++ console_unlock();
++}
++
++/*
++ * Print a record for a given console, not allowing another printk() caller
++ * to take over. This is appropriate for contexts that do not have the
++ * console_lock.
++ *
++ * See __console_emit_next_record() for argument and return details.
++ */
++static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
++ char *dropped_text)
++{
++ return __console_emit_next_record(con, text, ext_text, dropped_text, NULL);
++}
++
++static bool printer_should_wake(struct console *con, u64 seq)
++{
++ short flags;
++
++ if (kthread_should_stop() || !printk_kthreads_available)
++ return true;
++
++ if (con->blocked ||
++ console_kthreads_atomically_blocked() ||
++ block_console_kthreads ||
++ system_state > SYSTEM_RUNNING ||
++ oops_in_progress) {
++ return false;
++ }
++
++ /*
++ * This is an unsafe read from con->flags, but a false positive is
++ * not a problem. Worst case it would allow the printer to wake up
++ * although it is disabled. But the printer will notice that when
++ * attempting to print and instead go back to sleep.
++ */
++ flags = data_race(READ_ONCE(con->flags));
++
++ if (!__console_is_usable(flags))
++ return false;
++
++ return prb_read_valid(prb, seq, NULL);
++}
++
++static int printk_kthread_func(void *data)
++{
++ struct console *con = data;
++ char *dropped_text = NULL;
++ char *ext_text = NULL;
++ u64 seq = 0;
++ char *text;
++ int error;
++
++ text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
++ if (!text) {
++ con_printk(KERN_ERR, con, "failed to allocate text buffer\n");
++ printk_fallback_preferred_direct();
++ goto out;
++ }
++
++ if (con->flags & CON_EXTENDED) {
++ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
++ if (!ext_text) {
++ con_printk(KERN_ERR, con, "failed to allocate ext_text buffer\n");
++ printk_fallback_preferred_direct();
++ goto out;
++ }
++ } else {
++ dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL);
++ if (!dropped_text) {
++ con_printk(KERN_ERR, con, "failed to allocate dropped_text buffer\n");
++ printk_fallback_preferred_direct();
++ goto out;
++ }
++ }
++
++ con_printk(KERN_INFO, con, "printing thread started\n");
++ for (;;) {
++ /*
++ * Guarantee this task is visible on the waitqueue before
++ * checking the wake condition.
++ *
++ * The full memory barrier within set_current_state() of
++ * prepare_to_wait_event() pairs with the full memory barrier
++ * within wq_has_sleeper().
++ *
++ * This pairs with __wake_up_klogd:A.
++ */
++ error = wait_event_interruptible(log_wait,
++ printer_should_wake(con, seq)); /* LMM(printk_kthread_func:A) */
++
++ if (kthread_should_stop() || !printk_kthreads_available)
++ break;
++
++ if (error)
++ continue;
++
++ error = mutex_lock_interruptible(&con->lock);
++ if (error)
++ continue;
++
++ if (con->blocked ||
++ !console_kthread_printing_tryenter()) {
++ /* Another context has locked the console_lock. */
++ mutex_unlock(&con->lock);
++ continue;
++ }
++
++ /*
++ * Although this context has not locked the console_lock, it
++ * is known that the console_lock is not locked and it is not
++ * possible for any other context to lock the console_lock.
++ * Therefore it is safe to read con->flags.
++ */
++
++ if (!__console_is_usable(con->flags)) {
++ console_kthread_printing_exit();
++ mutex_unlock(&con->lock);
++ continue;
++ }
++
++ /*
++ * Even though the printk kthread is always preemptible, it is
++ * still not allowed to call cond_resched() from within
++ * console drivers. The task may become non-preemptible in the
++ * console driver call chain. For example, vt_console_print()
++ * takes a spinlock and then can call into fbcon_redraw(),
++ * which can conditionally invoke cond_resched().
++ */
++ console_may_schedule = 0;
++ console_emit_next_record(con, text, ext_text, dropped_text);
++
++ seq = con->seq;
++
++ console_kthread_printing_exit();
++
++ mutex_unlock(&con->lock);
++ }
++
++ con_printk(KERN_INFO, con, "printing thread stopped\n");
++out:
++ kfree(dropped_text);
++ kfree(ext_text);
++ kfree(text);
++
++ console_lock();
++ /*
++ * If this kthread is being stopped by another task, con->thread will
++ * already be NULL. That is fine. The important thing is that it is
++ * NULL after the kthread exits.
++ */
++ con->thread = NULL;
++ console_unlock();
++
++ return 0;
++}
++
++/* Must be called under console_lock. */
++static void printk_start_kthread(struct console *con)
++{
++ /*
++ * Do not start a kthread if there is no write() callback. The
++ * kthreads assume the write() callback exists.
++ */
++ if (!con->write)
++ return;
++
++ con->thread = kthread_run(printk_kthread_func, con,
++ "pr/%s%d", con->name, con->index);
++ if (IS_ERR(con->thread)) {
++ con->thread = NULL;
++ con_printk(KERN_ERR, con, "unable to start printing thread\n");
++ __printk_fallback_preferred_direct();
++ return;
++ }
++}
++
+ /*
+ * Delayed printk version, for scheduler-internal messages:
+ */
+-#define PRINTK_PENDING_WAKEUP 0x01
+-#define PRINTK_PENDING_OUTPUT 0x02
++#define PRINTK_PENDING_WAKEUP 0x01
++#define PRINTK_PENDING_DIRECT_OUTPUT 0x02
+
+ static DEFINE_PER_CPU(int, printk_pending);
+
+@@ -3456,10 +3913,14 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work)
+ {
+ int pending = this_cpu_xchg(printk_pending, 0);
+
+- if (pending & PRINTK_PENDING_OUTPUT) {
++ if (pending & PRINTK_PENDING_DIRECT_OUTPUT) {
++ printk_prefer_direct_enter();
++
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
++
++ printk_prefer_direct_exit();
+ }
+
+ if (pending & PRINTK_PENDING_WAKEUP)
+@@ -3484,10 +3945,11 @@ static void __wake_up_klogd(int val)
+ * prepare_to_wait_event(), which is called after ___wait_event() adds
+ * the waiter but before it has checked the wait condition.
+ *
+- * This pairs with devkmsg_read:A and syslog_print:A.
++ * This pairs with devkmsg_read:A, syslog_print:A, and
++ * printk_kthread_func:A.
+ */
+ if (wq_has_sleeper(&log_wait) || /* LMM(__wake_up_klogd:A) */
+- (val & PRINTK_PENDING_OUTPUT)) {
++ (val & PRINTK_PENDING_DIRECT_OUTPUT)) {
+ this_cpu_or(printk_pending, val);
+ irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
+ }
+@@ -3527,7 +3989,17 @@ 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;
++
++ /*
++ * Make sure that some context will print the messages when direct
++ * printing is allowed. This happens in situations when the kthreads
++ * may not be as reliable or perhaps unusable.
++ */
++ if (allow_direct_printing())
++ val |= PRINTK_PENDING_DIRECT_OUTPUT;
++
++ __wake_up_klogd(val);
+ }
+
+ void printk_trigger_flush(void)
+diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
+index 6d10927a07d8..8e8fd2fb0a5b 100644
+--- a/kernel/printk/printk_safe.c
++++ b/kernel/printk/printk_safe.c
+@@ -8,7 +8,9 @@
+ #include <linux/smp.h>
+ #include <linux/cpumask.h>
+ #include <linux/printk.h>
++#include <linux/console.h>
+ #include <linux/kprobes.h>
++#include <linux/delay.h>
+
+ #include "internal.h"
+
+@@ -45,3 +47,33 @@ asmlinkage int vprintk(const char *fmt, va_list args)
+ return vprintk_default(fmt, args);
+ }
+ EXPORT_SYMBOL(vprintk);
++
++/**
++ * try_block_console_kthreads() - Try to block console kthreads and
++ * make the global console_lock() avaialble
++ *
++ * @timeout_ms: The maximum time (in ms) to wait.
++ *
++ * Prevent console kthreads from starting processing new messages. Wait
++ * until the global console_lock() become available.
++ *
++ * Context: Can be called in any context.
++ */
++void try_block_console_kthreads(int timeout_ms)
++{
++ block_console_kthreads = true;
++
++ /* Do not wait when the console lock could not be safely taken. */
++ if (this_cpu_read(printk_context) || in_nmi())
++ return;
++
++ while (timeout_ms > 0) {
++ if (console_trylock()) {
++ console_unlock();
++ return;
++ }
++
++ udelay(1000);
++ timeout_ms -= 1;
++ }
++}
+diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
+index 7d15b5b5a235..7b411d663e8f 100644
+--- a/kernel/rcu/tree_stall.h
++++ b/kernel/rcu/tree_stall.h
+@@ -648,6 +648,7 @@ static void print_cpu_stall(unsigned long gps)
+ * See Documentation/RCU/stallwarn.rst for info on how to debug
+ * RCU CPU stall warnings.
+ */
++ printk_prefer_direct_enter();
+ trace_rcu_stall_warning(rcu_state.name, TPS("SelfDetected"));
+ pr_err("INFO: %s self-detected stall on CPU\n", rcu_state.name);
+ raw_spin_lock_irqsave_rcu_node(rdp->mynode, flags);
+@@ -682,6 +683,7 @@ static void print_cpu_stall(unsigned long gps)
+ */
+ set_tsk_need_resched(current);
+ set_preempt_need_resched();
++ printk_prefer_direct_exit();
+ }
+
+ static void check_cpu_stall(struct rcu_data *rdp)
+diff --git a/kernel/reboot.c b/kernel/reboot.c
+index 6ebef11c8876..23a8cfed1a72 100644
+--- a/kernel/reboot.c
++++ b/kernel/reboot.c
+@@ -83,6 +83,7 @@ void kernel_restart_prepare(char *cmd)
+ {
+ blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
+ system_state = SYSTEM_RESTART;
++ try_block_console_kthreads(10000);
+ usermodehelper_disable();
+ device_shutdown();
+ }
+@@ -283,6 +284,7 @@ static void kernel_shutdown_prepare(enum system_states state)
+ blocking_notifier_call_chain(&reboot_notifier_list,
+ (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
+ system_state = state;
++ try_block_console_kthreads(10000);
+ usermodehelper_disable();
+ device_shutdown();
+ }
+@@ -837,9 +839,11 @@ static int __orderly_reboot(void)
+ ret = run_cmd(reboot_cmd);
+
+ if (ret) {
++ printk_prefer_direct_enter();
+ pr_warn("Failed to start orderly reboot: forcing the issue\n");
+ emergency_sync();
+ kernel_restart(NULL);
++ printk_prefer_direct_exit();
+ }
+
+ return ret;
+@@ -852,6 +856,7 @@ static int __orderly_poweroff(bool force)
+ ret = run_cmd(poweroff_cmd);
+
+ if (ret && force) {
++ printk_prefer_direct_enter();
+ pr_warn("Failed to start orderly shutdown: forcing the issue\n");
+
+ /*
+@@ -861,6 +866,7 @@ static int __orderly_poweroff(bool force)
+ */
+ emergency_sync();
+ kernel_power_off();
++ printk_prefer_direct_exit();
+ }
+
+ return ret;
+@@ -918,6 +924,8 @@ EXPORT_SYMBOL_GPL(orderly_reboot);
+ */
+ static void hw_failure_emergency_poweroff_func(struct work_struct *work)
+ {
++ printk_prefer_direct_enter();
++
+ /*
+ * We have reached here after the emergency shutdown waiting period has
+ * expired. This means orderly_poweroff has not been able to shut off
+@@ -934,6 +942,8 @@ static void hw_failure_emergency_poweroff_func(struct work_struct *work)
+ */
+ pr_emerg("Hardware protection shutdown failed. Trying emergency restart\n");
+ emergency_restart();
++
++ printk_prefer_direct_exit();
+ }
+
+ static DECLARE_DELAYED_WORK(hw_failure_emergency_poweroff_work,
+@@ -972,11 +982,13 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced)
+ {
+ static atomic_t allow_proceed = ATOMIC_INIT(1);
+
++ printk_prefer_direct_enter();
++
+ pr_emerg("HARDWARE PROTECTION shutdown (%s)\n", reason);
+
+ /* Shutdown should be initiated only once. */
+ if (!atomic_dec_and_test(&allow_proceed))
+- return;
++ goto out;
+
+ /*
+ * Queue a backup emergency shutdown in the event of
+@@ -984,6 +996,8 @@ void hw_protection_shutdown(const char *reason, int ms_until_forced)
+ */
+ hw_failure_emergency_poweroff(ms_until_forced);
+ orderly_poweroff(true);
++out:
++ printk_prefer_direct_exit();
+ }
+ EXPORT_SYMBOL_GPL(hw_protection_shutdown);
+
+diff --git a/kernel/watchdog.c b/kernel/watchdog.c
+index 45693fb3e08d..f366008298ac 100644
+--- a/kernel/watchdog.c
++++ b/kernel/watchdog.c
+@@ -431,6 +431,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
+ /* Start period for the next softlockup warning. */
+ update_report_ts();
+
++ printk_prefer_direct_enter();
++
+ pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
+ smp_processor_id(), duration,
+ current->comm, task_pid_nr(current));
+@@ -449,6 +451,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
+ add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
+ if (softlockup_panic)
+ panic("softlockup: hung tasks");
++
++ printk_prefer_direct_exit();
+ }
+
+ return HRTIMER_RESTART;
+diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
+index 1e8a49dc956e..7c977b945c92 100644
+--- a/kernel/watchdog_hld.c
++++ b/kernel/watchdog_hld.c
+@@ -135,6 +135,8 @@ static void watchdog_overflow_callback(struct perf_event *event,
+ if (__this_cpu_read(hard_watchdog_warn) == true)
+ return;
+
++ printk_prefer_direct_enter();
++
+ pr_emerg("Watchdog detected hard LOCKUP on cpu %d\n",
+ this_cpu);
+ print_modules();
+@@ -155,6 +157,8 @@ static void watchdog_overflow_callback(struct perf_event *event,
+ if (hardlockup_panic)
+ nmi_panic(regs, "Hard LOCKUP");
+
++ printk_prefer_direct_exit();
++
+ __this_cpu_write(hard_watchdog_warn, true);
+ return;
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0020-printk-add-infrastucture-for-atomic-consoles.patch b/debian/patches-rt/0020-printk-add-infrastucture-for-atomic-consoles.patch
new file mode 100644
index 000000000..b86b20007
--- /dev/null
+++ b/debian/patches-rt/0020-printk-add-infrastucture-for-atomic-consoles.patch
@@ -0,0 +1,608 @@
+From 18343f23a5f1d466a0c74806983066efba932d5d Mon Sep 17 00:00:00 2001
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 4 Feb 2022 16:01:17 +0106
+Subject: [PATCH 20/62] printk: add infrastucture for atomic consoles
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Many times it is not possible to see the console output on
+panic because printing threads cannot be scheduled and/or the
+console is already taken and forcibly overtaking/busting the
+locks does provide the hoped results.
+
+Introduce a new infrastructure to support "atomic consoles".
+A new optional callback in struct console, write_atomic(), is
+available for consoles to provide an implemention for writing
+console messages. The implementation must be NMI safe if they
+can run on an architecture where NMIs exist.
+
+Console drivers implementing the write_atomic() callback must
+also select CONFIG_HAVE_ATOMIC_CONSOLE in order to enable the
+atomic console code within the printk subsystem.
+
+If atomic consoles are available, panic() will flush the kernel
+log only to the atomic consoles (before busting spinlocks).
+Afterwards, panic() will continue as before, which includes
+attempting to flush the other (non-atomic) consoles.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/console.h | 16 ++-
+ init/Kconfig | 4 +
+ kernel/panic.c | 6 +-
+ kernel/printk/printk.c | 293 ++++++++++++++++++++++++++++++++++++----
+ 4 files changed, 290 insertions(+), 29 deletions(-)
+
+diff --git a/include/linux/console.h b/include/linux/console.h
+index 143653090c48..8a813cbaf928 100644
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -138,9 +138,19 @@ static inline int con_debug_leave(void)
+ #define CON_BRL (32) /* Used for a braille device */
+ #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++struct console_atomic_data {
++ u64 seq;
++ char *text;
++ char *ext_text;
++ char *dropped_text;
++};
++#endif
++
+ struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
++ void (*write_atomic)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+@@ -153,7 +163,10 @@ struct console {
+ uint ispeed;
+ uint ospeed;
+ u64 seq;
+- unsigned long dropped;
++ atomic_long_t dropped;
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ struct console_atomic_data *atomic_data;
++#endif
+ struct task_struct *thread;
+ bool blocked;
+
+@@ -184,6 +197,7 @@ extern int console_set_on_cmdline;
+ extern struct console *early_console;
+
+ enum con_flush_mode {
++ CONSOLE_ATOMIC_FLUSH_PENDING,
+ CONSOLE_FLUSH_PENDING,
+ CONSOLE_REPLAY_ALL,
+ };
+diff --git a/init/Kconfig b/init/Kconfig
+index de255842f5d0..d45312780b3a 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1582,6 +1582,10 @@ config PRINTK
+ very difficult to diagnose system problems, saying N here is
+ strongly discouraged.
+
++config HAVE_ATOMIC_CONSOLE
++ bool
++ default n
++
+ config BUG
+ bool "BUG() support" if EXPERT
+ default y
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 88cd873c7c30..97cc495d95f8 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -322,7 +322,6 @@ void panic(const char *fmt, ...)
+ panic_smp_self_stop();
+
+ console_verbose();
+- bust_spinlocks(1);
+ va_start(args, fmt);
+ len = vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+@@ -339,6 +338,11 @@ void panic(const char *fmt, ...)
+ dump_stack();
+ #endif
+
++ /* If atomic consoles are available, flush the kernel log. */
++ console_flush_on_panic(CONSOLE_ATOMIC_FLUSH_PENDING);
++
++ bust_spinlocks(1);
++
+ /*
+ * If kgdb is enabled, give it a chance to run before we stop all
+ * the other CPUs or else we won't be able to debug processes left
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index e9f9b66608a0..73b1727087c7 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -44,6 +44,7 @@
+ #include <linux/irq_work.h>
+ #include <linux/ctype.h>
+ #include <linux/uio.h>
++#include <linux/clocksource.h>
+ #include <linux/sched/clock.h>
+ #include <linux/sched/debug.h>
+ #include <linux/sched/task_stack.h>
+@@ -2060,19 +2061,28 @@ static int console_trylock_spinning(void)
+ * dropped, a dropped message will be written out first.
+ */
+ static void call_console_driver(struct console *con, const char *text, size_t len,
+- char *dropped_text)
++ char *dropped_text, bool atomic_printing)
+ {
++ unsigned long dropped = 0;
+ size_t dropped_len;
+
+- if (con->dropped && dropped_text) {
++ if (dropped_text)
++ dropped = atomic_long_xchg_relaxed(&con->dropped, 0);
++
++ if (dropped) {
+ dropped_len = snprintf(dropped_text, DROPPED_TEXT_MAX,
+ "** %lu printk messages dropped **\n",
+- con->dropped);
+- con->dropped = 0;
+- con->write(con, dropped_text, dropped_len);
++ dropped);
++ if (atomic_printing)
++ con->write_atomic(con, dropped_text, dropped_len);
++ else
++ con->write(con, dropped_text, dropped_len);
+ }
+
+- con->write(con, text, len);
++ if (atomic_printing)
++ con->write_atomic(con, text, len);
++ else
++ con->write(con, text, len);
+ }
+
+ /*
+@@ -2430,6 +2440,76 @@ asmlinkage __visible int _printk(const char *fmt, ...)
+ }
+ EXPORT_SYMBOL(_printk);
+
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++static void __free_atomic_data(struct console_atomic_data *d)
++{
++ kfree(d->text);
++ kfree(d->ext_text);
++ kfree(d->dropped_text);
++}
++
++static void free_atomic_data(struct console_atomic_data *d)
++{
++ int count = 1;
++ int i;
++
++ if (!d)
++ return;
++
++#ifdef CONFIG_HAVE_NMI
++ count = 2;
++#endif
++
++ for (i = 0; i < count; i++)
++ __free_atomic_data(&d[i]);
++ kfree(d);
++}
++
++static int __alloc_atomic_data(struct console_atomic_data *d, short flags)
++{
++ d->text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
++ if (!d->text)
++ return -1;
++
++ if (flags & CON_EXTENDED) {
++ d->ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
++ if (!d->ext_text)
++ return -1;
++ } else {
++ d->dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL);
++ if (!d->dropped_text)
++ return -1;
++ }
++
++ return 0;
++}
++
++static struct console_atomic_data *alloc_atomic_data(short flags)
++{
++ struct console_atomic_data *d;
++ int count = 1;
++ int i;
++
++#ifdef CONFIG_HAVE_NMI
++ count = 2;
++#endif
++
++ d = kzalloc(sizeof(*d) * count, GFP_KERNEL);
++ if (!d)
++ goto err_out;
++
++ for (i = 0; i < count; i++) {
++ if (__alloc_atomic_data(&d[i], flags) != 0)
++ goto err_out;
++ }
++
++ return d;
++err_out:
++ free_atomic_data(d);
++ return NULL;
++}
++#endif /* CONFIG_HAVE_ATOMIC_CONSOLE */
++
+ 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);
+
+@@ -2445,6 +2525,8 @@ static void printk_start_kthread(struct console *con);
+ #define prb_first_valid_seq(rb) 0
+ #define prb_next_seq(rb) 0
+
++#define free_atomic_data(d)
++
+ static u64 syslog_seq;
+
+ static size_t record_print_text(const struct printk_record *r,
+@@ -2463,7 +2545,7 @@ static ssize_t msg_print_ext_body(char *buf, size_t size,
+ static void console_lock_spinning_enable(void) { }
+ static int console_lock_spinning_disable_and_check(void) { return 0; }
+ static void call_console_driver(struct console *con, const char *text, size_t len,
+- char *dropped_text)
++ char *dropped_text, bool atomic_printing)
+ {
+ }
+ static bool suppress_message_printing(int level) { return false; }
+@@ -2819,10 +2901,20 @@ static inline bool __console_is_usable(short flags)
+ *
+ * Requires holding the console_lock.
+ */
+-static inline bool console_is_usable(struct console *con)
++static inline bool console_is_usable(struct console *con, bool atomic_printing)
+ {
+- if (!con->write)
++ if (atomic_printing) {
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ if (!con->write_atomic)
++ return false;
++ if (!con->atomic_data)
++ return false;
++#else
++ return false;
++#endif
++ } else if (!con->write) {
+ return false;
++ }
+
+ return __console_is_usable(con->flags);
+ }
+@@ -2847,6 +2939,66 @@ static void __console_unlock(void)
+ up_console_sem();
+ }
+
++static u64 read_console_seq(struct console *con)
++{
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ unsigned long flags;
++ u64 seq2;
++ u64 seq;
++
++ if (!con->atomic_data)
++ return con->seq;
++
++ printk_cpu_sync_get_irqsave(flags);
++
++ seq = con->seq;
++ seq2 = con->atomic_data[0].seq;
++ if (seq2 > seq)
++ seq = seq2;
++#ifdef CONFIG_HAVE_NMI
++ seq2 = con->atomic_data[1].seq;
++ if (seq2 > seq)
++ seq = seq2;
++#endif
++
++ printk_cpu_sync_put_irqrestore(flags);
++
++ return seq;
++#else /* CONFIG_HAVE_ATOMIC_CONSOLE */
++ return con->seq;
++#endif
++}
++
++static void write_console_seq(struct console *con, u64 val, bool atomic_printing)
++{
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ unsigned long flags;
++ u64 *seq;
++
++ if (!con->atomic_data) {
++ con->seq = val;
++ return;
++ }
++
++ printk_cpu_sync_get_irqsave(flags);
++
++ if (atomic_printing) {
++ seq = &con->atomic_data[0].seq;
++#ifdef CONFIG_HAVE_NMI
++ if (in_nmi())
++ seq = &con->atomic_data[1].seq;
++#endif
++ } else {
++ seq = &con->seq;
++ }
++ *seq = val;
++
++ printk_cpu_sync_put_irqrestore(flags);
++#else /* CONFIG_HAVE_ATOMIC_CONSOLE */
++ con->seq = val;
++#endif
++}
++
+ /*
+ * Print one record for the given console. The record printed is whatever
+ * record is the next available record for the given console.
+@@ -2859,6 +3011,8 @@ static void __console_unlock(void)
+ * If dropped messages should be printed, @dropped_text is a buffer of size
+ * DROPPED_TEXT_MAX. Otherwise @dropped_text must be NULL.
+ *
++ * @atomic_printing specifies if atomic printing should be used.
++ *
+ * @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 the
+ * console_lock. Otherwise it is set to false. A NULL pointer may be provided
+@@ -2871,7 +3025,8 @@ static void __console_unlock(void)
+ * Requires con->lock otherwise.
+ */
+ static bool __console_emit_next_record(struct console *con, char *text, char *ext_text,
+- char *dropped_text, bool *handover)
++ char *dropped_text, bool atomic_printing,
++ bool *handover)
+ {
+ static atomic_t panic_console_dropped = ATOMIC_INIT(0);
+ struct printk_info info;
+@@ -2879,18 +3034,22 @@ static bool __console_emit_next_record(struct console *con, char *text, char *ex
+ unsigned long flags;
+ char *write_text;
+ size_t len;
++ u64 seq;
+
+ prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX);
+
+ if (handover)
+ *handover = false;
+
+- if (!prb_read_valid(prb, con->seq, &r))
++ seq = read_console_seq(con);
++
++ if (!prb_read_valid(prb, seq, &r))
+ return false;
+
+- if (con->seq != r.info->seq) {
+- con->dropped += r.info->seq - con->seq;
+- con->seq = r.info->seq;
++ if (seq != r.info->seq) {
++ atomic_long_add((unsigned long)(r.info->seq - seq), &con->dropped);
++ write_console_seq(con, r.info->seq, atomic_printing);
++ seq = r.info->seq;
+ if (panic_in_progress() &&
+ atomic_fetch_inc_relaxed(&panic_console_dropped) > 10) {
+ suppress_panic_printk = 1;
+@@ -2900,7 +3059,7 @@ static bool __console_emit_next_record(struct console *con, char *text, char *ex
+
+ /* Skip record that has level above the console loglevel. */
+ if (suppress_message_printing(r.info->level)) {
+- con->seq++;
++ write_console_seq(con, seq + 1, atomic_printing);
+ goto skip;
+ }
+
+@@ -2932,9 +3091,9 @@ static bool __console_emit_next_record(struct console *con, char *text, char *ex
+ stop_critical_timings();
+ }
+
+- call_console_driver(con, write_text, len, dropped_text);
++ call_console_driver(con, write_text, len, dropped_text, atomic_printing);
+
+- con->seq++;
++ write_console_seq(con, seq + 1, atomic_printing);
+
+ if (handover) {
+ start_critical_timings();
+@@ -2966,7 +3125,7 @@ static bool console_emit_next_record_transferable(struct console *con, char *tex
+ handover = NULL;
+ }
+
+- return __console_emit_next_record(con, text, ext_text, dropped_text, handover);
++ return __console_emit_next_record(con, text, ext_text, dropped_text, false, handover);
+ }
+
+ /*
+@@ -3014,7 +3173,7 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
+ for_each_console(con) {
+ bool progress;
+
+- if (!console_is_usable(con))
++ if (!console_is_usable(con, false))
+ continue;
+ any_usable = true;
+
+@@ -3049,6 +3208,68 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove
+ return any_usable;
+ }
+
++#if defined(CONFIG_HAVE_ATOMIC_CONSOLE) && defined(CONFIG_PRINTK)
++static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
++ char *dropped_text, bool atomic_printing);
++
++static void atomic_console_flush_all(void)
++{
++ unsigned long flags;
++ struct console *con;
++ bool any_progress;
++ int index = 0;
++
++ if (console_suspended)
++ return;
++
++#ifdef CONFIG_HAVE_NMI
++ if (in_nmi())
++ index = 1;
++#endif
++
++ printk_cpu_sync_get_irqsave(flags);
++
++ do {
++ any_progress = false;
++
++ for_each_console(con) {
++ bool progress;
++
++ if (!console_is_usable(con, true))
++ continue;
++
++ if (con->flags & CON_EXTENDED) {
++ /* Extended consoles do not print "dropped messages". */
++ progress = console_emit_next_record(con,
++ &con->atomic_data->text[index],
++ &con->atomic_data->ext_text[index],
++ NULL,
++ true);
++ } else {
++ progress = console_emit_next_record(con,
++ &con->atomic_data->text[index],
++ NULL,
++ &con->atomic_data->dropped_text[index],
++ true);
++ }
++
++ if (!progress)
++ continue;
++ any_progress = true;
++
++ touch_softlockup_watchdog_sync();
++ clocksource_touch_watchdog();
++ rcu_cpu_stall_reset();
++ touch_nmi_watchdog();
++ }
++ } while (any_progress);
++
++ printk_cpu_sync_put_irqrestore(flags);
++}
++#else /* CONFIG_HAVE_ATOMIC_CONSOLE && CONFIG_PRINTK */
++#define atomic_console_flush_all()
++#endif
++
+ /**
+ * console_unlock - unlock the console system
+ *
+@@ -3164,6 +3385,11 @@ void console_unblank(void)
+ */
+ void console_flush_on_panic(enum con_flush_mode mode)
+ {
++ if (mode == CONSOLE_ATOMIC_FLUSH_PENDING) {
++ atomic_console_flush_all();
++ return;
++ }
++
+ /*
+ * If someone else is holding the console lock, trylock will fail
+ * and may_schedule may be set. Ignore and proceed to unlock so
+@@ -3180,7 +3406,7 @@ void console_flush_on_panic(enum con_flush_mode mode)
+
+ seq = prb_first_valid_seq(prb);
+ for_each_console(c)
+- c->seq = seq;
++ write_console_seq(c, seq, false);
+ }
+ console_unlock();
+ }
+@@ -3420,19 +3646,22 @@ void register_console(struct console *newcon)
+ console_drivers->next = newcon;
+ }
+
+- newcon->dropped = 0;
++ atomic_long_set(&newcon->dropped, 0);
+ newcon->thread = NULL;
+ newcon->blocked = true;
+ mutex_init(&newcon->lock);
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ newcon->atomic_data = NULL;
++#endif
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /* Get a consistent copy of @syslog_seq. */
+ mutex_lock(&syslog_lock);
+- newcon->seq = syslog_seq;
++ write_console_seq(newcon, syslog_seq, false);
+ mutex_unlock(&syslog_lock);
+ } else {
+ /* Begin with next message. */
+- newcon->seq = prb_next_seq(prb);
++ write_console_seq(newcon, prb_next_seq(prb), false);
+ }
+
+ if (printk_kthreads_available)
+@@ -3515,6 +3744,10 @@ int unregister_console(struct console *console)
+
+ console_sysfs_notify();
+
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ free_atomic_data(console->atomic_data);
++#endif
++
+ if (console->exit)
+ res = console->exit(console);
+
+@@ -3645,7 +3878,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
+ for_each_console(c) {
+ if (con && con != c)
+ continue;
+- if (!console_is_usable(c))
++ if (!console_is_usable(c, false))
+ continue;
+ printk_seq = c->seq;
+ if (printk_seq < seq)
+@@ -3734,9 +3967,10 @@ static void printk_fallback_preferred_direct(void)
+ * See __console_emit_next_record() for argument and return details.
+ */
+ static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
+- char *dropped_text)
++ char *dropped_text, bool atomic_printing)
+ {
+- return __console_emit_next_record(con, text, ext_text, dropped_text, NULL);
++ return __console_emit_next_record(con, text, ext_text, dropped_text,
++ atomic_printing, NULL);
+ }
+
+ static bool printer_should_wake(struct console *con, u64 seq)
+@@ -3777,6 +4011,11 @@ static int printk_kthread_func(void *data)
+ char *text;
+ int error;
+
++#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++ if (con->write_atomic)
++ con->atomic_data = alloc_atomic_data(con->flags);
++#endif
++
+ text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
+ if (!text) {
+ con_printk(KERN_ERR, con, "failed to allocate text buffer\n");
+@@ -3854,7 +4093,7 @@ static int printk_kthread_func(void *data)
+ * which can conditionally invoke cond_resched().
+ */
+ console_may_schedule = 0;
+- console_emit_next_record(con, text, ext_text, dropped_text);
++ console_emit_next_record(con, text, ext_text, dropped_text, false);
+
+ seq = con->seq;
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0021-serial-8250-implement-write_atomic.patch b/debian/patches-rt/0021-serial-8250-implement-write_atomic.patch
new file mode 100644
index 000000000..6a5f5abe2
--- /dev/null
+++ b/debian/patches-rt/0021-serial-8250-implement-write_atomic.patch
@@ -0,0 +1,938 @@
+From 08b8c0b589806331dc645a8ead6be51c174d93e0 Mon Sep 17 00:00:00 2001
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 4 Feb 2022 16:01:17 +0106
+Subject: [PATCH 21/62] serial: 8250: implement write_atomic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Implement a non-sleeping NMI-safe write_atomic() console function in
+order to support atomic console printing during a panic.
+
+Trasmitting data requires disabling interrupts. Since write_atomic()
+can be called from any context, it may be called while another CPU
+is executing in console code. In order to maintain the correct state
+of the IER register, use the global cpu_sync to synchronize all
+access to the IER register. This synchronization is only necessary
+for serial ports that are being used as consoles.
+
+The global cpu_sync is also used to synchronize between the write()
+and write_atomic() callbacks. write() synchronizes per character,
+write_atomic() synchronizes per line.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250.h | 41 ++++-
+ drivers/tty/serial/8250/8250_aspeed_vuart.c | 2 +-
+ drivers/tty/serial/8250/8250_bcm7271.c | 21 ++-
+ drivers/tty/serial/8250/8250_core.c | 24 ++-
+ drivers/tty/serial/8250/8250_exar.c | 4 +-
+ drivers/tty/serial/8250/8250_fsl.c | 3 +-
+ drivers/tty/serial/8250/8250_ingenic.c | 3 +-
+ drivers/tty/serial/8250/8250_mtk.c | 32 +++-
+ drivers/tty/serial/8250/8250_omap.c | 18 +--
+ drivers/tty/serial/8250/8250_port.c | 158 ++++++++++++++++----
+ drivers/tty/serial/8250/Kconfig | 1 +
+ include/linux/serial_8250.h | 5 +
+ 12 files changed, 261 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
+index eeb7b43ebe53..b17715d340c3 100644
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -176,12 +176,49 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
+ up->dl_write(up, value);
+ }
+
++static inline int serial8250_in_IER(struct uart_8250_port *up)
++{
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++ int ier;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ ier = serial_in(up, UART_IER);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++
++ return ier;
++}
++
++static inline void serial8250_set_IER(struct uart_8250_port *up, int ier)
++{
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ serial_out(up, UART_IER, ier);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++}
++
+ static inline bool serial8250_set_THRI(struct uart_8250_port *up)
+ {
+ if (up->ier & UART_IER_THRI)
+ return false;
+ up->ier |= UART_IER_THRI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ return true;
+ }
+
+@@ -190,7 +227,7 @@ static inline bool serial8250_clear_THRI(struct uart_8250_port *up)
+ if (!(up->ier & UART_IER_THRI))
+ return false;
+ up->ier &= ~UART_IER_THRI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ return true;
+ }
+
+diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
+index 9d2a7856784f..7cc6b527c088 100644
+--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
++++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
+@@ -278,7 +278,7 @@ static void __aspeed_vuart_set_throttle(struct uart_8250_port *up,
+ up->ier &= ~irqs;
+ if (!throttle)
+ up->ier |= irqs;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ }
+ static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle)
+ {
+diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
+index ffc7f67e27e3..8b211e668bc0 100644
+--- a/drivers/tty/serial/8250/8250_bcm7271.c
++++ b/drivers/tty/serial/8250/8250_bcm7271.c
+@@ -609,7 +609,7 @@ static int brcmuart_startup(struct uart_port *port)
+ * will handle this.
+ */
+ up->ier &= ~UART_IER_RDI;
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ priv->tx_running = false;
+ priv->dma.rx_dma = NULL;
+@@ -775,10 +775,12 @@ static int brcmuart_handle_irq(struct uart_port *p)
+ unsigned int iir = serial_port_in(p, UART_IIR);
+ struct brcmuart_priv *priv = p->private_data;
+ struct uart_8250_port *up = up_to_u8250p(p);
++ unsigned long cs_flags;
+ unsigned int status;
+ unsigned long flags;
+ unsigned int ier;
+ unsigned int mcr;
++ bool is_console;
+ int handled = 0;
+
+ /*
+@@ -789,6 +791,10 @@ static int brcmuart_handle_irq(struct uart_port *p)
+ spin_lock_irqsave(&p->lock, flags);
+ status = serial_port_in(p, UART_LSR);
+ if ((status & UART_LSR_DR) == 0) {
++ is_console = uart_console(p);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
+
+ ier = serial_port_in(p, UART_IER);
+ /*
+@@ -809,6 +815,9 @@ static int brcmuart_handle_irq(struct uart_port *p)
+ serial_port_in(p, UART_RX);
+ }
+
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
++
+ handled = 1;
+ }
+ spin_unlock_irqrestore(&p->lock, flags);
+@@ -823,8 +832,10 @@ static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t)
+ struct brcmuart_priv *priv = container_of(t, struct brcmuart_priv, hrt);
+ struct uart_port *p = priv->up;
+ struct uart_8250_port *up = up_to_u8250p(p);
++ unsigned long cs_flags;
+ unsigned int status;
+ unsigned long flags;
++ bool is_console;
+
+ if (priv->shutdown)
+ return HRTIMER_NORESTART;
+@@ -846,12 +857,20 @@ static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t)
+ /* re-enable receive unless upper layer has disabled it */
+ if ((up->ier & (UART_IER_RLSI | UART_IER_RDI)) ==
+ (UART_IER_RLSI | UART_IER_RDI)) {
++ is_console = uart_console(p);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ status = serial_port_in(p, UART_IER);
+ status |= (UART_IER_RLSI | UART_IER_RDI);
+ serial_port_out(p, UART_IER, status);
+ status = serial_port_in(p, UART_MCR);
+ status |= UART_MCR_RTS;
+ serial_port_out(p, UART_MCR, status);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
+ }
+ spin_unlock_irqrestore(&p->lock, flags);
+ return HRTIMER_NORESTART;
+diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
+index 81a5dab1a828..536f639ff56c 100644
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -255,8 +255,11 @@ static void serial8250_timeout(struct timer_list *t)
+ static void serial8250_backup_timeout(struct timer_list *t)
+ {
+ struct uart_8250_port *up = from_timer(up, t, timer);
++ struct uart_port *port = &up->port;
+ unsigned int iir, ier = 0, lsr;
++ unsigned long cs_flags;
+ unsigned long flags;
++ bool is_console;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+@@ -265,8 +268,16 @@ static void serial8250_backup_timeout(struct timer_list *t)
+ * based handler.
+ */
+ if (up->port.irq) {
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
+ }
+
+ iir = serial_in(up, UART_IIR);
+@@ -289,7 +300,7 @@ static void serial8250_backup_timeout(struct timer_list *t)
+ serial8250_tx_chars(up);
+
+ if (up->port.irq)
+- serial_out(up, UART_IER, ier);
++ serial8250_set_IER(up, ier);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+@@ -575,6 +586,14 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev)
+
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+
++static void univ8250_console_write_atomic(struct console *co, const char *s,
++ unsigned int count)
++{
++ struct uart_8250_port *up = &serial8250_ports[co->index];
++
++ serial8250_console_write_atomic(up, s, count);
++}
++
+ static void univ8250_console_write(struct console *co, const char *s,
+ unsigned int count)
+ {
+@@ -668,6 +687,7 @@ static int univ8250_console_match(struct console *co, char *name, int idx,
+
+ static struct console univ8250_console = {
+ .name = "ttyS",
++ .write_atomic = univ8250_console_write_atomic,
+ .write = univ8250_console_write,
+ .device = uart_console_device,
+ .setup = univ8250_console_setup,
+@@ -961,7 +981,7 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work)
+ spin_lock_irqsave(&port->lock, flags);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ up->port.read_status_mask |= UART_LSR_DR;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
+index b406cba10b0e..246c32c75a4c 100644
+--- a/drivers/tty/serial/8250/8250_exar.c
++++ b/drivers/tty/serial/8250/8250_exar.c
+@@ -189,6 +189,8 @@ static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
+
+ static int xr17v35x_startup(struct uart_port *port)
+ {
++ struct uart_8250_port *up = up_to_u8250p(port);
++
+ /*
+ * First enable access to IER [7:5], ISR [5:4], FCR [5:4],
+ * MCR [7:5] and MSR [7:0]
+@@ -199,7 +201,7 @@ static int xr17v35x_startup(struct uart_port *port)
+ * Make sure all interrups are masked until initialization is
+ * complete and the FIFOs are cleared
+ */
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+
+ return serial8250_do_startup(port);
+ }
+diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
+index 8adfaa183f77..eaf148245a10 100644
+--- a/drivers/tty/serial/8250/8250_fsl.c
++++ b/drivers/tty/serial/8250/8250_fsl.c
+@@ -58,7 +58,8 @@ int fsl8250_handle_irq(struct uart_port *port)
+ if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) {
+ unsigned long delay;
+
+- up->ier = port->serial_in(port, UART_IER);
++ up->ier = serial8250_in_IER(up);
++
+ if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
+ port->ops->stop_rx(port);
+ } else {
+diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
+index 2b2f5d8d24b9..2b78e6c394fb 100644
+--- a/drivers/tty/serial/8250/8250_ingenic.c
++++ b/drivers/tty/serial/8250/8250_ingenic.c
+@@ -146,6 +146,7 @@ OF_EARLYCON_DECLARE(x1000_uart, "ingenic,x1000-uart",
+
+ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
+ {
++ struct uart_8250_port *up = up_to_u8250p(p);
+ int ier;
+
+ switch (offset) {
+@@ -167,7 +168,7 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
+ * If we have enabled modem status IRQs we should enable
+ * modem mode.
+ */
+- ier = p->serial_in(p, UART_IER);
++ ier = serial8250_in_IER(up);
+
+ if (ier & UART_IER_MSI)
+ value |= UART_MCR_MDCE | UART_MCR_FCM;
+diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
+index fb1d5ec0940e..3e7203909d6a 100644
+--- a/drivers/tty/serial/8250/8250_mtk.c
++++ b/drivers/tty/serial/8250/8250_mtk.c
+@@ -222,12 +222,40 @@ static void mtk8250_shutdown(struct uart_port *port)
+
+ static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
+ {
+- serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask));
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++ int ier;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ ier = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, ier & (~mask));
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
+ }
+
+ static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask)
+ {
+- serial_out(up, UART_IER, serial_in(up, UART_IER) | mask);
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++ int ier;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ ier = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, ier | mask);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
+ }
+
+ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
+diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
+index 0b04d810b3e6..2b8ad5176399 100644
+--- a/drivers/tty/serial/8250/8250_omap.c
++++ b/drivers/tty/serial/8250/8250_omap.c
+@@ -330,7 +330,7 @@ static void omap8250_restore_regs(struct uart_8250_port *up)
+ /* drop TCR + TLR access, we setup XON/XOFF later */
+ serial8250_out_MCR(up, mcr);
+
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_dl_write(up, priv->quot);
+@@ -520,7 +520,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state,
+ serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0);
+
+- serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
++ serial8250_set_IER(up, (state != 0) ? UART_IERX_SLEEP : 0);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, 0);
+@@ -703,7 +703,7 @@ static int omap_8250_startup(struct uart_port *port)
+ goto err;
+
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ #ifdef CONFIG_PM
+ up->capabilities |= UART_CAP_RPM;
+@@ -744,7 +744,7 @@ static void omap_8250_shutdown(struct uart_port *port)
+ serial_out(up, UART_OMAP_EFR2, 0x0);
+
+ up->ier = 0;
+- serial_out(up, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+
+ if (up->dma)
+ serial8250_release_dma(up);
+@@ -792,7 +792,7 @@ static void omap_8250_unthrottle(struct uart_port *port)
+ 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);
++ serial8250_set_IER(up, up->ier);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ pm_runtime_mark_last_busy(port->dev);
+@@ -883,7 +883,7 @@ static void __dma_rx_complete(void *param)
+ __dma_rx_do_complete(p);
+ if (!priv->throttled) {
+ p->ier |= UART_IER_RLSI | UART_IER_RDI;
+- serial_out(p, UART_IER, p->ier);
++ serial8250_set_IER(p, p->ier);
+ if (!(priv->habit & UART_HAS_EFR2))
+ omap_8250_rx_dma(p);
+ }
+@@ -940,7 +940,7 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)
+ * callback to run.
+ */
+ p->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+- serial_out(p, UART_IER, p->ier);
++ serial8250_set_IER(p, p->ier);
+ }
+ goto out;
+ }
+@@ -1153,12 +1153,12 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
+ * periodic timeouts, re-enable interrupts.
+ */
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ omap_8250_rx_dma_flush(up);
+ serial_in(up, UART_IIR);
+ serial_out(up, UART_OMAP_EFR2, 0x0);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ }
+ }
+
+diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
+index 8efe31448df3..975c16267196 100644
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -744,7 +744,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+ serial_out(p, UART_EFR, UART_EFR_ECB);
+ serial_out(p, UART_LCR, 0);
+ }
+- serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
++ serial8250_set_IER(p, sleep ? UART_IERX_SLEEP : 0);
+ if (p->capabilities & UART_CAP_EFR) {
+ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(p, UART_EFR, efr);
+@@ -755,12 +755,29 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+ serial8250_rpm_put(p);
+ }
+
+-static void serial8250_clear_IER(struct uart_8250_port *up)
++static unsigned int serial8250_clear_IER(struct uart_8250_port *up)
+ {
++ struct uart_port *port = &up->port;
++ unsigned int clearval = 0;
++ unsigned long flags;
++ bool is_console;
++ unsigned int prior;
++
++ is_console = uart_console(port);
++
+ if (up->capabilities & UART_CAP_UUE)
+- serial_out(up, UART_IER, UART_IER_UUE);
+- else
+- serial_out(up, UART_IER, 0);
++ clearval = UART_IER_UUE;
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ prior = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, clearval);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++
++ return prior;
+ }
+
+ #ifdef CONFIG_SERIAL_8250_RSA
+@@ -1026,8 +1043,11 @@ static int broken_efr(struct uart_8250_port *up)
+ */
+ static void autoconfig_16550a(struct uart_8250_port *up)
+ {
++ struct uart_port *port = &up->port;
+ unsigned char status1, status2;
+ unsigned int iersave;
++ unsigned long flags;
++ bool is_console;
+
+ up->port.type = PORT_16550A;
+ up->capabilities |= UART_CAP_FIFO;
+@@ -1139,6 +1159,11 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ return;
+ }
+
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
+ /*
+ * Try writing and reading the UART_IER_UUE bit (b6).
+ * If it works, this is probably one of the Xscale platform's
+@@ -1174,6 +1199,9 @@ static void autoconfig_16550a(struct uart_8250_port *up)
+ }
+ serial_out(up, UART_IER, iersave);
+
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++
+ /*
+ * We distinguish between 16550A and U6 16550A by counting
+ * how many bytes are in the FIFO.
+@@ -1196,8 +1224,10 @@ static void autoconfig(struct uart_8250_port *up)
+ unsigned char status1, scratch, scratch2, scratch3;
+ unsigned char save_lcr, save_mcr;
+ struct uart_port *port = &up->port;
++ unsigned long cs_flags;
+ unsigned long flags;
+ unsigned int old_capabilities;
++ bool is_console;
+
+ if (!port->iobase && !port->mapbase && !port->membase)
+ return;
+@@ -1215,6 +1245,11 @@ static void autoconfig(struct uart_8250_port *up)
+ up->bugs = 0;
+
+ if (!(port->flags & UPF_BUGGY_UART)) {
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ /*
+ * Do a simple existence test first; if we fail this,
+ * there's no point trying anything else.
+@@ -1244,6 +1279,10 @@ static void autoconfig(struct uart_8250_port *up)
+ #endif
+ scratch3 = serial_in(up, UART_IER) & 0x0f;
+ serial_out(up, UART_IER, scratch);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
++
+ if (scratch2 != 0 || scratch3 != 0x0F) {
+ /*
+ * We failed; there's nothing here
+@@ -1367,7 +1406,9 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ unsigned char save_mcr, save_ier;
+ unsigned char save_ICP = 0;
+ unsigned int ICP = 0;
++ unsigned long flags;
+ unsigned long irqs;
++ bool is_console;
+ int irq;
+
+ if (port->flags & UPF_FOURPORT) {
+@@ -1377,8 +1418,12 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ inb_p(ICP);
+ }
+
+- if (uart_console(port))
++ is_console = uart_console(port);
++
++ if (is_console) {
+ console_lock();
++ printk_cpu_sync_get_irqsave(flags);
++ }
+
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+@@ -1410,8 +1455,10 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ if (port->flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+
+- if (uart_console(port))
++ if (is_console) {
++ printk_cpu_sync_put_irqrestore(flags);
+ console_unlock();
++ }
+
+ port->irq = (irq > 0) ? irq : 0;
+ }
+@@ -1424,7 +1471,7 @@ static void serial8250_stop_rx(struct uart_port *port)
+
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ up->port.read_status_mask &= ~UART_LSR_DR;
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ serial8250_rpm_put(up);
+ }
+@@ -1454,7 +1501,7 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p)
+ serial8250_clear_and_reinit_fifos(p);
+
+ p->ier |= UART_IER_RLSI | UART_IER_RDI;
+- serial_port_out(&p->port, UART_IER, p->ier);
++ serial8250_set_IER(p, p->ier);
+ }
+ }
+ EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
+@@ -1703,7 +1750,7 @@ static void serial8250_disable_ms(struct uart_port *port)
+ mctrl_gpio_disable_ms(up->gpios);
+
+ up->ier &= ~UART_IER_MSI;
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ }
+
+ static void serial8250_enable_ms(struct uart_port *port)
+@@ -1719,7 +1766,7 @@ static void serial8250_enable_ms(struct uart_port *port)
+ up->ier |= UART_IER_MSI;
+
+ serial8250_rpm_get(up);
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ serial8250_rpm_put(up);
+ }
+
+@@ -2174,8 +2221,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
+ /*
+ * First save the IER then disable the interrupts
+ */
+- ier = serial_port_in(port, UART_IER);
+- serial8250_clear_IER(up);
++ ier = serial8250_clear_IER(up);
+
+ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
+ /*
+@@ -2188,7 +2234,7 @@ static void serial8250_put_poll_char(struct uart_port *port,
+ * and restore the IER
+ */
+ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
+- serial_port_out(port, UART_IER, ier);
++ serial8250_set_IER(up, ier);
+ serial8250_rpm_put(up);
+ }
+
+@@ -2197,8 +2243,10 @@ static void serial8250_put_poll_char(struct uart_port *port,
+ int serial8250_do_startup(struct uart_port *port)
+ {
+ struct uart_8250_port *up = up_to_u8250p(port);
++ unsigned long cs_flags;
+ unsigned long flags;
+ unsigned char iir;
++ bool is_console;
+ int retval;
+ u16 lsr;
+
+@@ -2219,7 +2267,7 @@ int serial8250_do_startup(struct uart_port *port)
+ up->acr = 0;
+ 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_IER, 0);
++ serial8250_set_IER(up, 0);
+ serial_port_out(port, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+@@ -2229,7 +2277,7 @@ int serial8250_do_startup(struct uart_port *port)
+
+ if (port->type == PORT_DA830) {
+ /* Reset the port */
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+ serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
+ mdelay(10);
+
+@@ -2328,6 +2376,8 @@ int serial8250_do_startup(struct uart_port *port)
+ if (retval)
+ goto out;
+
++ is_console = uart_console(port);
++
+ if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
+ unsigned char iir1;
+
+@@ -2344,6 +2394,9 @@ int serial8250_do_startup(struct uart_port *port)
+ */
+ spin_lock_irqsave(&port->lock, flags);
+
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+@@ -2354,6 +2407,9 @@ int serial8250_do_startup(struct uart_port *port)
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
++
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (port->irqflags & IRQF_SHARED)
+@@ -2408,10 +2464,14 @@ int serial8250_do_startup(struct uart_port *port)
+ * Do a quick test to see if we receive an interrupt when we enable
+ * the TX irq.
+ */
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
+ serial_port_out(port, UART_IER, UART_IER_THRI);
+ lsr = serial_port_in(port, UART_LSR);
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+@@ -2443,7 +2503,7 @@ int serial8250_do_startup(struct uart_port *port)
+ if (up->dma) {
+ const char *msg = NULL;
+
+- if (uart_console(port))
++ if (is_console)
+ msg = "forbid DMA for kernel console";
+ else if (serial8250_request_dma(up))
+ msg = "failed to request DMA";
+@@ -2494,7 +2554,7 @@ void serial8250_do_shutdown(struct uart_port *port)
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ up->ier = 0;
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ synchronize_irq(port->irq);
+@@ -2856,7 +2916,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ if (up->capabilities & UART_CAP_RTOIE)
+ up->ier |= UART_IER_RTOIE;
+
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ if (up->capabilities & UART_CAP_EFR) {
+ unsigned char efr = 0;
+@@ -3321,7 +3381,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults);
+
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+
+-static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
++static void serial8250_console_putchar_locked(struct uart_port *port, unsigned char ch)
+ {
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+@@ -3329,6 +3389,18 @@ static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
+ serial_port_out(port, UART_TX, ch);
+ }
+
++static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
++{
++ struct uart_8250_port *up = up_to_u8250p(port);
++ unsigned long flags;
++
++ wait_for_xmitr(up, UART_LSR_THRE);
++
++ printk_cpu_sync_get_irqsave(flags);
++ serial8250_console_putchar_locked(port, ch);
++ printk_cpu_sync_put_irqrestore(flags);
++}
++
+ /*
+ * Restore serial console when h/w power-off detected
+ */
+@@ -3355,6 +3427,32 @@ static void serial8250_console_restore(struct uart_8250_port *up)
+ serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
+ }
+
++void serial8250_console_write_atomic(struct uart_8250_port *up,
++ const char *s, unsigned int count)
++{
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ unsigned int ier;
++
++ printk_cpu_sync_get_irqsave(flags);
++
++ touch_nmi_watchdog();
++
++ ier = serial8250_clear_IER(up);
++
++ if (atomic_fetch_inc(&up->console_printing)) {
++ uart_console_write(port, "\n", 1,
++ serial8250_console_putchar_locked);
++ }
++ uart_console_write(port, s, count, serial8250_console_putchar_locked);
++ atomic_dec(&up->console_printing);
++
++ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
++ serial8250_set_IER(up, ier);
++
++ printk_cpu_sync_put_irqrestore(flags);
++}
++
+ /*
+ * Print a string to the serial port using the device FIFO
+ *
+@@ -3400,20 +3498,15 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ struct uart_port *port = &up->port;
+ unsigned long flags;
+ unsigned int ier, use_fifo;
+- int locked = 1;
+
+ touch_nmi_watchdog();
+
+- if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
+- else
+- spin_lock_irqsave(&port->lock, flags);
++ spin_lock_irqsave(&port->lock, flags);
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+- ier = serial_port_in(port, UART_IER);
+- serial8250_clear_IER(up);
++ ier = 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))) {
+@@ -3447,10 +3540,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ */
+ !(up->port.flags & UPF_CONS_FLOW);
+
++ atomic_inc(&up->console_printing);
+ if (likely(use_fifo))
+ serial8250_console_fifo_write(up, s, count);
+ else
+ uart_console_write(port, s, count, serial8250_console_putchar);
++ atomic_dec(&up->console_printing);
+
+ /*
+ * Finally, wait for transmitter to become empty
+@@ -3463,8 +3558,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ if (em485->tx_stopped)
+ up->rs485_stop_tx(up);
+ }
+-
+- serial_port_out(port, UART_IER, ier);
++ serial8250_set_IER(up, ier);
+
+ /*
+ * The receive handling will happen properly because the
+@@ -3476,8 +3570,7 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ if (up->msr_saved_flags)
+ serial8250_modem_status(up);
+
+- if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ static unsigned int probe_baud(struct uart_port *port)
+@@ -3497,6 +3590,7 @@ static unsigned int probe_baud(struct uart_port *port)
+
+ 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';
+@@ -3506,6 +3600,8 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
+ if (!port->iobase && !port->membase)
+ return -ENODEV;
+
++ atomic_set(&up->console_printing, 0);
++
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else if (probe)
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+index 583a340f9934..1f31320820a6 100644
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -9,6 +9,7 @@ config SERIAL_8250
+ depends on !S390
+ select SERIAL_CORE
+ select SERIAL_MCTRL_GPIO if GPIOLIB
++ select HAVE_ATOMIC_CONSOLE
+ help
+ This selects whether you want to include the driver for the standard
+ serial ports. The standard answer is Y. People who might say N
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index 79b328861c5f..35f44352e641 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -7,6 +7,7 @@
+ #ifndef _LINUX_SERIAL_8250_H
+ #define _LINUX_SERIAL_8250_H
+
++#include <linux/atomic.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial_reg.h>
+ #include <linux/platform_device.h>
+@@ -124,6 +125,8 @@ struct uart_8250_port {
+ #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+
++ atomic_t console_printing;
++
+ struct uart_8250_dma *dma;
+ const struct uart_8250_ops *ops;
+
+@@ -179,6 +182,8 @@ void serial8250_init_port(struct uart_8250_port *up);
+ void serial8250_set_defaults(struct uart_8250_port *up);
+ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ unsigned int count);
++void serial8250_console_write_atomic(struct uart_8250_port *up, const char *s,
++ unsigned int count);
+ int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
+ int serial8250_console_exit(struct uart_port *port);
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0022-printk-avoid-preempt_disable-for-PREEMPT_RT.patch b/debian/patches-rt/0022-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
new file mode 100644
index 000000000..ff28f79d9
--- /dev/null
+++ b/debian/patches-rt/0022-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
@@ -0,0 +1,96 @@
+From a549c0dff2a1a3b11b40abc969358d8cb367871d Mon Sep 17 00:00:00 2001
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 4 Feb 2022 16:01:17 +0106
+Subject: [PATCH 22/62] printk: avoid preempt_disable() for PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+During non-normal operation, printk() calls will attempt to
+write the messages directly to the consoles. This involves
+using console_trylock() to acquire @console_sem.
+
+Preemption is disabled while directly printing to the consoles
+in order to ensure that the printing task is not scheduled away
+while holding @console_sem, thus blocking all other printers
+and causing delays in printing.
+
+Commit fd5f7cde1b85 ("printk: Never set console_may_schedule in
+console_trylock()") specifically reverted a previous attempt at
+allowing preemption while printing.
+
+However, on PREEMPT_RT systems, disabling preemption while
+printing is not allowed because console drivers typically
+acquire a spin lock (which under PREEMPT_RT is an rtmutex).
+Since direct printing is only used during early boot and
+non-panic dumps, the risks of delayed print output for these
+scenarios will be accepted under PREEMPT_RT.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 73b1727087c7..3d0ff49cca29 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -1981,6 +1981,7 @@ static int console_lock_spinning_disable_and_check(void)
+ return 1;
+ }
+
++#if !IS_ENABLED(CONFIG_PREEMPT_RT)
+ /**
+ * console_trylock_spinning - try to get console_lock by busy waiting
+ *
+@@ -2054,6 +2055,7 @@ static int console_trylock_spinning(void)
+
+ return 1;
+ }
++#endif /* CONFIG_PREEMPT_RT */
+
+ /*
+ * Call the specified console driver, asking it to write out the specified
+@@ -2393,6 +2395,18 @@ asmlinkage int vprintk_emit(int facility, int level,
+
+ /* If called from the scheduler, we can not call up(). */
+ if (!in_sched && allow_direct_printing()) {
++#if IS_ENABLED(CONFIG_PREEMPT_RT)
++ /*
++ * Use the non-spinning trylock since PREEMPT_RT does not
++ * support console lock handovers.
++ *
++ * Direct printing will most likely involve taking spinlocks.
++ * For PREEMPT_RT, this is only allowed if in a preemptible
++ * context.
++ */
++ if (preemptible() && console_trylock())
++ console_unlock();
++#else
+ /*
+ * The caller may be holding system-critical or
+ * timing-sensitive locks. Disable preemption during direct
+@@ -2410,6 +2424,7 @@ asmlinkage int vprintk_emit(int facility, int level,
+ if (console_trylock_spinning())
+ console_unlock();
+ preempt_enable();
++#endif
+ }
+
+ if (in_sched)
+@@ -3119,8 +3134,12 @@ static bool console_emit_next_record_transferable(struct console *con, char *tex
+ /*
+ * Handovers are only supported if threaded printers are atomically
+ * blocked. The context taking over the console_lock may be atomic.
++ *
++ * PREEMPT_RT also does not support handovers because the spinning
++ * waiter can cause large latencies.
+ */
+- if (!console_kthreads_atomically_blocked()) {
++ if (!console_kthreads_atomically_blocked() ||
++ IS_ENABLED(CONFIG_PREEMPT_RT)) {
+ *handover = false;
+ handover = NULL;
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0023-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch b/debian/patches-rt/0023-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
new file mode 100644
index 000000000..dcee3a6dc
--- /dev/null
+++ b/debian/patches-rt/0023-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
@@ -0,0 +1,62 @@
+From f99a0874dccc1ba9f9ead4473ba09603d10946b4 Mon Sep 17 00:00:00 2001
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Sat, 27 Feb 2016 08:09:11 +0100
+Subject: [PATCH 23/62] drm/i915: Use preempt_disable/enable_rt() where
+ recommended
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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/i915_irq.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
+index f93ffa6626a5..6e9d033cf808 100644
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -917,7 +917,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,
+ */
+ 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)
+@@ -981,7 +982,8 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc,
+ 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);
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0024-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch b/debian/patches-rt/0024-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
new file mode 100644
index 000000000..c05066850
--- /dev/null
+++ b/debian/patches-rt/0024-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
@@ -0,0 +1,91 @@
+From 7540de1a42a1a7409b4367b67c76480f7e96d25b Mon Sep 17 00:00:00 2001
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Sat, 27 Feb 2016 09:01:42 +0100
+Subject: [PATCH 24/62] drm/i915: Don't disable interrupts on PREEMPT_RT during
+ atomic updates
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
+index 6792a9056f46..43cedfef104f 100644
+--- a/drivers/gpu/drm/i915/display/intel_crtc.c
++++ b/drivers/gpu/drm/i915/display/intel_crtc.c
+@@ -521,7 +521,8 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
+ */
+ 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;
+@@ -546,11 +547,13 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
+ 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);
+@@ -583,7 +586,8 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state)
+ return;
+
+ irq_disable:
+- local_irq_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_disable();
+ }
+
+ #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE)
+@@ -684,7 +688,8 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
+ */
+ intel_vrr_send_push(new_crtc_state);
+
+- local_irq_enable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ local_irq_enable();
+
+ if (intel_vgpu_active(dev_priv))
+ return;
+--
+2.43.0
+
diff --git a/debian/patches-rt/0025-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch b/debian/patches-rt/0025-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
new file mode 100644
index 000000000..2bbcdfed9
--- /dev/null
+++ b/debian/patches-rt/0025-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
@@ -0,0 +1,36 @@
+From d9970290d810087f44a37de7ae6f3638ecddd3a0 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 25 Oct 2021 15:05:18 +0200
+Subject: [PATCH 25/62] drm/i915: Don't check for atomic context on PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
+index 6c14d13364bf..de58855e6926 100644
+--- a/drivers/gpu/drm/i915/i915_utils.h
++++ b/drivers/gpu/drm/i915/i915_utils.h
+@@ -294,7 +294,7 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
+ #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)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0026-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch b/debian/patches-rt/0026-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch
new file mode 100644
index 000000000..bcd36cace
--- /dev/null
+++ b/debian/patches-rt/0026-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch
@@ -0,0 +1,51 @@
+From 05b1ad300df55e576476a0dee533c90068480372 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 6 Dec 2018 09:52:20 +0100
+Subject: [PATCH 26/62] drm/i915: Disable tracing points on PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(+)
+
+diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
+index 37b5c9e9d260..1434485cb536 100644
+--- 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>
+--
+2.43.0
+
diff --git a/debian/patches-rt/0027-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch b/debian/patches-rt/0027-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch
new file mode 100644
index 000000000..77fa1b420
--- /dev/null
+++ b/debian/patches-rt/0027-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch
@@ -0,0 +1,35 @@
+From 1fcbddeff5b9a56382a6ba0aba49578f8cdf9aa4 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 19 Dec 2018 10:47:02 +0100
+Subject: [PATCH 27/62] drm/i915: skip DRM_I915_LOW_LEVEL_TRACEPOINTS with
+ NOTRACE
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
+index 1434485cb536..73f29d8008f0 100644
+--- a/drivers/gpu/drm/i915/i915_trace.h
++++ b/drivers/gpu/drm/i915/i915_trace.h
+@@ -327,7 +327,7 @@ DEFINE_EVENT(i915_request, i915_request_add,
+ 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)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0028-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch b/debian/patches-rt/0028-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch
new file mode 100644
index 000000000..61bd48e8b
--- /dev/null
+++ b/debian/patches-rt/0028-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch
@@ -0,0 +1,48 @@
+From 6dfc680fe2808eaf10a9feed7e3116df60b6032f Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 8 Sep 2021 17:18:00 +0200
+Subject: [PATCH 28/62] drm/i915/gt: Queue and wait for the irq_work item.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+index ecc990ec1b95..8d04b10681f0 100644
+--- 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 intel_breadcrumbs *b)
+ /* 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);
+ }
+ }
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0029-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch b/debian/patches-rt/0029-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
new file mode 100644
index 000000000..d7696f54a
--- /dev/null
+++ b/debian/patches-rt/0029-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
@@ -0,0 +1,95 @@
+From 6ca6d59038e0a61a7bb4904310525b1df57a2867 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 8 Sep 2021 19:03:41 +0200
+Subject: [PATCH 29/62] 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.1/older/patches-6.1.69-rt21.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>
+---
+ .../drm/i915/gt/intel_execlists_submission.c | 17 +++++------------
+ 1 file changed, 5 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+index f903ee1ce06e..f54059b63ea9 100644
+--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+@@ -1302,7 +1302,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
+ * and context switches) submission.
+ */
+
+- spin_lock(&sched_engine->lock);
++ spin_lock_irq(&sched_engine->lock);
+
+ /*
+ * If the queue is higher priority than the last
+@@ -1402,7 +1402,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
+ * 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;
+ }
+ }
+@@ -1428,7 +1428,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
+
+ 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 */
+ }
+
+@@ -1590,7 +1590,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
+ */
+ 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
+@@ -1616,13 +1616,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
+ }
+ }
+
+-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);
+@@ -2476,7 +2469,7 @@ static void execlists_submission_tasklet(struct tasklet_struct *t)
+ }
+
+ if (!engine->execlists.pending[0]) {
+- execlists_dequeue_irq(engine);
++ execlists_dequeue(engine);
+ start_timeslice(engine);
+ }
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0030-drm-i915-Drop-the-irqs_disabled-check.patch b/debian/patches-rt/0030-drm-i915-Drop-the-irqs_disabled-check.patch
new file mode 100644
index 000000000..4d49e26f7
--- /dev/null
+++ b/debian/patches-rt/0030-drm-i915-Drop-the-irqs_disabled-check.patch
@@ -0,0 +1,45 @@
+From 6779399c1acfc91f6e9b0bd4dc4abb4f3cb30c78 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 1 Oct 2021 20:01:03 +0200
+Subject: [PATCH 30/62] drm/i915: Drop the irqs_disabled() check
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
+index 7ce126a01cbf..64a032dfaa90 100644
+--- 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_request *request)
+
+ 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_request *request)
+ */
+ RQ_TRACE(request, "\n");
+
+- GEM_BUG_ON(!irqs_disabled());
+ lockdep_assert_held(&engine->sched_engine->lock);
+
+ /*
+--
+2.43.0
+
diff --git a/debian/patches-rt/0031-Revert-drm-i915-Depend-on-PREEMPT_RT.patch b/debian/patches-rt/0031-Revert-drm-i915-Depend-on-PREEMPT_RT.patch
new file mode 100644
index 000000000..9ef52335e
--- /dev/null
+++ b/debian/patches-rt/0031-Revert-drm-i915-Depend-on-PREEMPT_RT.patch
@@ -0,0 +1,29 @@
+From fe8c8e1f1ec5c61814ee0c4c90a2cef9d35ecad6 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 21 Feb 2022 17:59:14 +0100
+Subject: [PATCH 31/62] Revert "drm/i915: Depend on !PREEMPT_RT."
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
+index 6b10868ec72f..1fbdb7b4e6e1 100644
+--- 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
+--
+2.43.0
+
diff --git a/debian/patches-rt/0032-sched-Add-support-for-lazy-preemption.patch b/debian/patches-rt/0032-sched-Add-support-for-lazy-preemption.patch
new file mode 100644
index 000000000..54c21bbb9
--- /dev/null
+++ b/debian/patches-rt/0032-sched-Add-support-for-lazy-preemption.patch
@@ -0,0 +1,714 @@
+From 87194c420f8ef3b1a8b9b63ae640180e2414e8c4 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 26 Oct 2012 18:50:54 +0100
+Subject: [PATCH 32/62] sched: Add support for lazy preemption
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+It has become an obsession to mitigate the determinism vs. throughput
+loss of RT. Looking at the mainline semantics of preemption points
+gives a hint why RT sucks throughput wise for ordinary SCHED_OTHER
+tasks. One major issue is the wakeup of tasks which are right away
+preempting the waking task while the waking task holds a lock on which
+the woken task will block right after having preempted the wakee. In
+mainline this is prevented due to the implicit preemption disable of
+spin/rw_lock held regions. On RT this is not possible due to the fully
+preemptible nature of sleeping spinlocks.
+
+Though for a SCHED_OTHER task preempting another SCHED_OTHER task this
+is really not a correctness issue. RT folks are concerned about
+SCHED_FIFO/RR tasks preemption and not about the purely fairness
+driven SCHED_OTHER preemption latencies.
+
+So I introduced a lazy preemption mechanism which only applies to
+SCHED_OTHER tasks preempting another SCHED_OTHER task. Aside of the
+existing preempt_count each tasks sports now a preempt_lazy_count
+which is manipulated on lock acquiry and release. This is slightly
+incorrect as for lazyness reasons I coupled this on
+migrate_disable/enable so some other mechanisms get the same treatment
+(e.g. get_cpu_light).
+
+Now on the scheduler side instead of setting NEED_RESCHED this sets
+NEED_RESCHED_LAZY in case of a SCHED_OTHER/SCHED_OTHER preemption and
+therefor allows to exit the waking task the lock held region before
+the woken task preempts. That also works better for cross CPU wakeups
+as the other side can stay in the adaptive spinning loop.
+
+For RT class preemption there is no change. This simply sets
+NEED_RESCHED and forgoes the lazy preemption counter.
+
+ Initial test do not expose any observable latency increasement, but
+history shows that I've been proven wrong before :)
+
+The lazy preemption mode is per default on, but with
+CONFIG_SCHED_DEBUG enabled it can be disabled via:
+
+ # echo NO_PREEMPT_LAZY >/sys/kernel/debug/sched_features
+
+and reenabled via
+
+ # echo PREEMPT_LAZY >/sys/kernel/debug/sched_features
+
+The test results so far are very machine and workload dependent, but
+there is a clear trend that it enhances the non RT workload
+performance.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ include/linux/preempt.h | 54 ++++++++++++++++++++++--
+ include/linux/sched.h | 37 +++++++++++++++++
+ include/linux/thread_info.h | 12 +++++-
+ include/linux/trace_events.h | 10 ++++-
+ kernel/Kconfig.preempt | 6 +++
+ kernel/sched/core.c | 79 +++++++++++++++++++++++++++++++++++-
+ kernel/sched/fair.c | 16 ++++----
+ kernel/sched/features.h | 3 ++
+ kernel/sched/sched.h | 9 ++++
+ kernel/trace/trace.c | 50 ++++++++++++++---------
+ kernel/trace/trace_events.c | 1 +
+ kernel/trace/trace_output.c | 18 +++++++-
+ 12 files changed, 260 insertions(+), 35 deletions(-)
+
+diff --git a/include/linux/preempt.h b/include/linux/preempt.h
+index 8cfcc5d45451..9fc4c4bb320f 100644
+--- a/include/linux/preempt.h
++++ b/include/linux/preempt.h
+@@ -207,6 +207,20 @@ extern void preempt_count_sub(int val);
+ #define preempt_count_inc() preempt_count_add(1)
+ #define preempt_count_dec() preempt_count_sub(1)
+
++#ifdef CONFIG_PREEMPT_LAZY
++#define add_preempt_lazy_count(val) do { preempt_lazy_count() += (val); } while (0)
++#define sub_preempt_lazy_count(val) do { preempt_lazy_count() -= (val); } while (0)
++#define inc_preempt_lazy_count() add_preempt_lazy_count(1)
++#define dec_preempt_lazy_count() sub_preempt_lazy_count(1)
++#define preempt_lazy_count() (current_thread_info()->preempt_lazy_count)
++#else
++#define add_preempt_lazy_count(val) do { } while (0)
++#define sub_preempt_lazy_count(val) do { } while (0)
++#define inc_preempt_lazy_count() do { } while (0)
++#define dec_preempt_lazy_count() do { } while (0)
++#define preempt_lazy_count() (0)
++#endif
++
+ #ifdef CONFIG_PREEMPT_COUNT
+
+ #define preempt_disable() \
+@@ -215,6 +229,12 @@ do { \
+ barrier(); \
+ } while (0)
+
++#define preempt_lazy_disable() \
++do { \
++ inc_preempt_lazy_count(); \
++ barrier(); \
++} while (0)
++
+ #define sched_preempt_enable_no_resched() \
+ do { \
+ barrier(); \
+@@ -246,6 +266,18 @@ do { \
+ __preempt_schedule(); \
+ } while (0)
+
++/*
++ * open code preempt_check_resched() because it is not exported to modules and
++ * used by local_unlock() or bpf_enable_instrumentation().
++ */
++#define preempt_lazy_enable() \
++do { \
++ dec_preempt_lazy_count(); \
++ barrier(); \
++ if (should_resched(0)) \
++ __preempt_schedule(); \
++} while (0)
++
+ #else /* !CONFIG_PREEMPTION */
+ #define preempt_enable() \
+ do { \
+@@ -253,6 +285,12 @@ do { \
+ preempt_count_dec(); \
+ } while (0)
+
++#define preempt_lazy_enable() \
++do { \
++ dec_preempt_lazy_count(); \
++ barrier(); \
++} while (0)
++
+ #define preempt_enable_notrace() \
+ do { \
+ barrier(); \
+@@ -293,6 +331,9 @@ do { \
+ #define preempt_enable_notrace() barrier()
+ #define preemptible() 0
+
++#define preempt_lazy_disable() barrier()
++#define preempt_lazy_enable() barrier()
++
+ #endif /* CONFIG_PREEMPT_COUNT */
+
+ #ifdef MODULE
+@@ -311,7 +352,7 @@ do { \
+ } while (0)
+ #define preempt_fold_need_resched() \
+ do { \
+- if (tif_need_resched()) \
++ if (tif_need_resched_now()) \
+ set_preempt_need_resched(); \
+ } while (0)
+
+@@ -427,8 +468,15 @@ extern void migrate_enable(void);
+
+ #else
+
+-static inline void migrate_disable(void) { }
+-static inline void migrate_enable(void) { }
++static inline void migrate_disable(void)
++{
++ preempt_lazy_disable();
++}
++
++static inline void migrate_enable(void)
++{
++ preempt_lazy_enable();
++}
+
+ #endif /* CONFIG_SMP */
+
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 0cac69902ec5..67ec36dbfacf 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2061,6 +2061,43 @@ static inline int test_tsk_need_resched(struct task_struct *tsk)
+ return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED));
+ }
+
++#ifdef CONFIG_PREEMPT_LAZY
++static inline void set_tsk_need_resched_lazy(struct task_struct *tsk)
++{
++ set_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY);
++}
++
++static inline void clear_tsk_need_resched_lazy(struct task_struct *tsk)
++{
++ clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY);
++}
++
++static inline int test_tsk_need_resched_lazy(struct task_struct *tsk)
++{
++ return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED_LAZY));
++}
++
++static inline int need_resched_lazy(void)
++{
++ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
++}
++
++static inline int need_resched_now(void)
++{
++ return test_thread_flag(TIF_NEED_RESCHED);
++}
++
++#else
++static inline void clear_tsk_need_resched_lazy(struct task_struct *tsk) { }
++static inline int need_resched_lazy(void) { return 0; }
++
++static inline int need_resched_now(void)
++{
++ return test_thread_flag(TIF_NEED_RESCHED);
++}
++
++#endif
++
+ /*
+ * cond_resched() and cond_resched_lock(): latency reduction via
+ * explicit rescheduling in places that are safe. The return
+diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
+index 9f392ec76f2b..779e0e96b9cb 100644
+--- a/include/linux/thread_info.h
++++ b/include/linux/thread_info.h
+@@ -177,7 +177,17 @@ static __always_inline unsigned long read_ti_thread_flags(struct thread_info *ti
+ clear_ti_thread_flag(task_thread_info(t), TIF_##fl)
+ #endif /* !CONFIG_GENERIC_ENTRY */
+
+-#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
++#ifdef CONFIG_PREEMPT_LAZY
++#define tif_need_resched() (test_thread_flag(TIF_NEED_RESCHED) || \
++ test_thread_flag(TIF_NEED_RESCHED_LAZY))
++#define tif_need_resched_now() (test_thread_flag(TIF_NEED_RESCHED))
++#define tif_need_resched_lazy() test_thread_flag(TIF_NEED_RESCHED_LAZY)
++
++#else
++#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
++#define tif_need_resched_now() test_thread_flag(TIF_NEED_RESCHED)
++#define tif_need_resched_lazy() 0
++#endif
+
+ #ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
+ static inline int arch_within_stack_frames(const void * const stack,
+diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
+index c8b5e9781d01..743b1183d184 100644
+--- a/include/linux/trace_events.h
++++ b/include/linux/trace_events.h
+@@ -70,6 +70,7 @@ struct trace_entry {
+ unsigned char flags;
+ unsigned char preempt_count;
+ int pid;
++ unsigned char preempt_lazy_count;
+ };
+
+ #define TRACE_EVENT_TYPE_MAX \
+@@ -159,9 +160,10 @@ static inline void tracing_generic_entry_update(struct trace_entry *entry,
+ unsigned int trace_ctx)
+ {
+ entry->preempt_count = trace_ctx & 0xff;
++ entry->preempt_lazy_count = (trace_ctx >> 16) & 0xff;
+ entry->pid = current->pid;
+ entry->type = type;
+- entry->flags = trace_ctx >> 16;
++ entry->flags = trace_ctx >> 24;
+ }
+
+ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status);
+@@ -172,7 +174,13 @@ enum trace_flag_type {
+ TRACE_FLAG_NEED_RESCHED = 0x04,
+ TRACE_FLAG_HARDIRQ = 0x08,
+ TRACE_FLAG_SOFTIRQ = 0x10,
++#ifdef CONFIG_PREEMPT_LAZY
++ TRACE_FLAG_PREEMPT_RESCHED = 0x00,
++ TRACE_FLAG_NEED_RESCHED_LAZY = 0x20,
++#else
++ TRACE_FLAG_NEED_RESCHED_LAZY = 0x00,
+ TRACE_FLAG_PREEMPT_RESCHED = 0x20,
++#endif
+ TRACE_FLAG_NMI = 0x40,
+ TRACE_FLAG_BH_OFF = 0x80,
+ };
+diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
+index c2f1fd95a821..260c08efeb48 100644
+--- a/kernel/Kconfig.preempt
++++ b/kernel/Kconfig.preempt
+@@ -1,5 +1,11 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+
++config HAVE_PREEMPT_LAZY
++ bool
++
++config PREEMPT_LAZY
++ def_bool y if HAVE_PREEMPT_LAZY && PREEMPT_RT
++
+ config PREEMPT_NONE_BUILD
+ bool
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 6bd06122850a..b72fc7d336e4 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -1040,6 +1040,46 @@ void resched_curr(struct rq *rq)
+ trace_sched_wake_idle_without_ipi(cpu);
+ }
+
++#ifdef CONFIG_PREEMPT_LAZY
++
++static int tsk_is_polling(struct task_struct *p)
++{
++#ifdef TIF_POLLING_NRFLAG
++ return test_tsk_thread_flag(p, TIF_POLLING_NRFLAG);
++#else
++ return 0;
++#endif
++}
++
++void resched_curr_lazy(struct rq *rq)
++{
++ struct task_struct *curr = rq->curr;
++ int cpu;
++
++ if (!sched_feat(PREEMPT_LAZY)) {
++ resched_curr(rq);
++ return;
++ }
++
++ if (test_tsk_need_resched(curr))
++ return;
++
++ if (test_tsk_need_resched_lazy(curr))
++ return;
++
++ set_tsk_need_resched_lazy(curr);
++
++ cpu = cpu_of(rq);
++ if (cpu == smp_processor_id())
++ return;
++
++ /* NEED_RESCHED_LAZY must be visible before we test polling */
++ smp_mb();
++ if (!tsk_is_polling(curr))
++ smp_send_reschedule(cpu);
++}
++#endif
++
+ void resched_cpu(int cpu)
+ {
+ struct rq *rq = cpu_rq(cpu);
+@@ -2224,6 +2264,7 @@ void migrate_disable(void)
+ preempt_disable();
+ this_rq()->nr_pinned++;
+ p->migration_disabled = 1;
++ preempt_lazy_disable();
+ preempt_enable();
+ }
+ EXPORT_SYMBOL_GPL(migrate_disable);
+@@ -2255,6 +2296,7 @@ void migrate_enable(void)
+ barrier();
+ p->migration_disabled = 0;
+ this_rq()->nr_pinned--;
++ preempt_lazy_enable();
+ preempt_enable();
+ }
+ EXPORT_SYMBOL_GPL(migrate_enable);
+@@ -4722,6 +4764,9 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
+ p->on_cpu = 0;
+ #endif
+ init_task_preempt_count(p);
++#ifdef CONFIG_HAVE_PREEMPT_LAZY
++ task_thread_info(p)->preempt_lazy_count = 0;
++#endif
+ #ifdef CONFIG_SMP
+ plist_node_init(&p->pushable_tasks, MAX_PRIO);
+ RB_CLEAR_NODE(&p->pushable_dl_tasks);
+@@ -6592,6 +6637,7 @@ static void __sched notrace __schedule(unsigned int sched_mode)
+
+ next = pick_next_task(rq, prev, &rf);
+ clear_tsk_need_resched(prev);
++ clear_tsk_need_resched_lazy(prev);
+ clear_preempt_need_resched();
+ #ifdef CONFIG_SCHED_DEBUG
+ rq->last_seen_need_resched_ns = 0;
+@@ -6806,6 +6852,30 @@ static void __sched notrace preempt_schedule_common(void)
+ } while (need_resched());
+ }
+
++#ifdef CONFIG_PREEMPT_LAZY
++/*
++ * If TIF_NEED_RESCHED is then we allow to be scheduled away since this is
++ * set by a RT task. Oterwise we try to avoid beeing scheduled out as long as
++ * preempt_lazy_count counter >0.
++ */
++static __always_inline int preemptible_lazy(void)
++{
++ if (test_thread_flag(TIF_NEED_RESCHED))
++ return 1;
++ if (current_thread_info()->preempt_lazy_count)
++ return 0;
++ return 1;
++}
++
++#else
++
++static inline int preemptible_lazy(void)
++{
++ return 1;
++}
++
++#endif
++
+ #ifdef CONFIG_PREEMPTION
+ /*
+ * This is the entry point to schedule() from in-kernel preemption
+@@ -6819,6 +6889,8 @@ asmlinkage __visible void __sched notrace preempt_schedule(void)
+ */
+ if (likely(!preemptible()))
+ return;
++ if (!preemptible_lazy())
++ return;
+ preempt_schedule_common();
+ }
+ NOKPROBE_SYMBOL(preempt_schedule);
+@@ -6866,6 +6938,9 @@ asmlinkage __visible void __sched notrace preempt_schedule_notrace(void)
+ if (likely(!preemptible()))
+ return;
+
++ if (!preemptible_lazy())
++ return;
++
+ do {
+ /*
+ * Because the function tracer can trace preempt_count_sub()
+@@ -9131,7 +9206,9 @@ void __init init_idle(struct task_struct *idle, int cpu)
+
+ /* Set the preempt count _outside_ the spinlocks! */
+ init_idle_preempt_count(idle, cpu);
+-
++#ifdef CONFIG_HAVE_PREEMPT_LAZY
++ task_thread_info(idle)->preempt_lazy_count = 0;
++#endif
+ /*
+ * The idle tasks have their own, simple scheduling class:
+ */
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 2558ab9033be..2dc35af7b5a6 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -4914,7 +4914,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
+ ideal_runtime = sched_slice(cfs_rq, curr);
+ delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
+ if (delta_exec > ideal_runtime) {
+- resched_curr(rq_of(cfs_rq));
++ resched_curr_lazy(rq_of(cfs_rq));
+ /*
+ * The current task ran long enough, ensure it doesn't get
+ * re-elected due to buddy favours.
+@@ -4938,7 +4938,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
+ return;
+
+ if (delta > ideal_runtime)
+- resched_curr(rq_of(cfs_rq));
++ resched_curr_lazy(rq_of(cfs_rq));
+ }
+
+ static void
+@@ -5084,7 +5084,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
+ * validating it and just reschedule.
+ */
+ if (queued) {
+- resched_curr(rq_of(cfs_rq));
++ resched_curr_lazy(rq_of(cfs_rq));
+ return;
+ }
+ /*
+@@ -5233,7 +5233,7 @@ static void __account_cfs_rq_runtime(struct cfs_rq *cfs_rq, u64 delta_exec)
+ * 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
+@@ -5984,7 +5984,7 @@ static void hrtick_start_fair(struct rq *rq, struct task_struct *p)
+
+ if (delta < 0) {
+ if (task_current(rq, p))
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ return;
+ }
+ hrtick_start(rq, delta);
+@@ -7712,7 +7712,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
+ return;
+
+ preempt:
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ /*
+ * Only set the backward buddy when the current task is still
+ * on the rq. This can happen when a wakeup gets interleaved
+@@ -11877,7 +11877,7 @@ static void task_fork_fair(struct task_struct *p)
+ * 'current' within the tree based on its new key value.
+ */
+ swap(curr->vruntime, se->vruntime);
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ }
+
+ se->vruntime -= cfs_rq->min_vruntime;
+@@ -11904,7 +11904,7 @@ prio_changed_fair(struct rq *rq, struct task_struct *p, int oldprio)
+ */
+ if (task_current(rq, p)) {
+ if (p->prio > oldprio)
+- resched_curr(rq);
++ resched_curr_lazy(rq);
+ } else
+ check_preempt_curr(rq, p, 0);
+ }
+diff --git a/kernel/sched/features.h b/kernel/sched/features.h
+index ee7f23c76bd3..e13090e33f3c 100644
+--- a/kernel/sched/features.h
++++ b/kernel/sched/features.h
+@@ -48,6 +48,9 @@ SCHED_FEAT(NONTASK_CAPACITY, true)
+
+ #ifdef CONFIG_PREEMPT_RT
+ SCHED_FEAT(TTWU_QUEUE, false)
++# ifdef CONFIG_PREEMPT_LAZY
++SCHED_FEAT(PREEMPT_LAZY, true)
++# endif
+ #else
+
+ /*
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index b62d53d7c264..f2577f511a41 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -2350,6 +2350,15 @@ extern void reweight_task(struct task_struct *p, int prio);
+ extern void resched_curr(struct rq *rq);
+ extern void resched_cpu(int cpu);
+
++#ifdef CONFIG_PREEMPT_LAZY
++extern void resched_curr_lazy(struct rq *rq);
++#else
++static inline void resched_curr_lazy(struct rq *rq)
++{
++ resched_curr(rq);
++}
++#endif
++
+ extern struct rt_bandwidth def_rt_bandwidth;
+ extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
+ extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 87eca95b57fb..462564d652be 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -2616,11 +2616,19 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status)
+ if (softirq_count() >> (SOFTIRQ_SHIFT + 1))
+ trace_flags |= TRACE_FLAG_BH_OFF;
+
+- if (tif_need_resched())
++ if (tif_need_resched_now())
+ trace_flags |= TRACE_FLAG_NEED_RESCHED;
++#ifdef CONFIG_PREEMPT_LAZY
++ /* Run out of bits. Share the LAZY and PREEMPT_RESCHED */
++ if (need_resched_lazy())
++ trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY;
++#else
+ if (test_preempt_need_resched())
+ trace_flags |= TRACE_FLAG_PREEMPT_RESCHED;
+- return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) |
++#endif
++
++ return (trace_flags << 24) | (min_t(unsigned int, pc & 0xff, 0xf)) |
++ (preempt_lazy_count() & 0xff) << 16 |
+ (min_t(unsigned int, migration_disable_value(), 0xf)) << 4;
+ }
+
+@@ -4212,15 +4220,17 @@ unsigned long trace_total_entries(struct trace_array *tr)
+
+ static void print_lat_help_header(struct seq_file *m)
+ {
+- seq_puts(m, "# _------=> CPU# \n"
+- "# / _-----=> irqs-off/BH-disabled\n"
+- "# | / _----=> need-resched \n"
+- "# || / _---=> hardirq/softirq \n"
+- "# ||| / _--=> preempt-depth \n"
+- "# |||| / _-=> migrate-disable \n"
+- "# ||||| / delay \n"
+- "# cmd pid |||||| time | caller \n"
+- "# \\ / |||||| \\ | / \n");
++ seq_puts(m, "# _--------=> CPU# \n"
++ "# / _-------=> irqs-off/BH-disabled\n"
++ "# | / _------=> need-resched \n"
++ "# || / _-----=> need-resched-lazy\n"
++ "# ||| / _----=> hardirq/softirq \n"
++ "# |||| / _---=> preempt-depth \n"
++ "# ||||| / _--=> preempt-lazy-depth\n"
++ "# |||||| / _-=> migrate-disable \n"
++ "# ||||||| / delay \n"
++ "# cmd pid |||||||| time | caller \n"
++ "# \\ / |||||||| \\ | / \n");
+ }
+
+ static void print_event_info(struct array_buffer *buf, struct seq_file *m)
+@@ -4254,14 +4264,16 @@ static void print_func_help_header_irq(struct array_buffer *buf, struct seq_file
+
+ print_event_info(buf, m);
+
+- seq_printf(m, "# %.*s _-----=> irqs-off/BH-disabled\n", prec, space);
+- seq_printf(m, "# %.*s / _----=> need-resched\n", prec, space);
+- seq_printf(m, "# %.*s| / _---=> hardirq/softirq\n", prec, space);
+- seq_printf(m, "# %.*s|| / _--=> preempt-depth\n", prec, space);
+- seq_printf(m, "# %.*s||| / _-=> migrate-disable\n", prec, space);
+- seq_printf(m, "# %.*s|||| / delay\n", prec, space);
+- seq_printf(m, "# TASK-PID %.*s CPU# ||||| TIMESTAMP FUNCTION\n", prec, " TGID ");
+- seq_printf(m, "# | | %.*s | ||||| | |\n", prec, " | ");
++ seq_printf(m, "# %.*s _-------=> irqs-off/BH-disabled\n", prec, space);
++ seq_printf(m, "# %.*s / _------=> need-resched\n", prec, space);
++ seq_printf(m, "# %.*s| / _-----=> need-resched-lazy\n", prec, space);
++ seq_printf(m, "# %.*s|| / _----=> hardirq/softirq\n", prec, space);
++ seq_printf(m, "# %.*s||| / _---=> preempt-depth\n", prec, space);
++ seq_printf(m, "# %.*s|||| / _--=> preempt-lazy-depth\n", prec, space);
++ seq_printf(m, "# %.*s||||| / _-=> migrate-disable\n", prec, space);
++ seq_printf(m, "# %.*s|||||| / delay\n", prec, space);
++ seq_printf(m, "# TASK-PID %.*s CPU# ||||||| TIMESTAMP FUNCTION\n", prec, " TGID ");
++ seq_printf(m, "# | | %.*s | ||||||| | |\n", prec, " | ");
+ }
+
+ void
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index a6d2f99f847d..493c3f9cf01a 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -208,6 +208,7 @@ static int trace_define_common_fields(void)
+ /* Holds both preempt_count and migrate_disable */
+ __common_field(unsigned char, preempt_count);
+ __common_field(int, pid);
++ __common_field(unsigned char, preempt_lazy_count);
+
+ return ret;
+ }
+diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
+index 5cd4fb656306..3c227e2843ae 100644
+--- a/kernel/trace/trace_output.c
++++ b/kernel/trace/trace_output.c
+@@ -442,6 +442,7 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
+ {
+ char hardsoft_irq;
+ char need_resched;
++ char need_resched_lazy;
+ char irqs_off;
+ int hardirq;
+ int softirq;
+@@ -462,20 +463,27 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
+
+ switch (entry->flags & (TRACE_FLAG_NEED_RESCHED |
+ TRACE_FLAG_PREEMPT_RESCHED)) {
++#ifndef CONFIG_PREEMPT_LAZY
+ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
+ need_resched = 'N';
+ break;
++#endif
+ case TRACE_FLAG_NEED_RESCHED:
+ need_resched = 'n';
+ break;
++#ifndef CONFIG_PREEMPT_LAZY
+ case TRACE_FLAG_PREEMPT_RESCHED:
+ need_resched = 'p';
+ break;
++#endif
+ default:
+ need_resched = '.';
+ break;
+ }
+
++ need_resched_lazy =
++ (entry->flags & TRACE_FLAG_NEED_RESCHED_LAZY) ? 'L' : '.';
++
+ hardsoft_irq =
+ (nmi && hardirq) ? 'Z' :
+ nmi ? 'z' :
+@@ -484,14 +492,20 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
+ softirq ? 's' :
+ '.' ;
+
+- trace_seq_printf(s, "%c%c%c",
+- irqs_off, need_resched, hardsoft_irq);
++ trace_seq_printf(s, "%c%c%c%c",
++ irqs_off, need_resched, need_resched_lazy,
++ hardsoft_irq);
+
+ if (entry->preempt_count & 0xf)
+ trace_seq_printf(s, "%x", entry->preempt_count & 0xf);
+ else
+ trace_seq_putc(s, '.');
+
++ if (entry->preempt_lazy_count)
++ trace_seq_printf(s, "%x", entry->preempt_lazy_count);
++ else
++ trace_seq_putc(s, '.');
++
+ if (entry->preempt_count & 0xf0)
+ trace_seq_printf(s, "%x", entry->preempt_count >> 4);
+ else
+--
+2.43.0
+
diff --git a/debian/patches-rt/0033-x86-entry-Use-should_resched-in-idtentry_exit_cond_r.patch b/debian/patches-rt/0033-x86-entry-Use-should_resched-in-idtentry_exit_cond_r.patch
new file mode 100644
index 000000000..69ddd41b3
--- /dev/null
+++ b/debian/patches-rt/0033-x86-entry-Use-should_resched-in-idtentry_exit_cond_r.patch
@@ -0,0 +1,36 @@
+From 37719a07083b68dad1449227e9fe66e8e6c9f2b6 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 30 Jun 2020 11:45:14 +0200
+Subject: [PATCH 33/62] x86/entry: Use should_resched() in
+ idtentry_exit_cond_resched()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+The TIF_NEED_RESCHED bit is inlined on x86 into the preemption counter.
+By using should_resched(0) instead of need_resched() the same check can
+be performed which uses the same variable as 'preempt_count()` which was
+issued before.
+
+Use should_resched(0) instead need_resched().
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ kernel/entry/common.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/entry/common.c b/kernel/entry/common.c
+index be61332c66b5..97ff5faad4fb 100644
+--- a/kernel/entry/common.c
++++ b/kernel/entry/common.c
+@@ -386,7 +386,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 (should_resched(0))
+ preempt_schedule_irq();
+ }
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0034-x86-Support-for-lazy-preemption.patch b/debian/patches-rt/0034-x86-Support-for-lazy-preemption.patch
new file mode 100644
index 000000000..511fe0a01
--- /dev/null
+++ b/debian/patches-rt/0034-x86-Support-for-lazy-preemption.patch
@@ -0,0 +1,158 @@
+From 65ce5ba8ccb26e6de364e76228e645b2c02b921d Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 1 Nov 2012 11:03:47 +0100
+Subject: [PATCH 34/62] x86: Support for lazy preemption
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Implement the x86 pieces for lazy preempt.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ arch/x86/Kconfig | 1 +
+ arch/x86/include/asm/preempt.h | 33 +++++++++++++++++++++++++++++-
+ arch/x86/include/asm/thread_info.h | 7 +++++++
+ include/linux/entry-common.h | 2 +-
+ kernel/entry/common.c | 2 +-
+ 5 files changed, 42 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index c9bed9c69423..f38bd8a5061e 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -251,6 +251,7 @@ config X86
+ select HAVE_PCI
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
++ select HAVE_PREEMPT_LAZY
+ select MMU_GATHER_RCU_TABLE_FREE if PARAVIRT
+ select MMU_GATHER_MERGE_VMAS
+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK
+diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h
+index 5f6daea1ee24..cd20b4a5719a 100644
+--- a/arch/x86/include/asm/preempt.h
++++ b/arch/x86/include/asm/preempt.h
+@@ -90,17 +90,48 @@ static __always_inline void __preempt_count_sub(int val)
+ * a decrement which hits zero means we have no preempt_count and should
+ * reschedule.
+ */
+-static __always_inline bool __preempt_count_dec_and_test(void)
++static __always_inline bool ____preempt_count_dec_and_test(void)
+ {
+ return GEN_UNARY_RMWcc("decl", __preempt_count, e, __percpu_arg([var]));
+ }
+
++static __always_inline bool __preempt_count_dec_and_test(void)
++{
++ if (____preempt_count_dec_and_test())
++ return true;
++#ifdef CONFIG_PREEMPT_LAZY
++ if (preempt_count())
++ return false;
++ if (current_thread_info()->preempt_lazy_count)
++ return false;
++ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
++#else
++ return false;
++#endif
++}
++
+ /*
+ * Returns true when we need to resched and can (barring IRQ state).
+ */
+ static __always_inline bool should_resched(int preempt_offset)
+ {
++#ifdef CONFIG_PREEMPT_LAZY
++ u32 tmp;
++ tmp = raw_cpu_read_4(__preempt_count);
++ if (tmp == preempt_offset)
++ return true;
++
++ /* preempt count == 0 ? */
++ tmp &= ~PREEMPT_NEED_RESCHED;
++ if (tmp != preempt_offset)
++ return false;
++ /* XXX PREEMPT_LOCK_OFFSET */
++ if (current_thread_info()->preempt_lazy_count)
++ return false;
++ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
++#else
+ return unlikely(raw_cpu_read_4(__preempt_count) == preempt_offset);
++#endif
+ }
+
+ #ifdef CONFIG_PREEMPTION
+diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
+index f0cb881c1d69..0da06a9b5f72 100644
+--- a/arch/x86/include/asm/thread_info.h
++++ b/arch/x86/include/asm/thread_info.h
+@@ -57,6 +57,8 @@ struct thread_info {
+ unsigned long flags; /* low level flags */
+ unsigned long syscall_work; /* SYSCALL_WORK_ flags */
+ u32 status; /* thread synchronous flags */
++ int preempt_lazy_count; /* 0 => lazy preemptable
++ <0 => BUG */
+ #ifdef CONFIG_SMP
+ u32 cpu; /* current CPU */
+ #endif
+@@ -65,6 +67,7 @@ struct thread_info {
+ #define INIT_THREAD_INFO(tsk) \
+ { \
+ .flags = 0, \
++ .preempt_lazy_count = 0, \
+ }
+
+ #else /* !__ASSEMBLY__ */
+@@ -92,6 +95,7 @@ struct thread_info {
+ #define TIF_NOCPUID 15 /* CPUID is not accessible in userland */
+ #define TIF_NOTSC 16 /* TSC is not accessible in userland */
+ #define TIF_NOTIFY_SIGNAL 17 /* signal notifications exist */
++#define TIF_NEED_RESCHED_LAZY 19 /* lazy rescheduling necessary */
+ #define TIF_MEMDIE 20 /* is terminating due to OOM killer */
+ #define TIF_POLLING_NRFLAG 21 /* idle is polling for TIF_NEED_RESCHED */
+ #define TIF_IO_BITMAP 22 /* uses I/O bitmap */
+@@ -115,6 +119,7 @@ struct thread_info {
+ #define _TIF_NOCPUID (1 << TIF_NOCPUID)
+ #define _TIF_NOTSC (1 << TIF_NOTSC)
+ #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
++#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
+ #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
+ #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
+ #define _TIF_SPEC_FORCE_UPDATE (1 << TIF_SPEC_FORCE_UPDATE)
+@@ -146,6 +151,8 @@ struct thread_info {
+
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
+
++#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
++
+ #define STACK_WARN (THREAD_SIZE/8)
+
+ /*
+diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
+index d95ab85f96ba..93cc1ae12125 100644
+--- a/include/linux/entry-common.h
++++ b/include/linux/entry-common.h
+@@ -59,7 +59,7 @@
+
+ #define EXIT_TO_USER_MODE_WORK \
+ (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+- _TIF_NEED_RESCHED | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \
++ _TIF_NEED_RESCHED_MASK | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \
+ ARCH_EXIT_TO_USER_MODE_WORK)
+
+ /**
+diff --git a/kernel/entry/common.c b/kernel/entry/common.c
+index 97ff5faad4fb..c6301e520d47 100644
+--- a/kernel/entry/common.c
++++ b/kernel/entry/common.c
+@@ -155,7 +155,7 @@ static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
+
+ local_irq_enable_exit_to_user(ti_work);
+
+- if (ti_work & _TIF_NEED_RESCHED)
++ if (ti_work & _TIF_NEED_RESCHED_MASK)
+ schedule();
+
+ if (ti_work & _TIF_UPROBE)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0035-entry-Fix-the-preempt-lazy-fallout.patch b/debian/patches-rt/0035-entry-Fix-the-preempt-lazy-fallout.patch
new file mode 100644
index 000000000..27139e9bb
--- /dev/null
+++ b/debian/patches-rt/0035-entry-Fix-the-preempt-lazy-fallout.patch
@@ -0,0 +1,49 @@
+From d37c604152cbded61a8e107918d3b9950725d897 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 13 Jul 2021 07:52:52 +0200
+Subject: [PATCH 35/62] entry: Fix the preempt lazy fallout
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Common code needs common defines....
+
+Fixes: f2f9e496208c ("x86: Support for lazy preemption")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ arch/x86/include/asm/thread_info.h | 2 --
+ include/linux/entry-common.h | 6 ++++++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
+index 0da06a9b5f72..fd8fb76f324f 100644
+--- a/arch/x86/include/asm/thread_info.h
++++ b/arch/x86/include/asm/thread_info.h
+@@ -151,8 +151,6 @@ struct thread_info {
+
+ #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
+
+-#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
+-
+ #define STACK_WARN (THREAD_SIZE/8)
+
+ /*
+diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h
+index 93cc1ae12125..3dc3704a3cdb 100644
+--- a/include/linux/entry-common.h
++++ b/include/linux/entry-common.h
+@@ -57,6 +57,12 @@
+ # define ARCH_EXIT_TO_USER_MODE_WORK (0)
+ #endif
+
++#ifdef CONFIG_PREEMPT_LAZY
++# define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
++#else
++# define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED)
++#endif
++
+ #define EXIT_TO_USER_MODE_WORK \
+ (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+ _TIF_NEED_RESCHED_MASK | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \
+--
+2.43.0
+
diff --git a/debian/patches-rt/0036-arm-Add-support-for-lazy-preemption.patch b/debian/patches-rt/0036-arm-Add-support-for-lazy-preemption.patch
new file mode 100644
index 000000000..8f76d13b0
--- /dev/null
+++ b/debian/patches-rt/0036-arm-Add-support-for-lazy-preemption.patch
@@ -0,0 +1,137 @@
+From f242fbbb3f85d6b9c8c8fc06ddbc83b9ca5a0511 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 31 Oct 2012 12:04:11 +0100
+Subject: [PATCH 36/62] arm: Add support for lazy preemption
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Implement the arm pieces for lazy preempt.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ arch/arm/Kconfig | 1 +
+ arch/arm/include/asm/thread_info.h | 6 +++++-
+ arch/arm/kernel/asm-offsets.c | 1 +
+ arch/arm/kernel/entry-armv.S | 19 ++++++++++++++++---
+ arch/arm/kernel/signal.c | 3 ++-
+ 5 files changed, 25 insertions(+), 5 deletions(-)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 6d5afe2e6ba3..717e596dc13b 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -115,6 +115,7 @@ config ARM
+ select HAVE_PERF_EVENTS
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
++ select HAVE_PREEMPT_LAZY
+ select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
+ select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RSEQ
+diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
+index 7f092cb55a41..ffcbf8ebed4b 100644
+--- a/arch/arm/include/asm/thread_info.h
++++ b/arch/arm/include/asm/thread_info.h
+@@ -62,6 +62,7 @@ struct cpu_context_save {
+ struct thread_info {
+ unsigned long flags; /* low level flags */
+ int preempt_count; /* 0 => preemptable, <0 => bug */
++ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
+ __u32 cpu; /* cpu */
+ __u32 cpu_domain; /* cpu domain */
+ struct cpu_context_save cpu_context; /* cpu context */
+@@ -129,6 +130,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
+ #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
+ #define TIF_UPROBE 3 /* breakpointed or singlestepping */
+ #define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */
++#define TIF_NEED_RESCHED_LAZY 5
+
+ #define TIF_USING_IWMMXT 17
+ #define TIF_MEMDIE 18 /* is terminating due to OOM killer */
+@@ -148,6 +150,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
+ #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
+ #define _TIF_SECCOMP (1 << TIF_SECCOMP)
+ #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
++#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
+ #define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
+
+ /* Checks for any syscall work in entry-common.S */
+@@ -157,7 +160,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
+ /*
+ * Change these and you break ASM code in entry-common.S
+ */
+-#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
++#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \
++ _TIF_SIGPENDING | \
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+ _TIF_NOTIFY_SIGNAL)
+
+diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
+index 2c8d76fd7c66..c3bdec7d2df9 100644
+--- a/arch/arm/kernel/asm-offsets.c
++++ b/arch/arm/kernel/asm-offsets.c
+@@ -43,6 +43,7 @@ int main(void)
+ BLANK();
+ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
++ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count));
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
+ DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
+diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
+index c39303e5c234..cfb4660e9fea 100644
+--- a/arch/arm/kernel/entry-armv.S
++++ b/arch/arm/kernel/entry-armv.S
+@@ -222,11 +222,18 @@ ENDPROC(__dabt_svc)
+
+ #ifdef CONFIG_PREEMPTION
+ ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
+- ldr r0, [tsk, #TI_FLAGS] @ get flags
+ teq r8, #0 @ if preempt count != 0
++ bne 1f @ return from exeption
++ ldr r0, [tsk, #TI_FLAGS] @ get flags
++ tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set
++ blne svc_preempt @ preempt!
++
++ ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
++ teq r8, #0 @ if preempt lazy count != 0
+ movne r0, #0 @ force flags to 0
+- tst r0, #_TIF_NEED_RESCHED
++ tst r0, #_TIF_NEED_RESCHED_LAZY
+ blne svc_preempt
++1:
+ #endif
+
+ svc_exit r5, irq = 1 @ return from exception
+@@ -241,8 +248,14 @@ ENDPROC(__irq_svc)
+ 1: bl preempt_schedule_irq @ irq en/disable is done inside
+ ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
+ tst r0, #_TIF_NEED_RESCHED
++ bne 1b
++ tst r0, #_TIF_NEED_RESCHED_LAZY
+ reteq r8 @ go again
+- b 1b
++ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
++ teq r0, #0 @ if preempt lazy count != 0
++ beq 1b
++ ret r8 @ go again
++
+ #endif
+
+ __und_fault:
+diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
+index e07f359254c3..b50a3248e79f 100644
+--- a/arch/arm/kernel/signal.c
++++ b/arch/arm/kernel/signal.c
+@@ -607,7 +607,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+ */
+ trace_hardirqs_off();
+ do {
+- if (likely(thread_flags & _TIF_NEED_RESCHED)) {
++ if (likely(thread_flags & (_TIF_NEED_RESCHED |
++ _TIF_NEED_RESCHED_LAZY))) {
+ schedule();
+ } else {
+ if (unlikely(!user_mode(regs)))
+--
+2.43.0
+
diff --git a/debian/patches-rt/0037-powerpc-Add-support-for-lazy-preemption.patch b/debian/patches-rt/0037-powerpc-Add-support-for-lazy-preemption.patch
new file mode 100644
index 000000000..bf8022c6c
--- /dev/null
+++ b/debian/patches-rt/0037-powerpc-Add-support-for-lazy-preemption.patch
@@ -0,0 +1,118 @@
+From 65e31d7b980c1413f19fcb84234387f97b09588f Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 1 Nov 2012 10:14:11 +0100
+Subject: [PATCH 37/62] powerpc: Add support for lazy preemption
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Implement the powerpc pieces for lazy preempt.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ arch/powerpc/Kconfig | 1 +
+ arch/powerpc/include/asm/thread_info.h | 8 ++++++++
+ arch/powerpc/kernel/interrupt.c | 8 ++++++--
+ 3 files changed, 15 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 6050e6e10d32..0eff864d6ec3 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -242,6 +242,7 @@ config PPC
+ select HAVE_PERF_EVENTS_NMI if PPC64
+ select HAVE_PERF_REGS
+ select HAVE_PERF_USER_STACK_DUMP
++ select HAVE_PREEMPT_LAZY
+ select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RELIABLE_STACKTRACE
+ select HAVE_RSEQ
+diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
+index af58f1ed3952..520864de8bb2 100644
+--- a/arch/powerpc/include/asm/thread_info.h
++++ b/arch/powerpc/include/asm/thread_info.h
+@@ -53,6 +53,8 @@
+ struct thread_info {
+ int preempt_count; /* 0 => preemptable,
+ <0 => BUG */
++ int preempt_lazy_count; /* 0 => preemptable,
++ <0 => BUG */
+ #ifdef CONFIG_SMP
+ unsigned int cpu;
+ #endif
+@@ -77,6 +79,7 @@ struct thread_info {
+ #define INIT_THREAD_INFO(tsk) \
+ { \
+ .preempt_count = INIT_PREEMPT_COUNT, \
++ .preempt_lazy_count = 0, \
+ .flags = 0, \
+ }
+
+@@ -102,6 +105,7 @@ void arch_setup_new_exec(void);
+ #define TIF_PATCH_PENDING 6 /* pending live patching update */
+ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
+ #define TIF_SINGLESTEP 8 /* singlestepping active */
++#define TIF_NEED_RESCHED_LAZY 9 /* lazy rescheduling necessary */
+ #define TIF_SECCOMP 10 /* secure computing */
+ #define TIF_RESTOREALL 11 /* Restore all regs (implies NOERROR) */
+ #define TIF_NOERROR 12 /* Force successful syscall return */
+@@ -117,6 +121,7 @@ void arch_setup_new_exec(void);
+ #define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */
+ #define TIF_32BIT 20 /* 32 bit binary */
+
++
+ /* as above, but as bit values */
+ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+ #define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+@@ -128,6 +133,7 @@ void arch_setup_new_exec(void);
+ #define _TIF_PATCH_PENDING (1<<TIF_PATCH_PENDING)
+ #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+ #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
++#define _TIF_NEED_RESCHED_LAZY (1<<TIF_NEED_RESCHED_LAZY)
+ #define _TIF_SECCOMP (1<<TIF_SECCOMP)
+ #define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
+ #define _TIF_NOERROR (1<<TIF_NOERROR)
+@@ -141,10 +147,12 @@ void arch_setup_new_exec(void);
+ _TIF_SYSCALL_EMU)
+
+ #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
++ _TIF_NEED_RESCHED_LAZY | \
+ _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
+ _TIF_RESTORE_TM | _TIF_PATCH_PENDING | \
+ _TIF_NOTIFY_SIGNAL)
+ #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
++#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
+
+ /* Bits in local_flags */
+ /* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
+diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
+index cf770d86c03c..2c454731c250 100644
+--- a/arch/powerpc/kernel/interrupt.c
++++ b/arch/powerpc/kernel/interrupt.c
+@@ -186,7 +186,7 @@ interrupt_exit_user_prepare_main(unsigned long ret, struct pt_regs *regs)
+ ti_flags = read_thread_flags();
+ while (unlikely(ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {
+ local_irq_enable();
+- if (ti_flags & _TIF_NEED_RESCHED) {
++ if (ti_flags & _TIF_NEED_RESCHED_MASK) {
+ schedule();
+ } else {
+ /*
+@@ -397,11 +397,15 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
+ /* Returning to a kernel context with local irqs enabled. */
+ WARN_ON_ONCE(!(regs->msr & MSR_EE));
+ again:
+- if (IS_ENABLED(CONFIG_PREEMPT)) {
++ if (IS_ENABLED(CONFIG_PREEMPTION)) {
+ /* Return to preemptible kernel context */
+ if (unlikely(read_thread_flags() & _TIF_NEED_RESCHED)) {
+ if (preempt_count() == 0)
+ preempt_schedule_irq();
++ } else if (unlikely(current_thread_info()->flags & _TIF_NEED_RESCHED_LAZY)) {
++ if ((preempt_count() == 0) &&
++ (current_thread_info()->preempt_lazy_count == 0))
++ preempt_schedule_irq();
+ }
+ }
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0038-arch-arm64-Add-lazy-preempt-support.patch b/debian/patches-rt/0038-arch-arm64-Add-lazy-preempt-support.patch
new file mode 100644
index 000000000..4df0c8a40
--- /dev/null
+++ b/debian/patches-rt/0038-arch-arm64-Add-lazy-preempt-support.patch
@@ -0,0 +1,146 @@
+From 12a36ad989490f5ae3ed6a50d764385e8e27e024 Mon Sep 17 00:00:00 2001
+From: Anders Roxell <anders.roxell@linaro.org>
+Date: Thu, 14 May 2015 17:52:17 +0200
+Subject: [PATCH 38/62] arch/arm64: Add lazy preempt support
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+arm64 is missing support for PREEMPT_RT. The main feature which is
+lacking is support for lazy preemption. The arch-specific entry code,
+thread information structure definitions, and associated data tables
+have to be extended to provide this support. Then the Kconfig file has
+to be extended to indicate the support is available, and also to
+indicate that support for full RT preemption is now available.
+
+Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ arch/arm64/Kconfig | 1 +
+ arch/arm64/include/asm/preempt.h | 25 ++++++++++++++++++++++++-
+ arch/arm64/include/asm/thread_info.h | 8 +++++++-
+ arch/arm64/kernel/asm-offsets.c | 1 +
+ arch/arm64/kernel/signal.c | 2 +-
+ 5 files changed, 34 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index ea70eb960565..6e16670a7f43 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -199,6 +199,7 @@ config ARM64
+ select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_DYNAMIC_KEY
+ select HAVE_REGS_AND_STACK_ACCESS_API
++ select HAVE_PREEMPT_LAZY
+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK
+ select HAVE_FUNCTION_ARG_ACCESS_API
+ select MMU_GATHER_RCU_TABLE_FREE
+diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h
+index 0159b625cc7f..a5486918e5ee 100644
+--- a/arch/arm64/include/asm/preempt.h
++++ b/arch/arm64/include/asm/preempt.h
+@@ -71,13 +71,36 @@ static inline bool __preempt_count_dec_and_test(void)
+ * interrupt occurring between the non-atomic READ_ONCE/WRITE_ONCE
+ * pair.
+ */
+- return !pc || !READ_ONCE(ti->preempt_count);
++ if (!pc || !READ_ONCE(ti->preempt_count))
++ return true;
++#ifdef CONFIG_PREEMPT_LAZY
++ if ((pc & ~PREEMPT_NEED_RESCHED))
++ return false;
++ if (current_thread_info()->preempt_lazy_count)
++ return false;
++ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
++#else
++ return false;
++#endif
+ }
+
+ static inline bool should_resched(int preempt_offset)
+ {
++#ifdef CONFIG_PREEMPT_LAZY
++ u64 pc = READ_ONCE(current_thread_info()->preempt_count);
++ if (pc == preempt_offset)
++ return true;
++
++ if ((pc & ~PREEMPT_NEED_RESCHED) != preempt_offset)
++ return false;
++
++ if (current_thread_info()->preempt_lazy_count)
++ return false;
++ return test_thread_flag(TIF_NEED_RESCHED_LAZY);
++#else
+ u64 pc = READ_ONCE(current_thread_info()->preempt_count);
+ return pc == preempt_offset;
++#endif
+ }
+
+ #ifdef CONFIG_PREEMPTION
+diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
+index 848739c15de8..4b7148fd5551 100644
+--- a/arch/arm64/include/asm/thread_info.h
++++ b/arch/arm64/include/asm/thread_info.h
+@@ -26,6 +26,7 @@ struct thread_info {
+ #ifdef CONFIG_ARM64_SW_TTBR0_PAN
+ u64 ttbr0; /* saved TTBR0_EL1 */
+ #endif
++ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
+ union {
+ u64 preempt_count; /* 0 => preemptible, <0 => bug */
+ struct {
+@@ -68,6 +69,7 @@ int arch_dup_task_struct(struct task_struct *dst,
+ #define TIF_UPROBE 4 /* uprobe breakpoint or singlestep */
+ #define TIF_MTE_ASYNC_FAULT 5 /* MTE Asynchronous Tag Check Fault */
+ #define TIF_NOTIFY_SIGNAL 6 /* signal notifications exist */
++#define TIF_NEED_RESCHED_LAZY 7
+ #define TIF_SYSCALL_TRACE 8 /* syscall trace active */
+ #define TIF_SYSCALL_AUDIT 9 /* syscall auditing */
+ #define TIF_SYSCALL_TRACEPOINT 10 /* syscall tracepoint for ftrace */
+@@ -100,8 +102,10 @@ int arch_dup_task_struct(struct task_struct *dst,
+ #define _TIF_SVE (1 << TIF_SVE)
+ #define _TIF_MTE_ASYNC_FAULT (1 << TIF_MTE_ASYNC_FAULT)
+ #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
++#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY)
+
+-#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
++#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY | \
++ _TIF_SIGPENDING | \
+ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
+ _TIF_UPROBE | _TIF_MTE_ASYNC_FAULT | \
+ _TIF_NOTIFY_SIGNAL)
+@@ -110,6 +114,8 @@ int arch_dup_task_struct(struct task_struct *dst,
+ _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
+ _TIF_SYSCALL_EMU)
+
++#define _TIF_NEED_RESCHED_MASK (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)
++
+ #ifdef CONFIG_SHADOW_CALL_STACK
+ #define INIT_SCS \
+ .scs_base = init_shadow_call_stack, \
+diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
+index 1197e7679882..e74c0415f67e 100644
+--- a/arch/arm64/kernel/asm-offsets.c
++++ b/arch/arm64/kernel/asm-offsets.c
+@@ -32,6 +32,7 @@ int main(void)
+ DEFINE(TSK_TI_CPU, offsetof(struct task_struct, thread_info.cpu));
+ DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
+ DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count));
++ DEFINE(TSK_TI_PREEMPT_LAZY, offsetof(struct task_struct, thread_info.preempt_lazy_count));
+ #ifdef CONFIG_ARM64_SW_TTBR0_PAN
+ DEFINE(TSK_TI_TTBR0, offsetof(struct task_struct, thread_info.ttbr0));
+ #endif
+diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
+index 82f4572c8ddf..2a606c7bf025 100644
+--- a/arch/arm64/kernel/signal.c
++++ b/arch/arm64/kernel/signal.c
+@@ -1108,7 +1108,7 @@ static void do_signal(struct pt_regs *regs)
+ void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
+ {
+ do {
+- if (thread_flags & _TIF_NEED_RESCHED) {
++ if (thread_flags & _TIF_NEED_RESCHED_MASK) {
+ /* Unmask Debug and SError for the next task */
+ local_daif_restore(DAIF_PROCCTX_NOIRQ);
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0039-arm-Disable-jump-label-on-PREEMPT_RT.patch b/debian/patches-rt/0039-arm-Disable-jump-label-on-PREEMPT_RT.patch
new file mode 100644
index 000000000..ac47159c4
--- /dev/null
+++ b/debian/patches-rt/0039-arm-Disable-jump-label-on-PREEMPT_RT.patch
@@ -0,0 +1,42 @@
+From f1c0950a69e46ee1d45192bfae026622da60bdc8 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 8 Jul 2015 17:14:48 +0200
+Subject: [PATCH 39/62] arm: Disable jump-label on PREEMPT_RT.
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.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(-)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 717e596dc13b..f170f29e98ac 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -71,7 +71,7 @@ config ARM
+ select HARDIRQS_SW_RESEND
+ 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
+--
+2.43.0
+
diff --git a/debian/patches-rt/0040-ARM-enable-irq-in-translation-section-permission-fau.patch b/debian/patches-rt/0040-ARM-enable-irq-in-translation-section-permission-fau.patch
new file mode 100644
index 000000000..ee53f7bd6
--- /dev/null
+++ b/debian/patches-rt/0040-ARM-enable-irq-in-translation-section-permission-fau.patch
@@ -0,0 +1,97 @@
+From 802d6978bf4ebdec28d2ba4e715c2e414d9c7d06 Mon Sep 17 00:00:00 2001
+From: "Yadi.hu" <yadi.hu@windriver.com>
+Date: Wed, 10 Dec 2014 10:32:09 +0800
+Subject: [PATCH 40/62] ARM: enable irq in translation/section permission fault
+ handlers
+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.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
+index b0db85310331..77877dcb54ed 100644
+--- a/arch/arm/mm/fault.c
++++ b/arch/arm/mm/fault.c
+@@ -400,6 +400,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
+ 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;
+
+@@ -470,6 +473,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
+ 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;
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0041-tty-serial-omap-Make-the-locking-RT-aware.patch b/debian/patches-rt/0041-tty-serial-omap-Make-the-locking-RT-aware.patch
new file mode 100644
index 000000000..b719f7f3b
--- /dev/null
+++ b/debian/patches-rt/0041-tty-serial-omap-Make-the-locking-RT-aware.patch
@@ -0,0 +1,49 @@
+From 2a89ee21ea5c408b560839cc06bd0c13580fb3a4 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 28 Jul 2011 13:32:57 +0200
+Subject: [PATCH 41/62] tty/serial/omap: Make the locking RT aware
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(-)
+
+diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
+index 7d0d2718ef59..aa216fdbcb1d 100644
+--- a/drivers/tty/serial/omap-serial.c
++++ b/drivers/tty/serial/omap-serial.c
+@@ -1241,13 +1241,10 @@ serial_omap_console_write(struct console *co, const char *s,
+ unsigned int ier;
+ int locked = 1;
+
+- local_irq_save(flags);
+- if (up->port.sysrq)
+- locked = 0;
+- else if (oops_in_progress)
+- locked = spin_trylock(&up->port.lock);
++ if (up->port.sysrq || oops_in_progress)
++ locked = spin_trylock_irqsave(&up->port.lock, flags);
+ else
+- spin_lock(&up->port.lock);
++ spin_lock_irqsave(&up->port.lock, flags);
+
+ /*
+ * First save the IER then disable the interrupts
+@@ -1274,8 +1271,7 @@ serial_omap_console_write(struct console *co, const char *s,
+ check_modem_status(up);
+
+ if (locked)
+- spin_unlock(&up->port.lock);
+- local_irq_restore(flags);
++ spin_unlock_irqrestore(&up->port.lock, flags);
+ }
+
+ static int __init
+--
+2.43.0
+
diff --git a/debian/patches-rt/0042-tty-serial-pl011-Make-the-locking-work-on-RT.patch b/debian/patches-rt/0042-tty-serial-pl011-Make-the-locking-work-on-RT.patch
new file mode 100644
index 000000000..c80dc32de
--- /dev/null
+++ b/debian/patches-rt/0042-tty-serial-pl011-Make-the-locking-work-on-RT.patch
@@ -0,0 +1,60 @@
+From 1db3dc8a6af68447b52efbbf8dbb4d210d23d57b Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 8 Jan 2013 21:36:51 +0100
+Subject: [PATCH 42/62] tty/serial/pl011: Make the locking work on RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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 | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
+index c74eaf2552c3..38eb30b8491b 100644
+--- a/drivers/tty/serial/amba-pl011.c
++++ b/drivers/tty/serial/amba-pl011.c
+@@ -2316,18 +2316,24 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
+ {
+ struct uart_amba_port *uap = amba_ports[co->index];
+ unsigned int old_cr = 0, new_cr;
+- unsigned long flags;
++ unsigned long flags = 0;
+ int locked = 1;
+
+ clk_enable(uap->clk);
+
+- local_irq_save(flags);
++ /*
++ * local_irq_save(flags);
++ *
++ * This local_irq_save() is nonsense. If we come in via sysrq
++ * handling then interrupts are already disabled. Aside of
++ * that the port.sysrq check is racy on SMP regardless.
++ */
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+- locked = spin_trylock(&uap->port.lock);
++ locked = spin_trylock_irqsave(&uap->port.lock, flags);
+ else
+- spin_lock(&uap->port.lock);
++ spin_lock_irqsave(&uap->port.lock, flags);
+
+ /*
+ * First save the CR then disable the interrupts
+@@ -2353,8 +2359,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
+ pl011_write(old_cr, uap, REG_CR);
+
+ if (locked)
+- spin_unlock(&uap->port.lock);
+- local_irq_restore(flags);
++ spin_unlock_irqrestore(&uap->port.lock, flags);
+
+ clk_disable(uap->clk);
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0043-ARM-Allow-to-enable-RT.patch b/debian/patches-rt/0043-ARM-Allow-to-enable-RT.patch
new file mode 100644
index 000000000..dd5a320a2
--- /dev/null
+++ b/debian/patches-rt/0043-ARM-Allow-to-enable-RT.patch
@@ -0,0 +1,37 @@
+From 47c9956482a592a16b58831ded27e3c0f62ec11d Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 11 Oct 2019 13:14:29 +0200
+Subject: [PATCH 43/62] ARM: Allow to enable RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index f170f29e98ac..d1f2e062ce0b 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -33,6 +33,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
+@@ -115,6 +116,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 HAVE_PREEMPT_LAZY
+ select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
+ select HAVE_REGS_AND_STACK_ACCESS_API
+--
+2.43.0
+
diff --git a/debian/patches-rt/0044-ARM64-Allow-to-enable-RT.patch b/debian/patches-rt/0044-ARM64-Allow-to-enable-RT.patch
new file mode 100644
index 000000000..478d2e7a8
--- /dev/null
+++ b/debian/patches-rt/0044-ARM64-Allow-to-enable-RT.patch
@@ -0,0 +1,29 @@
+From c71e1e0561e008bb2fe230ad7022c3e2483cd6c0 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 11 Oct 2019 13:14:35 +0200
+Subject: [PATCH 44/62] ARM64: Allow to enable RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 6e16670a7f43..0c617e48177c 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -93,6 +93,7 @@ config ARM64
+ select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
+ select ARCH_SUPPORTS_NUMA_BALANCING
+ select ARCH_SUPPORTS_PAGE_TABLE_CHECK
++ select ARCH_SUPPORTS_RT
+ select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
+ select ARCH_WANT_DEFAULT_BPF_JIT
+ select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
+--
+2.43.0
+
diff --git a/debian/patches-rt/0045-powerpc-traps-Use-PREEMPT_RT.patch b/debian/patches-rt/0045-powerpc-traps-Use-PREEMPT_RT.patch
new file mode 100644
index 000000000..76c18de22
--- /dev/null
+++ b/debian/patches-rt/0045-powerpc-traps-Use-PREEMPT_RT.patch
@@ -0,0 +1,40 @@
+From 4d7273bd07600b933e6d25807cd96df04e435cbe Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 26 Jul 2019 11:30:49 +0200
+Subject: [PATCH 45/62] powerpc: traps: Use PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(-)
+
+diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
+index 3956f32682c6..8e15205e51ef 100644
+--- 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" : "",
+--
+2.43.0
+
diff --git a/debian/patches-rt/0046-powerpc-pseries-iommu-Use-a-locallock-instead-local_.patch b/debian/patches-rt/0046-powerpc-pseries-iommu-Use-a-locallock-instead-local_.patch
new file mode 100644
index 000000000..9d6e8ab00
--- /dev/null
+++ b/debian/patches-rt/0046-powerpc-pseries-iommu-Use-a-locallock-instead-local_.patch
@@ -0,0 +1,118 @@
+From 1d20f49e62250211b43cbe18a087fdf19c313081 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 26 Mar 2019 18:31:54 +0100
+Subject: [PATCH 46/62] powerpc/pseries/iommu: Use a locallock instead
+ local_irq_save()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(-)
+
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index 97b026130c71..01b3d19be382 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -24,6 +24,7 @@
+ #include <linux/of.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>
+@@ -200,7 +201,13 @@ static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
+ 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,
+@@ -223,9 +230,10 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+ 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}()
+@@ -234,12 +242,12 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+ 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;
+@@ -269,7 +277,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+ 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;
+@@ -454,16 +462,17 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
+ 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;
+@@ -506,7 +515,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
+
+ /* error cleanup: caller will clear whole range */
+
+- local_irq_enable();
++ local_unlock_irq(&tce_page.lock);
+ return rc;
+ }
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0047-powerpc-kvm-Disable-in-kernel-MPIC-emulation-for-PRE.patch b/debian/patches-rt/0047-powerpc-kvm-Disable-in-kernel-MPIC-emulation-for-PRE.patch
new file mode 100644
index 000000000..937a75d99
--- /dev/null
+++ b/debian/patches-rt/0047-powerpc-kvm-Disable-in-kernel-MPIC-emulation-for-PRE.patch
@@ -0,0 +1,46 @@
+From 34f52991170848510810b486dd6fe9a19cbe4c46 Mon Sep 17 00:00:00 2001
+From: Bogdan Purcareata <bogdan.purcareata@freescale.com>
+Date: Fri, 24 Apr 2015 15:53:13 +0000
+Subject: [PATCH 47/62] powerpc/kvm: Disable in-kernel MPIC emulation for
+ PREEMPT_RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
+index a9f57dad6d91..a0b528d4bb7c 100644
+--- a/arch/powerpc/kvm/Kconfig
++++ b/arch/powerpc/kvm/Kconfig
+@@ -225,6 +225,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
+--
+2.43.0
+
diff --git a/debian/patches-rt/0048-powerpc-stackprotector-work-around-stack-guard-init-.patch b/debian/patches-rt/0048-powerpc-stackprotector-work-around-stack-guard-init-.patch
new file mode 100644
index 000000000..df6dbe080
--- /dev/null
+++ b/debian/patches-rt/0048-powerpc-stackprotector-work-around-stack-guard-init-.patch
@@ -0,0 +1,37 @@
+From d2e9a96e5570459dd886f87bf81c7714fb0a2108 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 26 Mar 2019 18:31:29 +0100
+Subject: [PATCH 48/62] powerpc/stackprotector: work around stack-guard init
+ from atomic
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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 | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
+index 1c8460e23583..b1653c160bab 100644
+--- a/arch/powerpc/include/asm/stackprotector.h
++++ b/arch/powerpc/include/asm/stackprotector.h
+@@ -24,7 +24,11 @@ static __always_inline void boot_init_stack_canary(void)
+ unsigned long canary;
+
+ /* Try to get a semi random initial value. */
++#ifdef CONFIG_PREEMPT_RT
++ canary = (unsigned long)&canary;
++#else
+ canary = get_random_canary();
++#endif
+ canary ^= mftb();
+ canary ^= LINUX_VERSION_CODE;
+ canary &= CANARY_MASK;
+--
+2.43.0
+
diff --git a/debian/patches-rt/0049-POWERPC-Allow-to-enable-RT.patch b/debian/patches-rt/0049-POWERPC-Allow-to-enable-RT.patch
new file mode 100644
index 000000000..72ea26d09
--- /dev/null
+++ b/debian/patches-rt/0049-POWERPC-Allow-to-enable-RT.patch
@@ -0,0 +1,37 @@
+From 93941796079cb4515170adf454f9218adc89856d Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 11 Oct 2019 13:14:41 +0200
+Subject: [PATCH 49/62] POWERPC: Allow to enable RT
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 0eff864d6ec3..df697d3f68cd 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -151,6 +151,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
+@@ -245,6 +246,7 @@ config PPC
+ select HAVE_PREEMPT_LAZY
+ 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
+--
+2.43.0
+
diff --git a/debian/patches-rt/0050-sysfs-Add-sys-kernel-realtime-entry.patch b/debian/patches-rt/0050-sysfs-Add-sys-kernel-realtime-entry.patch
new file mode 100644
index 000000000..bebe5bd1b
--- /dev/null
+++ b/debian/patches-rt/0050-sysfs-Add-sys-kernel-realtime-entry.patch
@@ -0,0 +1,55 @@
+From b2103f830327ab5d1e6f49134c22d3c5adfb52cc Mon Sep 17 00:00:00 2001
+From: Clark Williams <williams@redhat.com>
+Date: Sat, 30 Jul 2011 21:55:53 -0500
+Subject: [PATCH 50/62] sysfs: Add /sys/kernel/realtime entry
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+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(+)
+
+diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
+index 65dba9076f31..ab18048e2186 100644
+--- a/kernel/ksysfs.c
++++ b/kernel/ksysfs.c
+@@ -142,6 +142,15 @@ KERNEL_ATTR_RO(vmcoreinfo);
+
+ #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)
+@@ -232,6 +241,9 @@ static struct attribute * kernel_attrs[] = {
+ #ifndef CONFIG_TINY_RCU
+ &rcu_expedited_attr.attr,
+ &rcu_normal_attr.attr,
++#endif
++#ifdef CONFIG_PREEMPT_RT
++ &realtime_attr.attr,
+ #endif
+ NULL
+ };
+--
+2.43.0
+
diff --git a/debian/patches-rt/0051-Add-localversion-for-RT-release.patch b/debian/patches-rt/0051-Add-localversion-for-RT-release.patch
new file mode 100644
index 000000000..f2ecbea44
--- /dev/null
+++ b/debian/patches-rt/0051-Add-localversion-for-RT-release.patch
@@ -0,0 +1,22 @@
+From 9c7d6e723acbbc184d1dd04811863378699134fb Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 8 Jul 2011 20:25:16 +0200
+Subject: [PATCH 51/62] Add localversion for -RT release
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+---
+ localversion-rt | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 localversion-rt
+
+diff --git a/localversion-rt b/localversion-rt
+new file mode 100644
+index 000000000000..045478966e9f
+--- /dev/null
++++ b/localversion-rt
+@@ -0,0 +1 @@
++-rt7
+--
+2.43.0
+
diff --git a/debian/patches-rt/0052-Linux-6.1.46-rt13-REBASE.patch b/debian/patches-rt/0052-Linux-6.1.46-rt13-REBASE.patch
new file mode 100644
index 000000000..3096368f3
--- /dev/null
+++ b/debian/patches-rt/0052-Linux-6.1.46-rt13-REBASE.patch
@@ -0,0 +1,21 @@
+From 3f783498b292a814f8f364bbfd0efbfc1be6d30f Mon Sep 17 00:00:00 2001
+From: Clark Williams <clrkwllms@kernel.org>
+Date: Fri, 18 Aug 2023 10:45:35 -0500
+Subject: [PATCH 52/62] 'Linux 6.1.46-rt13 REBASE'
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Signed-off-by: Clark Williams <clrkwllms@kernel.org>
+---
+ localversion-rt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/localversion-rt b/localversion-rt
+index 045478966e9f..9f7d0bdbffb1 100644
+--- a/localversion-rt
++++ b/localversion-rt
+@@ -1 +1 @@
+--rt7
++-rt13
+--
+2.43.0
+
diff --git a/debian/patches-rt/0053-io-mapping-don-t-disable-preempt-on-RT-in-io_mapping.patch b/debian/patches-rt/0053-io-mapping-don-t-disable-preempt-on-RT-in-io_mapping.patch
new file mode 100644
index 000000000..b4b695541
--- /dev/null
+++ b/debian/patches-rt/0053-io-mapping-don-t-disable-preempt-on-RT-in-io_mapping.patch
@@ -0,0 +1,93 @@
+From 53c6a09e670e985d37ca05785a0155ab51b49cf4 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 10 Mar 2023 17:29:05 +0100
+Subject: [PATCH 53/62] io-mapping: don't disable preempt on RT in
+ io_mapping_map_atomic_wc().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+io_mapping_map_atomic_wc() disables preemption and pagefaults for
+historical reasons. The conversion to io_mapping_map_local_wc(), which
+only disables migration, cannot be done wholesale because quite some call
+sites need to be updated to accommodate with the changed semantics.
+
+On PREEMPT_RT enabled kernels the io_mapping_map_atomic_wc() semantics are
+problematic due to the implicit disabling of preemption which makes it
+impossible to acquire 'sleeping' spinlocks within the mapped atomic
+sections.
+
+PREEMPT_RT replaces the preempt_disable() with a migrate_disable() for
+more than a decade. It could be argued that this is a justification to do
+this unconditionally, but PREEMPT_RT covers only a limited number of
+architectures and it disables some functionality which limits the coverage
+further.
+
+Limit the replacement to PREEMPT_RT for now. This is also done
+kmap_atomic().
+
+Link: https://lkml.kernel.org/r/20230310162905.O57Pj7hh@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reported-by: Richard Weinberger <richard.weinberger@gmail.com>
+ Link: https://lore.kernel.org/CAFLxGvw0WMxaMqYqJ5WgvVSbKHq2D2xcXTOgMCpgq9nDC-MWTQ@mail.gmail.com
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+(cherry picked from commit 7eb16f23b9a415f062db22739e59bb144e0b24ab)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ include/linux/io-mapping.h | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
+index 66a774d2710e..b08532b8fba7 100644
+--- a/include/linux/io-mapping.h
++++ b/include/linux/io-mapping.h
+@@ -69,7 +69,10 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping,
+
+ BUG_ON(offset >= mapping->size);
+ phys_addr = mapping->base + offset;
+- preempt_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_disable();
++ else
++ migrate_disable();
+ pagefault_disable();
+ return __iomap_local_pfn_prot(PHYS_PFN(phys_addr), mapping->prot);
+ }
+@@ -79,7 +82,10 @@ io_mapping_unmap_atomic(void __iomem *vaddr)
+ {
+ kunmap_local_indexed((void __force *)vaddr);
+ pagefault_enable();
+- preempt_enable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_enable();
++ else
++ migrate_enable();
+ }
+
+ static inline void __iomem *
+@@ -162,7 +168,10 @@ static inline void __iomem *
+ io_mapping_map_atomic_wc(struct io_mapping *mapping,
+ unsigned long offset)
+ {
+- preempt_disable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_disable();
++ else
++ migrate_disable();
+ pagefault_disable();
+ return io_mapping_map_wc(mapping, offset, PAGE_SIZE);
+ }
+@@ -172,7 +181,10 @@ io_mapping_unmap_atomic(void __iomem *vaddr)
+ {
+ io_mapping_unmap(vaddr);
+ pagefault_enable();
+- preempt_enable();
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_enable();
++ else
++ migrate_enable();
+ }
+
+ static inline void __iomem *
+--
+2.43.0
+
diff --git a/debian/patches-rt/0054-locking-rwbase-Mitigate-indefinite-writer-starvation.patch b/debian/patches-rt/0054-locking-rwbase-Mitigate-indefinite-writer-starvation.patch
new file mode 100644
index 000000000..1940c66d7
--- /dev/null
+++ b/debian/patches-rt/0054-locking-rwbase-Mitigate-indefinite-writer-starvation.patch
@@ -0,0 +1,63 @@
+From 8785dde5198dc91cbb518044e1c6d301ef9a9857 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 21 Mar 2023 17:11:40 +0100
+Subject: [PATCH 54/62] locking/rwbase: Mitigate indefinite writer starvation
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+On PREEMPT_RT, rw_semaphore and rwlock_t locks are unfair to writers.
+Readers can indefinitely acquire the lock unless the writer fully acquired
+the lock, which might never happen if there is always a reader in the
+critical section owning the lock.
+
+Mel Gorman reported that since LTP-20220121 the dio_truncate test case
+went from having 1 reader to having 16 readers and that number of readers
+is sufficient to prevent the down_write ever succeeding while readers
+exist. Eventually the test is killed after 30 minutes as a failure.
+
+Mel proposed a timeout to limit how long a writer can be blocked until
+the reader is forced into the slowpath.
+
+Thomas argued that there is no added value by providing this timeout. From
+a PREEMPT_RT point of view, there are no critical rw_semaphore or rwlock_t
+locks left where the reader must be preferred.
+
+Mitigate indefinite writer starvation by forcing the READER into the
+slowpath once the WRITER attempts to acquire the lock.
+
+Reported-by: Mel Gorman <mgorman@techsingularity.net>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Mel Gorman <mgorman@techsingularity.net>
+Link: https://lore.kernel.org/877cwbq4cq.ffs@tglx
+Link: https://lore.kernel.org/r/20230321161140.HMcQEhHb@linutronix.de
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+(cherry picked from commit 286deb7ec03d941664ac3ffaff58814b454adf65)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ kernel/locking/rwbase_rt.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/kernel/locking/rwbase_rt.c b/kernel/locking/rwbase_rt.c
+index c201aadb9301..25ec0239477c 100644
+--- a/kernel/locking/rwbase_rt.c
++++ b/kernel/locking/rwbase_rt.c
+@@ -72,15 +72,6 @@ static int __sched __rwbase_read_lock(struct rwbase_rt *rwb,
+ int ret;
+
+ raw_spin_lock_irq(&rtm->wait_lock);
+- /*
+- * Allow readers, as long as the writer has not completely
+- * acquired the semaphore for write.
+- */
+- if (atomic_read(&rwb->readers) != WRITER_BIAS) {
+- atomic_inc(&rwb->readers);
+- raw_spin_unlock_irq(&rtm->wait_lock);
+- return 0;
+- }
+
+ /*
+ * Call into the slow lock path with the rtmutex->wait_lock
+--
+2.43.0
+
diff --git a/debian/patches-rt/0055-revert-softirq-Let-ksoftirqd-do-its-job.patch b/debian/patches-rt/0055-revert-softirq-Let-ksoftirqd-do-its-job.patch
new file mode 100644
index 000000000..c9ed7f6f6
--- /dev/null
+++ b/debian/patches-rt/0055-revert-softirq-Let-ksoftirqd-do-its-job.patch
@@ -0,0 +1,108 @@
+From fcdb9b29c6d58895a386ac23229564fad2c316b5 Mon Sep 17 00:00:00 2001
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Mon, 8 May 2023 08:17:44 +0200
+Subject: [PATCH 55/62] revert: "softirq: Let ksoftirqd do its job"
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Due to the mentioned commit, when the ksoftirqd processes take charge
+of softirq processing, the system can experience high latencies.
+
+In the past a few workarounds have been implemented for specific
+side-effects of the above:
+
+commit 1ff688209e2e ("watchdog: core: make sure the watchdog_worker is not deferred")
+commit 8d5755b3f77b ("watchdog: softdog: fire watchdog even if softirqs do not get to run")
+commit 217f69743681 ("net: busy-poll: allow preemption in sk_busy_loop()")
+commit 3c53776e29f8 ("Mark HI and TASKLET softirq synchronous")
+
+but the latency problem still exists in real-life workloads, see the
+link below.
+
+The reverted commit intended to solve a live-lock scenario that can now
+be addressed with the NAPI threaded mode, introduced with commit
+29863d41bb6e ("net: implement threaded-able napi poll loop support"),
+and nowadays in a pretty stable status.
+
+While a complete solution to put softirq processing under nice resource
+control would be preferable, that has proven to be a very hard task. In
+the short term, remove the main pain point, and also simplify a bit the
+current softirq implementation.
+
+Note that this change also reverts commit 3c53776e29f8 ("Mark HI and
+TASKLET softirq synchronous") and commit 1342d8080f61 ("softirq: Don't
+skip softirq execution when softirq thread is parking"), which are
+direct follow-ups of the feature commit. A single change is preferred to
+avoid known bad intermediate states introduced by a patch series
+reverting them individually.
+
+Link: https://lore.kernel.org/netdev/305d7742212cbe98621b16be782b0562f1012cb6.camel@redhat.com/
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Tested-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/57e66b364f1b6f09c9bc0316742c3b14f4ce83bd.1683526542.git.pabeni@redhat.com
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+(cherry picked from commit b8a04a538ed4755dc97c403ee3b8dd882955c98c)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ kernel/softirq.c | 22 ++--------------------
+ 1 file changed, 2 insertions(+), 20 deletions(-)
+
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 82f3e68fbe22..af9e879bbbf7 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -80,21 +80,6 @@ static void wakeup_softirqd(void)
+ wake_up_process(tsk);
+ }
+
+-/*
+- * If ksoftirqd is scheduled, we do not want to process pending softirqs
+- * right now. Let ksoftirqd handle this at its own rate, to get fairness,
+- * unless we're doing some of the synchronous softirqs.
+- */
+-#define SOFTIRQ_NOW_MASK ((1 << HI_SOFTIRQ) | (1 << TASKLET_SOFTIRQ))
+-static bool ksoftirqd_running(unsigned long pending)
+-{
+- struct task_struct *tsk = __this_cpu_read(ksoftirqd);
+-
+- if (pending & SOFTIRQ_NOW_MASK)
+- return false;
+- return tsk && task_is_running(tsk) && !__kthread_should_park(tsk);
+-}
+-
+ #ifdef CONFIG_TRACE_IRQFLAGS
+ DEFINE_PER_CPU(int, hardirqs_enabled);
+ DEFINE_PER_CPU(int, hardirq_context);
+@@ -236,7 +221,7 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt)
+ goto out;
+
+ pending = local_softirq_pending();
+- if (!pending || ksoftirqd_running(pending))
++ if (!pending)
+ goto out;
+
+ /*
+@@ -432,9 +417,6 @@ static inline bool should_wake_ksoftirqd(void)
+
+ static inline void invoke_softirq(void)
+ {
+- if (ksoftirqd_running(local_softirq_pending()))
+- return;
+-
+ if (!force_irqthreads() || !__this_cpu_read(ksoftirqd)) {
+ #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
+ /*
+@@ -468,7 +450,7 @@ asmlinkage __visible void do_softirq(void)
+
+ pending = local_softirq_pending();
+
+- if (pending && !ksoftirqd_running(pending))
++ if (pending)
+ do_softirq_own_stack();
+
+ local_irq_restore(flags);
+--
+2.43.0
+
diff --git a/debian/patches-rt/0056-debugobjects-locking-Annotate-debug_object_fill_pool.patch b/debian/patches-rt/0056-debugobjects-locking-Annotate-debug_object_fill_pool.patch
new file mode 100644
index 000000000..9528f771b
--- /dev/null
+++ b/debian/patches-rt/0056-debugobjects-locking-Annotate-debug_object_fill_pool.patch
@@ -0,0 +1,177 @@
+From c082e5d28e56252dca01b53c553bba5cd152fec1 Mon Sep 17 00:00:00 2001
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Tue, 25 Apr 2023 17:03:13 +0200
+Subject: [PATCH 56/62] debugobjects,locking: Annotate debug_object_fill_pool()
+ wait type violation
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+There is an explicit wait-type violation in debug_object_fill_pool()
+for PREEMPT_RT=n kernels which allows them to more easily fill the
+object pool and reduce the chance of allocation failures.
+
+Lockdep's wait-type checks are designed to check the PREEMPT_RT
+locking rules even for PREEMPT_RT=n kernels and object to this, so
+create a lockdep annotation to allow this to stand.
+
+Specifically, create a 'lock' type that overrides the inner wait-type
+while it is held -- allowing one to temporarily raise it, such that
+the violation is hidden.
+
+Reported-by: Vlastimil Babka <vbabka@suse.cz>
+Reported-by: Qi Zheng <zhengqi.arch@bytedance.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Tested-by: Qi Zheng <zhengqi.arch@bytedance.com>
+Link: https://lkml.kernel.org/r/20230429100614.GA1489784@hirez.programming.kicks-ass.net
+(cherry picked from commit 0cce06ba859a515bd06224085d3addb870608b6d)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ include/linux/lockdep.h | 14 ++++++++++++++
+ include/linux/lockdep_types.h | 1 +
+ kernel/locking/lockdep.c | 28 +++++++++++++++++++++-------
+ lib/debugobjects.c | 15 +++++++++++++--
+ 4 files changed, 49 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 1023f349af71..a3329fb49b33 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -339,6 +339,16 @@ extern void lock_unpin_lock(struct lockdep_map *lock, struct pin_cookie);
+ #define lockdep_repin_lock(l,c) lock_repin_lock(&(l)->dep_map, (c))
+ #define lockdep_unpin_lock(l,c) lock_unpin_lock(&(l)->dep_map, (c))
+
++/*
++ * Must use lock_map_aquire_try() with override maps to avoid
++ * lockdep thinking they participate in the block chain.
++ */
++#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type) \
++ struct lockdep_map _name = { \
++ .name = #_name "-wait-type-override", \
++ .wait_type_inner = _wait_type, \
++ .lock_type = LD_LOCK_WAIT_OVERRIDE, }
++
+ #else /* !CONFIG_LOCKDEP */
+
+ static inline void lockdep_init_task(struct task_struct *task)
+@@ -427,6 +437,9 @@ extern int lockdep_is_held(const void *);
+ #define lockdep_repin_lock(l, c) do { (void)(l); (void)(c); } while (0)
+ #define lockdep_unpin_lock(l, c) do { (void)(l); (void)(c); } while (0)
+
++#define DEFINE_WAIT_OVERRIDE_MAP(_name, _wait_type) \
++ struct lockdep_map __maybe_unused _name = {}
++
+ #endif /* !LOCKDEP */
+
+ enum xhlock_context_t {
+@@ -551,6 +564,7 @@ do { \
+ #define rwsem_release(l, i) lock_release(l, i)
+
+ #define lock_map_acquire(l) lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_)
++#define lock_map_acquire_try(l) lock_acquire_exclusive(l, 0, 1, NULL, _THIS_IP_)
+ #define lock_map_acquire_read(l) lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_)
+ #define lock_map_acquire_tryread(l) lock_acquire_shared_recursive(l, 0, 1, NULL, _THIS_IP_)
+ #define lock_map_release(l) lock_release(l, _THIS_IP_)
+diff --git a/include/linux/lockdep_types.h b/include/linux/lockdep_types.h
+index d22430840b53..59f4fb1626ea 100644
+--- a/include/linux/lockdep_types.h
++++ b/include/linux/lockdep_types.h
+@@ -33,6 +33,7 @@ enum lockdep_wait_type {
+ enum lockdep_lock_type {
+ LD_LOCK_NORMAL = 0, /* normal, catch all */
+ LD_LOCK_PERCPU, /* percpu */
++ LD_LOCK_WAIT_OVERRIDE, /* annotation */
+ LD_LOCK_MAX,
+ };
+
+diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
+index 3b38303ed27b..a046e03c7ead 100644
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -2245,6 +2245,9 @@ static inline bool usage_match(struct lock_list *entry, void *mask)
+
+ static inline bool usage_skip(struct lock_list *entry, void *mask)
+ {
++ if (entry->class->lock_type == LD_LOCK_NORMAL)
++ return false;
++
+ /*
+ * Skip local_lock() for irq inversion detection.
+ *
+@@ -2271,14 +2274,16 @@ static inline bool usage_skip(struct lock_list *entry, void *mask)
+ * As a result, we will skip local_lock(), when we search for irq
+ * inversion bugs.
+ */
+- if (entry->class->lock_type == LD_LOCK_PERCPU) {
+- if (DEBUG_LOCKS_WARN_ON(entry->class->wait_type_inner < LD_WAIT_CONFIG))
+- return false;
++ if (entry->class->lock_type == LD_LOCK_PERCPU &&
++ DEBUG_LOCKS_WARN_ON(entry->class->wait_type_inner < LD_WAIT_CONFIG))
++ return false;
+
+- return true;
+- }
++ /*
++ * Skip WAIT_OVERRIDE for irq inversion detection -- it's not actually
++ * a lock and only used to override the wait_type.
++ */
+
+- return false;
++ return true;
+ }
+
+ /*
+@@ -4745,7 +4750,8 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
+
+ for (; depth < curr->lockdep_depth; depth++) {
+ struct held_lock *prev = curr->held_locks + depth;
+- u8 prev_inner = hlock_class(prev)->wait_type_inner;
++ struct lock_class *class = hlock_class(prev);
++ u8 prev_inner = class->wait_type_inner;
+
+ if (prev_inner) {
+ /*
+@@ -4755,6 +4761,14 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
+ * Also due to trylocks.
+ */
+ curr_inner = min(curr_inner, prev_inner);
++
++ /*
++ * Allow override for annotations -- this is typically
++ * only valid/needed for code that only exists when
++ * CONFIG_PREEMPT_RT=n.
++ */
++ if (unlikely(class->lock_type == LD_LOCK_WAIT_OVERRIDE))
++ curr_inner = prev_inner;
+ }
+ }
+
+diff --git a/lib/debugobjects.c b/lib/debugobjects.c
+index dacb80c22c4f..3c9e00e207dc 100644
+--- a/lib/debugobjects.c
++++ b/lib/debugobjects.c
+@@ -600,10 +600,21 @@ static void debug_objects_fill_pool(void)
+ {
+ /*
+ * On RT enabled kernels the pool refill must happen in preemptible
+- * context:
++ * context -- for !RT kernels we rely on the fact that spinlock_t and
++ * raw_spinlock_t are basically the same type and this lock-type
++ * inversion works just fine.
+ */
+- if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible())
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT) || preemptible()) {
++ /*
++ * Annotate away the spinlock_t inside raw_spinlock_t warning
++ * by temporarily raising the wait-type to WAIT_SLEEP, matching
++ * the preemptible() condition above.
++ */
++ static DEFINE_WAIT_OVERRIDE_MAP(fill_pool_map, LD_WAIT_SLEEP);
++ lock_map_acquire_try(&fill_pool_map);
+ fill_pool();
++ lock_map_release(&fill_pool_map);
++ }
+ }
+
+ static void
+--
+2.43.0
+
diff --git a/debian/patches-rt/0057-sched-avoid-false-lockdep-splat-in-put_task_struct.patch b/debian/patches-rt/0057-sched-avoid-false-lockdep-splat-in-put_task_struct.patch
new file mode 100644
index 000000000..9da36bc08
--- /dev/null
+++ b/debian/patches-rt/0057-sched-avoid-false-lockdep-splat-in-put_task_struct.patch
@@ -0,0 +1,52 @@
+From 5c27e6fdf46d68180a46fdf7944aa7e4668680c3 Mon Sep 17 00:00:00 2001
+From: Wander Lairson Costa <wander@redhat.com>
+Date: Wed, 14 Jun 2023 09:23:22 -0300
+Subject: [PATCH 57/62] sched: avoid false lockdep splat in put_task_struct()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+In put_task_struct(), a spin_lock is indirectly acquired under the kernel
+stock. When running the kernel in real-time (RT) configuration, the
+operation is dispatched to a preemptible context call to ensure
+guaranteed preemption. However, if PROVE_RAW_LOCK_NESTING is enabled
+and __put_task_struct() is called while holding a raw_spinlock, lockdep
+incorrectly reports an "Invalid lock context" in the stock kernel.
+
+This false splat occurs because lockdep is unaware of the different
+route taken under RT. To address this issue, override the inner wait
+type to prevent the false lockdep splat.
+
+Signed-off-by: Wander Lairson Costa <wander@redhat.com>
+Suggested-by: Oleg Nesterov <oleg@redhat.com>
+Suggested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Luis Goncalves <lgoncalv@redhat.com>
+Link: https://lore.kernel.org/r/20230614122323.37957-3-wander@redhat.com
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+(cherry picked from commit a5e446e728e89d5f5c5e427cc919bc7813c64c28)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ include/linux/sched/task.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
+index 7291fb6399d2..de7ebd2bf3ba 100644
+--- a/include/linux/sched/task.h
++++ b/include/linux/sched/task.h
+@@ -141,8 +141,12 @@ static inline void put_task_struct(struct task_struct *t)
+ */
+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !preemptible())
+ call_rcu(&t->rcu, __put_task_struct_rcu_cb);
+- else
++ else {
++ static DEFINE_WAIT_OVERRIDE_MAP(put_task_map, LD_WAIT_SLEEP);
++ lock_map_acquire_try(&put_task_map);
+ __put_task_struct(t);
++ lock_map_release(&put_task_map);
++ }
+ }
+
+ static inline void put_task_struct_many(struct task_struct *t, int nr)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0058-mm-page_alloc-Use-write_seqlock_irqsave-instead-writ.patch b/debian/patches-rt/0058-mm-page_alloc-Use-write_seqlock_irqsave-instead-writ.patch
new file mode 100644
index 000000000..68d9f5008
--- /dev/null
+++ b/debian/patches-rt/0058-mm-page_alloc-Use-write_seqlock_irqsave-instead-writ.patch
@@ -0,0 +1,97 @@
+From 9512a9467dec62e03f2df4f15af9a38332b8de58 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 23 Jun 2023 22:15:17 +0200
+Subject: [PATCH 58/62] mm/page_alloc: Use write_seqlock_irqsave() instead
+ write_seqlock() + local_irq_save().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+__build_all_zonelists() acquires zonelist_update_seq by first disabling
+interrupts via local_irq_save() and then acquiring the seqlock with
+write_seqlock(). This is troublesome and leads to problems on
+PREEMPT_RT. The problem is that the inner spinlock_t becomes a sleeping
+lock on PREEMPT_RT and must not be acquired with disabled interrupts.
+
+The API provides write_seqlock_irqsave() which does the right thing in
+one step.
+printk_deferred_enter() has to be invoked in non-migrate-able context to
+ensure that deferred printing is enabled and disabled on the same CPU.
+This is the case after zonelist_update_seq has been acquired.
+
+There was discussion on the first submission that the order should be:
+ local_irq_disable();
+ printk_deferred_enter();
+ write_seqlock();
+
+to avoid pitfalls like having an unaccounted printk() coming from
+write_seqlock_irqsave() before printk_deferred_enter() is invoked. The
+only origin of such a printk() can be a lockdep splat because the
+lockdep annotation happens after the sequence count is incremented.
+This is exceptional and subject to change.
+
+It was also pointed that PREEMPT_RT can be affected by the printk
+problem since its write_seqlock_irqsave() does not really disable
+interrupts. This isn't the case because PREEMPT_RT's printk
+implementation differs from the mainline implementation in two important
+aspects:
+- Printing happens in a dedicated threads and not at during the
+ invocation of printk().
+- In emergency cases where synchronous printing is used, a different
+ driver is used which does not use tty_port::lock.
+
+Acquire zonelist_update_seq with write_seqlock_irqsave() and then defer
+printk output.
+
+Fixes: 1007843a91909 ("mm/page_alloc: fix potential deadlock on zonelist_update_seq seqlock")
+Acked-by: Michal Hocko <mhocko@suse.com>
+Reviewed-by: David Hildenbrand <david@redhat.com>
+Link: https://lore.kernel.org/r/20230623201517.yw286Knb@linutronix.de
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+(cherry picked from commit 4d1139baae8bc4fff3728d1d204bdb04c13dbe10)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ mm/page_alloc.c | 15 ++++++---------
+ 1 file changed, 6 insertions(+), 9 deletions(-)
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 4583f8a42d91..835b69a64f4f 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -6588,19 +6588,17 @@ static void __build_all_zonelists(void *data)
+ unsigned long flags;
+
+ /*
+- * Explicitly disable this CPU's interrupts before taking seqlock
+- * to prevent any IRQ handler from calling into the page allocator
+- * (e.g. GFP_ATOMIC) that could hit zonelist_iter_begin and livelock.
++ * The zonelist_update_seq must be acquired with irqsave because the
++ * reader can be invoked from IRQ with GFP_ATOMIC.
+ */
+- local_irq_save(flags);
++ write_seqlock_irqsave(&zonelist_update_seq, flags);
+ /*
+- * Explicitly disable this CPU's synchronous printk() before taking
+- * seqlock to prevent any printk() from trying to hold port->lock, for
++ * Also disable synchronous printk() to prevent any printk() from
++ * trying to hold port->lock, for
+ * tty_insert_flip_string_and_push_buffer() on other CPU might be
+ * calling kmalloc(GFP_ATOMIC | __GFP_NOWARN) with port->lock held.
+ */
+ printk_deferred_enter();
+- write_seqlock(&zonelist_update_seq);
+
+ #ifdef CONFIG_NUMA
+ memset(node_load, 0, sizeof(node_load));
+@@ -6637,9 +6635,8 @@ static void __build_all_zonelists(void *data)
+ #endif
+ }
+
+- write_sequnlock(&zonelist_update_seq);
+ printk_deferred_exit();
+- local_irq_restore(flags);
++ write_sequnlock_irqrestore(&zonelist_update_seq, flags);
+ }
+
+ static noinline void __init
+--
+2.43.0
+
diff --git a/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch b/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch
new file mode 100644
index 000000000..8abf764af
--- /dev/null
+++ b/debian/patches-rt/0059-bpf-Remove-in_atomic-from-bpf_link_put.patch
@@ -0,0 +1,120 @@
+From 05999b640eb04be872e5491a040701fcddc73349 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 14 Jun 2023 10:34:30 +0200
+Subject: [PATCH 59/62] bpf: Remove in_atomic() from bpf_link_put().
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+bpf_free_inode() is invoked as a RCU callback. Usually RCU callbacks are
+invoked within softirq context. By setting rcutree.use_softirq=0 boot
+option the RCU callbacks will be invoked in a per-CPU kthread with
+bottom halves disabled which implies a RCU read section.
+
+On PREEMPT_RT the context remains fully preemptible. The RCU read
+section however does not allow schedule() invocation. The latter happens
+in mutex_lock() performed by bpf_trampoline_unlink_prog() originated
+from bpf_link_put().
+
+It was pointed out that the bpf_link_put() invocation should not be
+delayed if originated from close(). It was also pointed out that other
+invocations from within a syscall should also avoid the workqueue.
+Everyone else should use workqueue by default to remain safe in the
+future (while auditing the code, every caller was preemptible except for
+the RCU case).
+
+Let bpf_link_put() use the worker unconditionally. Add
+bpf_link_put_direct() which will directly free the resources and is used
+by close() and from within __sys_bpf().
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20230614083430.oENawF8f@linutronix.de
+(cherry picked from commit ab5d47bd41b1db82c295b0e751e2b822b43a4b5a)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ kernel/bpf/syscall.c | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index c0915e2424f1..f8ba6e0a5c08 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -2732,28 +2732,31 @@ static void bpf_link_put_deferred(struct work_struct *work)
+ bpf_link_free(link);
+ }
+
+-/* bpf_link_put can be called from atomic context, but ensures that resources
+- * are freed from process context
++/* bpf_link_put might be called from atomic context. It needs to be called
++ * from sleepable context in order to acquire sleeping locks during the process.
+ */
+ void bpf_link_put(struct bpf_link *link)
+ {
+ if (!atomic64_dec_and_test(&link->refcnt))
+ return;
+
+- if (in_atomic()) {
+- INIT_WORK(&link->work, bpf_link_put_deferred);
+- schedule_work(&link->work);
+- } else {
+- bpf_link_free(link);
+- }
++ INIT_WORK(&link->work, bpf_link_put_deferred);
++ schedule_work(&link->work);
+ }
+ EXPORT_SYMBOL(bpf_link_put);
+
++static void bpf_link_put_direct(struct bpf_link *link)
++{
++ if (!atomic64_dec_and_test(&link->refcnt))
++ return;
++ bpf_link_free(link);
++}
++
+ static int bpf_link_release(struct inode *inode, struct file *filp)
+ {
+ struct bpf_link *link = filp->private_data;
+
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+ return 0;
+ }
+
+@@ -4674,7 +4677,7 @@ static int link_update(union bpf_attr *attr)
+ if (ret)
+ bpf_prog_put(new_prog);
+ out_put_link:
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+ return ret;
+ }
+
+@@ -4697,7 +4700,7 @@ static int link_detach(union bpf_attr *attr)
+ else
+ ret = -EOPNOTSUPP;
+
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+ return ret;
+ }
+
+@@ -4767,7 +4770,7 @@ static int bpf_link_get_fd_by_id(const union bpf_attr *attr)
+
+ fd = bpf_link_new_fd(link);
+ if (fd < 0)
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+
+ return fd;
+ }
+@@ -4844,7 +4847,7 @@ static int bpf_iter_create(union bpf_attr *attr)
+ return PTR_ERR(link);
+
+ err = bpf_iter_new_fd(link);
+- bpf_link_put(link);
++ bpf_link_put_direct(link);
+
+ return err;
+ }
+--
+2.43.0
+
diff --git a/debian/patches-rt/0060-posix-timers-Ensure-timer-ID-search-loop-limit-is-va.patch b/debian/patches-rt/0060-posix-timers-Ensure-timer-ID-search-loop-limit-is-va.patch
new file mode 100644
index 000000000..8b22f207c
--- /dev/null
+++ b/debian/patches-rt/0060-posix-timers-Ensure-timer-ID-search-loop-limit-is-va.patch
@@ -0,0 +1,115 @@
+From a0d2c56749857956cb8ef1ccf2d982e2c1770f08 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 1 Jun 2023 20:58:47 +0200
+Subject: [PATCH 60/62] posix-timers: Ensure timer ID search-loop limit is
+ valid
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+posix_timer_add() tries to allocate a posix timer ID by starting from the
+cached ID which was stored by the last successful allocation.
+
+This is done in a loop searching the ID space for a free slot one by
+one. The loop has to terminate when the search wrapped around to the
+starting point.
+
+But that's racy vs. establishing the starting point. That is read out
+lockless, which leads to the following problem:
+
+CPU0 CPU1
+posix_timer_add()
+ start = sig->posix_timer_id;
+ lock(hash_lock);
+ ... posix_timer_add()
+ if (++sig->posix_timer_id < 0)
+ start = sig->posix_timer_id;
+ sig->posix_timer_id = 0;
+
+So CPU1 can observe a negative start value, i.e. -1, and the loop break
+never happens because the condition can never be true:
+
+ if (sig->posix_timer_id == start)
+ break;
+
+While this is unlikely to ever turn into an endless loop as the ID space is
+huge (INT_MAX), the racy read of the start value caught the attention of
+KCSAN and Dmitry unearthed that incorrectness.
+
+Rewrite it so that all id operations are under the hash lock.
+
+Reported-by: syzbot+5c54bd3eb218bb595aa9@syzkaller.appspotmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
+Link: https://lore.kernel.org/r/87bkhzdn6g.ffs@tglx
+
+(cherry picked from commit 8ce8849dd1e78dadcee0ec9acbd259d239b7069f)
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ include/linux/sched/signal.h | 2 +-
+ kernel/time/posix-timers.c | 31 ++++++++++++++++++-------------
+ 2 files changed, 19 insertions(+), 14 deletions(-)
+
+diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
+index 20099268fa25..669e8cff40c7 100644
+--- a/include/linux/sched/signal.h
++++ b/include/linux/sched/signal.h
+@@ -135,7 +135,7 @@ struct signal_struct {
+ #ifdef CONFIG_POSIX_TIMERS
+
+ /* POSIX.1b Interval Timers */
+- int posix_timer_id;
++ unsigned int next_posix_timer_id;
+ struct list_head posix_timers;
+
+ /* ITIMER_REAL timer for the process */
+diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
+index ed3c4a954398..2d6cf93ca370 100644
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -140,25 +140,30 @@ static struct k_itimer *posix_timer_by_id(timer_t id)
+ static int posix_timer_add(struct k_itimer *timer)
+ {
+ struct signal_struct *sig = current->signal;
+- int first_free_id = sig->posix_timer_id;
+ struct hlist_head *head;
+- int ret = -ENOENT;
++ unsigned int cnt, id;
+
+- do {
++ /*
++ * FIXME: Replace this by a per signal struct xarray once there is
++ * a plan to handle the resulting CRIU regression gracefully.
++ */
++ for (cnt = 0; cnt <= INT_MAX; cnt++) {
+ spin_lock(&hash_lock);
+- head = &posix_timers_hashtable[hash(sig, sig->posix_timer_id)];
+- if (!__posix_timers_find(head, sig, sig->posix_timer_id)) {
++ id = sig->next_posix_timer_id;
++
++ /* Write the next ID back. Clamp it to the positive space */
++ sig->next_posix_timer_id = (id + 1) & INT_MAX;
++
++ head = &posix_timers_hashtable[hash(sig, id)];
++ if (!__posix_timers_find(head, sig, id)) {
+ hlist_add_head_rcu(&timer->t_hash, head);
+- ret = sig->posix_timer_id;
++ spin_unlock(&hash_lock);
++ return id;
+ }
+- if (++sig->posix_timer_id < 0)
+- sig->posix_timer_id = 0;
+- if ((sig->posix_timer_id == first_free_id) && (ret == -ENOENT))
+- /* Loop over all possible ids completed */
+- ret = -EAGAIN;
+ spin_unlock(&hash_lock);
+- } while (ret == -ENOENT);
+- return ret;
++ }
++ /* POSIX return code when no timer ID could be allocated */
++ return -EAGAIN;
+ }
+
+ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
+--
+2.43.0
+
diff --git a/debian/patches-rt/0061-drm-i915-Do-not-disable-preemption-for-resets.patch b/debian/patches-rt/0061-drm-i915-Do-not-disable-preemption-for-resets.patch
new file mode 100644
index 000000000..db8400741
--- /dev/null
+++ b/debian/patches-rt/0061-drm-i915-Do-not-disable-preemption-for-resets.patch
@@ -0,0 +1,110 @@
+From 1d651fe6c67cb3b355cc228f75289657496520ff Mon Sep 17 00:00:00 2001
+From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
+Date: Fri, 18 Aug 2023 22:45:25 -0400
+Subject: [PATCH 61/62] drm/i915: Do not disable preemption for resets
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+[commit 40cd2835ced288789a685aa4aa7bc04b492dcd45 in linux-rt-devel]
+
+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>
+[PG: backport from v6.4-rt ; minor context fixup caused by b7d70b8b06ed]
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Clark Williams <williams@redhat.com>
+---
+ drivers/gpu/drm/i915/gt/intel_reset.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
+index 10b930eaa8cb..6108a449cd19 100644
+--- a/drivers/gpu/drm/i915/gt/intel_reset.c
++++ b/drivers/gpu/drm/i915/gt/intel_reset.c
+@@ -174,13 +174,13 @@ static int i915_do_reset(struct intel_gt *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;
+ }
+@@ -200,7 +200,7 @@ static int g33_do_reset(struct intel_gt *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,
+@@ -217,7 +217,7 @@ static int g4x_do_reset(struct intel_gt *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;
+@@ -225,7 +225,7 @@ static int g4x_do_reset(struct intel_gt *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;
+@@ -718,9 +718,7 @@ int __intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t engine_mask)
+ intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
+ for (retry = 0; ret == -ETIMEDOUT && retry < retries; retry++) {
+ GT_TRACE(gt, "engine_mask=%x\n", engine_mask);
+- preempt_disable();
+ ret = reset(gt, engine_mask, retry);
+- preempt_enable();
+ }
+ intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
+
+--
+2.43.0
+
diff --git a/debian/patches-rt/0062-Linux-6.1.69-rt21-REBASE.patch b/debian/patches-rt/0062-Linux-6.1.69-rt21-REBASE.patch
new file mode 100644
index 000000000..d5e736785
--- /dev/null
+++ b/debian/patches-rt/0062-Linux-6.1.69-rt21-REBASE.patch
@@ -0,0 +1,21 @@
+From 8aa6a280fc011cccf7cfcc0f5942e3ec6bdd73b4 Mon Sep 17 00:00:00 2001
+From: Clark Williams <clark.williams@gmail.com>
+Date: Thu, 28 Dec 2023 23:45:11 -0600
+Subject: [PATCH 62/62] Linux 6.1.69-rt21 REBASE
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.1/older/patches-6.1.69-rt21.tar.xz
+
+Signed-off-by: Clark Williams <clark.williams@gmail.com>
+---
+ localversion-rt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/localversion-rt b/localversion-rt
+index 9f7d0bdbffb1..6c6cde1c29e3 100644
+--- a/localversion-rt
++++ b/localversion-rt
+@@ -1 +1 @@
+--rt13
++-rt21
+--
+2.43.0
+
diff --git a/debian/patches-rt/series b/debian/patches-rt/series
new file mode 100644
index 000000000..a07ceae89
--- /dev/null
+++ b/debian/patches-rt/series
@@ -0,0 +1,62 @@
+0001-vduse-Remove-include-of-rwlock.h.patch
+0002-signal-Don-t-disable-preemption-in-ptrace_stop-on-PR.patch
+0003-sched-Consider-task_struct-saved_state-in-wait_task_.patch
+0004-spi-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch
+0005-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch
+0006-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-n.patch
+0007-bpf-Remove-the-obsolte-u64_stats_fetch_-_irq-users.patch
+0008-u64_stat-Remove-the-obsolete-fetch_irq-variants.patch
+0009-net-Avoid-the-IPI-to-free-the.patch
+0010-x86-Allow-to-enable-RT.patch
+0011-x86-Enable-RT-also-on-32bit.patch
+0012-softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
+0013-rcutorture-Also-force-sched-priority-to-timersd-on-b.patch
+0014-tick-Fix-timer-storm-since-introduction-of-timersd.patch
+0015-softirq-Wake-ktimers-thread-also-in-softirq.patch
+0016-tpm_tis-fix-stall-after-iowrite-s.patch
+0017-zram-Replace-bit-spinlocks-with-spinlock_t-for-PREEM.patch
+0018-locking-lockdep-Remove-lockdep_init_map_crosslock.patch
+0019-printk-Bring-back-the-RT-bits.patch
+0020-printk-add-infrastucture-for-atomic-consoles.patch
+0021-serial-8250-implement-write_atomic.patch
+0022-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
+0023-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
+0024-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
+0025-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
+0026-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch
+0027-drm-i915-skip-DRM_I915_LOW_LEVEL_TRACEPOINTS-with-NO.patch
+0028-drm-i915-gt-Queue-and-wait-for-the-irq_work-item.patch
+0029-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
+0030-drm-i915-Drop-the-irqs_disabled-check.patch
+0031-Revert-drm-i915-Depend-on-PREEMPT_RT.patch
+0032-sched-Add-support-for-lazy-preemption.patch
+0033-x86-entry-Use-should_resched-in-idtentry_exit_cond_r.patch
+0034-x86-Support-for-lazy-preemption.patch
+0035-entry-Fix-the-preempt-lazy-fallout.patch
+0036-arm-Add-support-for-lazy-preemption.patch
+0037-powerpc-Add-support-for-lazy-preemption.patch
+0038-arch-arm64-Add-lazy-preempt-support.patch
+0039-arm-Disable-jump-label-on-PREEMPT_RT.patch
+0040-ARM-enable-irq-in-translation-section-permission-fau.patch
+0041-tty-serial-omap-Make-the-locking-RT-aware.patch
+0042-tty-serial-pl011-Make-the-locking-work-on-RT.patch
+0043-ARM-Allow-to-enable-RT.patch
+0044-ARM64-Allow-to-enable-RT.patch
+0045-powerpc-traps-Use-PREEMPT_RT.patch
+0046-powerpc-pseries-iommu-Use-a-locallock-instead-local_.patch
+0047-powerpc-kvm-Disable-in-kernel-MPIC-emulation-for-PRE.patch
+0048-powerpc-stackprotector-work-around-stack-guard-init-.patch
+0049-POWERPC-Allow-to-enable-RT.patch
+0050-sysfs-Add-sys-kernel-realtime-entry.patch
+0051-Add-localversion-for-RT-release.patch
+0052-Linux-6.1.46-rt13-REBASE.patch
+0053-io-mapping-don-t-disable-preempt-on-RT-in-io_mapping.patch
+0054-locking-rwbase-Mitigate-indefinite-writer-starvation.patch
+0055-revert-softirq-Let-ksoftirqd-do-its-job.patch
+0056-debugobjects-locking-Annotate-debug_object_fill_pool.patch
+0057-sched-avoid-false-lockdep-splat-in-put_task_struct.patch
+0058-mm-page_alloc-Use-write_seqlock_irqsave-instead-writ.patch
+0059-bpf-Remove-in_atomic-from-bpf_link_put.patch
+0060-posix-timers-Ensure-timer-ID-search-loop-limit-is-va.patch
+0061-drm-i915-Do-not-disable-preemption-for-resets.patch
+0062-Linux-6.1.69-rt21-REBASE.patch
diff --git a/debian/patches/bugfix/all/cpupower-bump-soname-version.patch b/debian/patches/bugfix/all/cpupower-bump-soname-version.patch
new file mode 100644
index 000000000..7e5f52eaa
--- /dev/null
+++ b/debian/patches/bugfix/all/cpupower-bump-soname-version.patch
@@ -0,0 +1,27 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 9 Jun 2016 23:35:08 +0100
+Subject: cpupower: Bump soname version
+Forwarded: http://mid.gmane.org/20160610005619.GQ7555@decadent.org.uk
+
+Several functions in the libcpupower API are renamed or removed in
+Linux 4.7. This is an backward-incompatible ABI change, so the
+library soname should change from libcpupower.so.0 to
+libcpupower.so.1.
+
+Fixes: ac5a181d065d ("cpupower: Add cpuidle parts into library")
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ tools/power/cpupower/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/power/cpupower/Makefile
++++ b/tools/power/cpupower/Makefile
+@@ -53,7 +53,7 @@ DESTDIR ?=
+
+ VERSION:= $(shell ./utils/version-gen.sh)
+ LIB_MAJ= 0.0.1
+-LIB_MIN= 0
++LIB_MIN= 1
+
+ PACKAGE = cpupower
+ PACKAGE_BUGREPORT = linux-pm@vger.kernel.org
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 000000000..5cce9b76a
--- /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://marc.info/?l=linux-pm&m=149248268214265
+
+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 000000000..9c4987116
--- /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: http://thread.gmane.org/gmane.linux.debian.devel.bugs.general/1107774/
+
+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
+@@ -1262,6 +1262,7 @@
+ return genphy_soft_reset(phydev);
+ }
+
++#if 0
+ static int m88e1149_config_init(struct phy_device *phydev)
+ {
+ int err;
+@@ -1287,7 +1288,9 @@
+
+ return genphy_soft_reset(phydev);
+ }
++#endif
+
++#if 0
+ static int m88e1145_config_init_rgmii(struct phy_device *phydev)
+ {
+ int err;
+@@ -1365,6 +1368,7 @@
+
+ return 0;
+ }
++#endif
+
+ static int m88e1540_get_fld(struct phy_device *phydev, u8 *msecs)
+ {
+@@ -2853,6 +2857,7 @@
+ .get_strings = marvell_get_strings,
+ .get_stats = marvell_get_stats,
+ },
++#if 0
+ {
+ .phy_id = MARVELL_PHY_ID_88E1145,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+@@ -2873,6 +2878,8 @@
+ .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,
+@@ -2891,6 +2898,8 @@
+ .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,
+@@ -2911,6 +2920,7 @@
+ .get_tunable = m88e1011_get_tunable,
+ .set_tunable = m88e1011_set_tunable,
+ },
++#endif
+ {
+ .phy_id = MARVELL_PHY_ID_88E1116R,
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
+@@ -3163,9 +3173,9 @@
+ { 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 000000000..fc4cb5b33
--- /dev/null
+++ b/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch
@@ -0,0 +1,2716 @@
+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.
+
+Index: linux/arch/x86/kernel/cpu/microcode/amd.c
+===================================================================
+--- linux.orig/arch/x86/kernel/cpu/microcode/amd.c
++++ linux/arch/x86/kernel/cpu/microcode/amd.c
+@@ -907,10 +907,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))
+Index: linux/drivers/atm/fore200e.c
+===================================================================
+--- linux.orig/drivers/atm/fore200e.c
++++ linux/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);
+Index: linux/drivers/bluetooth/ath3k.c
+===================================================================
+--- linux.orig/drivers/bluetooth/ath3k.c
++++ linux/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);
+Index: linux/drivers/bluetooth/bcm203x.c
+===================================================================
+--- linux.orig/drivers/bluetooth/bcm203x.c
++++ linux/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;
+Index: linux/drivers/bluetooth/bfusb.c
+===================================================================
+--- linux.orig/drivers/bluetooth/bfusb.c
++++ linux/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);
+
+Index: linux/drivers/bluetooth/bt3c_cs.c
+===================================================================
+--- linux.orig/drivers/bluetooth/bt3c_cs.c
++++ linux/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);
+
+Index: linux/drivers/bluetooth/btmrvl_sdio.c
+===================================================================
+--- linux.orig/drivers/bluetooth/btmrvl_sdio.c
++++ linux/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;
+ }
+Index: linux/drivers/char/dsp56k.c
+===================================================================
+--- linux.orig/drivers/char/dsp56k.c
++++ linux/drivers/char/dsp56k.c
+@@ -140,11 +140,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);
+Index: linux/drivers/dma/imx-sdma.c
+===================================================================
+--- linux.orig/drivers/dma/imx-sdma.c
++++ linux/drivers/dma/imx-sdma.c
+@@ -1910,11 +1910,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;
+Index: linux/drivers/gpu/drm/mga/mga_warp.c
+===================================================================
+--- linux.orig/drivers/gpu/drm/mga/mga_warp.c
++++ linux/drivers/gpu/drm/mga/mga_warp.c
+@@ -77,11 +77,8 @@ int mga_warp_install_microcode(drm_mga_p
+ }
+ rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev);
+ platform_device_unregister(pdev);
+- if (rc) {
+- DRM_ERROR("mga: Failed to load microcode \"%s\"\n",
+- firmware_name);
++ if (rc)
+ return rc;
+- }
+
+ size = 0;
+ where = 0;
+Index: linux/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+===================================================================
+--- linux.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
++++ linux/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+@@ -2445,10 +2445,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;
+Index: linux/drivers/gpu/drm/r128/r128_cce.c
+===================================================================
+--- linux.orig/drivers/gpu/drm/r128/r128_cce.c
++++ linux/drivers/gpu/drm/r128/r128_cce.c
+@@ -161,11 +161,8 @@ static int r128_cce_load_microcode(drm_r
+ }
+ rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
+ platform_device_unregister(pdev);
+- if (rc) {
+- pr_err("r128_cce: Failed to load firmware \"%s\"\n",
+- FIRMWARE_NAME);
++ if (rc)
+ return rc;
+- }
+
+ if (fw->size != 256 * 8) {
+ pr_err("r128_cce: Bogus length %zu in firmware \"%s\"\n",
+Index: linux/drivers/gpu/drm/radeon/ni.c
+===================================================================
+--- linux.orig/drivers/gpu/drm/radeon/ni.c
++++ linux/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);
+Index: linux/drivers/gpu/drm/radeon/r100.c
+===================================================================
+--- linux.orig/drivers/gpu/drm/radeon/r100.c
++++ linux/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;
+Index: linux/drivers/gpu/drm/radeon/r600.c
+===================================================================
+--- linux.orig/drivers/gpu/drm/radeon/r600.c
++++ linux/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);
+Index: linux/drivers/infiniband/hw/qib/qib_sd7220.c
+===================================================================
+--- linux.orig/drivers/infiniband/hw/qib/qib_sd7220.c
++++ linux/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);
+Index: linux/drivers/input/touchscreen/atmel_mxt_ts.c
+===================================================================
+--- linux.orig/drivers/input/touchscreen/atmel_mxt_ts.c
++++ linux/drivers/input/touchscreen/atmel_mxt_ts.c
+@@ -2870,10 +2870,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);
+Index: linux/drivers/isdn/hardware/mISDN/speedfax.c
+===================================================================
+--- linux.orig/drivers/isdn/hardware/mISDN/speedfax.c
++++ linux/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);
+Index: linux/drivers/media/common/siano/smscoreapi.c
+===================================================================
+--- linux.orig/drivers/media/common/siano/smscoreapi.c
++++ linux/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);
+Index: linux/drivers/media/dvb-frontends/af9013.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/af9013.c
++++ linux/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++)
+Index: linux/drivers/media/dvb-frontends/bcm3510.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/bcm3510.c
++++ linux/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;
+Index: linux/drivers/media/dvb-frontends/cx24116.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/cx24116.c
++++ linux/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 */
+Index: linux/drivers/media/dvb-frontends/drxd_hard.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/drxd_hard.c
++++ linux/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) {
+Index: linux/drivers/media/dvb-frontends/drxk_hard.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/drxk_hard.c
++++ linux/drivers/media/dvb-frontends/drxk_hard.c
+@@ -6247,10 +6247,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;
+
+ /*
+Index: linux/drivers/media/dvb-frontends/ds3000.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/ds3000.c
++++ linux/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)
+Index: linux/drivers/media/dvb-frontends/nxt200x.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/nxt200x.c
++++ linux/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);
+Index: linux/drivers/media/dvb-frontends/or51132.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/or51132.c
++++ linux/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) {
+Index: linux/drivers/media/dvb-frontends/or51211.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/or51211.c
++++ linux/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);
+Index: linux/drivers/media/dvb-frontends/sp887x.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/sp887x.c
++++ linux/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);
+Index: linux/drivers/media/dvb-frontends/tda10048.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/tda10048.c
++++ linux/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",
+Index: linux/drivers/media/dvb-frontends/tda1004x.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/tda1004x.c
++++ linux/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",
+Index: linux/drivers/media/dvb-frontends/tda10071.c
+===================================================================
+--- linux.orig/drivers/media/dvb-frontends/tda10071.c
++++ linux/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++) {
+Index: linux/drivers/media/i2c/cx25840/cx25840-firmware.c
+===================================================================
+--- linux.orig/drivers/media/i2c/cx25840/cx25840-firmware.c
++++ linux/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);
+
+Index: linux/drivers/media/pci/bt8xx/bttv-cards.c
+===================================================================
+--- linux.orig/drivers/media/pci/bt8xx/bttv-cards.c
++++ linux/drivers/media/pci/bt8xx/bttv-cards.c
+@@ -3904,10 +3904,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");
+Index: linux/drivers/media/pci/cx18/cx18-av-firmware.c
+===================================================================
+--- linux.orig/drivers/media/pci/cx18/cx18-av-firmware.c
++++ linux/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. */
+Index: linux/drivers/media/pci/cx18/cx18-dvb.c
+===================================================================
+--- linux.orig/drivers/media/pci/cx18/cx18-dvb.c
++++ linux/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",
+Index: linux/drivers/media/pci/cx18/cx18-firmware.c
+===================================================================
+--- linux.orig/drivers/media/pci/cx18/cx18-firmware.c
++++ linux/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;
+ }
+Index: linux/drivers/media/pci/cx23885/cx23885-417.c
+===================================================================
+--- linux.orig/drivers/media/pci/cx23885/cx23885-417.c
++++ linux/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",
+Index: linux/drivers/media/pci/cx23885/cx23885-cards.c
+===================================================================
+--- linux.orig/drivers/media/pci/cx23885/cx23885-cards.c
++++ linux/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);
+Index: linux/drivers/media/pci/cx88/cx88-blackbird.c
+===================================================================
+--- linux.orig/drivers/media/pci/cx88/cx88-blackbird.c
++++ linux/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",
+Index: linux/drivers/media/pci/ivtv/ivtv-firmware.c
+===================================================================
+--- linux.orig/drivers/media/pci/ivtv/ivtv-firmware.c
++++ linux/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;
+ }
+
+Index: linux/drivers/media/pci/ngene/ngene-core.c
+===================================================================
+--- linux.orig/drivers/media/pci/ngene/ngene-core.c
++++ linux/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);
+ }
+Index: linux/drivers/media/pci/saa7164/saa7164-fw.c
+===================================================================
+--- linux.orig/drivers/media/pci/saa7164/saa7164-fw.c
++++ linux/drivers/media/pci/saa7164/saa7164-fw.c
+@@ -406,11 +406,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);
+Index: linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
+===================================================================
+--- linux.orig/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
++++ linux/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);
+Index: linux/drivers/media/radio/radio-wl1273.c
+===================================================================
+--- linux.orig/drivers/media/radio/radio-wl1273.c
++++ linux/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];
+Index: linux/drivers/media/radio/wl128x/fmdrv_common.c
+===================================================================
+--- linux.orig/drivers/media/radio/wl128x/fmdrv_common.c
++++ linux/drivers/media/radio/wl128x/fmdrv_common.c
+@@ -1241,10 +1241,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;
+Index: linux/drivers/media/tuners/xc2028.c
+===================================================================
+--- linux.orig/drivers/media/tuners/xc2028.c
++++ linux/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;
+ }
+Index: linux/drivers/media/usb/cx231xx/cx231xx-417.c
+===================================================================
+--- linux.orig/drivers/media/usb/cx231xx/cx231xx-417.c
++++ linux/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;
+Index: linux/drivers/media/usb/dvb-usb/dib0700_devices.c
+===================================================================
+--- linux.orig/drivers/media/usb/dvb-usb/dib0700_devices.c
++++ linux/drivers/media/usb/dvb-usb/dib0700_devices.c
+@@ -2408,12 +2408,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;
+
+@@ -2478,12 +2475,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;
+Index: linux/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
+===================================================================
+--- linux.orig/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
++++ linux/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:
+Index: linux/drivers/media/usb/dvb-usb/gp8psk.c
+===================================================================
+--- linux.orig/drivers/media/usb/dvb-usb/gp8psk.c
++++ linux/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) {
+Index: linux/drivers/media/usb/dvb-usb/opera1.c
+===================================================================
+--- linux.orig/drivers/media/usb/dvb-usb/opera1.c
++++ linux/drivers/media/usb/dvb-usb/opera1.c
+@@ -455,8 +455,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);
+Index: linux/drivers/media/usb/go7007/go7007-driver.c
+===================================================================
+--- linux.orig/drivers/media/usb/go7007/go7007-driver.c
++++ linux/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);
+Index: linux/drivers/media/usb/go7007/go7007-fw.c
+===================================================================
+--- linux.orig/drivers/media/usb/go7007/go7007-fw.c
++++ linux/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;
+Index: linux/drivers/media/usb/go7007/go7007-loader.c
+===================================================================
+--- linux.orig/drivers/media/usb/go7007/go7007-loader.c
++++ linux/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) {
+Index: linux/drivers/media/usb/gspca/vicam.c
+===================================================================
+--- linux.orig/drivers/media/usb/gspca/vicam.c
++++ linux/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) {
+Index: linux/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+===================================================================
+--- linux.orig/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
++++ linux/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;
+ }
+
+Index: linux/drivers/media/usb/s2255/s2255drv.c
+===================================================================
+--- linux.orig/drivers/media/usb/s2255/s2255drv.c
++++ linux/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];
+Index: linux/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
+===================================================================
+--- linux.orig/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
++++ linux/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;
+Index: linux/drivers/media/usb/ttusb-dec/ttusb_dec.c
+===================================================================
+--- linux.orig/drivers/media/usb/ttusb-dec/ttusb_dec.c
++++ linux/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;
+Index: linux/drivers/misc/ti-st/st_kim.c
+===================================================================
+--- linux.orig/drivers/misc/ti-st/st_kim.c
++++ linux/drivers/misc/ti-st/st_kim.c
+@@ -295,11 +295,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;
+ /*
+Index: linux/drivers/net/can/softing/softing_fw.c
+===================================================================
+--- linux.orig/drivers/net/can/softing/softing_fw.c
++++ linux/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 */
+Index: linux/drivers/net/ethernet/3com/typhoon.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/3com/typhoon.c
++++ linux/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;
+Index: linux/drivers/net/ethernet/adaptec/starfire.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/adaptec/starfire.c
++++ linux/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);
+Index: linux/drivers/net/ethernet/alacritech/slicoss.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/alacritech/slicoss.c
++++ linux/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.
+ */
+Index: linux/drivers/net/ethernet/alteon/acenic.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/alteon/acenic.c
++++ linux/drivers/net/ethernet/alteon/acenic.c
+@@ -2878,11 +2878,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;
+
+Index: linux/drivers/net/ethernet/broadcom/bnx2.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/broadcom/bnx2.c
++++ linux/drivers/net/ethernet/broadcom/bnx2.c
+@@ -3712,16 +3712,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) ||
+Index: linux/drivers/net/ethernet/broadcom/tg3.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/broadcom/tg3.c
++++ linux/drivers/net/ethernet/broadcom/tg3.c
+@@ -11398,11 +11398,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;
+
+Index: linux/drivers/net/ethernet/brocade/bna/cna_fwimg.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/brocade/bna/cna_fwimg.c
++++ linux/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);
+Index: linux/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
++++ linux/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)
+Index: linux/drivers/net/ethernet/intel/e100.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/intel/e100.c
++++ linux/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,
+Index: linux/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
++++ linux/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;
+ }
+Index: linux/drivers/net/ethernet/smsc/smc91c92_cs.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/smsc/smc91c92_cs.c
++++ linux/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++) {
+Index: linux/drivers/net/ethernet/sun/cassini.c
+===================================================================
+--- linux.orig/drivers/net/ethernet/sun/cassini.c
++++ linux/drivers/net/ethernet/sun/cassini.c
+@@ -794,11 +794,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);
+Index: linux/drivers/net/hamradio/yam.c
+===================================================================
+--- linux.orig/drivers/net/hamradio/yam.c
++++ linux/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]);
+Index: linux/drivers/net/usb/kaweth.c
+===================================================================
+--- linux.orig/drivers/net/usb/kaweth.c
++++ linux/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",
+Index: linux/drivers/net/wireless/ath/ath9k/hif_usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/ath/ath9k/hif_usb.c
++++ linux/drivers/net/wireless/ath/ath9k/hif_usb.c
+@@ -1222,9 +1222,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;
+ }
+
+Index: linux/drivers/net/wireless/ath/carl9170/usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/ath/carl9170/usb.c
++++ linux/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);
+ }
+
+Index: linux/drivers/net/wireless/atmel/at76c50x-usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/atmel/at76c50x-usb.c
++++ linux/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);
+Index: linux/drivers/net/wireless/atmel/atmel.c
+===================================================================
+--- linux.orig/drivers/net/wireless/atmel/atmel.c
++++ linux/drivers/net/wireless/atmel/atmel.c
+@@ -3896,12 +3896,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;
+Index: linux/drivers/net/wireless/broadcom/b43/main.c
+===================================================================
+--- linux.orig/drivers/net/wireless/broadcom/b43/main.c
++++ linux/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;
+Index: linux/drivers/net/wireless/broadcom/b43legacy/main.c
+===================================================================
+--- linux.orig/drivers/net/wireless/broadcom/b43legacy/main.c
++++ linux/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);
+Index: linux/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
+===================================================================
+--- linux.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
++++ linux/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));
+ }
+Index: linux/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intel/ipw2x00/ipw2100.c
++++ linux/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+@@ -8370,12 +8370,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);
+
+Index: linux/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intel/ipw2x00/ipw2200.c
++++ linux/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+@@ -3393,10 +3393,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);
+Index: linux/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intel/iwlegacy/3945-mac.c
++++ linux/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+@@ -1835,7 +1835,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
+Index: linux/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
++++ linux/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+@@ -183,8 +183,6 @@ static int iwl_request_firmware(struct i
+ }
+
+ 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", cfg->fw_name_pre,
+ cfg->ucode_api_max);
+Index: linux/drivers/net/wireless/intersil/orinoco/fw.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intersil/orinoco/fw.c
++++ linux/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);
+
+Index: linux/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
++++ linux/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;
+ }
+
+Index: linux/drivers/net/wireless/intersil/p54/p54pci.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intersil/p54/p54pci.c
++++ linux/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;
+ }
+Index: linux/drivers/net/wireless/intersil/p54/p54spi.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intersil/p54/p54spi.c
++++ linux/drivers/net/wireless/intersil/p54/p54spi.c
+@@ -157,10 +157,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) {
+Index: linux/drivers/net/wireless/intersil/p54/p54usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/intersil/p54/p54usb.c
++++ linux/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);
+Index: linux/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/marvell/libertas_tf/if_usb.c
++++ linux/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;
+ }
+Index: linux/drivers/net/wireless/marvell/mwifiex/main.c
+===================================================================
+--- linux.orig/drivers/net/wireless/marvell/mwifiex/main.c
++++ linux/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;
+Index: linux/drivers/net/wireless/marvell/mwl8k.c
+===================================================================
+--- linux.orig/drivers/net/wireless/marvell/mwl8k.c
++++ linux/drivers/net/wireless/marvell/mwl8k.c
+@@ -5735,16 +5735,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);
+@@ -5779,11 +5775,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)
+@@ -5821,10 +5814,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;
+Index: linux/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
+===================================================================
+--- linux.orig/drivers/net/wireless/ralink/rt2x00/rt2x00firmware.c
++++ linux/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");
+Index: linux/drivers/net/wireless/realtek/rtlwifi/core.c
+===================================================================
+--- linux.orig/drivers/net/wireless/realtek/rtlwifi/core.c
++++ linux/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;
+ }
+Index: linux/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+===================================================================
+--- linux.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
++++ linux/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;
+ }
+Index: linux/drivers/net/wireless/ti/wl1251/main.c
+===================================================================
+--- linux.orig/drivers/net/wireless/ti/wl1251/main.c
++++ linux/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",
+Index: linux/drivers/net/wireless/ti/wlcore/main.c
+===================================================================
+--- linux.orig/drivers/net/wireless/ti/wlcore/main.c
++++ linux/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",
+Index: linux/drivers/net/wireless/zydas/zd1201.c
+===================================================================
+--- linux.orig/drivers/net/wireless/zydas/zd1201.c
++++ linux/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;
+ }
+Index: linux/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
+===================================================================
+--- linux.orig/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
++++ linux/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)
+Index: linux/drivers/scsi/advansys.c
+===================================================================
+--- linux.orig/drivers/scsi/advansys.c
++++ linux/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;
+ }
+Index: linux/drivers/scsi/aic94xx/aic94xx_init.c
+===================================================================
+--- linux.orig/drivers/scsi/aic94xx/aic94xx_init.c
++++ linux/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;
+ }
+Index: linux/drivers/scsi/aic94xx/aic94xx_seq.c
+===================================================================
+--- linux.orig/drivers/scsi/aic94xx/aic94xx_seq.c
++++ linux/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) {
+Index: linux/drivers/scsi/bfa/bfad.c
+===================================================================
+--- linux.orig/drivers/scsi/bfa/bfad.c
++++ linux/drivers/scsi/bfa/bfad.c
+@@ -1743,7 +1743,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;
+ }
+Index: linux/drivers/scsi/ipr.c
+===================================================================
+--- linux.orig/drivers/scsi/ipr.c
++++ linux/drivers/scsi/ipr.c
+@@ -4102,10 +4102,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;
+
+Index: linux/drivers/scsi/pm8001/pm8001_ctl.c
+===================================================================
+--- linux.orig/drivers/scsi/pm8001/pm8001_ctl.c
++++ linux/drivers/scsi/pm8001/pm8001_ctl.c
+@@ -846,9 +846,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;
+ }
+Index: linux/drivers/scsi/qla1280.c
+===================================================================
+--- linux.orig/drivers/scsi/qla1280.c
++++ linux/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;
+ }
+Index: linux/drivers/scsi/qla2xxx/qla_init.c
+===================================================================
+--- linux.orig/drivers/scsi/qla2xxx/qla_init.c
++++ linux/drivers/scsi/qla2xxx/qla_init.c
+@@ -8316,10 +8316,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;
+ }
+
+@@ -8422,9 +8418,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;
+ }
+
+Index: linux/drivers/scsi/qla2xxx/qla_nx.c
+===================================================================
+--- linux.orig/drivers/scsi/qla2xxx/qla_nx.c
++++ linux/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,
+Index: linux/drivers/scsi/qla2xxx/qla_os.c
+===================================================================
+--- linux.orig/drivers/scsi/qla2xxx/qla_os.c
++++ linux/drivers/scsi/qla2xxx/qla_os.c
+@@ -7651,8 +7651,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;
+ }
+Index: linux/drivers/scsi/qlogicpti.c
+===================================================================
+--- linux.orig/drivers/scsi/qlogicpti.c
++++ linux/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);
+Index: linux/drivers/staging/rtl8192u/r819xU_firmware.c
+===================================================================
+--- linux.orig/drivers/staging/rtl8192u/r819xU_firmware.c
++++ linux/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");
+Index: linux/drivers/staging/rtl8712/hal_init.c
+===================================================================
+--- linux.orig/drivers/staging/rtl8712/hal_init.c
++++ linux/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");
+Index: linux/drivers/staging/vt6656/main_usb.c
+===================================================================
+--- linux.orig/drivers/staging/vt6656/main_usb.c
++++ linux/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);
+Index: linux/drivers/tty/moxa.c
+===================================================================
+--- linux.orig/drivers/tty/moxa.c
++++ linux/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);
+
+Index: linux/drivers/tty/serial/icom.c
+===================================================================
+--- linux.orig/drivers/tty/serial/icom.c
++++ linux/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;
+ }
+Index: linux/drivers/tty/serial/ucc_uart.c
+===================================================================
+--- linux.orig/drivers/tty/serial/ucc_uart.c
++++ linux/drivers/tty/serial/ucc_uart.c
+@@ -1151,10 +1151,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;
+
+Index: linux/drivers/usb/atm/cxacru.c
+===================================================================
+--- linux.orig/drivers/usb/atm/cxacru.c
++++ linux/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;
+ }
+
+Index: linux/drivers/usb/atm/ueagle-atm.c
+===================================================================
+--- linux.orig/drivers/usb/atm/ueagle-atm.c
++++ linux/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;
+Index: linux/drivers/usb/misc/emi26.c
+===================================================================
+--- linux.orig/drivers/usb/misc/emi26.c
++++ linux/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);
+Index: linux/drivers/usb/misc/ezusb.c
+===================================================================
+--- linux.orig/drivers/usb/misc/ezusb.c
++++ linux/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)
+Index: linux/drivers/usb/misc/isight_firmware.c
+===================================================================
+--- linux.orig/drivers/usb/misc/isight_firmware.c
++++ linux/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;
+ }
+Index: linux/drivers/usb/serial/io_edgeport.c
+===================================================================
+--- linux.orig/drivers/usb/serial/io_edgeport.c
++++ linux/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];
+Index: linux/drivers/usb/serial/io_ti.c
+===================================================================
+--- linux.orig/drivers/usb/serial/io_ti.c
++++ linux/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;
+ }
+
+Index: linux/drivers/usb/serial/ti_usb_3410_5052.c
+===================================================================
+--- linux.orig/drivers/usb/serial/ti_usb_3410_5052.c
++++ linux/drivers/usb/serial/ti_usb_3410_5052.c
+@@ -1631,10 +1631,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);
+Index: linux/drivers/video/fbdev/broadsheetfb.c
+===================================================================
+--- linux.orig/drivers/video/fbdev/broadsheetfb.c
++++ linux/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)) {
+Index: linux/drivers/video/fbdev/metronomefb.c
+===================================================================
+--- linux.orig/drivers/video/fbdev/metronomefb.c
++++ linux/drivers/video/fbdev/metronomefb.c
+@@ -679,10 +679,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);
+Index: linux/sound/drivers/vx/vx_hwdep.c
+===================================================================
+--- linux.orig/sound/drivers/vx/vx_hwdep.c
++++ linux/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);
+Index: linux/sound/isa/msnd/msnd_pinnacle.c
+===================================================================
+--- linux.orig/sound/isa/msnd/msnd_pinnacle.c
++++ linux/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) {
+Index: linux/sound/isa/sscape.c
+===================================================================
+--- linux.orig/sound/isa/sscape.c
++++ linux/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
+ snprintf(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",
+Index: linux/sound/isa/wavefront/wavefront_synth.c
+===================================================================
+--- linux.orig/sound/isa/wavefront/wavefront_synth.c
++++ linux/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;
+Index: linux/sound/pci/asihpi/hpidspcd.c
+===================================================================
+--- linux.orig/sound/pci/asihpi/hpidspcd.c
++++ linux/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)) {
+Index: linux/sound/pci/cs46xx/cs46xx_lib.c
+===================================================================
+--- linux.orig/sound/pci/cs46xx/cs46xx_lib.c
++++ linux/sound/pci/cs46xx/cs46xx_lib.c
+@@ -3199,11 +3199,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",
+Index: linux/sound/pci/echoaudio/echoaudio.c
+===================================================================
+--- linux.orig/sound/pci/echoaudio/echoaudio.c
++++ linux/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;
+Index: linux/sound/pci/emu10k1/emu10k1_main.c
+===================================================================
+--- linux.orig/sound/pci/emu10k1/emu10k1_main.c
++++ linux/sound/pci/emu10k1/emu10k1_main.c
+@@ -873,10 +873,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);
+Index: linux/sound/pci/hda/hda_intel.c
+===================================================================
+--- linux.orig/sound/pci/hda/hda_intel.c
++++ linux/sound/pci/hda/hda_intel.c
+@@ -2017,8 +2017,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);
+Index: linux/sound/pci/korg1212/korg1212.c
+===================================================================
+--- linux.orig/sound/pci/korg1212/korg1212.c
++++ linux/sound/pci/korg1212/korg1212.c
+@@ -2258,7 +2258,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;
+ }
+
+Index: linux/sound/pci/mixart/mixart_hwdep.c
+===================================================================
+--- linux.orig/sound/pci/mixart/mixart_hwdep.c
++++ linux/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);
+Index: linux/sound/pci/pcxhr/pcxhr_hwdep.c
+===================================================================
+--- linux.orig/sound/pci/pcxhr/pcxhr_hwdep.c
++++ linux/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);
+Index: linux/sound/pci/riptide/riptide.c
+===================================================================
+--- linux.orig/sound/pci/riptide/riptide.c
++++ linux/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) {
+Index: linux/sound/pci/rme9652/hdsp.c
+===================================================================
+--- linux.orig/sound/pci/rme9652/hdsp.c
++++ linux/sound/pci/rme9652/hdsp.c
+@@ -5201,11 +5201,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",
+Index: linux/sound/soc/codecs/wm2000.c
+===================================================================
+--- linux.orig/sound/soc/codecs/wm2000.c
++++ linux/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;
+Index: linux/sound/usb/6fire/firmware.c
+===================================================================
+--- linux.orig/sound/usb/6fire/firmware.c
++++ linux/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 000000000..092a74496
--- /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 000000000..35dacbf59
--- /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: http://mid.gmane.org/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
+@@ -2697,7 +2697,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
+@@ -6822,6 +6822,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
+@@ -3008,6 +3008,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
+@@ -1579,5 +1579,8 @@
+
+ MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
+ 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 000000000..8f9c21f56
--- /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 000000000..2c133d335
--- /dev/null
+++ b/debian/patches/bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch
@@ -0,0 +1,17 @@
+From: Ben Hutchings <benh@debian.org>
+Date: Sat, 15 Jan 2022 22:30:49 +0100
+Subject: libapi: Define _FORTIFY_SOURCE as 2, not empty
+
+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 000000000..8e0a7ee76
--- /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/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 000000000..fe502df7e
--- /dev/null
+++ b/debian/patches/bugfix/all/radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch
@@ -0,0 +1,135 @@
+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
+Forwarded: no
+
+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,amdgpu} when a device is probed, and abort if it
+is missing, except for the pre-R600 case.
+
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 29 ++++++++++++++++++++++++
+ drivers/gpu/drm/radeon/radeon_drv.c | 30 +++++++++++++++++++++++++
+ 2 files changed, 59 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -39,6 +39,8 @@
+ #include <linux/cc_platform.h>
+ #include <linux/fb.h>
+ #include <linux/dynamic_debug.h>
++#include <linux/namei.h>
++#include <linux/path.h>
+
+ #include "amdgpu.h"
+ #include "amdgpu_irq.h"
+@@ -2039,6 +2041,28 @@ static void amdgpu_get_secondary_funcs(s
+ }
+ }
+
++/* Test that /lib/firmware/amdgpu 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 amdgpu_firmware_installed(void)
++{
++#if IS_BUILTIN(CONFIG_DRM_AMDGPU)
++ /* It may be too early to tell. Assume it's there. */
++ return true;
++#else
++ struct path path;
++
++ if (kern_path("/lib/firmware/amdgpu", LOOKUP_DIRECTORY | LOOKUP_FOLLOW,
++ &path) == 0) {
++ path_put(&path);
++ return true;
++ }
++
++ return false;
++#endif
++}
++
+ static int amdgpu_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+ {
+@@ -2122,6 +2146,11 @@ static int amdgpu_pci_probe(struct pci_d
+ }
+ #endif
+
++ if (!amdgpu_firmware_installed()) {
++ DRM_ERROR("amdgpu requires firmware installed\n");
++ return -ENODEV;
++ }
++
+ adev = devm_drm_dev_alloc(&pdev->dev, &amdgpu_kms_driver, typeof(*adev), ddev);
+ if (IS_ERR(adev))
+ return PTR_ERR(adev);
+--- a/drivers/gpu/drm/radeon/radeon_drv.c
++++ b/drivers/gpu/drm/radeon/radeon_drv.c
+@@ -48,6 +48,8 @@
+ #include <drm/drm_probe_helper.h>
+ #include <drm/drm_vblank.h>
+ #include <drm/radeon_drm.h>
++#include <linux/namei.h>
++#include <linux/path.h>
+
+ #include "radeon_drv.h"
+ #include "radeon.h"
+@@ -284,6 +286,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)
+ {
+@@ -324,6 +348,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 000000000..3818dbb17
--- /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 000000000..2d8f29d25
--- /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 000000000..80a19b554
--- /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: http://mid.gmane.org/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-pmu-events-fix-reproducibility.patch b/debian/patches/bugfix/all/tools-perf-pmu-events-fix-reproducibility.patch
new file mode 100644
index 000000000..cd4f5c5a3
--- /dev/null
+++ b/debian/patches/bugfix/all/tools-perf-pmu-events-fix-reproducibility.patch
@@ -0,0 +1,26 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 25 Aug 2019 13:49:41 +0100
+Subject: tools/perf: pmu-events: Fix reproducibility
+Forwarded: https://lore.kernel.org/lkml/20190825131329.naqzd5kwg7mw5d3f@decadent.org.uk/T/#u
+
+jevents.py enumerates files and outputs the corresponding C structs in
+the order they are found. This makes it sensitive to directory
+ordering, so that the perf executable is not reproducible.
+
+To avoid this, sort the entries returned by os.scandir() before
+processing them.
+
+References: https://tests.reproducible-builds.org/debian/dbdtxt/bullseye/i386/linux_4.19.37-6.diffoscope.txt.gz
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/tools/perf/pmu-events/jevents.py
++++ b/tools/perf/pmu-events/jevents.py
+@@ -663,7 +663,7 @@ def main() -> None:
+ def ftw(path: str, parents: Sequence[str],
+ action: Callable[[Sequence[str], os.DirEntry], None]) -> None:
+ """Replicate the directory/file walking behavior of C's file tree walk."""
+- for item in os.scandir(path):
++ for item in sorted(os.scandir(path), key=(lambda item: item.name)):
+ action(parents, item)
+ if item.is_dir():
+ ftw(item.path, parents + [item.name], action)
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 000000000..9766e0e4a
--- /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/usbip-document-tcp-wrappers.patch b/debian/patches/bugfix/all/usbip-document-tcp-wrappers.patch
new file mode 100644
index 000000000..d9d7b301d
--- /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/all/wifi-mt76-do-not-run-mt76_unregister_device-on-unregistered-hw.patch b/debian/patches/bugfix/all/wifi-mt76-do-not-run-mt76_unregister_device-on-unregistered-hw.patch
new file mode 100644
index 000000000..4635a6778
--- /dev/null
+++ b/debian/patches/bugfix/all/wifi-mt76-do-not-run-mt76_unregister_device-on-unregistered-hw.patch
@@ -0,0 +1,78 @@
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Thu, 23 Feb 2023 00:10:25 +0100
+Subject: wifi: mt76: do not run mt76_unregister_device() on unregistered hw
+Origin: https://patchwork.kernel.org/project/linux-wireless/patch/be3457d82f4e44bb71a22b2b5db27b644a37b1e1.1677107277.git.lorenzo@kernel.org/
+Bug-Debian: https://bugs.debian.org/1029116
+
+Trying to probe a mt7921e pci card without firmware results in a
+successful probe where ieee80211_register_hw hasn't been called. When
+removing the driver, ieee802111_unregister_hw is called unconditionally
+leading to a kernel NULL pointer dereference.
+Fix the issue running mt76_unregister_device routine just for registered
+hw.
+
+Link: https://bugs.debian.org/1029116
+Link: https://bugs.kali.org/view.php?id=8140
+Reported-by: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Fixes: 1c71e03afe4b ("mt76: mt7921: move mt7921_init_hw in a dedicated work")
+Tested-by: Helmut Grohne <helmut@freexian.com>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+
+Currently queued for review for the v6.3 release cycle, backported in
+advance to prevent users from getting stuck in the installer.
+
+Signed-off-by: Cyril Brulebois <kibi@debian.org>
+
+---
+ drivers/net/wireless/mediatek/mt76/mac80211.c | 8 ++++++++
+ drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
++++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
+@@ -522,6 +522,7 @@ int mt76_register_phy(struct mt76_phy *p
+ if (ret)
+ return ret;
+
++ set_bit(MT76_STATE_REGISTERED, &phy->state);
+ phy->dev->phys[phy->band_idx] = phy;
+
+ return 0;
+@@ -532,6 +533,9 @@ void mt76_unregister_phy(struct mt76_phy
+ {
+ struct mt76_dev *dev = phy->dev;
+
++ if (!test_bit(MT76_STATE_REGISTERED, &phy->state))
++ return;
++
+ mt76_tx_status_check(dev, true);
+ ieee80211_unregister_hw(phy->hw);
+ dev->phys[phy->band_idx] = NULL;
+@@ -654,6 +658,7 @@ int mt76_register_device(struct mt76_dev
+ return ret;
+
+ WARN_ON(mt76_worker_setup(hw, &dev->tx_worker, NULL, "tx"));
++ set_bit(MT76_STATE_REGISTERED, &phy->state);
+ sched_set_fifo_low(dev->tx_worker.task);
+
+ return 0;
+@@ -664,6 +669,9 @@ void mt76_unregister_device(struct mt76_
+ {
+ struct ieee80211_hw *hw = dev->hw;
+
++ if (!test_bit(MT76_STATE_REGISTERED, &dev->phy.state))
++ return;
++
+ if (IS_ENABLED(CONFIG_MT76_LEDS))
+ mt76_led_cleanup(dev);
+ mt76_tx_status_check(dev, true);
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -388,6 +388,7 @@ struct mt76_tx_cb {
+
+ enum {
+ MT76_STATE_INITIALIZED,
++ MT76_STATE_REGISTERED,
+ MT76_STATE_RUNNING,
+ MT76_STATE_MCU_RUNNING,
+ MT76_SCANNING,
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 000000000..3da69882e
--- /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 000000000..9e6622fb0
--- /dev/null
+++ b/debian/patches/bugfix/arm/arm-dts-kirkwood-fix-sata-pinmux-ing-for-ts419.patch
@@ -0,0 +1,37 @@
+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://www.spinics.net/lists/arm-kernel/msg563610.html
+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/kirkwood-ts419.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/kirkwood-ts419.dtsi b/arch/arm/boot/dts/kirkwood-ts419.dtsi
+index 02bd53762705..532506cb0f4a 100644
+--- a/arch/arm/boot/dts/kirkwood-ts419.dtsi
++++ b/arch/arm/boot/dts/kirkwood-ts419.dtsi
+@@ -73,3 +73,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 000000000..1bdd37fbe
--- /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://marc.info/?l=linux-arm-kernel&m=153134944429241
+
+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 000000000..fc1e76a02
--- /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://patchwork.codeaurora.org/patch/547277/
+
+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/arm64/arm64-dts-rockchip-fix-spdif-fe460000-ordering-on-rk.patch b/debian/patches/bugfix/arm64/arm64-dts-rockchip-fix-spdif-fe460000-ordering-on-rk.patch
new file mode 100644
index 000000000..e7ee12ead
--- /dev/null
+++ b/debian/patches/bugfix/arm64/arm64-dts-rockchip-fix-spdif-fe460000-ordering-on-rk.patch
@@ -0,0 +1,63 @@
+From: Heiko Stuebner <heiko@sntech.de>
+Date: Sun, 30 Oct 2022 20:34:42 +0100
+Subject: arm64: dts: rockchip: fix spdif@fe460000 ordering on rk356x
+Origin: https://git.kernel.org/linus/d4eade428d22f2ac5f32b12ec183fdff84dc07a6
+
+Move the node to its correct position, based on its
+mmio-address.
+
+Link: https://lore.kernel.org/all/20221030193708.1671069-1-heiko@sntech.de
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk356x.dtsi | 28 ++++++++++++------------
+ 1 file changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+index 164708f1eb67..10e3a0862602 100644
+--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+@@ -1049,20 +1049,6 @@
+ status = "disabled";
+ };
+
+- spdif: spdif@fe460000 {
+- compatible = "rockchip,rk3568-spdif";
+- reg = <0x0 0xfe460000 0x0 0x1000>;
+- interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+- clock-names = "mclk", "hclk";
+- clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>;
+- dmas = <&dmac1 1>;
+- dma-names = "tx";
+- pinctrl-names = "default";
+- pinctrl-0 = <&spdifm0_tx>;
+- #sound-dai-cells = <0>;
+- status = "disabled";
+- };
+-
+ i2s0_8ch: i2s@fe400000 {
+ compatible = "rockchip,rk3568-i2s-tdm";
+ reg = <0x0 0xfe400000 0x0 0x1000>;
+@@ -1142,6 +1128,20 @@
+ status = "disabled";
+ };
+
++ spdif: spdif@fe460000 {
++ compatible = "rockchip,rk3568-spdif";
++ reg = <0x0 0xfe460000 0x0 0x1000>;
++ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
++ clock-names = "mclk", "hclk";
++ clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>;
++ dmas = <&dmac1 1>;
++ dma-names = "tx";
++ pinctrl-names = "default";
++ pinctrl-0 = <&spdifm0_tx>;
++ #sound-dai-cells = <0>;
++ status = "disabled";
++ };
++
+ dmac0: dma-controller@fe530000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0x0 0xfe530000 0x0 0x4000>;
+--
+2.39.0
+
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 000000000..d09035691
--- /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 000000000..a00a2a485
--- /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 000000000..31eb2eb5d
--- /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 000000000..f9baa7bd3
--- /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 000000000..cfbf98e82
--- /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 000000000..62b4eb7de
--- /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/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 000000000..205510d6b
--- /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 000000000..3b33f845a
--- /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 000000000..8a565c6c0
--- /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 000000000..89e626b6b
--- /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 000000000..9f21e0705
--- /dev/null
+++ b/debian/patches/debian/btrfs-warn-about-raid5-6-being-experimental-at-mount.patch
@@ -0,0 +1,35 @@
+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]
+---
+ fs/btrfs/disk-io.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -3060,6 +3060,15 @@ retry_root_backup:
+ 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);
++ }
++
+ /*
+ * Mount does not set all options immediately, we can do it now and do
+ * not have to wait for transaction commit
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 000000000..70b446860
--- /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 000000000..83583184e
--- /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 000000000..0e5176908
--- /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 000000000..840cf24d7
--- /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 000000000..4e42da9a9
--- /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 000000000..3bf7ca6b3
--- /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 000000000..4adc90c2d
--- /dev/null
+++ b/debian/patches/debian/dfsg/video-remove-nvidiafb-and-rivafb.patch
@@ -0,0 +1,128 @@
+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
+@@ -866,99 +866,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
+- 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
+- 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/dfsg/vs6624-disable.patch b/debian/patches/debian/dfsg/vs6624-disable.patch
new file mode 100644
index 000000000..182be87d3
--- /dev/null
+++ b/debian/patches/debian/dfsg/vs6624-disable.patch
@@ -0,0 +1,19 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 27 May 2012 01:56:58 +0100
+Subject: vs6624: mark as broken
+Forwarded: not-needed
+
+---
+ drivers/media/i2c/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -754,6 +754,7 @@ config VIDEO_SR030PC30
+ This driver supports SR030PC30 VGA camera from Siliconfile
+
+ config VIDEO_VS6624
++ depends on BROKEN
+ tristate "ST VS6624 sensor support"
+ depends on VIDEO_DEV && I2C
+ help
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 000000000..14f0ee40b
--- /dev/null
+++ b/debian/patches/debian/documentation-drop-sphinx-version-check.patch
@@ -0,0 +1,47 @@
+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 | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/Documentation/Makefile
++++ b/Documentation/Makefile
+@@ -92,14 +92,12 @@ quiet_cmd_sphinx = SPHINX $@ --> file:/
+ fi
+
+ htmldocs:
+- @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
+
+ 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)
+@@ -111,7 +109,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; \
+@@ -121,11 +118,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 000000000..860812230
--- /dev/null
+++ b/debian/patches/debian/export-symbols-needed-by-android-drivers.patch
@@ -0,0 +1,113 @@
+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
+@@ -813,6 +813,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
+@@ -7052,6 +7052,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
+@@ -243,6 +243,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
+@@ -1757,6 +1757,7 @@ void zap_page_range(struct vm_area_struc
+ mmu_notifier_invalidate_range_end(&range);
+ tlb_finish_mmu(&tlb);
+ }
++EXPORT_SYMBOL_GPL(zap_page_range);
+
+ /**
+ * zap_page_range_single - remove user pages in a given range
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -4245,6 +4245,7 @@ int shmem_zero_setup(struct vm_area_stru
+
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(shmem_zero_setup);
+
+ /**
+ * shmem_read_mapping_page_gfp - read into page cache, using specified page allocation flags.
+--- a/security/security.c
++++ b/security/security.c
+@@ -752,24 +752,28 @@ int security_binder_set_context_mgr(cons
+ {
+ return call_int_hook(binder_set_context_mgr, 0, mgr);
+ }
++EXPORT_SYMBOL_GPL(security_binder_set_context_mgr);
+
+ int security_binder_transaction(const struct cred *from,
+ const struct cred *to)
+ {
+ return call_int_hook(binder_transaction, 0, from, to);
+ }
++EXPORT_SYMBOL_GPL(security_binder_transaction);
+
+ int security_binder_transfer_binder(const struct cred *from,
+ const struct cred *to)
+ {
+ return call_int_hook(binder_transfer_binder, 0, from, to);
+ }
++EXPORT_SYMBOL_GPL(security_binder_transfer_binder);
+
+ int security_binder_transfer_file(const struct cred *from,
+ const struct cred *to, struct file *file)
+ {
+ return call_int_hook(binder_transfer_file, 0, from, to, file);
+ }
++EXPORT_SYMBOL_GPL(security_binder_transfer_file);
+
+ int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
+ {
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 000000000..88a2b15b3
--- /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 000000000..27bc69903
--- /dev/null
+++ b/debian/patches/debian/firmware_class-refer-to-debian-wiki-firmware-page.patch
@@ -0,0 +1,52 @@
+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
+Forwarded: not-needed
+
+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 and amdgpu drivers, where we have
+an early check to avoid failing at a point where we cannot display
+anything.
+
+---
+--- a/drivers/base/firmware_loader/main.c
++++ b/drivers/base/firmware_loader/main.c
+@@ -334,9 +334,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
+@@ -367,6 +367,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;
+ }
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -626,6 +626,7 @@ static int amdgpu_pci_probe(struct pci_d
+
+ if (!amdgpu_firmware_installed()) {
+ DRM_ERROR("amdgpu 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/fjes-disable-autoload.patch b/debian/patches/debian/fjes-disable-autoload.patch
new file mode 100644
index 000000000..873c6906e
--- /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 000000000..eab0e78ee
--- /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 000000000..f98a51426
--- /dev/null
+++ b/debian/patches/debian/gitignore.patch
@@ -0,0 +1,52 @@
+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 svn.
+Forwarded: not-needed
+
+[bwh: Tweak further for pure git]
+
+Index: linux/.gitignore
+===================================================================
+--- linux.orig/.gitignore
++++ linux/.gitignore
+@@ -76,11 +76,6 @@ modules.order
+ /*.spec
+
+ #
+-# Debian directory (make deb-pkg)
+-#
+-/debian/
+-
+-#
+ # Snap directory (make snap-pkg)
+ #
+ /snap/
+@@ -91,17 +86,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
+-!.mailmap
+-!.rustfmt.toml
+-
+-#
+ # Generated include files
+ #
+ /include/config/
+@@ -168,3 +152,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 000000000..b532d0054
--- /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 000000000..1b216d0d1
--- /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 000000000..56fdc4cb4
--- /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 -
+ -falign-functions=32 -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 +43,7 @@ drivers-y += arch/ia64/pci/ arch/ia64/
+
+ PHONY += compressed check
+
+-all: compressed unwcheck
++all: compressed
+
+ compressed: vmlinux.gz
+
+@@ -64,9 +55,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 000000000..c8061436d
--- /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 000000000..ec23040d8
--- /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 000000000..f9a22d892
--- /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' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
+
+ # Re-generate module BTFs if either module's .ko or vmlinux changed
+-$(modules): %.ko: %.o %.mod.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE
++$(modules): %.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 000000000..2196c8a43
--- /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
+@@ -395,36 +395,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
+
+@@ -540,6 +510,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 000000000..f0d5c80d7
--- /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 000000000..ca4de2daa
--- /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 000000000..b8fe8b44c
--- /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 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 000000000..20dff251c
--- /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 000000000..3582f4ba3
--- /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 000000000..207f9751e
--- /dev/null
+++ b/debian/patches/debian/ntfs-mark-it-as-broken.patch
@@ -0,0 +1,22 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 25 Apr 2019 15:31:33 +0100
+Subject: ntfs: mark it as broken
+
+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 NLS
+ help
+ NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003.
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 000000000..89df33ab0
--- /dev/null
+++ b/debian/patches/debian/perf-traceevent-support-asciidoctor-for-documentatio.patch
@@ -0,0 +1,54 @@
+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/lib/traceevent/Documentation/Makefile | 2 +-
+ tools/perf/Documentation/Makefile | 2 +-
+ 3 files changed, 3 insertions(+), 3 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/lib/traceevent/Documentation/Makefile b/tools/lib/traceevent/Documentation/Makefile
+index aa72ab96c3c1..f3a4ff3b8b0e 100644
+--- a/tools/lib/traceevent/Documentation/Makefile
++++ b/tools/lib/traceevent/Documentation/Makefile
+@@ -28,7 +28,7 @@ mandir?=$(prefix)/share/man
+ man3dir=$(mandir)/man3
+
+ 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 000000000..3343aecac
--- /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 000000000..c616fa46e
--- /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 000000000..e593f5144
--- /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 000000000..c3f174741
--- /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 000000000..eacd9ce17
--- /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
+@@ -947,21 +947,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)'
+ ifndef NO_LIBBPF
+ $(call QUIET_INSTALL, bpf-headers) \
+ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'; \
diff --git a/debian/patches/debian/uname-version-timestamp.patch b/debian/patches/debian/uname-version-timestamp.patch
new file mode 100644
index 000000000..4be158e09
--- /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 000000000..1425f555a
--- /dev/null
+++ b/debian/patches/debian/version.patch
@@ -0,0 +1,186 @@
+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(-)
+
+Index: linux/Makefile
+===================================================================
+--- linux.orig/Makefile
++++ linux/Makefile
+@@ -1263,7 +1263,8 @@ PHONY += prepare archprepare
+
+ archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
+ asm-generic $(version_h) $(autoksyms_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
+@@ -1321,6 +1322,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
+@@ -1335,6 +1346,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 \
+Index: linux/arch/ia64/kernel/process.c
+===================================================================
+--- linux.orig/arch/ia64/kernel/process.c
++++ linux/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);
+Index: linux/arch/powerpc/kernel/process.c
+===================================================================
+--- linux.orig/arch/powerpc/kernel/process.c
++++ linux/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>
+@@ -1520,8 +1521,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);
+Index: linux/arch/x86/um/sysrq_64.c
+===================================================================
+--- linux.orig/arch/x86/um/sysrq_64.c
++++ linux/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),
+Index: linux/kernel/hung_task.c
+===================================================================
+--- linux.orig/kernel/hung_task.c
++++ linux/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);
+Index: linux/lib/dump_stack.c
+===================================================================
+--- linux.orig/lib/dump_stack.c
++++ linux/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 000000000..edbf8657f
--- /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 000000000..c33ac0c9d
--- /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 000000000..f2278ce63
--- /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 000000000..e46aefe4d
--- /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 000000000..7c32a018f
--- /dev/null
+++ b/debian/patches/features/all/db-mok-keyring/trust-machine-keyring-by-default.patch
@@ -0,0 +1,16 @@
+Author: Luca Boccassi <bluca@debian.org>
+Description: trust machine keyring (MoK) by default
+ 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.
+--- a/security/integrity/platform_certs/machine_keyring.c
++++ b/security/integrity/platform_certs/machine_keyring.c
+@@ -69,8 +69,7 @@
+ if (!initialized) {
+ initialized = true;
+
+- 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 000000000..a24ba17ef
--- /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/ethernet-microsoft/0001-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch b/debian/patches/features/all/ethernet-microsoft/0001-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch
new file mode 100644
index 000000000..f17692d6c
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0001-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch
@@ -0,0 +1,89 @@
+From 7c765fdf86fc9089b75d15ee33cdf30d9d9115d6 Mon Sep 17 00:00:00 2001
+From: Bastian Blank <waldi@debian.org>
+Date: Wed, 12 Jul 2023 14:13:14 +0000
+Subject: [PATCH 01/23] net: Remove the obsolte u64_stats_fetch_*_irq() users
+ (drivers).
+
+Now that the 32bit UP oddity is gone and 32bit uses always a sequence
+count, there is no need for the fetch_irq() variants anymore.
+
+Convert to the regular interface.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit 068c38ad88ccb09e5e966d4db5cedab0e02b3b95)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 8 ++++----
+ drivers/net/ethernet/microsoft/mana/mana_ethtool.c | 8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 27a0f3af8aab..aec4bab6be56 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -315,10 +315,10 @@ static void mana_get_stats64(struct net_device *ndev,
+ rx_stats = &apc->rxqs[q]->stats;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
++ start = u64_stats_fetch_begin(&rx_stats->syncp);
+ packets = rx_stats->packets;
+ bytes = rx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+
+ st->rx_packets += packets;
+ st->rx_bytes += bytes;
+@@ -328,10 +328,10 @@ static void mana_get_stats64(struct net_device *ndev,
+ tx_stats = &apc->tx_qp[q].txq.stats;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
++ start = u64_stats_fetch_begin(&tx_stats->syncp);
+ packets = tx_stats->packets;
+ bytes = tx_stats->bytes;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+ st->tx_packets += packets;
+ st->tx_bytes += bytes;
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+index c530db76880f..96d55c91c969 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+@@ -90,13 +90,13 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
+ rx_stats = &apc->rxqs[q]->stats;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
++ start = u64_stats_fetch_begin(&rx_stats->syncp);
+ packets = rx_stats->packets;
+ bytes = rx_stats->bytes;
+ xdp_drop = rx_stats->xdp_drop;
+ xdp_tx = rx_stats->xdp_tx;
+ xdp_redirect = rx_stats->xdp_redirect;
+- } while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&rx_stats->syncp, start));
+
+ data[i++] = packets;
+ data[i++] = bytes;
+@@ -109,11 +109,11 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
+ tx_stats = &apc->tx_qp[q].txq.stats;
+
+ do {
+- start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
++ start = u64_stats_fetch_begin(&tx_stats->syncp);
+ packets = tx_stats->packets;
+ bytes = tx_stats->bytes;
+ xdp_xmit = tx_stats->xdp_xmit;
+- } while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
++ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+ data[i++] = packets;
+ data[i++] = bytes;
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0002-net-mana-Assign-interrupts-to-CPUs-based-on-NUMA-nod.patch b/debian/patches/features/all/ethernet-microsoft/0002-net-mana-Assign-interrupts-to-CPUs-based-on-NUMA-nod.patch
new file mode 100644
index 000000000..6fc9d9cc7
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0002-net-mana-Assign-interrupts-to-CPUs-based-on-NUMA-nod.patch
@@ -0,0 +1,114 @@
+From 8bdc2e0b4963e7cfd41b43ed117e8f0dec13fe29 Mon Sep 17 00:00:00 2001
+From: Saurabh Sengar <ssengar@linux.microsoft.com>
+Date: Mon, 31 Oct 2022 23:06:01 -0700
+Subject: [PATCH 02/23] net: mana: Assign interrupts to CPUs based on NUMA
+ nodes
+
+In large VMs with multiple NUMA nodes, network performance is usually
+best if network interrupts are all assigned to the same virtual NUMA
+node. This patch assigns online CPU according to a numa aware policy,
+local cpus are returned first, followed by non-local ones, then it wraps
+around.
+
+Signed-off-by: Saurabh Sengar <ssengar@linux.microsoft.com>
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Link: https://lore.kernel.org/r/1667282761-11547-1-git-send-email-ssengar@linux.microsoft.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+(cherry picked from commit 71fa6887eeca7b631528f9c7a39815498de8028c)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma.h | 1 +
+ .../net/ethernet/microsoft/mana/gdma_main.c | 30 +++++++++++++++++--
+ 2 files changed, 28 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma.h b/drivers/net/ethernet/microsoft/mana/gdma.h
+index 48b0ab56bdb0..68684a8bcead 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma.h
++++ b/drivers/net/ethernet/microsoft/mana/gdma.h
+@@ -356,6 +356,7 @@ struct gdma_context {
+ void __iomem *shm_base;
+ void __iomem *db_page_base;
+ u32 db_page_size;
++ int numa_node;
+
+ /* Shared memory chanenl (used to bootstrap HWC) */
+ struct shm_channel shm_channel;
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index d674ebda2053..abe9888a40aa 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -1208,8 +1208,10 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ struct gdma_context *gc = pci_get_drvdata(pdev);
+ struct gdma_irq_context *gic;
+ unsigned int max_irqs;
++ u16 *cpus;
++ cpumask_var_t req_mask;
+ int nvec, irq;
+- int err, i, j;
++ int err, i = 0, j;
+
+ if (max_queues_per_port > MANA_MAX_NUM_QUEUES)
+ max_queues_per_port = MANA_MAX_NUM_QUEUES;
+@@ -1228,7 +1230,21 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ goto free_irq_vector;
+ }
+
++ if (!zalloc_cpumask_var(&req_mask, GFP_KERNEL)) {
++ err = -ENOMEM;
++ goto free_irq;
++ }
++
++ cpus = kcalloc(nvec, sizeof(*cpus), GFP_KERNEL);
++ if (!cpus) {
++ err = -ENOMEM;
++ goto free_mask;
++ }
++ for (i = 0; i < nvec; i++)
++ cpus[i] = cpumask_local_spread(i, gc->numa_node);
++
+ for (i = 0; i < nvec; i++) {
++ cpumask_set_cpu(cpus[i], req_mask);
+ gic = &gc->irq_contexts[i];
+ gic->handler = NULL;
+ gic->arg = NULL;
+@@ -1243,13 +1259,17 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ irq = pci_irq_vector(pdev, i);
+ if (irq < 0) {
+ err = irq;
+- goto free_irq;
++ goto free_mask;
+ }
+
+ err = request_irq(irq, mana_gd_intr, 0, gic->name, gic);
+ if (err)
+- goto free_irq;
++ goto free_mask;
++ irq_set_affinity_and_hint(irq, req_mask);
++ cpumask_clear(req_mask);
+ }
++ free_cpumask_var(req_mask);
++ kfree(cpus);
+
+ err = mana_gd_alloc_res_map(nvec, &gc->msix_resource);
+ if (err)
+@@ -1260,6 +1280,9 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+
+ return 0;
+
++free_mask:
++ free_cpumask_var(req_mask);
++ kfree(cpus);
+ free_irq:
+ for (j = i - 1; j >= 0; j--) {
+ irq = pci_irq_vector(pdev, j);
+@@ -1389,6 +1412,7 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (!bar0_va)
+ goto free_gc;
+
++ gc->numa_node = dev_to_node(&pdev->dev);
+ gc->is_pf = mana_is_pf(pdev->device);
+ gc->bar0_va = bar0_va;
+ gc->dev = &pdev->dev;
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0003-net-mana-Add-support-for-auxiliary-device.patch b/debian/patches/features/all/ethernet-microsoft/0003-net-mana-Add-support-for-auxiliary-device.patch
new file mode 100644
index 000000000..a639b69c9
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0003-net-mana-Add-support-for-auxiliary-device.patch
@@ -0,0 +1,178 @@
+From 63ea159035f1c00da99016a1c71380d90f156ad4 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:19 -0700
+Subject: [PATCH 03/23] net: mana: Add support for auxiliary device
+
+In preparation for supporting MANA RDMA driver, add support for auxiliary
+device in the Ethernet driver. The RDMA device is modeled as an auxiliary
+device to the Ethernet device.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-2-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit a69839d4327d053b18d8e1b0e7ddeee78db78f4f)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/Kconfig | 1 +
+ drivers/net/ethernet/microsoft/mana/gdma.h | 2 +
+ .../ethernet/microsoft/mana/mana_auxiliary.h | 10 +++
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 83 ++++++++++++++++++-
+ 4 files changed, 95 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/ethernet/microsoft/mana/mana_auxiliary.h
+
+--- a/drivers/net/ethernet/microsoft/Kconfig
++++ b/drivers/net/ethernet/microsoft/Kconfig
+@@ -19,6 +19,7 @@ config MICROSOFT_MANA
+ tristate "Microsoft Azure Network Adapter (MANA) support"
+ depends on PCI_MSI && X86_64
+ depends on PCI_HYPERV
++ select AUXILIARY_BUS
+ select PAGE_POOL
+ help
+ This driver supports Microsoft Azure Network Adapter (MANA).
+--- a/drivers/net/ethernet/microsoft/mana/gdma.h
++++ b/drivers/net/ethernet/microsoft/mana/gdma.h
+@@ -204,6 +204,8 @@ struct gdma_dev {
+
+ /* GDMA driver specific pointer */
+ void *driver_data;
++
++ struct auxiliary_device *adev;
+ };
+
+ #define MINIMUM_SUPPORTED_PAGE_SIZE PAGE_SIZE
+--- /dev/null
++++ b/drivers/net/ethernet/microsoft/mana/mana_auxiliary.h
+@@ -0,0 +1,10 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/* Copyright (c) 2022, Microsoft Corporation. */
++
++#include "mana.h"
++#include <linux/auxiliary_bus.h>
++
++struct mana_adev {
++ struct auxiliary_device adev;
++ struct gdma_dev *mdev;
++};
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -14,6 +14,19 @@
+ #include <net/ip6_checksum.h>
+
+ #include "mana.h"
++#include "mana_auxiliary.h"
++
++static DEFINE_IDA(mana_adev_ida);
++
++static int mana_adev_idx_alloc(void)
++{
++ return ida_alloc(&mana_adev_ida, GFP_KERNEL);
++}
++
++static void mana_adev_idx_free(int idx)
++{
++ ida_free(&mana_adev_ida, idx);
++}
+
+ /* Microsoft Azure Network Adapter (MANA) functions */
+
+@@ -2145,6 +2158,69 @@ free_net:
+ return err;
+ }
+
++static void adev_release(struct device *dev)
++{
++ struct mana_adev *madev = container_of(dev, struct mana_adev, adev.dev);
++
++ kfree(madev);
++}
++
++static void remove_adev(struct gdma_dev *gd)
++{
++ struct auxiliary_device *adev = gd->adev;
++ int id = adev->id;
++
++ auxiliary_device_delete(adev);
++ auxiliary_device_uninit(adev);
++
++ mana_adev_idx_free(id);
++ gd->adev = NULL;
++}
++
++static int add_adev(struct gdma_dev *gd)
++{
++ struct auxiliary_device *adev;
++ struct mana_adev *madev;
++ int ret;
++
++ madev = kzalloc(sizeof(*madev), GFP_KERNEL);
++ if (!madev)
++ return -ENOMEM;
++
++ adev = &madev->adev;
++ ret = mana_adev_idx_alloc();
++ if (ret < 0)
++ goto idx_fail;
++ adev->id = ret;
++
++ adev->name = "rdma";
++ adev->dev.parent = gd->gdma_context->dev;
++ adev->dev.release = adev_release;
++ madev->mdev = gd;
++
++ ret = auxiliary_device_init(adev);
++ if (ret)
++ goto init_fail;
++
++ ret = auxiliary_device_add(adev);
++ if (ret)
++ goto add_fail;
++
++ gd->adev = adev;
++ return 0;
++
++add_fail:
++ auxiliary_device_uninit(adev);
++
++init_fail:
++ mana_adev_idx_free(adev->id);
++
++idx_fail:
++ kfree(madev);
++
++ return ret;
++}
++
+ int mana_probe(struct gdma_dev *gd, bool resuming)
+ {
+ struct gdma_context *gc = gd->gdma_context;
+@@ -2212,6 +2288,8 @@ int mana_probe(struct gdma_dev *gd, bool
+ break;
+ }
+ }
++
++ err = add_adev(gd);
+ out:
+ if (err)
+ mana_remove(gd, false);
+@@ -2228,6 +2306,10 @@ void mana_remove(struct gdma_dev *gd, bo
+ int err;
+ int i;
+
++ /* adev currently doesn't support suspending, always remove it */
++ if (gd->adev)
++ remove_adev(gd);
++
+ for (i = 0; i < ac->num_ports; i++) {
+ ndev = ac->ports[i];
+ if (!ndev) {
+@@ -2260,7 +2342,6 @@ void mana_remove(struct gdma_dev *gd, bo
+ }
+
+ mana_destroy_eq(ac);
+-
+ out:
+ mana_gd_deregister_device(gd);
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0004-net-mana-Record-the-physical-address-for-doorbell-pa.patch b/debian/patches/features/all/ethernet-microsoft/0004-net-mana-Record-the-physical-address-for-doorbell-pa.patch
new file mode 100644
index 000000000..21568f6aa
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0004-net-mana-Record-the-physical-address-for-doorbell-pa.patch
@@ -0,0 +1,63 @@
+From 108ed3960c8f1e65ad64b22a4a073c4e42204132 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:20 -0700
+Subject: [PATCH 04/23] net: mana: Record the physical address for doorbell
+ page region
+
+For supporting RDMA device with multiple user contexts with their
+individual doorbell pages, record the start address of doorbell page
+region for use by the RDMA driver to allocate user context doorbell IDs.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-3-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit f3dc096246091048677c45cfc0e24ad512927b52)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma.h | 2 ++
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma.h b/drivers/net/ethernet/microsoft/mana/gdma.h
+index df0ffe35db92..86d8a9e36005 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma.h
++++ b/drivers/net/ethernet/microsoft/mana/gdma.h
+@@ -354,9 +354,11 @@ struct gdma_context {
+ u32 test_event_eq_id;
+
+ bool is_pf;
++ phys_addr_t bar0_pa;
+ void __iomem *bar0_va;
+ void __iomem *shm_base;
+ void __iomem *db_page_base;
++ phys_addr_t phys_db_page_base;
+ u32 db_page_size;
+ int numa_node;
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index abe9888a40aa..a00bd88443d3 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -44,6 +44,9 @@ static void mana_gd_init_vf_regs(struct pci_dev *pdev)
+ gc->db_page_base = gc->bar0_va +
+ mana_gd_r64(gc, GDMA_REG_DB_PAGE_OFFSET);
+
++ gc->phys_db_page_base = gc->bar0_pa +
++ mana_gd_r64(gc, GDMA_REG_DB_PAGE_OFFSET);
++
+ gc->shm_base = gc->bar0_va + mana_gd_r64(gc, GDMA_REG_SHM_OFFSET);
+ }
+
+@@ -1407,6 +1410,7 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ mutex_init(&gc->eq_test_event_mutex);
+ pci_set_drvdata(pdev, gc);
++ gc->bar0_pa = pci_resource_start(pdev, 0);
+
+ bar0_va = pci_iomap(pdev, bar, 0);
+ if (!bar0_va)
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0005-net-mana-Handle-vport-sharing-between-devices.patch b/debian/patches/features/all/ethernet-microsoft/0005-net-mana-Handle-vport-sharing-between-devices.patch
new file mode 100644
index 000000000..f02172221
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0005-net-mana-Handle-vport-sharing-between-devices.patch
@@ -0,0 +1,150 @@
+From 35238c1a74198a73e35ed386a7a3992522de804d Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:21 -0700
+Subject: [PATCH 05/23] net: mana: Handle vport sharing between devices
+
+For outgoing packets, the PF requires the VF to configure the vport with
+corresponding protection domain and doorbell ID for the kernel or user
+context. The vport can't be shared between different contexts.
+
+Implement the logic to exclusively take over the vport by either the
+Ethernet device or RDMA device.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-4-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit b5c1c9855be3b5b978fde975a63df3cabc273faa)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana.h | 7 +++
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 53 ++++++++++++++++++-
+ 2 files changed, 58 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana.h b/drivers/net/ethernet/microsoft/mana/mana.h
+index d58be64374c8..2883a08dbfb5 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana.h
++++ b/drivers/net/ethernet/microsoft/mana/mana.h
+@@ -380,6 +380,10 @@ struct mana_port_context {
+ mana_handle_t port_handle;
+ mana_handle_t pf_filter_handle;
+
++ /* Mutex for sharing access to vport_use_count */
++ struct mutex vport_mutex;
++ int vport_use_count;
++
+ u16 port_idx;
+
+ bool port_is_up;
+@@ -631,4 +635,7 @@ struct mana_tx_package {
+ struct gdma_posted_wqe_info wqe_info;
+ };
+
++int mana_cfg_vport(struct mana_port_context *apc, u32 protection_dom_id,
++ u32 doorbell_pg_id);
++void mana_uncfg_vport(struct mana_port_context *apc);
+ #endif /* _MANA_H */
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index b9e2723ce167..c5ab5cb63cb7 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -646,13 +646,48 @@ static int mana_query_vport_cfg(struct mana_port_context *apc, u32 vport_index,
+ return 0;
+ }
+
+-static int mana_cfg_vport(struct mana_port_context *apc, u32 protection_dom_id,
+- u32 doorbell_pg_id)
++void mana_uncfg_vport(struct mana_port_context *apc)
++{
++ mutex_lock(&apc->vport_mutex);
++ apc->vport_use_count--;
++ WARN_ON(apc->vport_use_count < 0);
++ mutex_unlock(&apc->vport_mutex);
++}
++EXPORT_SYMBOL_NS(mana_uncfg_vport, NET_MANA);
++
++int mana_cfg_vport(struct mana_port_context *apc, u32 protection_dom_id,
++ u32 doorbell_pg_id)
+ {
+ struct mana_config_vport_resp resp = {};
+ struct mana_config_vport_req req = {};
+ int err;
+
++ /* This function is used to program the Ethernet port in the hardware
++ * table. It can be called from the Ethernet driver or the RDMA driver.
++ *
++ * For Ethernet usage, the hardware supports only one active user on a
++ * physical port. The driver checks on the port usage before programming
++ * the hardware when creating the RAW QP (RDMA driver) or exposing the
++ * device to kernel NET layer (Ethernet driver).
++ *
++ * Because the RDMA driver doesn't know in advance which QP type the
++ * user will create, it exposes the device with all its ports. The user
++ * may not be able to create RAW QP on a port if this port is already
++ * in used by the Ethernet driver from the kernel.
++ *
++ * This physical port limitation only applies to the RAW QP. For RC QP,
++ * the hardware doesn't have this limitation. The user can create RC
++ * QPs on a physical port up to the hardware limits independent of the
++ * Ethernet usage on the same port.
++ */
++ mutex_lock(&apc->vport_mutex);
++ if (apc->vport_use_count > 0) {
++ mutex_unlock(&apc->vport_mutex);
++ return -EBUSY;
++ }
++ apc->vport_use_count++;
++ mutex_unlock(&apc->vport_mutex);
++
+ mana_gd_init_req_hdr(&req.hdr, MANA_CONFIG_VPORT_TX,
+ sizeof(req), sizeof(resp));
+ req.vport = apc->port_handle;
+@@ -679,9 +714,16 @@ static int mana_cfg_vport(struct mana_port_context *apc, u32 protection_dom_id,
+
+ apc->tx_shortform_allowed = resp.short_form_allowed;
+ apc->tx_vp_offset = resp.tx_vport_offset;
++
++ netdev_info(apc->ndev, "Configured vPort %llu PD %u DB %u\n",
++ apc->port_handle, protection_dom_id, doorbell_pg_id);
+ out:
++ if (err)
++ mana_uncfg_vport(apc);
++
+ return err;
+ }
++EXPORT_SYMBOL_NS(mana_cfg_vport, NET_MANA);
+
+ static int mana_cfg_vport_steering(struct mana_port_context *apc,
+ enum TRI_STATE rx,
+@@ -742,6 +784,9 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
+ resp.hdr.status);
+ err = -EPROTO;
+ }
++
++ netdev_info(ndev, "Configured steering vPort %llu entries %u\n",
++ apc->port_handle, num_entries);
+ out:
+ kfree(req);
+ return err;
+@@ -1810,6 +1855,7 @@ static void mana_destroy_vport(struct mana_port_context *apc)
+ }
+
+ mana_destroy_txq(apc);
++ mana_uncfg_vport(apc);
+
+ if (gd->gdma_context->is_pf)
+ mana_pf_deregister_hw_vport(apc);
+@@ -2082,6 +2128,9 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
+ apc->pf_filter_handle = INVALID_MANA_HANDLE;
+ apc->port_idx = port_idx;
+
++ mutex_init(&apc->vport_mutex);
++ apc->vport_use_count = 0;
++
+ ndev->netdev_ops = &mana_devops;
+ ndev->ethtool_ops = &mana_ethtool_ops;
+ ndev->mtu = ETH_DATA_LEN;
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0006-net-mana-Set-the-DMA-device-max-segment-size.patch b/debian/patches/features/all/ethernet-microsoft/0006-net-mana-Set-the-DMA-device-max-segment-size.patch
new file mode 100644
index 000000000..6ac8249d0
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0006-net-mana-Set-the-DMA-device-max-segment-size.patch
@@ -0,0 +1,40 @@
+From 09b5391c16655893159fe8a58c8b7e31499ef107 Mon Sep 17 00:00:00 2001
+From: Ajay Sharma <sharmaajay@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:22 -0700
+Subject: [PATCH 06/23] net: mana: Set the DMA device max segment size
+
+MANA hardware doesn't have any restrictions on the DMA segment size, set it
+to the max allowed value.
+
+Signed-off-by: Ajay Sharma <sharmaajay@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-5-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit 6fe254160bd033a1e62dbad9b734183b31144678)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index a00bd88443d3..bc00a7d07232 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -1403,6 +1403,12 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (err)
+ goto release_region;
+
++ err = dma_set_max_seg_size(&pdev->dev, UINT_MAX);
++ if (err) {
++ dev_err(&pdev->dev, "Failed to set dma device segment size\n");
++ goto release_region;
++ }
++
+ err = -ENOMEM;
+ gc = vzalloc(sizeof(*gc));
+ if (!gc)
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0007-net-mana-Export-Work-Queue-functions-for-use-by-RDMA.patch b/debian/patches/features/all/ethernet-microsoft/0007-net-mana-Export-Work-Queue-functions-for-use-by-RDMA.patch
new file mode 100644
index 000000000..c846badc8
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0007-net-mana-Export-Work-Queue-functions-for-use-by-RDMA.patch
@@ -0,0 +1,100 @@
+From 8334d5a28eb711b8f464e0bd3ec0f76b0594bf95 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:23 -0700
+Subject: [PATCH 07/23] net: mana: Export Work Queue functions for use by RDMA
+ driver
+
+RDMA device may need to create Ethernet device queues for use by Queue
+Pair type RAW. This allows a user-mode context accesses Ethernet hardware
+queues. Export the supporting functions for use by the RDMA driver.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-6-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit 4c0ff7a106e16ab63e0b597557255c012f179578)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 1 +
+ drivers/net/ethernet/microsoft/mana/mana.h | 9 +++++++++
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 16 +++++++++-------
+ 3 files changed, 19 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index bc00a7d07232..d9be0f3044ea 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -152,6 +152,7 @@ int mana_gd_send_request(struct gdma_context *gc, u32 req_len, const void *req,
+
+ return mana_hwc_send_request(hwc, req_len, req, resp_len, resp);
+ }
++EXPORT_SYMBOL_NS(mana_gd_send_request, NET_MANA);
+
+ int mana_gd_alloc_memory(struct gdma_context *gc, unsigned int length,
+ struct gdma_mem_info *gmi)
+diff --git a/drivers/net/ethernet/microsoft/mana/mana.h b/drivers/net/ethernet/microsoft/mana/mana.h
+index 2883a08dbfb5..6e9e86fb4c02 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana.h
++++ b/drivers/net/ethernet/microsoft/mana/mana.h
+@@ -635,6 +635,15 @@ struct mana_tx_package {
+ struct gdma_posted_wqe_info wqe_info;
+ };
+
++int mana_create_wq_obj(struct mana_port_context *apc,
++ mana_handle_t vport,
++ u32 wq_type, struct mana_obj_spec *wq_spec,
++ struct mana_obj_spec *cq_spec,
++ mana_handle_t *wq_obj);
++
++void mana_destroy_wq_obj(struct mana_port_context *apc, u32 wq_type,
++ mana_handle_t wq_obj);
++
+ int mana_cfg_vport(struct mana_port_context *apc, u32 protection_dom_id,
+ u32 doorbell_pg_id);
+ void mana_uncfg_vport(struct mana_port_context *apc);
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index c5ab5cb63cb7..a526657f4edb 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -792,11 +792,11 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
+ return err;
+ }
+
+-static int mana_create_wq_obj(struct mana_port_context *apc,
+- mana_handle_t vport,
+- u32 wq_type, struct mana_obj_spec *wq_spec,
+- struct mana_obj_spec *cq_spec,
+- mana_handle_t *wq_obj)
++int mana_create_wq_obj(struct mana_port_context *apc,
++ mana_handle_t vport,
++ u32 wq_type, struct mana_obj_spec *wq_spec,
++ struct mana_obj_spec *cq_spec,
++ mana_handle_t *wq_obj)
+ {
+ struct mana_create_wqobj_resp resp = {};
+ struct mana_create_wqobj_req req = {};
+@@ -845,9 +845,10 @@ static int mana_create_wq_obj(struct mana_port_context *apc,
+ out:
+ return err;
+ }
++EXPORT_SYMBOL_NS(mana_create_wq_obj, NET_MANA);
+
+-static void mana_destroy_wq_obj(struct mana_port_context *apc, u32 wq_type,
+- mana_handle_t wq_obj)
++void mana_destroy_wq_obj(struct mana_port_context *apc, u32 wq_type,
++ mana_handle_t wq_obj)
+ {
+ struct mana_destroy_wqobj_resp resp = {};
+ struct mana_destroy_wqobj_req req = {};
+@@ -872,6 +873,7 @@ static void mana_destroy_wq_obj(struct mana_port_context *apc, u32 wq_type,
+ netdev_err(ndev, "Failed to destroy WQ object: %d, 0x%x\n", err,
+ resp.hdr.status);
+ }
++EXPORT_SYMBOL_NS(mana_destroy_wq_obj, NET_MANA);
+
+ static void mana_destroy_eq(struct mana_context *ac)
+ {
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0008-net-mana-Record-port-number-in-netdev.patch b/debian/patches/features/all/ethernet-microsoft/0008-net-mana-Record-port-number-in-netdev.patch
new file mode 100644
index 000000000..11a680a25
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0008-net-mana-Record-port-number-in-netdev.patch
@@ -0,0 +1,34 @@
+From 026293abc2d3962ebd7d9a4bc9375fa1bddc2995 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:24 -0700
+Subject: [PATCH 08/23] net: mana: Record port number in netdev
+
+The port number is useful for user-mode application to identify this
+net device based on port index. Set to the correct value in ndev.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-7-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit d44089e555ffe63a49cc6e94d0c03d933e413059)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index a526657f4edb..5b7aae9bf983 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -2139,6 +2139,7 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
+ ndev->max_mtu = ndev->mtu;
+ ndev->min_mtu = ndev->mtu;
+ ndev->needed_headroom = MANA_HEADROOM;
++ ndev->dev_port = port_idx;
+ SET_NETDEV_DEV(ndev, gc->dev);
+
+ netif_carrier_off(ndev);
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0009-net-mana-Move-header-files-to-a-common-location.patch b/debian/patches/features/all/ethernet-microsoft/0009-net-mana-Move-header-files-to-a-common-location.patch
new file mode 100644
index 000000000..e83e38049
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0009-net-mana-Move-header-files-to-a-common-location.patch
@@ -0,0 +1,152 @@
+From 36187c02914640d8c2e2ef9f11213842b5082671 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:25 -0700
+Subject: [PATCH 09/23] net: mana: Move header files to a common location
+
+In preparation to add MANA RDMA driver, move all the required header files
+to a common location for use by both Ethernet and RDMA drivers.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-8-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit fd325cd648f15eb9a8b32a68de3bafc72bcfe753)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ MAINTAINERS | 1 +
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 +-
+ drivers/net/ethernet/microsoft/mana/hw_channel.c | 4 ++--
+ drivers/net/ethernet/microsoft/mana/mana_bpf.c | 2 +-
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 4 ++--
+ drivers/net/ethernet/microsoft/mana/mana_ethtool.c | 2 +-
+ drivers/net/ethernet/microsoft/mana/shm_channel.c | 2 +-
+ {drivers/net/ethernet/microsoft => include/net}/mana/gdma.h | 0
+ .../net/ethernet/microsoft => include/net}/mana/hw_channel.h | 0
+ {drivers/net/ethernet/microsoft => include/net}/mana/mana.h | 0
+ .../ethernet/microsoft => include/net}/mana/mana_auxiliary.h | 0
+ .../net/ethernet/microsoft => include/net}/mana/shm_channel.h | 0
+ 12 files changed, 9 insertions(+), 8 deletions(-)
+ rename {drivers/net/ethernet/microsoft => include/net}/mana/gdma.h (100%)
+ rename {drivers/net/ethernet/microsoft => include/net}/mana/hw_channel.h (100%)
+ rename {drivers/net/ethernet/microsoft => include/net}/mana/mana.h (100%)
+ rename {drivers/net/ethernet/microsoft => include/net}/mana/mana_auxiliary.h (100%)
+ rename {drivers/net/ethernet/microsoft => include/net}/mana/shm_channel.h (100%)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 379387e20a96..a923933bbe82 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -9536,6 +9536,7 @@ F: include/asm-generic/hyperv-tlfs.h
+ F: include/asm-generic/mshyperv.h
+ F: include/clocksource/hyperv_timer.h
+ F: include/linux/hyperv.h
++F: include/net/mana
+ F: include/uapi/linux/hyperv.h
+ F: net/vmw_vsock/hyperv_transport.c
+ F: tools/hv/
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index d9be0f3044ea..b114c31d70ba 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -6,7 +6,7 @@
+ #include <linux/utsname.h>
+ #include <linux/version.h>
+
+-#include "mana.h"
++#include <net/mana/mana.h>
+
+ static u32 mana_gd_r32(struct gdma_context *g, u64 offset)
+ {
+diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+index 543a5d5c304f..76829ab43d40 100644
+--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
++++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+@@ -1,8 +1,8 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /* Copyright (c) 2021, Microsoft Corporation. */
+
+-#include "gdma.h"
+-#include "hw_channel.h"
++#include <net/mana/gdma.h>
++#include <net/mana/hw_channel.h>
+
+ static int mana_hwc_get_msg_index(struct hw_channel_context *hwc, u16 *msg_id)
+ {
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+index 421fd39ff3a8..3caea631229c 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+@@ -8,7 +8,7 @@
+ #include <linux/bpf_trace.h>
+ #include <net/xdp.h>
+
+-#include "mana.h"
++#include <net/mana/mana.h>
+
+ void mana_xdp_tx(struct sk_buff *skb, struct net_device *ndev)
+ {
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 5b7aae9bf983..c0421c4a80d4 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -12,8 +12,8 @@
+ #include <net/checksum.h>
+ #include <net/ip6_checksum.h>
+
+-#include "mana.h"
+-#include "mana_auxiliary.h"
++#include <net/mana/mana.h>
++#include <net/mana/mana_auxiliary.h>
+
+ static DEFINE_IDA(mana_adev_ida);
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+index 96d55c91c969..5b776a33a817 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+@@ -5,7 +5,7 @@
+ #include <linux/etherdevice.h>
+ #include <linux/ethtool.h>
+
+-#include "mana.h"
++#include <net/mana/mana.h>
+
+ static const struct {
+ char name[ETH_GSTRING_LEN];
+diff --git a/drivers/net/ethernet/microsoft/mana/shm_channel.c b/drivers/net/ethernet/microsoft/mana/shm_channel.c
+index da255da62176..5553af9c8085 100644
+--- a/drivers/net/ethernet/microsoft/mana/shm_channel.c
++++ b/drivers/net/ethernet/microsoft/mana/shm_channel.c
+@@ -6,7 +6,7 @@
+ #include <linux/io.h>
+ #include <linux/mm.h>
+
+-#include "shm_channel.h"
++#include <net/mana/shm_channel.h>
+
+ #define PAGE_FRAME_L48_WIDTH_BYTES 6
+ #define PAGE_FRAME_L48_WIDTH_BITS (PAGE_FRAME_L48_WIDTH_BYTES * 8)
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma.h b/include/net/mana/gdma.h
+similarity index 100%
+rename from drivers/net/ethernet/microsoft/mana/gdma.h
+rename to include/net/mana/gdma.h
+diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.h b/include/net/mana/hw_channel.h
+similarity index 100%
+rename from drivers/net/ethernet/microsoft/mana/hw_channel.h
+rename to include/net/mana/hw_channel.h
+diff --git a/drivers/net/ethernet/microsoft/mana/mana.h b/include/net/mana/mana.h
+similarity index 100%
+rename from drivers/net/ethernet/microsoft/mana/mana.h
+rename to include/net/mana/mana.h
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_auxiliary.h b/include/net/mana/mana_auxiliary.h
+similarity index 100%
+rename from drivers/net/ethernet/microsoft/mana/mana_auxiliary.h
+rename to include/net/mana/mana_auxiliary.h
+diff --git a/drivers/net/ethernet/microsoft/mana/shm_channel.h b/include/net/mana/shm_channel.h
+similarity index 100%
+rename from drivers/net/ethernet/microsoft/mana/shm_channel.h
+rename to include/net/mana/shm_channel.h
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0010-net-mana-Define-max-values-for-SGL-entries.patch b/debian/patches/features/all/ethernet-microsoft/0010-net-mana-Define-max-values-for-SGL-entries.patch
new file mode 100644
index 000000000..25af5ac09
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0010-net-mana-Define-max-values-for-SGL-entries.patch
@@ -0,0 +1,79 @@
+From 5e6b27eabf53e70c084cf61e3d3860cd6ed1c321 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:26 -0700
+Subject: [PATCH 10/23] net: mana: Define max values for SGL entries
+
+The number of maximum SGl entries should be computed from the maximum
+WQE size for the intended queue type and the corresponding OOB data
+size. This guarantees the hardware queue can successfully queue requests
+up to the queue depth exposed to the upper layer.
+
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-9-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit aa56549792fb348892fbbae67f6f0c71bb750b65)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 2 +-
+ include/net/mana/gdma.h | 7 +++++++
+ include/net/mana/mana.h | 4 +---
+ 3 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index c0421c4a80d4..958e55c936b5 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -189,7 +189,7 @@ int mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ pkg.wqe_req.client_data_unit = 0;
+
+ pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags;
+- WARN_ON_ONCE(pkg.wqe_req.num_sge > 30);
++ WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES);
+
+ if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) {
+ pkg.wqe_req.sgl = pkg.sgl_array;
+diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
+index 86d8a9e36005..11fc1cc67c01 100644
+--- a/include/net/mana/gdma.h
++++ b/include/net/mana/gdma.h
+@@ -431,6 +431,13 @@ struct gdma_wqe {
+ #define MAX_TX_WQE_SIZE 512
+ #define MAX_RX_WQE_SIZE 256
+
++#define MAX_TX_WQE_SGL_ENTRIES ((GDMA_MAX_SQE_SIZE - \
++ sizeof(struct gdma_sge) - INLINE_OOB_SMALL_SIZE) / \
++ sizeof(struct gdma_sge))
++
++#define MAX_RX_WQE_SGL_ENTRIES ((GDMA_MAX_RQE_SIZE - \
++ sizeof(struct gdma_sge)) / sizeof(struct gdma_sge))
++
+ struct gdma_cqe {
+ u32 cqe_data[GDMA_COMP_DATA_SIZE / 4];
+
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 6e9e86fb4c02..713a8f8cca9a 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -265,8 +265,6 @@ struct mana_cq {
+ int budget;
+ };
+
+-#define GDMA_MAX_RQE_SGES 15
+-
+ struct mana_recv_buf_oob {
+ /* A valid GDMA work request representing the data buffer. */
+ struct gdma_wqe_request wqe_req;
+@@ -276,7 +274,7 @@ struct mana_recv_buf_oob {
+
+ /* SGL of the buffer going to be sent has part of the work request. */
+ u32 num_sge;
+- struct gdma_sge sgl[GDMA_MAX_RQE_SGES];
++ struct gdma_sge sgl[MAX_RX_WQE_SGL_ENTRIES];
+
+ /* Required to store the result of mana_gd_post_work_request.
+ * gdma_posted_wqe_info.wqe_size_in_bu is required for progressing the
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0011-net-mana-Define-and-process-GDMA-response-code-GDMA_.patch b/debian/patches/features/all/ethernet-microsoft/0011-net-mana-Define-and-process-GDMA-response-code-GDMA_.patch
new file mode 100644
index 000000000..539f450c0
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0011-net-mana-Define-and-process-GDMA-response-code-GDMA_.patch
@@ -0,0 +1,52 @@
+From 71b611192d6e5c0aa276eba89c4ac0b15ca1851b Mon Sep 17 00:00:00 2001
+From: Ajay Sharma <sharmaajay@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:27 -0700
+Subject: [PATCH 11/23] net: mana: Define and process GDMA response code
+ GDMA_STATUS_MORE_ENTRIES
+
+When doing memory registration, the PF may respond with
+GDMA_STATUS_MORE_ENTRIES to indicate a follow request is needed. This is
+not an error and should be processed as expected.
+
+Signed-off-by: Ajay Sharma <sharmaajay@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-10-git-send-email-longli@linuxonhyperv.com
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit de372f2a9ca7ada2698ecac7df8f02407cd98fa0)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/hw_channel.c | 2 +-
+ include/net/mana/gdma.h | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+index 76829ab43d40..9d1507eba5b9 100644
+--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
++++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+@@ -836,7 +836,7 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
+ goto out;
+ }
+
+- if (ctx->status_code) {
++ if (ctx->status_code && ctx->status_code != GDMA_STATUS_MORE_ENTRIES) {
+ dev_err(hwc->dev, "HWC: Failed hw_channel req: 0x%x\n",
+ ctx->status_code);
+ err = -EPROTO;
+diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
+index 11fc1cc67c01..202ac405ab59 100644
+--- a/include/net/mana/gdma.h
++++ b/include/net/mana/gdma.h
+@@ -9,6 +9,8 @@
+
+ #include "shm_channel.h"
+
++#define GDMA_STATUS_MORE_ENTRIES 0x00000105
++
+ /* Structures labeled with "HW DATA" are exchanged with the hardware. All of
+ * them are naturally aligned and hence don't need __packed.
+ */
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0012-net-mana-Define-data-structures-for-protection-domai.patch b/debian/patches/features/all/ethernet-microsoft/0012-net-mana-Define-data-structures-for-protection-domai.patch
new file mode 100644
index 000000000..fb9a2a84d
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0012-net-mana-Define-data-structures-for-protection-domai.patch
@@ -0,0 +1,353 @@
+From b6589e00fed6f5a53bd4ffd172b7e4d2d300447c Mon Sep 17 00:00:00 2001
+From: Ajay Sharma <sharmaajay@microsoft.com>
+Date: Thu, 3 Nov 2022 12:16:29 -0700
+Subject: [PATCH 12/23] net: mana: Define data structures for protection domain
+ and memory registration
+
+The MANA hardware support protection domain and memory registration for use
+in RDMA environment. Add those definitions and expose them for use by the
+RDMA driver.
+
+Signed-off-by: Ajay Sharma <sharmaajay@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1667502990-2559-12-git-send-email-longli@linuxonhyperv.com
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Acked-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+(cherry picked from commit 28c66cfa45388af1126985d1114e0ed762eb2abd)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ .../net/ethernet/microsoft/mana/gdma_main.c | 27 ++--
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 18 +--
+ include/net/mana/gdma.h | 121 +++++++++++++++++-
+ 3 files changed, 143 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index b114c31d70ba..690691e3e86c 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -198,7 +198,7 @@ static int mana_gd_create_hw_eq(struct gdma_context *gc,
+ req.type = queue->type;
+ req.pdid = queue->gdma_dev->pdid;
+ req.doolbell_id = queue->gdma_dev->doorbell;
+- req.gdma_region = queue->mem_info.gdma_region;
++ req.gdma_region = queue->mem_info.dma_region_handle;
+ req.queue_size = queue->queue_size;
+ req.log2_throttle_limit = queue->eq.log2_throttle_limit;
+ req.eq_pci_msix_index = queue->eq.msix_index;
+@@ -212,7 +212,7 @@ static int mana_gd_create_hw_eq(struct gdma_context *gc,
+
+ queue->id = resp.queue_index;
+ queue->eq.disable_needed = true;
+- queue->mem_info.gdma_region = GDMA_INVALID_DMA_REGION;
++ queue->mem_info.dma_region_handle = GDMA_INVALID_DMA_REGION;
+ return 0;
+ }
+
+@@ -671,24 +671,30 @@ int mana_gd_create_hwc_queue(struct gdma_dev *gd,
+ return err;
+ }
+
+-static void mana_gd_destroy_dma_region(struct gdma_context *gc, u64 gdma_region)
++int mana_gd_destroy_dma_region(struct gdma_context *gc,
++ gdma_obj_handle_t dma_region_handle)
+ {
+ struct gdma_destroy_dma_region_req req = {};
+ struct gdma_general_resp resp = {};
+ int err;
+
+- if (gdma_region == GDMA_INVALID_DMA_REGION)
+- return;
++ if (dma_region_handle == GDMA_INVALID_DMA_REGION)
++ return 0;
+
+ mana_gd_init_req_hdr(&req.hdr, GDMA_DESTROY_DMA_REGION, sizeof(req),
+ sizeof(resp));
+- req.gdma_region = gdma_region;
++ req.dma_region_handle = dma_region_handle;
+
+ err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);
+- if (err || resp.hdr.status)
++ if (err || resp.hdr.status) {
+ dev_err(gc->dev, "Failed to destroy DMA region: %d, 0x%x\n",
+ err, resp.hdr.status);
++ return -EPROTO;
++ }
++
++ return 0;
+ }
++EXPORT_SYMBOL_NS(mana_gd_destroy_dma_region, NET_MANA);
+
+ static int mana_gd_create_dma_region(struct gdma_dev *gd,
+ struct gdma_mem_info *gmi)
+@@ -733,14 +739,15 @@ static int mana_gd_create_dma_region(struct gdma_dev *gd,
+ if (err)
+ goto out;
+
+- if (resp.hdr.status || resp.gdma_region == GDMA_INVALID_DMA_REGION) {
++ if (resp.hdr.status ||
++ resp.dma_region_handle == GDMA_INVALID_DMA_REGION) {
+ dev_err(gc->dev, "Failed to create DMA region: 0x%x\n",
+ resp.hdr.status);
+ err = -EPROTO;
+ goto out;
+ }
+
+- gmi->gdma_region = resp.gdma_region;
++ gmi->dma_region_handle = resp.dma_region_handle;
+ out:
+ kfree(req);
+ return err;
+@@ -863,7 +870,7 @@ void mana_gd_destroy_queue(struct gdma_context *gc, struct gdma_queue *queue)
+ return;
+ }
+
+- mana_gd_destroy_dma_region(gc, gmi->gdma_region);
++ mana_gd_destroy_dma_region(gc, gmi->dma_region_handle);
+ mana_gd_free_memory(gmi);
+ kfree(queue);
+ }
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 958e55c936b5..9bce13714b25 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1529,10 +1529,10 @@ static int mana_create_txq(struct mana_port_context *apc,
+ memset(&wq_spec, 0, sizeof(wq_spec));
+ memset(&cq_spec, 0, sizeof(cq_spec));
+
+- wq_spec.gdma_region = txq->gdma_sq->mem_info.gdma_region;
++ wq_spec.gdma_region = txq->gdma_sq->mem_info.dma_region_handle;
+ wq_spec.queue_size = txq->gdma_sq->queue_size;
+
+- cq_spec.gdma_region = cq->gdma_cq->mem_info.gdma_region;
++ cq_spec.gdma_region = cq->gdma_cq->mem_info.dma_region_handle;
+ cq_spec.queue_size = cq->gdma_cq->queue_size;
+ cq_spec.modr_ctx_id = 0;
+ cq_spec.attached_eq = cq->gdma_cq->cq.parent->id;
+@@ -1547,8 +1547,10 @@ static int mana_create_txq(struct mana_port_context *apc,
+ txq->gdma_sq->id = wq_spec.queue_index;
+ cq->gdma_cq->id = cq_spec.queue_index;
+
+- txq->gdma_sq->mem_info.gdma_region = GDMA_INVALID_DMA_REGION;
+- cq->gdma_cq->mem_info.gdma_region = GDMA_INVALID_DMA_REGION;
++ txq->gdma_sq->mem_info.dma_region_handle =
++ GDMA_INVALID_DMA_REGION;
++ cq->gdma_cq->mem_info.dma_region_handle =
++ GDMA_INVALID_DMA_REGION;
+
+ txq->gdma_txq_id = txq->gdma_sq->id;
+
+@@ -1759,10 +1761,10 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+
+ memset(&wq_spec, 0, sizeof(wq_spec));
+ memset(&cq_spec, 0, sizeof(cq_spec));
+- wq_spec.gdma_region = rxq->gdma_rq->mem_info.gdma_region;
++ wq_spec.gdma_region = rxq->gdma_rq->mem_info.dma_region_handle;
+ wq_spec.queue_size = rxq->gdma_rq->queue_size;
+
+- cq_spec.gdma_region = cq->gdma_cq->mem_info.gdma_region;
++ cq_spec.gdma_region = cq->gdma_cq->mem_info.dma_region_handle;
+ cq_spec.queue_size = cq->gdma_cq->queue_size;
+ cq_spec.modr_ctx_id = 0;
+ cq_spec.attached_eq = cq->gdma_cq->cq.parent->id;
+@@ -1775,8 +1777,8 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+ rxq->gdma_rq->id = wq_spec.queue_index;
+ cq->gdma_cq->id = cq_spec.queue_index;
+
+- rxq->gdma_rq->mem_info.gdma_region = GDMA_INVALID_DMA_REGION;
+- cq->gdma_cq->mem_info.gdma_region = GDMA_INVALID_DMA_REGION;
++ rxq->gdma_rq->mem_info.dma_region_handle = GDMA_INVALID_DMA_REGION;
++ cq->gdma_cq->mem_info.dma_region_handle = GDMA_INVALID_DMA_REGION;
+
+ rxq->gdma_id = rxq->gdma_rq->id;
+ cq->gdma_id = cq->gdma_cq->id;
+diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
+index 202ac405ab59..aabc7cea8a49 100644
+--- a/include/net/mana/gdma.h
++++ b/include/net/mana/gdma.h
+@@ -27,6 +27,10 @@ enum gdma_request_type {
+ GDMA_CREATE_DMA_REGION = 25,
+ GDMA_DMA_REGION_ADD_PAGES = 26,
+ GDMA_DESTROY_DMA_REGION = 27,
++ GDMA_CREATE_PD = 29,
++ GDMA_DESTROY_PD = 30,
++ GDMA_CREATE_MR = 31,
++ GDMA_DESTROY_MR = 32,
+ };
+
+ enum gdma_queue_type {
+@@ -57,6 +61,8 @@ enum {
+ GDMA_DEVICE_MANA = 2,
+ };
+
++typedef u64 gdma_obj_handle_t;
++
+ struct gdma_resource {
+ /* Protect the bitmap */
+ spinlock_t lock;
+@@ -190,7 +196,7 @@ struct gdma_mem_info {
+ u64 length;
+
+ /* Allocated by the PF driver */
+- u64 gdma_region;
++ gdma_obj_handle_t dma_region_handle;
+ };
+
+ #define REGISTER_ATB_MST_MKEY_LOWER_SIZE 8
+@@ -605,7 +611,7 @@ struct gdma_create_queue_req {
+ u32 reserved1;
+ u32 pdid;
+ u32 doolbell_id;
+- u64 gdma_region;
++ gdma_obj_handle_t gdma_region;
+ u32 reserved2;
+ u32 queue_size;
+ u32 log2_throttle_limit;
+@@ -632,6 +638,28 @@ struct gdma_disable_queue_req {
+ u32 alloc_res_id_on_creation;
+ }; /* HW DATA */
+
++enum atb_page_size {
++ ATB_PAGE_SIZE_4K,
++ ATB_PAGE_SIZE_8K,
++ ATB_PAGE_SIZE_16K,
++ ATB_PAGE_SIZE_32K,
++ ATB_PAGE_SIZE_64K,
++ ATB_PAGE_SIZE_128K,
++ ATB_PAGE_SIZE_256K,
++ ATB_PAGE_SIZE_512K,
++ ATB_PAGE_SIZE_1M,
++ ATB_PAGE_SIZE_2M,
++ ATB_PAGE_SIZE_MAX,
++};
++
++enum gdma_mr_access_flags {
++ GDMA_ACCESS_FLAG_LOCAL_READ = BIT_ULL(0),
++ GDMA_ACCESS_FLAG_LOCAL_WRITE = BIT_ULL(1),
++ GDMA_ACCESS_FLAG_REMOTE_READ = BIT_ULL(2),
++ GDMA_ACCESS_FLAG_REMOTE_WRITE = BIT_ULL(3),
++ GDMA_ACCESS_FLAG_REMOTE_ATOMIC = BIT_ULL(4),
++};
++
+ /* GDMA_CREATE_DMA_REGION */
+ struct gdma_create_dma_region_req {
+ struct gdma_req_hdr hdr;
+@@ -658,14 +686,14 @@ struct gdma_create_dma_region_req {
+
+ struct gdma_create_dma_region_resp {
+ struct gdma_resp_hdr hdr;
+- u64 gdma_region;
++ gdma_obj_handle_t dma_region_handle;
+ }; /* HW DATA */
+
+ /* GDMA_DMA_REGION_ADD_PAGES */
+ struct gdma_dma_region_add_pages_req {
+ struct gdma_req_hdr hdr;
+
+- u64 gdma_region;
++ gdma_obj_handle_t dma_region_handle;
+
+ u32 page_addr_list_len;
+ u32 reserved3;
+@@ -677,9 +705,88 @@ struct gdma_dma_region_add_pages_req {
+ struct gdma_destroy_dma_region_req {
+ struct gdma_req_hdr hdr;
+
+- u64 gdma_region;
++ gdma_obj_handle_t dma_region_handle;
+ }; /* HW DATA */
+
++enum gdma_pd_flags {
++ GDMA_PD_FLAG_INVALID = 0,
++};
++
++struct gdma_create_pd_req {
++ struct gdma_req_hdr hdr;
++ enum gdma_pd_flags flags;
++ u32 reserved;
++};/* HW DATA */
++
++struct gdma_create_pd_resp {
++ struct gdma_resp_hdr hdr;
++ gdma_obj_handle_t pd_handle;
++ u32 pd_id;
++ u32 reserved;
++};/* HW DATA */
++
++struct gdma_destroy_pd_req {
++ struct gdma_req_hdr hdr;
++ gdma_obj_handle_t pd_handle;
++};/* HW DATA */
++
++struct gdma_destory_pd_resp {
++ struct gdma_resp_hdr hdr;
++};/* HW DATA */
++
++enum gdma_mr_type {
++ /* Guest Virtual Address - MRs of this type allow access
++ * to memory mapped by PTEs associated with this MR using a virtual
++ * address that is set up in the MST
++ */
++ GDMA_MR_TYPE_GVA = 2,
++};
++
++struct gdma_create_mr_params {
++ gdma_obj_handle_t pd_handle;
++ enum gdma_mr_type mr_type;
++ union {
++ struct {
++ gdma_obj_handle_t dma_region_handle;
++ u64 virtual_address;
++ enum gdma_mr_access_flags access_flags;
++ } gva;
++ };
++};
++
++struct gdma_create_mr_request {
++ struct gdma_req_hdr hdr;
++ gdma_obj_handle_t pd_handle;
++ enum gdma_mr_type mr_type;
++ u32 reserved_1;
++
++ union {
++ struct {
++ gdma_obj_handle_t dma_region_handle;
++ u64 virtual_address;
++ enum gdma_mr_access_flags access_flags;
++ } gva;
++
++ };
++ u32 reserved_2;
++};/* HW DATA */
++
++struct gdma_create_mr_response {
++ struct gdma_resp_hdr hdr;
++ gdma_obj_handle_t mr_handle;
++ u32 lkey;
++ u32 rkey;
++};/* HW DATA */
++
++struct gdma_destroy_mr_request {
++ struct gdma_req_hdr hdr;
++ gdma_obj_handle_t mr_handle;
++};/* HW DATA */
++
++struct gdma_destroy_mr_response {
++ struct gdma_resp_hdr hdr;
++};/* HW DATA */
++
+ int mana_gd_verify_vf_version(struct pci_dev *pdev);
+
+ int mana_gd_register_device(struct gdma_dev *gd);
+@@ -706,4 +813,8 @@ void mana_gd_free_memory(struct gdma_mem_info *gmi);
+
+ int mana_gd_send_request(struct gdma_context *gc, u32 req_len, const void *req,
+ u32 resp_len, void *resp);
++
++int mana_gd_destroy_dma_region(struct gdma_context *gc,
++ gdma_obj_handle_t dma_region_handle);
++
+ #endif /* _GDMA_H */
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0013-net-mana-Fix-return-type-of-mana_start_xmit.patch b/debian/patches/features/all/ethernet-microsoft/0013-net-mana-Fix-return-type-of-mana_start_xmit.patch
new file mode 100644
index 000000000..8f966405a
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0013-net-mana-Fix-return-type-of-mana_start_xmit.patch
@@ -0,0 +1,66 @@
+From 37ec026c96afe1091f91d40515a91463ea50c150 Mon Sep 17 00:00:00 2001
+From: Nathan Huckleberry <nhuck@google.com>
+Date: Tue, 8 Nov 2022 17:26:30 -0700
+Subject: [PATCH 13/23] net: mana: Fix return type of mana_start_xmit()
+
+The ndo_start_xmit field in net_device_ops is expected to be of type
+netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev).
+
+The mismatched return type breaks forward edge kCFI since the underlying
+function definition does not match the function hook definition. A new
+warning in clang will catch this at compile time:
+
+ drivers/net/ethernet/microsoft/mana/mana_en.c:382:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict]
+ .ndo_start_xmit = mana_start_xmit,
+ ^~~~~~~~~~~~~~~
+ 1 error generated.
+
+The return type of mana_start_xmit should be changed from int to
+netdev_tx_t.
+
+Reported-by: Dan Carpenter <error27@gmail.com>
+Link: https://github.com/ClangBuiltLinux/linux/issues/1703
+Link: https://github.com/ClangBuiltLinux/linux/issues/1750
+Signed-off-by: Nathan Huckleberry <nhuck@google.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+[nathan: Rebase on net-next and resolve conflicts
+ Add note about new clang warning]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Link: https://lore.kernel.org/r/20221109002629.1446680-1-nathan@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+(cherry picked from commit 0c9ef08a4d0fd6c5e6000597b506235d71a85a61)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 2 +-
+ include/net/mana/mana.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 9bce13714b25..2f6a048dee90 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -141,7 +141,7 @@ static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc,
+ return -ENOMEM;
+ }
+
+-int mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ {
+ enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT;
+ struct mana_port_context *apc = netdev_priv(ndev);
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 713a8f8cca9a..575ea36ce606 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -390,7 +390,7 @@ struct mana_port_context {
+ struct mana_ethtool_stats eth_stats;
+ };
+
+-int mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);
++netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+ int mana_config_rss(struct mana_port_context *ac, enum TRI_STATE rx,
+ bool update_hash, bool update_tab);
+
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0014-net-mana-Fix-accessing-freed-irq-affinity_hint.patch b/debian/patches/features/all/ethernet-microsoft/0014-net-mana-Fix-accessing-freed-irq-affinity_hint.patch
new file mode 100644
index 000000000..2aa627612
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0014-net-mana-Fix-accessing-freed-irq-affinity_hint.patch
@@ -0,0 +1,135 @@
+From 1b71f96ff9b962c904cefc9a57500869fa0d1d44 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Mon, 6 Feb 2023 13:28:49 -0800
+Subject: [PATCH 14/23] net: mana: Fix accessing freed irq affinity_hint
+
+After calling irq_set_affinity_and_hint(), the cpumask pointer is
+saved in desc->affinity_hint, and will be used later when reading
+/proc/irq/<num>/affinity_hint. So the cpumask variable needs to be
+persistent. Otherwise, we are accessing freed memory when reading
+the affinity_hint file.
+
+Also, need to clear affinity_hint before free_irq(), otherwise there
+is a one-time warning and stack trace during module unloading:
+
+ [ 243.948687] WARNING: CPU: 10 PID: 1589 at kernel/irq/manage.c:1913 free_irq+0x318/0x360
+ ...
+ [ 243.948753] Call Trace:
+ [ 243.948754] <TASK>
+ [ 243.948760] mana_gd_remove_irqs+0x78/0xc0 [mana]
+ [ 243.948767] mana_gd_remove+0x3e/0x80 [mana]
+ [ 243.948773] pci_device_remove+0x3d/0xb0
+ [ 243.948778] device_remove+0x46/0x70
+ [ 243.948782] device_release_driver_internal+0x1fe/0x280
+ [ 243.948785] driver_detach+0x4e/0xa0
+ [ 243.948787] bus_remove_driver+0x70/0xf0
+ [ 243.948789] driver_unregister+0x35/0x60
+ [ 243.948792] pci_unregister_driver+0x44/0x90
+ [ 243.948794] mana_driver_exit+0x14/0x3fe [mana]
+ [ 243.948800] __do_sys_delete_module.constprop.0+0x185/0x2f0
+
+To fix the bug, use the persistent mask, cpumask_of(cpu#), and set
+affinity_hint to NULL before freeing the IRQ, as required by free_irq().
+
+Cc: stable@vger.kernel.org
+Fixes: 71fa6887eeca ("net: mana: Assign interrupts to CPUs based on NUMA nodes")
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Michael Kelley <mikelley@microsoft.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Link: https://lore.kernel.org/r/1675718929-19565-1-git-send-email-haiyangz@microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit 18a048370b06a3a521219e9e5b10bdc2178ef19c)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ .../net/ethernet/microsoft/mana/gdma_main.c | 37 ++++++-------------
+ 1 file changed, 11 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index 690691e3e86c..5b7fddfc9ff1 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -1218,9 +1218,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ unsigned int max_queues_per_port = num_online_cpus();
+ struct gdma_context *gc = pci_get_drvdata(pdev);
+ struct gdma_irq_context *gic;
+- unsigned int max_irqs;
+- u16 *cpus;
+- cpumask_var_t req_mask;
++ unsigned int max_irqs, cpu;
+ int nvec, irq;
+ int err, i = 0, j;
+
+@@ -1241,21 +1239,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ goto free_irq_vector;
+ }
+
+- if (!zalloc_cpumask_var(&req_mask, GFP_KERNEL)) {
+- err = -ENOMEM;
+- goto free_irq;
+- }
+-
+- cpus = kcalloc(nvec, sizeof(*cpus), GFP_KERNEL);
+- if (!cpus) {
+- err = -ENOMEM;
+- goto free_mask;
+- }
+- for (i = 0; i < nvec; i++)
+- cpus[i] = cpumask_local_spread(i, gc->numa_node);
+-
+ for (i = 0; i < nvec; i++) {
+- cpumask_set_cpu(cpus[i], req_mask);
+ gic = &gc->irq_contexts[i];
+ gic->handler = NULL;
+ gic->arg = NULL;
+@@ -1270,17 +1254,16 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+ irq = pci_irq_vector(pdev, i);
+ if (irq < 0) {
+ err = irq;
+- goto free_mask;
++ goto free_irq;
+ }
+
+ err = request_irq(irq, mana_gd_intr, 0, gic->name, gic);
+ if (err)
+- goto free_mask;
+- irq_set_affinity_and_hint(irq, req_mask);
+- cpumask_clear(req_mask);
++ goto free_irq;
++
++ cpu = cpumask_local_spread(i, gc->numa_node);
++ irq_set_affinity_and_hint(irq, cpumask_of(cpu));
+ }
+- free_cpumask_var(req_mask);
+- kfree(cpus);
+
+ err = mana_gd_alloc_res_map(nvec, &gc->msix_resource);
+ if (err)
+@@ -1291,13 +1274,12 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
+
+ return 0;
+
+-free_mask:
+- free_cpumask_var(req_mask);
+- kfree(cpus);
+ free_irq:
+ for (j = i - 1; j >= 0; j--) {
+ irq = pci_irq_vector(pdev, j);
+ gic = &gc->irq_contexts[j];
++
++ irq_update_affinity_hint(irq, NULL);
+ free_irq(irq, gic);
+ }
+
+@@ -1325,6 +1307,9 @@ static void mana_gd_remove_irqs(struct pci_dev *pdev)
+ continue;
+
+ gic = &gc->irq_contexts[i];
++
++ /* Need to clear the hint before free_irq */
++ irq_update_affinity_hint(irq, NULL);
+ free_irq(irq, gic);
+ }
+
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0015-net-mana-Add-new-MANA-VF-performance-counters-for-ea.patch b/debian/patches/features/all/ethernet-microsoft/0015-net-mana-Add-new-MANA-VF-performance-counters-for-ea.patch
new file mode 100644
index 000000000..0ada4dca6
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0015-net-mana-Add-new-MANA-VF-performance-counters-for-ea.patch
@@ -0,0 +1,334 @@
+From fbefc731a4cc001fe7ce5786e08053d707dde85f Mon Sep 17 00:00:00 2001
+From: Shradha Gupta <shradhagupta@linux.microsoft.com>
+Date: Wed, 15 Mar 2023 04:55:13 -0700
+Subject: [PATCH 15/23] net: mana: Add new MANA VF performance counters for
+ easier troubleshooting
+
+Extended performance counter stats in 'ethtool -S <interface>' output
+for MANA VF to facilitate troubleshooting.
+
+Tested-on: Ubuntu22
+Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit bd7fc6e1957c2102866f9e464c1f2302e891b7e9)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 62 ++++++++++++++++++-
+ .../ethernet/microsoft/mana/mana_ethtool.c | 52 +++++++++++++++-
+ include/net/mana/mana.h | 18 ++++++
+ 3 files changed, 128 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -157,6 +157,7 @@ netdev_tx_t mana_start_xmit(struct sk_bu
+ struct mana_txq *txq;
+ struct mana_cq *cq;
+ int err, len;
++ u16 ihs;
+
+ if (unlikely(!apc->port_is_up))
+ goto tx_drop;
+@@ -167,6 +168,7 @@ netdev_tx_t mana_start_xmit(struct sk_bu
+ txq = &apc->tx_qp[txq_idx].txq;
+ gdma_sq = txq->gdma_sq;
+ cq = &apc->tx_qp[txq_idx].tx_cq;
++ tx_stats = &txq->stats;
+
+ pkg.tx_oob.s_oob.vcq_num = cq->gdma_id;
+ pkg.tx_oob.s_oob.vsq_frame = txq->vsq_frame;
+@@ -180,10 +182,17 @@ netdev_tx_t mana_start_xmit(struct sk_bu
+
+ pkg.tx_oob.s_oob.pkt_fmt = pkt_fmt;
+
+- if (pkt_fmt == MANA_SHORT_PKT_FMT)
++ if (pkt_fmt == MANA_SHORT_PKT_FMT) {
+ pkg.wqe_req.inline_oob_size = sizeof(struct mana_tx_short_oob);
+- else
++ u64_stats_update_begin(&tx_stats->syncp);
++ tx_stats->short_pkt_fmt++;
++ u64_stats_update_end(&tx_stats->syncp);
++ } else {
+ pkg.wqe_req.inline_oob_size = sizeof(struct mana_tx_oob);
++ u64_stats_update_begin(&tx_stats->syncp);
++ tx_stats->long_pkt_fmt++;
++ u64_stats_update_end(&tx_stats->syncp);
++ }
+
+ pkg.wqe_req.inline_oob_data = &pkg.tx_oob;
+ pkg.wqe_req.flags = 0;
+@@ -233,9 +242,35 @@ netdev_tx_t mana_start_xmit(struct sk_bu
+ &ipv6_hdr(skb)->daddr, 0,
+ IPPROTO_TCP, 0);
+ }
++
++ if (skb->encapsulation) {
++ ihs = skb_inner_tcp_all_headers(skb);
++ u64_stats_update_begin(&tx_stats->syncp);
++ tx_stats->tso_inner_packets++;
++ tx_stats->tso_inner_bytes += skb->len - ihs;
++ u64_stats_update_end(&tx_stats->syncp);
++ } else {
++ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) {
++ ihs = skb_transport_offset(skb) + sizeof(struct udphdr);
++ } else {
++ ihs = skb_tcp_all_headers(skb);
++ if (ipv6_has_hopopt_jumbo(skb))
++ ihs -= sizeof(struct hop_jumbo_hdr);
++ }
++
++ u64_stats_update_begin(&tx_stats->syncp);
++ tx_stats->tso_packets++;
++ tx_stats->tso_bytes += skb->len - ihs;
++ u64_stats_update_end(&tx_stats->syncp);
++ }
++
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ csum_type = mana_checksum_info(skb);
+
++ u64_stats_update_begin(&tx_stats->syncp);
++ tx_stats->csum_partial++;
++ u64_stats_update_end(&tx_stats->syncp);
++
+ if (csum_type == IPPROTO_TCP) {
+ pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4;
+ pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6;
+@@ -255,8 +290,12 @@ netdev_tx_t mana_start_xmit(struct sk_bu
+ }
+ }
+
+- if (mana_map_skb(skb, apc, &pkg))
++ if (mana_map_skb(skb, apc, &pkg)) {
++ u64_stats_update_begin(&tx_stats->syncp);
++ tx_stats->mana_map_err++;
++ u64_stats_update_end(&tx_stats->syncp);
+ goto free_sgl_ptr;
++ }
+
+ skb_queue_tail(&txq->pending_skbs, skb);
+
+@@ -1039,6 +1078,8 @@ static void mana_poll_tx_cq(struct mana_
+ if (comp_read < 1)
+ return;
+
++ apc->eth_stats.tx_cqes = comp_read;
++
+ for (i = 0; i < comp_read; i++) {
+ struct mana_tx_comp_oob *cqe_oob;
+
+@@ -1067,6 +1108,7 @@ static void mana_poll_tx_cq(struct mana_
+ netdev_err(ndev, "TX: CQE error %d\n",
+ cqe_oob->cqe_hdr.cqe_type);
+
++ apc->eth_stats.tx_cqe_err++;
+ break;
+
+ default:
+@@ -1077,6 +1119,7 @@ static void mana_poll_tx_cq(struct mana_
+ netdev_err(ndev, "TX: unknown CQE type %d\n",
+ cqe_oob->cqe_hdr.cqe_type);
+
++ apc->eth_stats.tx_cqe_unknown_type++;
+ break;
+ }
+
+@@ -1123,6 +1166,8 @@ static void mana_poll_tx_cq(struct mana_
+ WARN_ON_ONCE(1);
+
+ cq->work_done = pkt_transmitted;
++
++ apc->eth_stats.tx_cqes -= pkt_transmitted;
+ }
+
+ static void mana_post_pkt_rxq(struct mana_rxq *rxq)
+@@ -1257,12 +1302,15 @@ static void mana_process_rx_cqe(struct m
+ struct gdma_context *gc = rxq->gdma_rq->gdma_dev->gdma_context;
+ struct net_device *ndev = rxq->ndev;
+ struct mana_recv_buf_oob *rxbuf_oob;
++ struct mana_port_context *apc;
+ struct device *dev = gc->dev;
+ void *new_buf, *old_buf;
+ struct page *new_page;
+ u32 curr, pktlen;
+ dma_addr_t da;
+
++ apc = netdev_priv(ndev);
++
+ switch (oob->cqe_hdr.cqe_type) {
+ case CQE_RX_OKAY:
+ break;
+@@ -1275,6 +1323,7 @@ static void mana_process_rx_cqe(struct m
+
+ case CQE_RX_COALESCED_4:
+ netdev_err(ndev, "RX coalescing is unsupported\n");
++ apc->eth_stats.rx_coalesced_err++;
+ return;
+
+ case CQE_RX_OBJECT_FENCE:
+@@ -1284,6 +1333,7 @@ static void mana_process_rx_cqe(struct m
+ default:
+ netdev_err(ndev, "Unknown RX CQE type = %d\n",
+ oob->cqe_hdr.cqe_type);
++ apc->eth_stats.rx_cqe_unknown_type++;
+ return;
+ }
+
+@@ -1346,11 +1396,15 @@ static void mana_poll_rx_cq(struct mana_
+ {
+ struct gdma_comp *comp = cq->gdma_comp_buf;
+ struct mana_rxq *rxq = cq->rxq;
++ struct mana_port_context *apc;
+ int comp_read, i;
+
++ apc = netdev_priv(rxq->ndev);
++
+ comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER);
+ WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER);
+
++ apc->eth_stats.rx_cqes = comp_read;
+ rxq->xdp_flush = false;
+
+ for (i = 0; i < comp_read; i++) {
+@@ -1362,6 +1416,8 @@ static void mana_poll_rx_cq(struct mana_
+ return;
+
+ mana_process_rx_cqe(rxq, cq, &comp[i]);
++
++ apc->eth_stats.rx_cqes--;
+ }
+
+ if (rxq->xdp_flush)
+--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+@@ -13,6 +13,15 @@ static const struct {
+ } mana_eth_stats[] = {
+ {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)},
+ {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)},
++ {"tx_cqes", offsetof(struct mana_ethtool_stats, tx_cqes)},
++ {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)},
++ {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
++ tx_cqe_unknown_type)},
++ {"rx_cqes", offsetof(struct mana_ethtool_stats, rx_cqes)},
++ {"rx_coalesced_err", offsetof(struct mana_ethtool_stats,
++ rx_coalesced_err)},
++ {"rx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
++ rx_cqe_unknown_type)},
+ };
+
+ static int mana_get_sset_count(struct net_device *ndev, int stringset)
+@@ -23,7 +32,8 @@ static int mana_get_sset_count(struct ne
+ if (stringset != ETH_SS_STATS)
+ return -EINVAL;
+
+- return ARRAY_SIZE(mana_eth_stats) + num_queues * 8;
++ return ARRAY_SIZE(mana_eth_stats) + num_queues *
++ (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
+ }
+
+ static void mana_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+@@ -61,6 +71,22 @@ static void mana_get_strings(struct net_
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_%d_xdp_xmit", i);
+ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_tso_packets", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_tso_bytes", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_tso_inner_packets", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_tso_inner_bytes", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_long_pkt_fmt", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_short_pkt_fmt", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_csum_partial", i);
++ p += ETH_GSTRING_LEN;
++ sprintf(p, "tx_%d_mana_map_err", i);
++ p += ETH_GSTRING_LEN;
+ }
+ }
+
+@@ -78,6 +104,14 @@ static void mana_get_ethtool_stats(struc
+ u64 xdp_xmit;
+ u64 xdp_drop;
+ u64 xdp_tx;
++ u64 tso_packets;
++ u64 tso_bytes;
++ u64 tso_inner_packets;
++ u64 tso_inner_bytes;
++ u64 long_pkt_fmt;
++ u64 short_pkt_fmt;
++ u64 csum_partial;
++ u64 mana_map_err;
+ int q, i = 0;
+
+ if (!apc->port_is_up)
+@@ -113,11 +147,27 @@ static void mana_get_ethtool_stats(struc
+ packets = tx_stats->packets;
+ bytes = tx_stats->bytes;
+ xdp_xmit = tx_stats->xdp_xmit;
++ tso_packets = tx_stats->tso_packets;
++ tso_bytes = tx_stats->tso_bytes;
++ tso_inner_packets = tx_stats->tso_inner_packets;
++ tso_inner_bytes = tx_stats->tso_inner_bytes;
++ long_pkt_fmt = tx_stats->long_pkt_fmt;
++ short_pkt_fmt = tx_stats->short_pkt_fmt;
++ csum_partial = tx_stats->csum_partial;
++ mana_map_err = tx_stats->mana_map_err;
+ } while (u64_stats_fetch_retry(&tx_stats->syncp, start));
+
+ data[i++] = packets;
+ data[i++] = bytes;
+ data[i++] = xdp_xmit;
++ data[i++] = tso_packets;
++ data[i++] = tso_bytes;
++ data[i++] = tso_inner_packets;
++ data[i++] = tso_inner_bytes;
++ data[i++] = long_pkt_fmt;
++ data[i++] = short_pkt_fmt;
++ data[i++] = csum_partial;
++ data[i++] = mana_map_err;
+ }
+ }
+
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -48,6 +48,10 @@ enum TRI_STATE {
+
+ #define MAX_PORTS_IN_MANA_DEV 256
+
++/* Update this count whenever the respective structures are changed */
++#define MANA_STATS_RX_COUNT 5
++#define MANA_STATS_TX_COUNT 11
++
+ struct mana_stats_rx {
+ u64 packets;
+ u64 bytes;
+@@ -61,6 +65,14 @@ struct mana_stats_tx {
+ u64 packets;
+ u64 bytes;
+ u64 xdp_xmit;
++ u64 tso_packets;
++ u64 tso_bytes;
++ u64 tso_inner_packets;
++ u64 tso_inner_bytes;
++ u64 short_pkt_fmt;
++ u64 long_pkt_fmt;
++ u64 csum_partial;
++ u64 mana_map_err;
+ struct u64_stats_sync syncp;
+ };
+
+@@ -331,6 +343,12 @@ struct mana_tx_qp {
+ struct mana_ethtool_stats {
+ u64 stop_queue;
+ u64 wake_queue;
++ u64 tx_cqes;
++ u64 tx_cqe_err;
++ u64 tx_cqe_unknown_type;
++ u64 rx_cqes;
++ u64 rx_coalesced_err;
++ u64 rx_cqe_unknown_type;
+ };
+
+ struct mana_context {
diff --git a/debian/patches/features/all/ethernet-microsoft/0016-net-mana-Remove-redundant-pci_clear_master.patch b/debian/patches/features/all/ethernet-microsoft/0016-net-mana-Remove-redundant-pci_clear_master.patch
new file mode 100644
index 000000000..c0bd34da8
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0016-net-mana-Remove-redundant-pci_clear_master.patch
@@ -0,0 +1,54 @@
+From 0022db71934d56cc601cacee4c1e414d7f3cbb37 Mon Sep 17 00:00:00 2001
+From: Cai Huoqing <cai.huoqing@linux.dev>
+Date: Thu, 23 Mar 2023 17:03:05 +0800
+Subject: [PATCH 16/23] net: mana: Remove redundant pci_clear_master
+
+Remove pci_clear_master to simplify the code,
+the bus-mastering is also cleared in do_pci_disable_device,
+like this:
+./drivers/pci/pci.c:2197
+static void do_pci_disable_device(struct pci_dev *dev)
+{
+ u16 pci_command;
+
+ pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+ if (pci_command & PCI_COMMAND_MASTER) {
+ pci_command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(dev, PCI_COMMAND, pci_command);
+ }
+
+ pcibios_disable_device(dev);
+}.
+And dev->is_busmaster is set to 0 in pci_disable_device.
+
+Signed-off-by: Cai Huoqing <cai.huoqing@linux.dev>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 2d59af8307526f2829fdec9c5c5898a857d55180)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index 5b7fddfc9ff1..97a1845c676a 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -1440,7 +1440,6 @@ static int mana_gd_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ release_region:
+ pci_release_regions(pdev);
+ disable_dev:
+- pci_clear_master(pdev);
+ pci_disable_device(pdev);
+ dev_err(&pdev->dev, "gdma probe failed: err = %d\n", err);
+ return err;
+@@ -1459,7 +1458,6 @@ static void mana_gd_remove(struct pci_dev *pdev)
+ vfree(gc);
+
+ pci_release_regions(pdev);
+- pci_clear_master(pdev);
+ pci_disable_device(pdev);
+ }
+
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0017-net-mana-Use-napi_build_skb-in-RX-path.patch b/debian/patches/features/all/ethernet-microsoft/0017-net-mana-Use-napi_build_skb-in-RX-path.patch
new file mode 100644
index 000000000..c8f0f4588
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0017-net-mana-Use-napi_build_skb-in-RX-path.patch
@@ -0,0 +1,33 @@
+From a8796c5278b15a55111d43ccd622b745945ca3d4 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Wed, 12 Apr 2023 14:16:00 -0700
+Subject: [PATCH 17/23] net: mana: Use napi_build_skb in RX path
+
+Use napi_build_skb() instead of build_skb() to take advantage of the
+NAPI percpu caches to obtain skbuff_head.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit ce518bc3e9ca342309995c9270c3ec4892963695)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 55bf40e5ee71..a1b7905ed2f7 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1188,7 +1188,7 @@ static void mana_post_pkt_rxq(struct mana_rxq *rxq)
+ static struct sk_buff *mana_build_skb(void *buf_va, uint pkt_len,
+ struct xdp_buff *xdp)
+ {
+- struct sk_buff *skb = build_skb(buf_va, PAGE_SIZE);
++ struct sk_buff *skb = napi_build_skb(buf_va, PAGE_SIZE);
+
+ if (!skb)
+ return NULL;
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0018-net-mana-Refactor-RX-buffer-allocation-code-to-prepa.patch b/debian/patches/features/all/ethernet-microsoft/0018-net-mana-Refactor-RX-buffer-allocation-code-to-prepa.patch
new file mode 100644
index 000000000..7c072d77c
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0018-net-mana-Refactor-RX-buffer-allocation-code-to-prepa.patch
@@ -0,0 +1,289 @@
+From cf9f102448044cea851cb97666bf6e853c8963e3 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Wed, 12 Apr 2023 14:16:01 -0700
+Subject: [PATCH 18/23] net: mana: Refactor RX buffer allocation code to
+ prepare for various MTU
+
+Move out common buffer allocation code from mana_process_rx_cqe() and
+mana_alloc_rx_wqe() to helper functions.
+Refactor related variables so they can be changed in one place, and buffer
+sizes are in sync.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit a2917b23497e4205db32271e4e06e142a9f8a6aa)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 154 ++++++++++--------
+ include/net/mana/mana.h | 6 +-
+ 2 files changed, 91 insertions(+), 69 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index a1b7905ed2f7..af0c0ee95d87 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1282,14 +1282,64 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
+ u64_stats_update_end(&rx_stats->syncp);
+
+ drop:
+- WARN_ON_ONCE(rxq->xdp_save_page);
+- rxq->xdp_save_page = virt_to_page(buf_va);
++ WARN_ON_ONCE(rxq->xdp_save_va);
++ /* Save for reuse */
++ rxq->xdp_save_va = buf_va;
+
+ ++ndev->stats.rx_dropped;
+
+ return;
+ }
+
++static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
++ dma_addr_t *da, bool is_napi)
++{
++ struct page *page;
++ void *va;
++
++ /* Reuse XDP dropped page if available */
++ if (rxq->xdp_save_va) {
++ va = rxq->xdp_save_va;
++ rxq->xdp_save_va = NULL;
++ } else {
++ page = dev_alloc_page();
++ if (!page)
++ return NULL;
++
++ va = page_to_virt(page);
++ }
++
++ *da = dma_map_single(dev, va + XDP_PACKET_HEADROOM, rxq->datasize,
++ DMA_FROM_DEVICE);
++
++ if (dma_mapping_error(dev, *da)) {
++ put_page(virt_to_head_page(va));
++ return NULL;
++ }
++
++ return va;
++}
++
++/* Allocate frag for rx buffer, and save the old buf */
++static void mana_refill_rxoob(struct device *dev, struct mana_rxq *rxq,
++ struct mana_recv_buf_oob *rxoob, void **old_buf)
++{
++ dma_addr_t da;
++ void *va;
++
++ va = mana_get_rxfrag(rxq, dev, &da, true);
++
++ if (!va)
++ return;
++
++ dma_unmap_single(dev, rxoob->sgl[0].address, rxq->datasize,
++ DMA_FROM_DEVICE);
++ *old_buf = rxoob->buf_va;
++
++ rxoob->buf_va = va;
++ rxoob->sgl[0].address = da;
++}
++
+ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
+ struct gdma_comp *cqe)
+ {
+@@ -1299,10 +1349,8 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
+ struct mana_recv_buf_oob *rxbuf_oob;
+ struct mana_port_context *apc;
+ struct device *dev = gc->dev;
+- void *new_buf, *old_buf;
+- struct page *new_page;
++ void *old_buf = NULL;
+ u32 curr, pktlen;
+- dma_addr_t da;
+
+ apc = netdev_priv(ndev);
+
+@@ -1345,40 +1393,11 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
+ rxbuf_oob = &rxq->rx_oobs[curr];
+ WARN_ON_ONCE(rxbuf_oob->wqe_inf.wqe_size_in_bu != 1);
+
+- /* Reuse XDP dropped page if available */
+- if (rxq->xdp_save_page) {
+- new_page = rxq->xdp_save_page;
+- rxq->xdp_save_page = NULL;
+- } else {
+- new_page = alloc_page(GFP_ATOMIC);
+- }
+-
+- if (new_page) {
+- da = dma_map_page(dev, new_page, XDP_PACKET_HEADROOM, rxq->datasize,
+- DMA_FROM_DEVICE);
+-
+- if (dma_mapping_error(dev, da)) {
+- __free_page(new_page);
+- new_page = NULL;
+- }
+- }
+-
+- new_buf = new_page ? page_to_virt(new_page) : NULL;
+-
+- if (new_buf) {
+- dma_unmap_page(dev, rxbuf_oob->buf_dma_addr, rxq->datasize,
+- DMA_FROM_DEVICE);
+-
+- old_buf = rxbuf_oob->buf_va;
+-
+- /* refresh the rxbuf_oob with the new page */
+- rxbuf_oob->buf_va = new_buf;
+- rxbuf_oob->buf_dma_addr = da;
+- rxbuf_oob->sgl[0].address = rxbuf_oob->buf_dma_addr;
+- } else {
+- old_buf = NULL; /* drop the packet if no memory */
+- }
++ mana_refill_rxoob(dev, rxq, rxbuf_oob, &old_buf);
+
++ /* Unsuccessful refill will have old_buf == NULL.
++ * In this case, mana_rx_skb() will drop the packet.
++ */
+ mana_rx_skb(old_buf, oob, rxq);
+
+ drop:
+@@ -1659,8 +1678,8 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
+
+ mana_deinit_cq(apc, &rxq->rx_cq);
+
+- if (rxq->xdp_save_page)
+- __free_page(rxq->xdp_save_page);
++ if (rxq->xdp_save_va)
++ put_page(virt_to_head_page(rxq->xdp_save_va));
+
+ for (i = 0; i < rxq->num_rx_buf; i++) {
+ rx_oob = &rxq->rx_oobs[i];
+@@ -1668,10 +1687,10 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
+ if (!rx_oob->buf_va)
+ continue;
+
+- dma_unmap_page(dev, rx_oob->buf_dma_addr, rxq->datasize,
+- DMA_FROM_DEVICE);
++ dma_unmap_single(dev, rx_oob->sgl[0].address,
++ rx_oob->sgl[0].size, DMA_FROM_DEVICE);
+
+- free_page((unsigned long)rx_oob->buf_va);
++ put_page(virt_to_head_page(rx_oob->buf_va));
+ rx_oob->buf_va = NULL;
+ }
+
+@@ -1681,6 +1700,26 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
+ kfree(rxq);
+ }
+
++static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
++ struct mana_rxq *rxq, struct device *dev)
++{
++ dma_addr_t da;
++ void *va;
++
++ va = mana_get_rxfrag(rxq, dev, &da, false);
++
++ if (!va)
++ return -ENOMEM;
++
++ rx_oob->buf_va = va;
++
++ rx_oob->sgl[0].address = da;
++ rx_oob->sgl[0].size = rxq->datasize;
++ rx_oob->sgl[0].mem_key = mem_key;
++
++ return 0;
++}
++
+ #define MANA_WQE_HEADER_SIZE 16
+ #define MANA_WQE_SGE_SIZE 16
+
+@@ -1690,9 +1729,8 @@ static int mana_alloc_rx_wqe(struct mana_port_context *apc,
+ struct gdma_context *gc = apc->ac->gdma_dev->gdma_context;
+ struct mana_recv_buf_oob *rx_oob;
+ struct device *dev = gc->dev;
+- struct page *page;
+- dma_addr_t da;
+ u32 buf_idx;
++ int ret;
+
+ WARN_ON(rxq->datasize == 0 || rxq->datasize > PAGE_SIZE);
+
+@@ -1703,25 +1741,12 @@ static int mana_alloc_rx_wqe(struct mana_port_context *apc,
+ rx_oob = &rxq->rx_oobs[buf_idx];
+ memset(rx_oob, 0, sizeof(*rx_oob));
+
+- page = alloc_page(GFP_KERNEL);
+- if (!page)
+- return -ENOMEM;
+-
+- da = dma_map_page(dev, page, XDP_PACKET_HEADROOM, rxq->datasize,
+- DMA_FROM_DEVICE);
+-
+- if (dma_mapping_error(dev, da)) {
+- __free_page(page);
+- return -ENOMEM;
+- }
+-
+- rx_oob->buf_va = page_to_virt(page);
+- rx_oob->buf_dma_addr = da;
+-
+ rx_oob->num_sge = 1;
+- rx_oob->sgl[0].address = rx_oob->buf_dma_addr;
+- rx_oob->sgl[0].size = rxq->datasize;
+- rx_oob->sgl[0].mem_key = apc->ac->gdma_dev->gpa_mkey;
++
++ ret = mana_fill_rx_oob(rx_oob, apc->ac->gdma_dev->gpa_mkey, rxq,
++ dev);
++ if (ret)
++ return ret;
+
+ rx_oob->wqe_req.sgl = rx_oob->sgl;
+ rx_oob->wqe_req.num_sge = rx_oob->num_sge;
+@@ -1780,9 +1805,10 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+ rxq->ndev = ndev;
+ rxq->num_rx_buf = RX_BUFFERS_PER_QUEUE;
+ rxq->rxq_idx = rxq_idx;
+- rxq->datasize = ALIGN(MAX_FRAME_SIZE, 64);
+ rxq->rxobj = INVALID_MANA_HANDLE;
+
++ rxq->datasize = ALIGN(ETH_FRAME_LEN, 64);
++
+ err = mana_alloc_rx_wqe(apc, rxq, &rq_size, &cq_size);
+ if (err)
+ goto out;
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 343ace6de20e..da556246233e 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -36,9 +36,6 @@ enum TRI_STATE {
+
+ #define COMP_ENTRY_SIZE 64
+
+-#define ADAPTER_MTU_SIZE 1500
+-#define MAX_FRAME_SIZE (ADAPTER_MTU_SIZE + 14)
+-
+ #define RX_BUFFERS_PER_QUEUE 512
+
+ #define MAX_SEND_BUFFERS_PER_QUEUE 256
+@@ -282,7 +279,6 @@ struct mana_recv_buf_oob {
+ struct gdma_wqe_request wqe_req;
+
+ void *buf_va;
+- dma_addr_t buf_dma_addr;
+
+ /* SGL of the buffer going to be sent has part of the work request. */
+ u32 num_sge;
+@@ -322,7 +318,7 @@ struct mana_rxq {
+
+ struct bpf_prog __rcu *bpf_prog;
+ struct xdp_rxq_info xdp_rxq;
+- struct page *xdp_save_page;
++ void *xdp_save_va; /* for reusing */
+ bool xdp_flush;
+ int xdp_rc; /* XDP redirect return code */
+
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0019-net-mana-Enable-RX-path-to-handle-various-MTU-sizes.patch b/debian/patches/features/all/ethernet-microsoft/0019-net-mana-Enable-RX-path-to-handle-various-MTU-sizes.patch
new file mode 100644
index 000000000..7fb93c495
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0019-net-mana-Enable-RX-path-to-handle-various-MTU-sizes.patch
@@ -0,0 +1,147 @@
+From 8640f747acafd65c43be07bd7db9a431b5926db3 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Wed, 12 Apr 2023 14:16:02 -0700
+Subject: [PATCH 19/23] net: mana: Enable RX path to handle various MTU sizes
+
+Update RX data path to allocate and use RX queue DMA buffers with
+proper size based on potentially various MTU sizes.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 2fbbd712baf1c60996554326728bbdbef5616e12)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 38 ++++++++++++++-----
+ include/net/mana/mana.h | 7 ++++
+ 2 files changed, 35 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index af0c0ee95d87..afbbe447de1d 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1185,10 +1185,10 @@ static void mana_post_pkt_rxq(struct mana_rxq *rxq)
+ WARN_ON_ONCE(recv_buf_oob->wqe_inf.wqe_size_in_bu != 1);
+ }
+
+-static struct sk_buff *mana_build_skb(void *buf_va, uint pkt_len,
+- struct xdp_buff *xdp)
++static struct sk_buff *mana_build_skb(struct mana_rxq *rxq, void *buf_va,
++ uint pkt_len, struct xdp_buff *xdp)
+ {
+- struct sk_buff *skb = napi_build_skb(buf_va, PAGE_SIZE);
++ struct sk_buff *skb = napi_build_skb(buf_va, rxq->alloc_size);
+
+ if (!skb)
+ return NULL;
+@@ -1196,11 +1196,12 @@ static struct sk_buff *mana_build_skb(void *buf_va, uint pkt_len,
+ if (xdp->data_hard_start) {
+ skb_reserve(skb, xdp->data - xdp->data_hard_start);
+ skb_put(skb, xdp->data_end - xdp->data);
+- } else {
+- skb_reserve(skb, XDP_PACKET_HEADROOM);
+- skb_put(skb, pkt_len);
++ return skb;
+ }
+
++ skb_reserve(skb, rxq->headroom);
++ skb_put(skb, pkt_len);
++
+ return skb;
+ }
+
+@@ -1233,7 +1234,7 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
+ if (act != XDP_PASS && act != XDP_TX)
+ goto drop_xdp;
+
+- skb = mana_build_skb(buf_va, pkt_len, &xdp);
++ skb = mana_build_skb(rxq, buf_va, pkt_len, &xdp);
+
+ if (!skb)
+ goto drop;
+@@ -1301,6 +1302,14 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
+ if (rxq->xdp_save_va) {
+ va = rxq->xdp_save_va;
+ rxq->xdp_save_va = NULL;
++ } else if (rxq->alloc_size > PAGE_SIZE) {
++ if (is_napi)
++ va = napi_alloc_frag(rxq->alloc_size);
++ else
++ va = netdev_alloc_frag(rxq->alloc_size);
++
++ if (!va)
++ return NULL;
+ } else {
+ page = dev_alloc_page();
+ if (!page)
+@@ -1309,7 +1318,7 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
+ va = page_to_virt(page);
+ }
+
+- *da = dma_map_single(dev, va + XDP_PACKET_HEADROOM, rxq->datasize,
++ *da = dma_map_single(dev, va + rxq->headroom, rxq->datasize,
+ DMA_FROM_DEVICE);
+
+ if (dma_mapping_error(dev, *da)) {
+@@ -1732,7 +1741,7 @@ static int mana_alloc_rx_wqe(struct mana_port_context *apc,
+ u32 buf_idx;
+ int ret;
+
+- WARN_ON(rxq->datasize == 0 || rxq->datasize > PAGE_SIZE);
++ WARN_ON(rxq->datasize == 0);
+
+ *rxq_size = 0;
+ *cq_size = 0;
+@@ -1788,6 +1797,7 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+ struct gdma_dev *gd = apc->ac->gdma_dev;
+ struct mana_obj_spec wq_spec;
+ struct mana_obj_spec cq_spec;
++ unsigned int mtu = ndev->mtu;
+ struct gdma_queue_spec spec;
+ struct mana_cq *cq = NULL;
+ struct gdma_context *gc;
+@@ -1807,7 +1817,15 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+ rxq->rxq_idx = rxq_idx;
+ rxq->rxobj = INVALID_MANA_HANDLE;
+
+- rxq->datasize = ALIGN(ETH_FRAME_LEN, 64);
++ rxq->datasize = ALIGN(mtu + ETH_HLEN, 64);
++
++ if (mtu > MANA_XDP_MTU_MAX) {
++ rxq->alloc_size = mtu + MANA_RXBUF_PAD;
++ rxq->headroom = 0;
++ } else {
++ rxq->alloc_size = mtu + MANA_RXBUF_PAD + XDP_PACKET_HEADROOM;
++ rxq->headroom = XDP_PACKET_HEADROOM;
++ }
+
+ err = mana_alloc_rx_wqe(apc, rxq, &rq_size, &cq_size);
+ if (err)
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index da556246233e..42795849d68c 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -291,6 +291,11 @@ struct mana_recv_buf_oob {
+ struct gdma_posted_wqe_info wqe_inf;
+ };
+
++#define MANA_RXBUF_PAD (SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) \
++ + ETH_HLEN)
++
++#define MANA_XDP_MTU_MAX (PAGE_SIZE - MANA_RXBUF_PAD - XDP_PACKET_HEADROOM)
++
+ struct mana_rxq {
+ struct gdma_queue *gdma_rq;
+ /* Cache the gdma receive queue id */
+@@ -300,6 +305,8 @@ struct mana_rxq {
+ u32 rxq_idx;
+
+ u32 datasize;
++ u32 alloc_size;
++ u32 headroom;
+
+ mana_handle_t rxobj;
+
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0020-net-mana-Add-support-for-jumbo-frame.patch b/debian/patches/features/all/ethernet-microsoft/0020-net-mana-Add-support-for-jumbo-frame.patch
new file mode 100644
index 000000000..5a5a44d88
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0020-net-mana-Add-support-for-jumbo-frame.patch
@@ -0,0 +1,423 @@
+From 2552a80c48dd33368d0e7a2b94e1eb72e3053b99 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Wed, 12 Apr 2023 14:16:03 -0700
+Subject: [PATCH 20/23] net: mana: Add support for jumbo frame
+
+During probe, get the hardware-allowed max MTU by querying the device
+configuration. Users can select MTU up to the device limit.
+When XDP is in use, limit MTU settings so the buffer size is within
+one page. And, when MTU is set to a too large value, XDP is not allowed
+to run.
+Also, to prevent changing MTU fails, and leaves the NIC in a bad state,
+pre-allocate all buffers before starting the change. So in low memory
+condition, it will return error, without affecting the NIC.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 80f6215b450eb8e92d8b1f117abf5ecf867f963e)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ .../net/ethernet/microsoft/mana/mana_bpf.c | 22 +-
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 217 ++++++++++++++++--
+ include/net/mana/gdma.h | 4 +
+ include/net/mana/mana.h | 14 ++
+ 4 files changed, 233 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_bpf.c b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+index 3caea631229c..23b1521c0df9 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_bpf.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_bpf.c
+@@ -133,12 +133,6 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
+ return act;
+ }
+
+-static unsigned int mana_xdp_fraglen(unsigned int len)
+-{
+- return SKB_DATA_ALIGN(len) +
+- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+-}
+-
+ struct bpf_prog *mana_xdp_get(struct mana_port_context *apc)
+ {
+ ASSERT_RTNL();
+@@ -179,17 +173,18 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,
+ {
+ struct mana_port_context *apc = netdev_priv(ndev);
+ struct bpf_prog *old_prog;
+- int buf_max;
++ struct gdma_context *gc;
++
++ gc = apc->ac->gdma_dev->gdma_context;
+
+ old_prog = mana_xdp_get(apc);
+
+ if (!old_prog && !prog)
+ return 0;
+
+- buf_max = XDP_PACKET_HEADROOM + mana_xdp_fraglen(ndev->mtu + ETH_HLEN);
+- if (prog && buf_max > PAGE_SIZE) {
+- netdev_err(ndev, "XDP: mtu:%u too large, buf_max:%u\n",
+- ndev->mtu, buf_max);
++ if (prog && ndev->mtu > MANA_XDP_MTU_MAX) {
++ netdev_err(ndev, "XDP: mtu:%u too large, mtu_max:%lu\n",
++ ndev->mtu, MANA_XDP_MTU_MAX);
+ NL_SET_ERR_MSG_MOD(extack, "XDP: mtu too large");
+
+ return -EOPNOTSUPP;
+@@ -206,6 +201,11 @@ static int mana_xdp_set(struct net_device *ndev, struct bpf_prog *prog,
+ if (apc->port_is_up)
+ mana_chn_setxdp(apc, prog);
+
++ if (prog)
++ ndev->max_mtu = MANA_XDP_MTU_MAX;
++ else
++ ndev->max_mtu = gc->adapter_mtu - ETH_HLEN;
++
+ return 0;
+ }
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index afbbe447de1d..34fa5c758b28 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -427,6 +427,192 @@ static u16 mana_select_queue(struct net_device *ndev, struct sk_buff *skb,
+ return txq;
+ }
+
++/* Release pre-allocated RX buffers */
++static void mana_pre_dealloc_rxbufs(struct mana_port_context *mpc)
++{
++ struct device *dev;
++ int i;
++
++ dev = mpc->ac->gdma_dev->gdma_context->dev;
++
++ if (!mpc->rxbufs_pre)
++ goto out1;
++
++ if (!mpc->das_pre)
++ goto out2;
++
++ while (mpc->rxbpre_total) {
++ i = --mpc->rxbpre_total;
++ dma_unmap_single(dev, mpc->das_pre[i], mpc->rxbpre_datasize,
++ DMA_FROM_DEVICE);
++ put_page(virt_to_head_page(mpc->rxbufs_pre[i]));
++ }
++
++ kfree(mpc->das_pre);
++ mpc->das_pre = NULL;
++
++out2:
++ kfree(mpc->rxbufs_pre);
++ mpc->rxbufs_pre = NULL;
++
++out1:
++ mpc->rxbpre_datasize = 0;
++ mpc->rxbpre_alloc_size = 0;
++ mpc->rxbpre_headroom = 0;
++}
++
++/* Get a buffer from the pre-allocated RX buffers */
++static void *mana_get_rxbuf_pre(struct mana_rxq *rxq, dma_addr_t *da)
++{
++ struct net_device *ndev = rxq->ndev;
++ struct mana_port_context *mpc;
++ void *va;
++
++ mpc = netdev_priv(ndev);
++
++ if (!mpc->rxbufs_pre || !mpc->das_pre || !mpc->rxbpre_total) {
++ netdev_err(ndev, "No RX pre-allocated bufs\n");
++ return NULL;
++ }
++
++ /* Check sizes to catch unexpected coding error */
++ if (mpc->rxbpre_datasize != rxq->datasize) {
++ netdev_err(ndev, "rxbpre_datasize mismatch: %u: %u\n",
++ mpc->rxbpre_datasize, rxq->datasize);
++ return NULL;
++ }
++
++ if (mpc->rxbpre_alloc_size != rxq->alloc_size) {
++ netdev_err(ndev, "rxbpre_alloc_size mismatch: %u: %u\n",
++ mpc->rxbpre_alloc_size, rxq->alloc_size);
++ return NULL;
++ }
++
++ if (mpc->rxbpre_headroom != rxq->headroom) {
++ netdev_err(ndev, "rxbpre_headroom mismatch: %u: %u\n",
++ mpc->rxbpre_headroom, rxq->headroom);
++ return NULL;
++ }
++
++ mpc->rxbpre_total--;
++
++ *da = mpc->das_pre[mpc->rxbpre_total];
++ va = mpc->rxbufs_pre[mpc->rxbpre_total];
++ mpc->rxbufs_pre[mpc->rxbpre_total] = NULL;
++
++ /* Deallocate the array after all buffers are gone */
++ if (!mpc->rxbpre_total)
++ mana_pre_dealloc_rxbufs(mpc);
++
++ return va;
++}
++
++/* Get RX buffer's data size, alloc size, XDP headroom based on MTU */
++static void mana_get_rxbuf_cfg(int mtu, u32 *datasize, u32 *alloc_size,
++ u32 *headroom)
++{
++ if (mtu > MANA_XDP_MTU_MAX)
++ *headroom = 0; /* no support for XDP */
++ else
++ *headroom = XDP_PACKET_HEADROOM;
++
++ *alloc_size = mtu + MANA_RXBUF_PAD + *headroom;
++
++ *datasize = ALIGN(mtu + ETH_HLEN, MANA_RX_DATA_ALIGN);
++}
++
++static int mana_pre_alloc_rxbufs(struct mana_port_context *mpc, int new_mtu)
++{
++ struct device *dev;
++ struct page *page;
++ dma_addr_t da;
++ int num_rxb;
++ void *va;
++ int i;
++
++ mana_get_rxbuf_cfg(new_mtu, &mpc->rxbpre_datasize,
++ &mpc->rxbpre_alloc_size, &mpc->rxbpre_headroom);
++
++ dev = mpc->ac->gdma_dev->gdma_context->dev;
++
++ num_rxb = mpc->num_queues * RX_BUFFERS_PER_QUEUE;
++
++ WARN(mpc->rxbufs_pre, "mana rxbufs_pre exists\n");
++ mpc->rxbufs_pre = kmalloc_array(num_rxb, sizeof(void *), GFP_KERNEL);
++ if (!mpc->rxbufs_pre)
++ goto error;
++
++ mpc->das_pre = kmalloc_array(num_rxb, sizeof(dma_addr_t), GFP_KERNEL);
++ if (!mpc->das_pre)
++ goto error;
++
++ mpc->rxbpre_total = 0;
++
++ for (i = 0; i < num_rxb; i++) {
++ if (mpc->rxbpre_alloc_size > PAGE_SIZE) {
++ va = netdev_alloc_frag(mpc->rxbpre_alloc_size);
++ if (!va)
++ goto error;
++ } else {
++ page = dev_alloc_page();
++ if (!page)
++ goto error;
++
++ va = page_to_virt(page);
++ }
++
++ da = dma_map_single(dev, va + mpc->rxbpre_headroom,
++ mpc->rxbpre_datasize, DMA_FROM_DEVICE);
++
++ if (dma_mapping_error(dev, da)) {
++ put_page(virt_to_head_page(va));
++ goto error;
++ }
++
++ mpc->rxbufs_pre[i] = va;
++ mpc->das_pre[i] = da;
++ mpc->rxbpre_total = i + 1;
++ }
++
++ return 0;
++
++error:
++ mana_pre_dealloc_rxbufs(mpc);
++ return -ENOMEM;
++}
++
++static int mana_change_mtu(struct net_device *ndev, int new_mtu)
++{
++ struct mana_port_context *mpc = netdev_priv(ndev);
++ unsigned int old_mtu = ndev->mtu;
++ int err;
++
++ /* Pre-allocate buffers to prevent failure in mana_attach later */
++ err = mana_pre_alloc_rxbufs(mpc, new_mtu);
++ if (err) {
++ netdev_err(ndev, "Insufficient memory for new MTU\n");
++ return err;
++ }
++
++ err = mana_detach(ndev, false);
++ if (err) {
++ netdev_err(ndev, "mana_detach failed: %d\n", err);
++ goto out;
++ }
++
++ ndev->mtu = new_mtu;
++
++ err = mana_attach(ndev);
++ if (err) {
++ netdev_err(ndev, "mana_attach failed: %d\n", err);
++ ndev->mtu = old_mtu;
++ }
++
++out:
++ mana_pre_dealloc_rxbufs(mpc);
++ return err;
++}
++
+ static const struct net_device_ops mana_devops = {
+ .ndo_open = mana_open,
+ .ndo_stop = mana_close,
+@@ -436,6 +622,7 @@ static const struct net_device_ops mana_devops = {
+ .ndo_get_stats64 = mana_get_stats64,
+ .ndo_bpf = mana_bpf,
+ .ndo_xdp_xmit = mana_xdp_xmit,
++ .ndo_change_mtu = mana_change_mtu,
+ };
+
+ static void mana_cleanup_port_context(struct mana_port_context *apc)
+@@ -625,6 +812,9 @@ static int mana_query_device_cfg(struct mana_context *ac, u32 proto_major_ver,
+
+ mana_gd_init_req_hdr(&req.hdr, MANA_QUERY_DEV_CONFIG,
+ sizeof(req), sizeof(resp));
++
++ req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
++
+ req.proto_major_ver = proto_major_ver;
+ req.proto_minor_ver = proto_minor_ver;
+ req.proto_micro_ver = proto_micro_ver;
+@@ -647,6 +837,11 @@ static int mana_query_device_cfg(struct mana_context *ac, u32 proto_major_ver,
+
+ *max_num_vports = resp.max_num_vports;
+
++ if (resp.hdr.response.msg_version == GDMA_MESSAGE_V2)
++ gc->adapter_mtu = resp.adapter_mtu;
++ else
++ gc->adapter_mtu = ETH_FRAME_LEN;
++
+ return 0;
+ }
+
+@@ -1712,10 +1907,14 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
+ static int mana_fill_rx_oob(struct mana_recv_buf_oob *rx_oob, u32 mem_key,
+ struct mana_rxq *rxq, struct device *dev)
+ {
++ struct mana_port_context *mpc = netdev_priv(rxq->ndev);
+ dma_addr_t da;
+ void *va;
+
+- va = mana_get_rxfrag(rxq, dev, &da, false);
++ if (mpc->rxbufs_pre)
++ va = mana_get_rxbuf_pre(rxq, &da);
++ else
++ va = mana_get_rxfrag(rxq, dev, &da, false);
+
+ if (!va)
+ return -ENOMEM;
+@@ -1797,7 +1996,6 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+ struct gdma_dev *gd = apc->ac->gdma_dev;
+ struct mana_obj_spec wq_spec;
+ struct mana_obj_spec cq_spec;
+- unsigned int mtu = ndev->mtu;
+ struct gdma_queue_spec spec;
+ struct mana_cq *cq = NULL;
+ struct gdma_context *gc;
+@@ -1817,15 +2015,8 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,
+ rxq->rxq_idx = rxq_idx;
+ rxq->rxobj = INVALID_MANA_HANDLE;
+
+- rxq->datasize = ALIGN(mtu + ETH_HLEN, 64);
+-
+- if (mtu > MANA_XDP_MTU_MAX) {
+- rxq->alloc_size = mtu + MANA_RXBUF_PAD;
+- rxq->headroom = 0;
+- } else {
+- rxq->alloc_size = mtu + MANA_RXBUF_PAD + XDP_PACKET_HEADROOM;
+- rxq->headroom = XDP_PACKET_HEADROOM;
+- }
++ mana_get_rxbuf_cfg(ndev->mtu, &rxq->datasize, &rxq->alloc_size,
++ &rxq->headroom);
+
+ err = mana_alloc_rx_wqe(apc, rxq, &rq_size, &cq_size);
+ if (err)
+@@ -2238,8 +2429,8 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
+ ndev->netdev_ops = &mana_devops;
+ ndev->ethtool_ops = &mana_ethtool_ops;
+ ndev->mtu = ETH_DATA_LEN;
+- ndev->max_mtu = ndev->mtu;
+- ndev->min_mtu = ndev->mtu;
++ ndev->max_mtu = gc->adapter_mtu - ETH_HLEN;
++ ndev->min_mtu = ETH_MIN_MTU;
+ ndev->needed_headroom = MANA_HEADROOM;
+ ndev->dev_port = port_idx;
+ SET_NETDEV_DEV(ndev, gc->dev);
+diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
+index aabc7cea8a49..b27bf852471b 100644
+--- a/include/net/mana/gdma.h
++++ b/include/net/mana/gdma.h
+@@ -143,6 +143,7 @@ struct gdma_general_req {
+ }; /* HW DATA */
+
+ #define GDMA_MESSAGE_V1 1
++#define GDMA_MESSAGE_V2 2
+
+ struct gdma_general_resp {
+ struct gdma_resp_hdr hdr;
+@@ -352,6 +353,9 @@ struct gdma_context {
+ struct gdma_resource msix_resource;
+ struct gdma_irq_context *irq_contexts;
+
++ /* L2 MTU */
++ u16 adapter_mtu;
++
+ /* This maps a CQ index to the queue structure. */
+ unsigned int max_num_cqs;
+ struct gdma_queue **cq_table;
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 42795849d68c..4f19d73b66ae 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -37,6 +37,7 @@ enum TRI_STATE {
+ #define COMP_ENTRY_SIZE 64
+
+ #define RX_BUFFERS_PER_QUEUE 512
++#define MANA_RX_DATA_ALIGN 64
+
+ #define MAX_SEND_BUFFERS_PER_QUEUE 256
+
+@@ -390,6 +391,14 @@ struct mana_port_context {
+ /* This points to an array of num_queues of RQ pointers. */
+ struct mana_rxq **rxqs;
+
++ /* pre-allocated rx buffer array */
++ void **rxbufs_pre;
++ dma_addr_t *das_pre;
++ int rxbpre_total;
++ u32 rxbpre_datasize;
++ u32 rxbpre_alloc_size;
++ u32 rxbpre_headroom;
++
+ struct bpf_prog *bpf_prog;
+
+ /* Create num_queues EQs, SQs, SQ-CQs, RQs and RQ-CQs, respectively. */
+@@ -486,6 +495,11 @@ struct mana_query_device_cfg_resp {
+ u16 max_num_vports;
+ u16 reserved;
+ u32 max_num_eqs;
++
++ /* response v2: */
++ u16 adapter_mtu;
++ u16 reserved2;
++ u32 reserved3;
+ }; /* HW DATA */
+
+ /* Query vPort Configuration */
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0021-net-mana-Check-if-netdev-napi_alloc_frag-returns-sin.patch b/debian/patches/features/all/ethernet-microsoft/0021-net-mana-Check-if-netdev-napi_alloc_frag-returns-sin.patch
new file mode 100644
index 000000000..33ca4257b
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0021-net-mana-Check-if-netdev-napi_alloc_frag-returns-sin.patch
@@ -0,0 +1,54 @@
+From e1541b0cdf147beef46101f2b9fa8aeb9793bd8d Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Fri, 21 Apr 2023 10:06:58 -0700
+Subject: [PATCH 21/23] net: mana: Check if netdev/napi_alloc_frag returns
+ single page
+
+netdev/napi_alloc_frag() may fall back to single page which is smaller
+than the requested size.
+Add error checking to avoid memory overwritten.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit df18f2da302f169e1a29098c6ca3b474f1b0269e)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 34fa5c758b28..fc19e62c9c84 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -553,6 +553,14 @@ static int mana_pre_alloc_rxbufs(struct mana_port_context *mpc, int new_mtu)
+ va = netdev_alloc_frag(mpc->rxbpre_alloc_size);
+ if (!va)
+ goto error;
++
++ page = virt_to_head_page(va);
++ /* Check if the frag falls back to single page */
++ if (compound_order(page) <
++ get_order(mpc->rxbpre_alloc_size)) {
++ put_page(page);
++ goto error;
++ }
+ } else {
+ page = dev_alloc_page();
+ if (!page)
+@@ -1505,6 +1513,13 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
+
+ if (!va)
+ return NULL;
++
++ page = virt_to_head_page(va);
++ /* Check if the frag falls back to single page */
++ if (compound_order(page) < get_order(rxq->alloc_size)) {
++ put_page(page);
++ return NULL;
++ }
+ } else {
+ page = dev_alloc_page();
+ if (!page)
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0022-net-mana-Fix-perf-regression-remove-rx_cqes-tx_cqes-.patch b/debian/patches/features/all/ethernet-microsoft/0022-net-mana-Fix-perf-regression-remove-rx_cqes-tx_cqes-.patch
new file mode 100644
index 000000000..21a354cc8
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0022-net-mana-Fix-perf-regression-remove-rx_cqes-tx_cqes-.patch
@@ -0,0 +1,121 @@
+From a6967df15a72ffd53963492b8cf52438cf0c27f7 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Fri, 26 May 2023 08:38:57 -0700
+Subject: [PATCH 22/23] net: mana: Fix perf regression: remove rx_cqes, tx_cqes
+ counters
+
+The apc->eth_stats.rx_cqes is one per NIC (vport), and it's on the
+frequent and parallel code path of all queues. So, r/w into this
+single shared variable by many threads on different CPUs creates a
+lot caching and memory overhead, hence perf regression. And, it's
+not accurate due to the high volume concurrent r/w.
+
+For example, a workload is iperf with 128 threads, and with RPS
+enabled. We saw perf regression of 25% with the previous patch
+adding the counters. And this patch eliminates the regression.
+
+Since the error path of mana_poll_rx_cq() already has warnings, so
+keeping the counter and convert it to a per-queue variable is not
+necessary. So, just remove this counter from this high frequency
+code path.
+
+Also, remove the tx_cqes counter for the same reason. We have
+warnings & other counters for errors on that path, and don't need
+to count every normal cqe processing.
+
+Cc: stable@vger.kernel.org
+Fixes: bd7fc6e1957c ("net: mana: Add new MANA VF performance counters for easier troubleshooting")
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://lore.kernel.org/r/1685115537-31675-1-git-send-email-haiyangz@microsoft.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+(cherry picked from commit 1919b39fc6eabb9a6f9a51706ff6d03865f5df29)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 10 ----------
+ drivers/net/ethernet/microsoft/mana/mana_ethtool.c | 2 --
+ include/net/mana/mana.h | 2 --
+ 3 files changed, 14 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index fc19e62c9c84..25b17213e54d 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1280,8 +1280,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
+ if (comp_read < 1)
+ return;
+
+- apc->eth_stats.tx_cqes = comp_read;
+-
+ for (i = 0; i < comp_read; i++) {
+ struct mana_tx_comp_oob *cqe_oob;
+
+@@ -1364,8 +1362,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq)
+ WARN_ON_ONCE(1);
+
+ cq->work_done = pkt_transmitted;
+-
+- apc->eth_stats.tx_cqes -= pkt_transmitted;
+ }
+
+ static void mana_post_pkt_rxq(struct mana_rxq *rxq)
+@@ -1629,15 +1625,11 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
+ {
+ struct gdma_comp *comp = cq->gdma_comp_buf;
+ struct mana_rxq *rxq = cq->rxq;
+- struct mana_port_context *apc;
+ int comp_read, i;
+
+- apc = netdev_priv(rxq->ndev);
+-
+ comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER);
+ WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER);
+
+- apc->eth_stats.rx_cqes = comp_read;
+ rxq->xdp_flush = false;
+
+ for (i = 0; i < comp_read; i++) {
+@@ -1649,8 +1641,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
+ return;
+
+ mana_process_rx_cqe(rxq, cq, &comp[i]);
+-
+- apc->eth_stats.rx_cqes--;
+ }
+
+ if (rxq->xdp_flush)
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+index a64c81410dc1..0dc78679f620 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+@@ -13,11 +13,9 @@ static const struct {
+ } mana_eth_stats[] = {
+ {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)},
+ {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)},
+- {"tx_cqes", offsetof(struct mana_ethtool_stats, tx_cqes)},
+ {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)},
+ {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
+ tx_cqe_unknown_type)},
+- {"rx_cqes", offsetof(struct mana_ethtool_stats, rx_cqes)},
+ {"rx_coalesced_err", offsetof(struct mana_ethtool_stats,
+ rx_coalesced_err)},
+ {"rx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 4f19d73b66ae..3abfce420594 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -347,10 +347,8 @@ struct mana_tx_qp {
+ struct mana_ethtool_stats {
+ u64 stop_queue;
+ u64 wake_queue;
+- u64 tx_cqes;
+ u64 tx_cqe_err;
+ u64 tx_cqe_unknown_type;
+- u64 rx_cqes;
+ u64 rx_coalesced_err;
+ u64 rx_cqe_unknown_type;
+ };
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0023-net-mana-Add-support-for-vlan-tagging.patch b/debian/patches/features/all/ethernet-microsoft/0023-net-mana-Add-support-for-vlan-tagging.patch
new file mode 100644
index 000000000..74866c088
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0023-net-mana-Add-support-for-vlan-tagging.patch
@@ -0,0 +1,67 @@
+From dc801500fea4fd5ddecc4007acffb5716a761f51 Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Fri, 9 Jun 2023 05:47:17 -0700
+Subject: [PATCH 23/23] net: mana: Add support for vlan tagging
+
+To support vlan, use MANA_LONG_PKT_FMT if vlan tag is present in TX
+skb. Then extract the vlan tag from the skb struct, and save it to
+tx_oob for the NIC to transmit. For vlan tags on the payload, they
+are accepted by the NIC too.
+
+For RX, extract the vlan tag from CQE and put it into skb.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit b803d1fded4085d268507a432dac8077ead68971)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 25b17213e54d..808dbf55beef 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -179,6 +179,14 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ pkg.tx_oob.s_oob.short_vp_offset = txq->vp_offset;
+ }
+
++ if (skb_vlan_tag_present(skb)) {
++ pkt_fmt = MANA_LONG_PKT_FMT;
++ pkg.tx_oob.l_oob.inject_vlan_pri_tag = 1;
++ pkg.tx_oob.l_oob.pcp = skb_vlan_tag_get_prio(skb);
++ pkg.tx_oob.l_oob.dei = skb_vlan_tag_get_cfi(skb);
++ pkg.tx_oob.l_oob.vlan_id = skb_vlan_tag_get_id(skb);
++ }
++
+ pkg.tx_oob.s_oob.pkt_fmt = pkt_fmt;
+
+ if (pkt_fmt == MANA_SHORT_PKT_FMT) {
+@@ -1458,6 +1466,12 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe,
+ skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L3);
+ }
+
++ if (cqe->rx_vlantag_present) {
++ u16 vlan_tci = cqe->rx_vlan_id;
++
++ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
++ }
++
+ u64_stats_update_begin(&rx_stats->syncp);
+ rx_stats->packets++;
+ rx_stats->bytes += pkt_len;
+@@ -2454,8 +2468,9 @@ static int mana_probe_port(struct mana_context *ac, int port_idx,
+ ndev->hw_features |= NETIF_F_RXCSUM;
+ ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
+ ndev->hw_features |= NETIF_F_RXHASH;
+- ndev->features = ndev->hw_features;
+- ndev->vlan_features = 0;
++ ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_CTAG_TX |
++ NETIF_F_HW_VLAN_CTAG_RX;
++ ndev->vlan_features = ndev->features;
+
+ err = register_netdev(ndev);
+ if (err) {
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0024-RDMA-mana_ib-Use-v2-version-of-cfg_rx_steer_req-to-e.patch b/debian/patches/features/all/ethernet-microsoft/0024-RDMA-mana_ib-Use-v2-version-of-cfg_rx_steer_req-to-e.patch
new file mode 100644
index 000000000..fb8020cdb
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0024-RDMA-mana_ib-Use-v2-version-of-cfg_rx_steer_req-to-e.patch
@@ -0,0 +1,78 @@
+From 672aac0622254a8f1f5f9d2aa8cee2319654d083 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Sat, 13 May 2023 23:18:15 -0700
+Subject: [PATCH 24/30] RDMA/mana_ib: Use v2 version of cfg_rx_steer_req to
+ enable RX coalescing
+
+With RX coalescing, one CQE entry can be used to indicate multiple packets
+on the receive queue. This saves processing time and PCI bandwidth over
+the CQ.
+
+The MANA Ethernet driver also uses the v2 version of the protocol. It
+doesn't use RX coalescing and its behavior is not changed.
+
+Link: https://lore.kernel.org/r/1684045095-31228-1-git-send-email-longli@linuxonhyperv.com
+Signed-off-by: Long Li <longli@microsoft.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+(cherry picked from commit 2145328515c8fa9b8a9f7889250bc6c032f2a0e6)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 5 ++++-
+ include/net/mana/mana.h | 4 +++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 808dbf55beef..7d82b8949a1e 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -981,7 +981,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
+ bool update_tab)
+ {
+ u16 num_entries = MANA_INDIRECT_TABLE_SIZE;
+- struct mana_cfg_rx_steer_req *req = NULL;
++ struct mana_cfg_rx_steer_req_v2 *req;
+ struct mana_cfg_rx_steer_resp resp = {};
+ struct net_device *ndev = apc->ndev;
+ mana_handle_t *req_indir_tab;
+@@ -996,6 +996,8 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
+ mana_gd_init_req_hdr(&req->hdr, MANA_CONFIG_VPORT_RX, req_buf_size,
+ sizeof(resp));
+
++ req->hdr.req.msg_version = GDMA_MESSAGE_V2;
++
+ req->vport = apc->port_handle;
+ req->num_indir_entries = num_entries;
+ req->indir_tab_offset = sizeof(*req);
+@@ -1005,6 +1007,7 @@ static int mana_cfg_vport_steering(struct mana_port_context *apc,
+ req->update_hashkey = update_key;
+ req->update_indir_tab = update_tab;
+ req->default_rxobj = apc->default_rxobj;
++ req->cqe_coalescing_enable = 0;
+
+ if (update_key)
+ memcpy(&req->hashkey, apc->hashkey, MANA_HASH_KEY_SIZE);
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 3abfce420594..46b5769a5b6a 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -576,7 +576,7 @@ struct mana_fence_rq_resp {
+ }; /* HW DATA */
+
+ /* Configure vPort Rx Steering */
+-struct mana_cfg_rx_steer_req {
++struct mana_cfg_rx_steer_req_v2 {
+ struct gdma_req_hdr hdr;
+ mana_handle_t vport;
+ u16 num_indir_entries;
+@@ -589,6 +589,8 @@ struct mana_cfg_rx_steer_req {
+ u8 reserved;
+ mana_handle_t default_rxobj;
+ u8 hashkey[MANA_HASH_KEY_SIZE];
++ u8 cqe_coalescing_enable;
++ u8 reserved2[7];
+ }; /* HW DATA */
+
+ struct mana_cfg_rx_steer_resp {
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0025-net-mana-use-vmalloc_array-and-vcalloc.patch b/debian/patches/features/all/ethernet-microsoft/0025-net-mana-use-vmalloc_array-and-vcalloc.patch
new file mode 100644
index 000000000..348583771
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0025-net-mana-use-vmalloc_array-and-vcalloc.patch
@@ -0,0 +1,75 @@
+From 4a202b0bfd1b2f3509361e5d3f6040f7af90c2ec Mon Sep 17 00:00:00 2001
+From: Julia Lawall <Julia.Lawall@inria.fr>
+Date: Tue, 27 Jun 2023 16:43:37 +0200
+Subject: [PATCH 25/30] net: mana: use vmalloc_array and vcalloc
+
+Use vmalloc_array and vcalloc to protect against
+multiplication overflows.
+
+The changes were done using the following Coccinelle
+semantic patch:
+
+// <smpl>
+@initialize:ocaml@
+@@
+
+let rename alloc =
+ match alloc with
+ "vmalloc" -> "vmalloc_array"
+ | "vzalloc" -> "vcalloc"
+ | _ -> failwith "unknown"
+
+@@
+ size_t e1,e2;
+ constant C1, C2;
+ expression E1, E2, COUNT, x1, x2, x3;
+ typedef u8;
+ typedef __u8;
+ type t = {u8,__u8,char,unsigned char};
+ identifier alloc = {vmalloc,vzalloc};
+ fresh identifier realloc = script:ocaml(alloc) { rename alloc };
+@@
+
+(
+ alloc(x1*x2*x3)
+|
+ alloc(C1 * C2)
+|
+ alloc((sizeof(t)) * (COUNT), ...)
+|
+- alloc((e1) * (e2))
++ realloc(e1, e2)
+|
+- alloc((e1) * (COUNT))
++ realloc(COUNT, e1)
+|
+- alloc((E1) * (E2))
++ realloc(E1, E2)
+)
+// </smpl>
+
+Signed-off-by: Julia Lawall <Julia.Lawall@inria.fr>
+Link: https://lore.kernel.org/r/20230627144339.144478-23-Julia.Lawall@inria.fr
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit e9c74f8b8a31f77f8e9d7bbed5fc9f2eacbf32a5)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/hw_channel.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+index 9d1507eba5b9..2bd1d74021f7 100644
+--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
++++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+@@ -627,7 +627,7 @@ static int mana_hwc_establish_channel(struct gdma_context *gc, u16 *q_depth,
+ if (WARN_ON(cq->id >= gc->max_num_cqs))
+ return -EPROTO;
+
+- gc->cq_table = vzalloc(gc->max_num_cqs * sizeof(struct gdma_queue *));
++ gc->cq_table = vcalloc(gc->max_num_cqs, sizeof(struct gdma_queue *));
+ if (!gc->cq_table)
+ return -ENOMEM;
+
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0026-net-mana-Batch-ringing-RX-queue-doorbell-on-receivin.patch b/debian/patches/features/all/ethernet-microsoft/0026-net-mana-Batch-ringing-RX-queue-doorbell-on-receivin.patch
new file mode 100644
index 000000000..6f03091cd
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0026-net-mana-Batch-ringing-RX-queue-doorbell-on-receivin.patch
@@ -0,0 +1,62 @@
+From ad96bbb0b221f0cc22fba13a28234636bf7fb9f5 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Mon, 17 Jul 2023 12:35:38 -0700
+Subject: [PATCH 26/30] net: mana: Batch ringing RX queue doorbell on receiving
+ packets
+
+It's inefficient to ring the doorbell page every time a WQE is posted to
+the received queue. Excessive MMIO writes result in CPU spending more
+time waiting on LOCK instructions (atomic operations), resulting in
+poor scaling performance.
+
+Move the code for ringing doorbell page to where after we have posted all
+WQEs to the receive queue during a callback from napi_poll().
+
+With this change, tests showed an improvement from 120G/s to 160G/s on a
+200G physical link, with 16 or 32 hardware queues.
+
+Tests showed no regression in network latency benchmarks on single
+connection.
+
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1689622539-5334-2-git-send-email-longli@linuxonhyperv.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit da4e8648079eb6f26f3a88d8c34270a057e2bfe6)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 7d82b8949a1e..75c1f81ce64f 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1387,8 +1387,8 @@ static void mana_post_pkt_rxq(struct mana_rxq *rxq)
+
+ recv_buf_oob = &rxq->rx_oobs[curr_index];
+
+- err = mana_gd_post_and_ring(rxq->gdma_rq, &recv_buf_oob->wqe_req,
+- &recv_buf_oob->wqe_inf);
++ err = mana_gd_post_work_request(rxq->gdma_rq, &recv_buf_oob->wqe_req,
++ &recv_buf_oob->wqe_inf);
+ if (WARN_ON_ONCE(err))
+ return;
+
+@@ -1660,6 +1660,12 @@ static void mana_poll_rx_cq(struct mana_cq *cq)
+ mana_process_rx_cqe(rxq, cq, &comp[i]);
+ }
+
++ if (comp_read > 0) {
++ struct gdma_context *gc = rxq->gdma_rq->gdma_dev->gdma_context;
++
++ mana_gd_wq_ring_doorbell(gc, rxq->gdma_rq);
++ }
++
+ if (rxq->xdp_flush)
+ xdp_do_flush();
+ }
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0027-net-mana-Use-the-correct-WQE-count-for-ringing-RQ-do.patch b/debian/patches/features/all/ethernet-microsoft/0027-net-mana-Use-the-correct-WQE-count-for-ringing-RQ-do.patch
new file mode 100644
index 000000000..d0bb113fc
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0027-net-mana-Use-the-correct-WQE-count-for-ringing-RQ-do.patch
@@ -0,0 +1,41 @@
+From ac7f97738c05e80f7de5e4ccbbf1ea82fdad956c Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Mon, 17 Jul 2023 12:35:39 -0700
+Subject: [PATCH 27/30] net: mana: Use the correct WQE count for ringing RQ
+ doorbell
+
+The hardware specification specifies that WQE_COUNT should set to 0 for
+the Receive Queue. Although currently the hardware doesn't enforce the
+check, in the future releases it may check on this value.
+
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Long Li <longli@microsoft.com>
+Link: https://lore.kernel.org/r/1689622539-5334-3-git-send-email-longli@linuxonhyperv.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit f5e39b57124fd4715d7f0e2f841b8609b38f3e40)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/gdma_main.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index 97a1845c676a..6108a481edcb 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -300,8 +300,11 @@ static void mana_gd_ring_doorbell(struct gdma_context *gc, u32 db_index,
+
+ void mana_gd_wq_ring_doorbell(struct gdma_context *gc, struct gdma_queue *queue)
+ {
++ /* Hardware Spec specifies that software client should set 0 for
++ * wqe_cnt for Receive Queues. This value is not used in Send Queues.
++ */
+ mana_gd_ring_doorbell(gc, queue->gdma_dev->doorbell, queue->type,
+- queue->id, queue->head * GDMA_WQE_BU_SIZE, 1);
++ queue->id, queue->head * GDMA_WQE_BU_SIZE, 0);
+ }
+
+ void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit)
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0028-net-mana-Configure-hwc-timeout-from-hardware.patch b/debian/patches/features/all/ethernet-microsoft/0028-net-mana-Configure-hwc-timeout-from-hardware.patch
new file mode 100644
index 000000000..b5c24df16
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0028-net-mana-Configure-hwc-timeout-from-hardware.patch
@@ -0,0 +1,217 @@
+From 4c91517cbcdd16c2a9aee0e21066f2f1aa193ece Mon Sep 17 00:00:00 2001
+From: Souradeep Chakrabarti <schakrabarti@linux.microsoft.com>
+Date: Wed, 2 Aug 2023 04:07:40 -0700
+Subject: [PATCH 28/30] net: mana: Configure hwc timeout from hardware
+
+At present hwc timeout value is a fixed value. This patch sets the hwc
+timeout from the hardware. It now uses a new hardware capability
+GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG to query and set the value
+in hwc_timeout.
+
+Signed-off-by: Souradeep Chakrabarti <schakrabarti@linux.microsoft.com>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit 62c1bff593b7e30041d0273b835af9fd6f5ee737)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ .../net/ethernet/microsoft/mana/gdma_main.c | 30 ++++++++++++++++++-
+ .../net/ethernet/microsoft/mana/hw_channel.c | 24 ++++++++++++++-
+ include/net/mana/gdma.h | 20 ++++++++++++-
+ include/net/mana/hw_channel.h | 5 ++++
+ 4 files changed, 76 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+index 6108a481edcb..4fa1901a2789 100644
+--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
++++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
+@@ -106,6 +106,25 @@ static int mana_gd_query_max_resources(struct pci_dev *pdev)
+ return 0;
+ }
+
++static int mana_gd_query_hwc_timeout(struct pci_dev *pdev, u32 *timeout_val)
++{
++ struct gdma_context *gc = pci_get_drvdata(pdev);
++ struct gdma_query_hwc_timeout_resp resp = {};
++ struct gdma_query_hwc_timeout_req req = {};
++ int err;
++
++ mana_gd_init_req_hdr(&req.hdr, GDMA_QUERY_HWC_TIMEOUT,
++ sizeof(req), sizeof(resp));
++ req.timeout_ms = *timeout_val;
++ err = mana_gd_send_request(gc, sizeof(req), &req, sizeof(resp), &resp);
++ if (err || resp.hdr.status)
++ return err ? err : -EPROTO;
++
++ *timeout_val = resp.timeout_ms;
++
++ return 0;
++}
++
+ static int mana_gd_detect_devices(struct pci_dev *pdev)
+ {
+ struct gdma_context *gc = pci_get_drvdata(pdev);
+@@ -883,8 +902,10 @@ int mana_gd_verify_vf_version(struct pci_dev *pdev)
+ struct gdma_context *gc = pci_get_drvdata(pdev);
+ struct gdma_verify_ver_resp resp = {};
+ struct gdma_verify_ver_req req = {};
++ struct hw_channel_context *hwc;
+ int err;
+
++ hwc = gc->hwc.driver_data;
+ mana_gd_init_req_hdr(&req.hdr, GDMA_VERIFY_VF_DRIVER_VERSION,
+ sizeof(req), sizeof(resp));
+
+@@ -911,7 +932,14 @@ int mana_gd_verify_vf_version(struct pci_dev *pdev)
+ err, resp.hdr.status);
+ return err ? err : -EPROTO;
+ }
+-
++ if (resp.pf_cap_flags1 & GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG) {
++ err = mana_gd_query_hwc_timeout(pdev, &hwc->hwc_timeout);
++ if (err) {
++ dev_err(gc->dev, "Failed to set the hwc timeout %d\n", err);
++ return err;
++ }
++ dev_dbg(gc->dev, "set the hwc timeout to %u\n", hwc->hwc_timeout);
++ }
+ return 0;
+ }
+
+diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+index 2bd1d74021f7..9d1cd3bfcf66 100644
+--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
++++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+@@ -174,7 +174,25 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,
+ complete(&hwc->hwc_init_eqe_comp);
+ break;
+
++ case GDMA_EQE_HWC_SOC_RECONFIG_DATA:
++ type_data.as_uint32 = event->details[0];
++ type = type_data.type;
++ val = type_data.value;
++
++ switch (type) {
++ case HWC_DATA_CFG_HWC_TIMEOUT:
++ hwc->hwc_timeout = val;
++ break;
++
++ default:
++ dev_warn(hwc->dev, "Received unknown reconfig type %u\n", type);
++ break;
++ }
++
++ break;
++
+ default:
++ dev_warn(hwc->dev, "Received unknown gdma event %u\n", event->type);
+ /* Ignore unknown events, which should never happen. */
+ break;
+ }
+@@ -696,6 +714,7 @@ int mana_hwc_create_channel(struct gdma_context *gc)
+ gd->driver_data = hwc;
+ hwc->gdma_dev = gd;
+ hwc->dev = gc->dev;
++ hwc->hwc_timeout = HW_CHANNEL_WAIT_RESOURCE_TIMEOUT_MS;
+
+ /* HWC's instance number is always 0. */
+ gd->dev_id.as_uint32 = 0;
+@@ -770,6 +789,8 @@ void mana_hwc_destroy_channel(struct gdma_context *gc)
+ hwc->gdma_dev->doorbell = INVALID_DOORBELL;
+ hwc->gdma_dev->pdid = INVALID_PDID;
+
++ hwc->hwc_timeout = 0;
++
+ kfree(hwc);
+ gc->hwc.driver_data = NULL;
+ gc->hwc.gdma_context = NULL;
+@@ -825,7 +846,8 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
+ goto out;
+ }
+
+- if (!wait_for_completion_timeout(&ctx->comp_event, 30 * HZ)) {
++ if (!wait_for_completion_timeout(&ctx->comp_event,
++ (msecs_to_jiffies(hwc->hwc_timeout) * HZ))) {
+ dev_err(hwc->dev, "HWC: Request timed out!\n");
+ err = -ETIMEDOUT;
+ goto out;
+diff --git a/include/net/mana/gdma.h b/include/net/mana/gdma.h
+index b27bf852471b..102bb73c7a4f 100644
+--- a/include/net/mana/gdma.h
++++ b/include/net/mana/gdma.h
+@@ -31,6 +31,7 @@ enum gdma_request_type {
+ GDMA_DESTROY_PD = 30,
+ GDMA_CREATE_MR = 31,
+ GDMA_DESTROY_MR = 32,
++ GDMA_QUERY_HWC_TIMEOUT = 84, /* 0x54 */
+ };
+
+ enum gdma_queue_type {
+@@ -53,6 +54,8 @@ enum gdma_eqe_type {
+ GDMA_EQE_HWC_INIT_EQ_ID_DB = 129,
+ GDMA_EQE_HWC_INIT_DATA = 130,
+ GDMA_EQE_HWC_INIT_DONE = 131,
++ GDMA_EQE_HWC_SOC_RECONFIG = 132,
++ GDMA_EQE_HWC_SOC_RECONFIG_DATA = 133,
+ };
+
+ enum {
+@@ -529,10 +532,12 @@ enum {
+ * so the driver is able to reliably support features like busy_poll.
+ */
+ #define GDMA_DRV_CAP_FLAG_1_NAPI_WKDONE_FIX BIT(2)
++#define GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG BIT(3)
+
+ #define GDMA_DRV_CAP_FLAGS1 \
+ (GDMA_DRV_CAP_FLAG_1_EQ_SHARING_MULTI_VPORT | \
+- GDMA_DRV_CAP_FLAG_1_NAPI_WKDONE_FIX)
++ GDMA_DRV_CAP_FLAG_1_NAPI_WKDONE_FIX | \
++ GDMA_DRV_CAP_FLAG_1_HWC_TIMEOUT_RECONFIG)
+
+ #define GDMA_DRV_CAP_FLAGS2 0
+
+@@ -642,6 +647,19 @@ struct gdma_disable_queue_req {
+ u32 alloc_res_id_on_creation;
+ }; /* HW DATA */
+
++/* GDMA_QUERY_HWC_TIMEOUT */
++struct gdma_query_hwc_timeout_req {
++ struct gdma_req_hdr hdr;
++ u32 timeout_ms;
++ u32 reserved;
++};
++
++struct gdma_query_hwc_timeout_resp {
++ struct gdma_resp_hdr hdr;
++ u32 timeout_ms;
++ u32 reserved;
++};
++
+ enum atb_page_size {
+ ATB_PAGE_SIZE_4K,
+ ATB_PAGE_SIZE_8K,
+diff --git a/include/net/mana/hw_channel.h b/include/net/mana/hw_channel.h
+index 6a757a6e2732..3d3b5c881bc1 100644
+--- a/include/net/mana/hw_channel.h
++++ b/include/net/mana/hw_channel.h
+@@ -23,6 +23,10 @@
+ #define HWC_INIT_DATA_PF_DEST_RQ_ID 10
+ #define HWC_INIT_DATA_PF_DEST_CQ_ID 11
+
++#define HWC_DATA_CFG_HWC_TIMEOUT 1
++
++#define HW_CHANNEL_WAIT_RESOURCE_TIMEOUT_MS 30000
++
+ /* Structures labeled with "HW DATA" are exchanged with the hardware. All of
+ * them are naturally aligned and hence don't need __packed.
+ */
+@@ -182,6 +186,7 @@ struct hw_channel_context {
+
+ u32 pf_dest_vrq_id;
+ u32 pf_dest_vrcq_id;
++ u32 hwc_timeout;
+
+ struct hwc_caller_ctx *caller_ctx;
+ };
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0029-net-mana-Rename-mana_refill_rxoob-and-remove-some-em.patch b/debian/patches/features/all/ethernet-microsoft/0029-net-mana-Rename-mana_refill_rxoob-and-remove-some-em.patch
new file mode 100644
index 000000000..a9f8249bd
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0029-net-mana-Rename-mana_refill_rxoob-and-remove-some-em.patch
@@ -0,0 +1,67 @@
+From 609fba0ab4ebdde830c8c52ef0dcc2ea8f5e82fe Mon Sep 17 00:00:00 2001
+From: Haiyang Zhang <haiyangz@microsoft.com>
+Date: Fri, 21 Apr 2023 10:06:57 -0700
+Subject: [PATCH 29/30] net: mana: Rename mana_refill_rxoob and remove some
+ empty lines
+
+Rename mana_refill_rxoob for naming consistency.
+And remove some empty lines between function call and error
+checking.
+
+Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+(cherry picked from commit 5c74064f43c291d9add2b436a2d70205b71a7cc7)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 75c1f81ce64f..6aa273b68327 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -579,7 +579,6 @@ static int mana_pre_alloc_rxbufs(struct mana_port_context *mpc, int new_mtu)
+
+ da = dma_map_single(dev, va + mpc->rxbpre_headroom,
+ mpc->rxbpre_datasize, DMA_FROM_DEVICE);
+-
+ if (dma_mapping_error(dev, da)) {
+ put_page(virt_to_head_page(va));
+ goto error;
+@@ -1543,7 +1542,6 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
+
+ *da = dma_map_single(dev, va + rxq->headroom, rxq->datasize,
+ DMA_FROM_DEVICE);
+-
+ if (dma_mapping_error(dev, *da)) {
+ put_page(virt_to_head_page(va));
+ return NULL;
+@@ -1553,14 +1551,13 @@ static void *mana_get_rxfrag(struct mana_rxq *rxq, struct device *dev,
+ }
+
+ /* Allocate frag for rx buffer, and save the old buf */
+-static void mana_refill_rxoob(struct device *dev, struct mana_rxq *rxq,
+- struct mana_recv_buf_oob *rxoob, void **old_buf)
++static void mana_refill_rx_oob(struct device *dev, struct mana_rxq *rxq,
++ struct mana_recv_buf_oob *rxoob, void **old_buf)
+ {
+ dma_addr_t da;
+ void *va;
+
+ va = mana_get_rxfrag(rxq, dev, &da, true);
+-
+ if (!va)
+ return;
+
+@@ -1625,7 +1622,7 @@ static void mana_process_rx_cqe(struct mana_rxq *rxq, struct mana_cq *cq,
+ rxbuf_oob = &rxq->rx_oobs[curr];
+ WARN_ON_ONCE(rxbuf_oob->wqe_inf.wqe_size_in_bu != 1);
+
+- mana_refill_rxoob(dev, rxq, rxbuf_oob, &old_buf);
++ mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf);
+
+ /* Unsuccessful refill will have old_buf == NULL.
+ * In this case, mana_rx_skb() will drop the packet.
+--
+2.40.1
+
diff --git a/debian/patches/features/all/ethernet-microsoft/0030-net-mana-Add-gdma-stats-to-ethtool-output-for-mana.patch b/debian/patches/features/all/ethernet-microsoft/0030-net-mana-Add-gdma-stats-to-ethtool-output-for-mana.patch
new file mode 100644
index 000000000..07caff6a9
--- /dev/null
+++ b/debian/patches/features/all/ethernet-microsoft/0030-net-mana-Add-gdma-stats-to-ethtool-output-for-mana.patch
@@ -0,0 +1,232 @@
+From b7a5d522d26c84055bcc410b51b8cefc64fcdbca Mon Sep 17 00:00:00 2001
+From: Shradha Gupta <shradhagupta@linux.microsoft.com>
+Date: Wed, 9 Aug 2023 21:15:22 -0700
+Subject: [PATCH 30/30] net: mana: Add gdma stats to ethtool output for mana
+
+Extended performance counter stats in 'ethtool -S <interface>'
+for MANA VF to include GDMA tx LSO packets and bytes count.
+
+Tested-on: Ubuntu22
+Testcases:
+1. LISA testcase:
+PERF-NETWORK-TCP-THROUGHPUT-MULTICONNECTION-NTTTCP-Synthetic
+2. LISA testcase:
+PERF-NETWORK-TCP-THROUGHPUT-MULTICONNECTION-NTTTCP-SRIOV
+3. Validated the GDMA stat packets and byte counters
+Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+(cherry picked from commit ac3899c6229649737b9d5cb86e417c98243883dc)
+Signed-off-by: Bastian Blank <waldi@debian.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 40 +++++++++
+ .../ethernet/microsoft/mana/mana_ethtool.c | 15 ++++
+ include/net/mana/mana.h | 87 +++++++++++++++++++
+ 3 files changed, 142 insertions(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 6aa273b68327..a006bd69b26e 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -2234,6 +2234,46 @@ int mana_config_rss(struct mana_port_context *apc, enum TRI_STATE rx,
+ return 0;
+ }
+
++void mana_query_gf_stats(struct mana_port_context *apc)
++{
++ struct mana_query_gf_stat_resp resp = {};
++ struct mana_query_gf_stat_req req = {};
++ struct net_device *ndev = apc->ndev;
++ int err;
++
++ mana_gd_init_req_hdr(&req.hdr, MANA_QUERY_GF_STAT,
++ sizeof(req), sizeof(resp));
++ req.req_stats = STATISTICS_FLAGS_HC_TX_BYTES |
++ STATISTICS_FLAGS_HC_TX_UCAST_PACKETS |
++ STATISTICS_FLAGS_HC_TX_UCAST_BYTES |
++ STATISTICS_FLAGS_HC_TX_MCAST_PACKETS |
++ STATISTICS_FLAGS_HC_TX_MCAST_BYTES |
++ STATISTICS_FLAGS_HC_TX_BCAST_PACKETS |
++ STATISTICS_FLAGS_HC_TX_BCAST_BYTES;
++
++ err = mana_send_request(apc->ac, &req, sizeof(req), &resp,
++ sizeof(resp));
++ if (err) {
++ netdev_err(ndev, "Failed to query GF stats: %d\n", err);
++ return;
++ }
++ err = mana_verify_resp_hdr(&resp.hdr, MANA_QUERY_GF_STAT,
++ sizeof(resp));
++ if (err || resp.hdr.status) {
++ netdev_err(ndev, "Failed to query GF stats: %d, 0x%x\n", err,
++ resp.hdr.status);
++ return;
++ }
++
++ apc->eth_stats.hc_tx_bytes = resp.hc_tx_bytes;
++ apc->eth_stats.hc_tx_ucast_pkts = resp.hc_tx_ucast_pkts;
++ apc->eth_stats.hc_tx_ucast_bytes = resp.hc_tx_ucast_bytes;
++ apc->eth_stats.hc_tx_bcast_pkts = resp.hc_tx_bcast_pkts;
++ apc->eth_stats.hc_tx_bcast_bytes = resp.hc_tx_bcast_bytes;
++ apc->eth_stats.hc_tx_mcast_pkts = resp.hc_tx_mcast_pkts;
++ apc->eth_stats.hc_tx_mcast_bytes = resp.hc_tx_mcast_bytes;
++}
++
+ static int mana_init_port(struct net_device *ndev)
+ {
+ struct mana_port_context *apc = netdev_priv(ndev);
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+index 0dc78679f620..607150165ab4 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c
+@@ -13,6 +13,19 @@ static const struct {
+ } mana_eth_stats[] = {
+ {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)},
+ {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)},
++ {"hc_tx_bytes", offsetof(struct mana_ethtool_stats, hc_tx_bytes)},
++ {"hc_tx_ucast_pkts", offsetof(struct mana_ethtool_stats,
++ hc_tx_ucast_pkts)},
++ {"hc_tx_ucast_bytes", offsetof(struct mana_ethtool_stats,
++ hc_tx_ucast_bytes)},
++ {"hc_tx_bcast_pkts", offsetof(struct mana_ethtool_stats,
++ hc_tx_bcast_pkts)},
++ {"hc_tx_bcast_bytes", offsetof(struct mana_ethtool_stats,
++ hc_tx_bcast_bytes)},
++ {"hc_tx_mcast_pkts", offsetof(struct mana_ethtool_stats,
++ hc_tx_mcast_pkts)},
++ {"hc_tx_mcast_bytes", offsetof(struct mana_ethtool_stats,
++ hc_tx_mcast_bytes)},
+ {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)},
+ {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats,
+ tx_cqe_unknown_type)},
+@@ -114,6 +127,8 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
+
+ if (!apc->port_is_up)
+ return;
++ /* we call mana function to update stats from GDMA */
++ mana_query_gf_stats(apc);
+
+ for (q = 0; q < ARRAY_SIZE(mana_eth_stats); q++)
+ data[i++] = *(u64 *)(eth_stats + mana_eth_stats[q].offset);
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 46b5769a5b6a..cc4502db2ced 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -347,6 +347,13 @@ struct mana_tx_qp {
+ struct mana_ethtool_stats {
+ u64 stop_queue;
+ u64 wake_queue;
++ u64 hc_tx_bytes;
++ u64 hc_tx_ucast_pkts;
++ u64 hc_tx_ucast_bytes;
++ u64 hc_tx_bcast_pkts;
++ u64 hc_tx_bcast_bytes;
++ u64 hc_tx_mcast_pkts;
++ u64 hc_tx_mcast_bytes;
+ u64 tx_cqe_err;
+ u64 tx_cqe_unknown_type;
+ u64 rx_coalesced_err;
+@@ -437,6 +444,7 @@ u32 mana_run_xdp(struct net_device *ndev, struct mana_rxq *rxq,
+ struct bpf_prog *mana_xdp_get(struct mana_port_context *apc);
+ void mana_chn_setxdp(struct mana_port_context *apc, struct bpf_prog *prog);
+ int mana_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
++void mana_query_gf_stats(struct mana_port_context *apc);
+
+ extern const struct ethtool_ops mana_ethtool_ops;
+
+@@ -575,6 +583,49 @@ struct mana_fence_rq_resp {
+ struct gdma_resp_hdr hdr;
+ }; /* HW DATA */
+
++/* Query stats RQ */
++struct mana_query_gf_stat_req {
++ struct gdma_req_hdr hdr;
++ u64 req_stats;
++}; /* HW DATA */
++
++struct mana_query_gf_stat_resp {
++ struct gdma_resp_hdr hdr;
++ u64 reported_stats;
++ /* rx errors/discards */
++ u64 discard_rx_nowqe;
++ u64 err_rx_vport_disabled;
++ /* rx bytes/packets */
++ u64 hc_rx_bytes;
++ u64 hc_rx_ucast_pkts;
++ u64 hc_rx_ucast_bytes;
++ u64 hc_rx_bcast_pkts;
++ u64 hc_rx_bcast_bytes;
++ u64 hc_rx_mcast_pkts;
++ u64 hc_rx_mcast_bytes;
++ /* tx errors */
++ u64 err_tx_gf_disabled;
++ u64 err_tx_vport_disabled;
++ u64 err_tx_inval_vport_offset_pkt;
++ u64 err_tx_vlan_enforcement;
++ u64 err_tx_ethtype_enforcement;
++ u64 err_tx_SA_enforecement;
++ u64 err_tx_SQPDID_enforcement;
++ u64 err_tx_CQPDID_enforcement;
++ u64 err_tx_mtu_violation;
++ u64 err_tx_inval_oob;
++ /* tx bytes/packets */
++ u64 hc_tx_bytes;
++ u64 hc_tx_ucast_pkts;
++ u64 hc_tx_ucast_bytes;
++ u64 hc_tx_bcast_pkts;
++ u64 hc_tx_bcast_bytes;
++ u64 hc_tx_mcast_pkts;
++ u64 hc_tx_mcast_bytes;
++ /* tx error */
++ u64 err_tx_gdma;
++}; /* HW DATA */
++
+ /* Configure vPort Rx Steering */
+ struct mana_cfg_rx_steer_req_v2 {
+ struct gdma_req_hdr hdr;
+@@ -654,6 +705,42 @@ struct mana_deregister_filter_resp {
+ struct gdma_resp_hdr hdr;
+ }; /* HW DATA */
+
++/* Requested GF stats Flags */
++/* Rx discards/Errors */
++#define STATISTICS_FLAGS_RX_DISCARDS_NO_WQE 0x0000000000000001
++#define STATISTICS_FLAGS_RX_ERRORS_VPORT_DISABLED 0x0000000000000002
++/* Rx bytes/pkts */
++#define STATISTICS_FLAGS_HC_RX_BYTES 0x0000000000000004
++#define STATISTICS_FLAGS_HC_RX_UCAST_PACKETS 0x0000000000000008
++#define STATISTICS_FLAGS_HC_RX_UCAST_BYTES 0x0000000000000010
++#define STATISTICS_FLAGS_HC_RX_MCAST_PACKETS 0x0000000000000020
++#define STATISTICS_FLAGS_HC_RX_MCAST_BYTES 0x0000000000000040
++#define STATISTICS_FLAGS_HC_RX_BCAST_PACKETS 0x0000000000000080
++#define STATISTICS_FLAGS_HC_RX_BCAST_BYTES 0x0000000000000100
++/* Tx errors */
++#define STATISTICS_FLAGS_TX_ERRORS_GF_DISABLED 0x0000000000000200
++#define STATISTICS_FLAGS_TX_ERRORS_VPORT_DISABLED 0x0000000000000400
++#define STATISTICS_FLAGS_TX_ERRORS_INVAL_VPORT_OFFSET_PACKETS \
++ 0x0000000000000800
++#define STATISTICS_FLAGS_TX_ERRORS_VLAN_ENFORCEMENT 0x0000000000001000
++#define STATISTICS_FLAGS_TX_ERRORS_ETH_TYPE_ENFORCEMENT \
++ 0x0000000000002000
++#define STATISTICS_FLAGS_TX_ERRORS_SA_ENFORCEMENT 0x0000000000004000
++#define STATISTICS_FLAGS_TX_ERRORS_SQPDID_ENFORCEMENT 0x0000000000008000
++#define STATISTICS_FLAGS_TX_ERRORS_CQPDID_ENFORCEMENT 0x0000000000010000
++#define STATISTICS_FLAGS_TX_ERRORS_MTU_VIOLATION 0x0000000000020000
++#define STATISTICS_FLAGS_TX_ERRORS_INVALID_OOB 0x0000000000040000
++/* Tx bytes/pkts */
++#define STATISTICS_FLAGS_HC_TX_BYTES 0x0000000000080000
++#define STATISTICS_FLAGS_HC_TX_UCAST_PACKETS 0x0000000000100000
++#define STATISTICS_FLAGS_HC_TX_UCAST_BYTES 0x0000000000200000
++#define STATISTICS_FLAGS_HC_TX_MCAST_PACKETS 0x0000000000400000
++#define STATISTICS_FLAGS_HC_TX_MCAST_BYTES 0x0000000000800000
++#define STATISTICS_FLAGS_HC_TX_BCAST_PACKETS 0x0000000001000000
++#define STATISTICS_FLAGS_HC_TX_BCAST_BYTES 0x0000000002000000
++/* Tx error */
++#define STATISTICS_FLAGS_TX_ERRORS_GDMA_ERROR 0x0000000004000000
++
+ #define MANA_MAX_NUM_QUEUES 64
+
+ #define MANA_SHORT_VPORT_OFFSET_MAX ((1U << 8) - 1)
+--
+2.40.1
+
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 000000000..6f1ba8e5a
--- /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 000000000..b46698757
--- /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
+@@ -1205,19 +1205,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
+@@ -27,6 +27,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
+@@ -849,6 +849,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
+ /*
+@@ -873,6 +881,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)
+ {
+@@ -892,6 +901,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);
+@@ -1107,13 +1117,6 @@ static inline bool efi_runtime_disabled(
+ extern void efi_call_virt_check_flags(unsigned long flags, const char *call);
+ 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 000000000..9ec425871
--- /dev/null
+++ b/debian/patches/features/all/lockdown/efi-lock-down-the-kernel-if-booted-in-secure-boot-mo.patch
@@ -0,0 +1,131 @@
+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 needs to be adjusted to
+mention that lockdown is triggered in integrity mode]
+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(-)
+
+Index: debian-kernel/arch/x86/kernel/setup.c
+===================================================================
+--- debian-kernel.orig/arch/x86/kernel/setup.c
++++ debian-kernel/arch/x86/kernel/setup.c
+@@ -979,6 +979,8 @@ void __init setup_arch(char **cmdline_p)
+ if (efi_enabled(EFI_BOOT))
+ efi_init();
+
++ efi_set_secure_boot(boot_params.secure_boot);
++
+ dmi_setup();
+
+ /*
+@@ -1130,8 +1132,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();
+Index: debian-kernel/drivers/firmware/efi/secureboot.c
+===================================================================
+--- debian-kernel.orig/drivers/firmware/efi/secureboot.c
++++ debian-kernel/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:
+Index: debian-kernel/include/linux/security.h
+===================================================================
+--- debian-kernel.orig/include/linux/security.h
++++ debian-kernel/include/linux/security.h
+@@ -451,6 +451,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)
+@@ -1291,6 +1292,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)
+Index: debian-kernel/security/lockdown/Kconfig
+===================================================================
+--- debian-kernel.orig/security/lockdown/Kconfig
++++ debian-kernel/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.
+Index: debian-kernel/security/lockdown/lockdown.c
+===================================================================
+--- debian-kernel.orig/security/lockdown/lockdown.c
++++ debian-kernel/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 000000000..c718e7e2f
--- /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 000000000..e58668ebe
--- /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://lkml.org/lkml/2016/1/11/587
+
+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 */
+@@ -12235,6 +12240,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/arm64/arm64-dts-rockchip-Add-Hardkernel-ODROID-M1-board.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-Hardkernel-ODROID-M1-board.patch
new file mode 100644
index 000000000..18b3218ee
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-Hardkernel-ODROID-M1-board.patch
@@ -0,0 +1,454 @@
+From: Dongjin Kim <tobetter@gmail.com>
+Date: Fri, 30 Sep 2022 07:12:35 +0200
+Subject: [02/13] arm64: dts: rockchip: Add Hardkernel ODROID-M1 board
+Origin: https://git.kernel.org/linus/fd35832677032980df230f02509d6c016664cc89
+
+This patch is to add a device tree for new board Hardkernel ODROID-M1
+based on Rockchip RK3568, includes basic peripherals -
+uart/eMMC/uSD/i2c and on-board ethernet.
+
+Signed-off-by: Dongjin Kim <tobetter@gmail.com>
+[aurelien@aurel32.net: addressed issues from initial review]
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-3-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/Makefile | 1 +
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 414 ++++++++++++++++++
+ 2 files changed, 415 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+
+diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
+index a5a6262936f0..68cc720a623a 100644
+--- a/arch/arm64/boot/dts/rockchip/Makefile
++++ b/arch/arm64/boot/dts/rockchip/Makefile
+@@ -72,4 +72,5 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-roc-pc.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-cm4.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb
++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-odroid-m1.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+new file mode 100644
+index 000000000000..b3016437640b
+--- /dev/null
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -0,0 +1,414 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++/*
++ * Copyright (c) 2022 Hardkernel Co., Ltd.
++ *
++ */
++
++/dts-v1/;
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/pinctrl/rockchip.h>
++#include "rk3568.dtsi"
++
++/ {
++ model = "Hardkernel ODROID-M1";
++ compatible = "rockchip,rk3568-odroid-m1", "rockchip,rk3568";
++
++ aliases {
++ ethernet0 = &gmac0;
++ i2c0 = &i2c3;
++ i2c3 = &i2c0;
++ mmc0 = &sdhci;
++ mmc1 = &sdmmc0;
++ serial0 = &uart1;
++ serial1 = &uart0;
++ };
++
++ chosen {
++ stdout-path = "serial2:1500000n8";
++ };
++
++ dc_12v: dc-12v-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "dc_12v";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <12000000>;
++ regulator-max-microvolt = <12000000>;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: led-0 {
++ gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_RED>;
++ default-state = "keep";
++ linux,default-trigger = "default-on";
++ pinctrl-names = "default";
++ pinctrl-0 = <&led_power_pin>;
++ };
++ led_work: led-1 {
++ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
++ function = LED_FUNCTION_HEARTBEAT;
++ color = <LED_COLOR_ID_BLUE>;
++ linux,default-trigger = "heartbeat";
++ pinctrl-names = "default";
++ pinctrl-0 = <&led_work_pin>;
++ };
++ };
++
++ vcc3v3_sys: vcc3v3-sys-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v3_sys";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <&dc_12v>;
++ };
++};
++
++&cpu0 {
++ cpu-supply = <&vdd_cpu>;
++};
++
++&cpu1 {
++ cpu-supply = <&vdd_cpu>;
++};
++
++&cpu2 {
++ cpu-supply = <&vdd_cpu>;
++};
++
++&cpu3 {
++ cpu-supply = <&vdd_cpu>;
++};
++
++&gmac0 {
++ assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;
++ assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>;
++ assigned-clock-rates = <0>, <125000000>;
++ clock_in_out = "output";
++ phy-handle = <&rgmii_phy0>;
++ phy-mode = "rgmii";
++ phy-supply = <&vcc3v3_sys>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&gmac0_miim
++ &gmac0_tx_bus2
++ &gmac0_rx_bus2
++ &gmac0_rgmii_clk
++ &gmac0_rgmii_bus>;
++ status = "okay";
++
++ tx_delay = <0x4f>;
++ rx_delay = <0x2d>;
++};
++
++&i2c0 {
++ status = "okay";
++
++ vdd_cpu: regulator@1c {
++ compatible = "tcs,tcs4525";
++ reg = <0x1c>;
++ fcs,suspend-voltage-selector = <1>;
++ regulator-name = "vdd_cpu";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <800000>;
++ regulator-max-microvolt = <1150000>;
++ regulator-ramp-delay = <2300>;
++ vin-supply = <&vcc3v3_sys>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ rk809: pmic@20 {
++ compatible = "rockchip,rk809";
++ reg = <0x20>;
++ interrupt-parent = <&gpio0>;
++ interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
++ #clock-cells = <1>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pmic_int_l>;
++ rockchip,system-power-controller;
++ vcc1-supply = <&vcc3v3_sys>;
++ vcc2-supply = <&vcc3v3_sys>;
++ vcc3-supply = <&vcc3v3_sys>;
++ vcc4-supply = <&vcc3v3_sys>;
++ vcc5-supply = <&vcc3v3_sys>;
++ vcc6-supply = <&vcc3v3_sys>;
++ vcc7-supply = <&vcc3v3_sys>;
++ vcc8-supply = <&vcc3v3_sys>;
++ vcc9-supply = <&vcc3v3_sys>;
++ wakeup-source;
++
++ regulators {
++ vdd_logic: DCDC_REG1 {
++ regulator-name = "vdd_logic";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-init-microvolt = <900000>;
++ regulator-initial-mode = <0x2>;
++ regulator-min-microvolt = <500000>;
++ regulator-max-microvolt = <1350000>;
++ regulator-ramp-delay = <6001>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vdd_gpu: DCDC_REG2 {
++ regulator-name = "vdd_gpu";
++ regulator-always-on;
++ regulator-init-microvolt = <900000>;
++ regulator-initial-mode = <0x2>;
++ regulator-min-microvolt = <500000>;
++ regulator-max-microvolt = <1350000>;
++ regulator-ramp-delay = <6001>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcc_ddr: DCDC_REG3 {
++ regulator-name = "vcc_ddr";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-initial-mode = <0x2>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ };
++ };
++
++ vdd_npu: DCDC_REG4 {
++ regulator-name = "vdd_npu";
++ regulator-init-microvolt = <900000>;
++ regulator-initial-mode = <0x2>;
++ regulator-min-microvolt = <500000>;
++ regulator-max-microvolt = <1350000>;
++ regulator-ramp-delay = <6001>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcc_1v8: DCDC_REG5 {
++ regulator-name = "vcc_1v8";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vdda0v9_image: LDO_REG1 {
++ regulator-name = "vdda0v9_image";
++ regulator-always-on;
++ regulator-min-microvolt = <900000>;
++ regulator-max-microvolt = <900000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vdda_0v9: LDO_REG2 {
++ regulator-name = "vdda_0v9";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <900000>;
++ regulator-max-microvolt = <900000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vdda0v9_pmu: LDO_REG3 {
++ regulator-name = "vdda0v9_pmu";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <900000>;
++ regulator-max-microvolt = <900000>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ regulator-suspend-microvolt = <900000>;
++ };
++ };
++
++ vccio_acodec: LDO_REG4 {
++ regulator-name = "vccio_acodec";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vccio_sd: LDO_REG5 {
++ regulator-name = "vccio_sd";
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <3300000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcc3v3_pmu: LDO_REG6 {
++ regulator-name = "vcc3v3_pmu";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ regulator-suspend-microvolt = <3300000>;
++ };
++ };
++
++ vcca_1v8: LDO_REG7 {
++ regulator-name = "vcca_1v8";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcca1v8_pmu: LDO_REG8 {
++ regulator-name = "vcca1v8_pmu";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++
++ regulator-state-mem {
++ regulator-on-in-suspend;
++ regulator-suspend-microvolt = <1800000>;
++ };
++ };
++
++ vcca1v8_image: LDO_REG9 {
++ regulator-name = "vcca1v8_image";
++ regulator-always-on;
++ regulator-min-microvolt = <1800000>;
++ regulator-max-microvolt = <1800000>;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcc_3v3: SWITCH_REG1 {
++ regulator-name = "vcc_3v3";
++ regulator-always-on;
++ regulator-boot-on;
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++
++ vcc3v3_sd: SWITCH_REG2 {
++ regulator-name = "vcc3v3_sd";
++
++ regulator-state-mem {
++ regulator-off-in-suspend;
++ };
++ };
++ };
++ };
++};
++
++&mdio0 {
++ rgmii_phy0: ethernet-phy@0 {
++ compatible = "ethernet-phy-ieee802.3-c22";
++ reg = <0x0>;
++ reset-assert-us = <20000>;
++ reset-deassert-us = <100000>;
++ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
++ };
++};
++
++&pinctrl {
++ leds {
++ led_power_pin: led-power-pin {
++ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ led_work_pin: led-work-pin {
++ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
++
++ pmic {
++ pmic_int_l: pmic-int-l {
++ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
++ };
++ };
++};
++
++&pmu_io_domains {
++ pmuio1-supply = <&vcc3v3_pmu>;
++ pmuio2-supply = <&vcc3v3_pmu>;
++ vccio1-supply = <&vccio_acodec>;
++ vccio2-supply = <&vcc_1v8>;
++ vccio3-supply = <&vccio_sd>;
++ vccio4-supply = <&vcc_1v8>;
++ vccio5-supply = <&vcc_3v3>;
++ vccio6-supply = <&vcc_3v3>;
++ vccio7-supply = <&vcc_3v3>;
++ status = "okay";
++};
++
++&saradc {
++ vref-supply = <&vcca_1v8>;
++ status = "okay";
++};
++
++&sdhci {
++ bus-width = <8>;
++ max-frequency = <200000000>;
++ non-removable;
++ pinctrl-names = "default";
++ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe &emmc_rstnout>;
++ vmmc-supply = <&vcc_3v3>;
++ vqmmc-supply = <&vcc_1v8>;
++ status = "okay";
++};
++
++&sdmmc0 {
++ bus-width = <4>;
++ cap-sd-highspeed;
++ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
++ disable-wp;
++ pinctrl-names = "default";
++ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
++ sd-uhs-sdr50;
++ vmmc-supply = <&vcc3v3_sd>;
++ vqmmc-supply = <&vccio_sd>;
++ status = "okay";
++};
++
++&uart2 {
++ status = "okay";
++};
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-IR-receiver-node-to-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-IR-receiver-node-to-ODROID-M1.patch
new file mode 100644
index 000000000..c94e717a5
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-IR-receiver-node-to-ODROID-M1.patch
@@ -0,0 +1,51 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:46 +0200
+Subject: [13/13] arm64: dts: rockchip: Add IR receiver node to ODROID-M1
+Origin: https://git.kernel.org/linus/d6882992fe8182e3122be34af3f491948a8b9069
+
+Add the infrared receiver and its associated pinctrl entry. Note that
+there is an external pullup to VCC3V3_SYS.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-14-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 2f685c606bb9..59ecf868dbd0 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -49,6 +49,13 @@ hdmi_con_in: endpoint {
+ };
+ };
+
++ ir-receiver {
++ compatible = "gpio-ir-receiver";
++ gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_LOW>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&ir_receiver_pin>;
++ };
++
+ leds {
+ compatible = "gpio-leds";
+
+@@ -519,6 +526,13 @@ fspi_dual_io_pins: fspi-dual-io-pins {
+ };
+ };
+
++ ir-receiver {
++ ir_receiver_pin: ir-receiver-pin {
++ /* external pullup to VCC3V3_SYS */
++ rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
++
+ leds {
+ led_power_pin: led-power-pin {
+ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-NOR-flash-to-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-NOR-flash-to-ODROID-M1.patch
new file mode 100644
index 000000000..ebc21afec
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-NOR-flash-to-ODROID-M1.patch
@@ -0,0 +1,100 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:37 +0200
+Subject: [04/13] arm64: dts: rockchip: Add NOR flash to ODROID-M1
+Origin: https://git.kernel.org/linus/9f96204b7dcf94d03cad41194447c665d10675b7
+
+Enable the Rockchip Serial Flash Controller for the ODROID-M1 and add
+the corresponding SPI NOR flash entry. The SFC is used in dual I/O mode
+and not quad I/O mode, as the FSPI_D2 pin is shared with the EMMC_RSTn
+pin.
+
+The partitions addresses and sizes are taken from the ODROID-M1
+Partition Table page on the ODROID wiki.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-5-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 58 +++++++++++++++++++
+ 1 file changed, 58 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 112c65af3f55..94e839c9afab 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -351,6 +351,20 @@ rgmii_phy0: ethernet-phy@0 {
+ };
+
+ &pinctrl {
++ fspi {
++ fspi_dual_io_pins: fspi-dual-io-pins {
++ rockchip,pins =
++ /* fspi_clk */
++ <1 RK_PD0 1 &pcfg_pull_none>,
++ /* fspi_cs0n */
++ <1 RK_PD3 1 &pcfg_pull_none>,
++ /* fspi_d0 */
++ <1 RK_PD1 1 &pcfg_pull_none>,
++ /* fspi_d1 */
++ <1 RK_PD2 1 &pcfg_pull_none>;
++ };
++ };
++
+ leds {
+ led_power_pin: led-power-pin {
+ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+@@ -409,6 +423,50 @@ &sdmmc0 {
+ status = "okay";
+ };
+
++&sfc {
++ /* Dual I/O mode as the D2 pin conflicts with the eMMC */
++ pinctrl-0 = <&fspi_dual_io_pins>;
++ pinctrl-names = "default";
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <100000000>;
++ spi-rx-bus-width = <2>;
++ spi-tx-bus-width = <1>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "SPL";
++ reg = <0x0 0xe0000>;
++ };
++ partition@e0000 {
++ label = "U-Boot Env";
++ reg = <0xe0000 0x20000>;
++ };
++ partition@100000 {
++ label = "U-Boot";
++ reg = <0x100000 0x200000>;
++ };
++ partition@300000 {
++ label = "splash";
++ reg = <0x300000 0x100000>;
++ };
++ partition@400000 {
++ label = "Filesystem";
++ reg = <0x400000 0xc00000>;
++ };
++ };
++ };
++};
++
+ &tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <0>;
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-PCIEe-v3-nodes-to-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-PCIEe-v3-nodes-to-ODROID-M1.patch
new file mode 100644
index 000000000..94c7d7952
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-PCIEe-v3-nodes-to-ODROID-M1.patch
@@ -0,0 +1,77 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:45 +0200
+Subject: [12/13] arm64: dts: rockchip: Add PCIEe v3 nodes to ODROID-M1
+Origin: https://git.kernel.org/linus/35b28582aa3dfd7b6861b7ebc72798b0ff50ed41
+
+Add nodes to ODROID-M1 to support PCIe v3 on the M2 slot.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-13-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 34 +++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index bd24ccf94e76..2f685c606bb9 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -96,6 +96,19 @@ simple-audio-card,codec {
+ };
+ };
+
++ vcc3v3_pcie: vcc3v3-pcie-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v3_pcie";
++ enable-active-high;
++ gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&vcc3v3_pcie_en_pin>;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ startup-delay-us = <5000>;
++ vin-supply = <&vcc3v3_sys>;
++ };
++
+ vcc3v3_sys: vcc3v3-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+@@ -479,6 +492,18 @@ rgmii_phy0: ethernet-phy@0 {
+ };
+ };
+
++&pcie30phy {
++ status = "okay";
++};
++
++&pcie3x2 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pcie_reset_pin>;
++ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>;
++ vpcie3v3-supply = <&vcc3v3_pcie>;
++ status = "okay";
++};
++
+ &pinctrl {
+ fspi {
+ fspi_dual_io_pins: fspi-dual-io-pins {
+@@ -503,6 +528,15 @@ led_work_pin: led-work-pin {
+ };
+ };
+
++ pcie {
++ pcie_reset_pin: pcie-reset-pin {
++ rockchip,pins = <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ vcc3v3_pcie_en_pin: vcc3v3-pcie-en-pin {
++ rockchip,pins = <4 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
++
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-SATA-support-to-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-SATA-support-to-ODROID-M1.patch
new file mode 100644
index 000000000..2025079e1
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-SATA-support-to-ODROID-M1.patch
@@ -0,0 +1,45 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:44 +0200
+Subject: [11/13] arm64: dts: rockchip: Add SATA support to ODROID-M1
+Origin: https://git.kernel.org/linus/6a5a04d52ccc42e0e59ff69fca9c1db7e08ba44b
+
+Enable the Combo PHY and SATA nodes in ODROID-M1.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-12-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 9a84a7e76d7a..bd24ccf94e76 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -153,6 +153,11 @@ &combphy1 {
+ status = "okay";
+ };
+
++&combphy2 {
++ /* used for SATA */
++ status = "okay";
++};
++
+ &cpu0 {
+ cpu-supply = <&vdd_cpu>;
+ };
+@@ -538,6 +543,10 @@ &saradc {
+ status = "okay";
+ };
+
++&sata2 {
++ status = "okay";
++};
++
+ &sdhci {
+ bus-width = <8>;
+ max-frequency = <200000000>;
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Add-analog-audio-on-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Add-analog-audio-on-ODROID-M1.patch
new file mode 100644
index 000000000..03cb99ff1
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Add-analog-audio-on-ODROID-M1.patch
@@ -0,0 +1,99 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:38 +0200
+Subject: [05/13] arm64: dts: rockchip: Add analog audio on ODROID-M1
+Origin: https://git.kernel.org/linus/78f858447cb78cac7259093d095fb783328b835c
+
+On the ODROID-M1, the I2S1 TDM controller is connected to the rk809
+codec in I2S mode. It is used to provide a stereo headphones output and
+a mono speaker output. A GPIO with an external pullup is used as an
+headphone detection input.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-6-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 43 ++++++++++++++++++-
+ 1 file changed, 42 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 94e839c9afab..634c1bd80b4e 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -59,6 +59,31 @@ led_work: led-1 {
+ };
+ };
+
++ rk809-sound {
++ compatible = "simple-audio-card";
++ pinctrl-names = "default";
++ pinctrl-0 = <&hp_det_pin>;
++ simple-audio-card,name = "Analog RK817";
++ simple-audio-card,format = "i2s";
++ simple-audio-card,hp-det-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
++ simple-audio-card,mclk-fs = <256>;
++ simple-audio-card,widgets =
++ "Headphone", "Headphones",
++ "Speaker", "Speaker";
++ simple-audio-card,routing =
++ "Headphones", "HPOL",
++ "Headphones", "HPOR",
++ "Speaker", "SPKO";
++
++ simple-audio-card,cpu {
++ sound-dai = <&i2s1_8ch>;
++ };
++
++ simple-audio-card,codec {
++ sound-dai = <&rk809>;
++ };
++ };
++
+ vcc3v3_sys: vcc3v3-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+@@ -131,10 +156,15 @@ rk809: pmic@20 {
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
++ assigned-clocks = <&cru I2S1_MCLKOUT_TX>;
++ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>;
+ #clock-cells = <1>;
++ clock-names = "mclk";
++ clocks = <&cru I2S1_MCLKOUT_TX>;
+ pinctrl-names = "default";
+- pinctrl-0 = <&pmic_int_l>;
++ pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
+ rockchip,system-power-controller;
++ #sound-dai-cells = <0>;
+ vcc1-supply = <&vcc3v3_sys>;
+ vcc2-supply = <&vcc3v3_sys>;
+ vcc3-supply = <&vcc3v3_sys>;
+@@ -340,6 +370,11 @@ regulator-state-mem {
+ };
+ };
+
++&i2s1_8ch {
++ rockchip,trcm-sync-tx-only;
++ status = "okay";
++};
++
+ &mdio0 {
+ rgmii_phy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+@@ -379,6 +414,12 @@ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
++
++ rk809 {
++ hp_det_pin: hp-det-pin {
++ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
+ };
+
+ &pmu_io_domains {
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Enable-HDMI-audio-on-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-HDMI-audio-on-ODROID-M1.patch
new file mode 100644
index 000000000..0dff4d2b7
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-HDMI-audio-on-ODROID-M1.patch
@@ -0,0 +1,45 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:40 +0200
+Subject: [07/13] arm64: dts: rockchip: Enable HDMI audio on ODROID-M1.
+Origin: https://git.kernel.org/linus/1ca7ddddf36494f0f6afd4f35d37827323271f39
+
+This enables the i2s0 controller and the hdmi-sound node on the
+ODROID-M1.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-8-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 126b893048fe..ac4e94d18feb 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -161,6 +161,10 @@ hdmi_out_con: endpoint {
+ };
+ };
+
++&hdmi_sound {
++ status = "okay";
++};
++
+ &i2c0 {
+ status = "okay";
+
+@@ -400,6 +404,10 @@ regulator-state-mem {
+ };
+ };
+
++&i2s0_8ch {
++ status = "okay";
++};
++
+ &i2s1_8ch {
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-GPU-on-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-GPU-on-ODROID-M1.patch
new file mode 100644
index 000000000..faed83fca
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-GPU-on-ODROID-M1.patch
@@ -0,0 +1,34 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:41 +0200
+Subject: [08/13] arm64: dts: rockchip: Enable the GPU on ODROID-M1
+Origin: https://git.kernel.org/linus/cb80b3455c7cadc4c1157879930e919f607d557c
+
+Enable the GPU core on the Rockchip RK3568 ODROID-M1.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-9-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index ac4e94d18feb..e4b7699d3eea 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -143,6 +143,11 @@ &gmac0_rgmii_clk
+ rx_delay = <0x2d>;
+ };
+
++&gpu {
++ mali-supply = <&vdd_gpu>;
++ status = "okay";
++};
++
+ &hdmi {
+ avdd-0v9-supply = <&vdda0v9_image>;
+ avdd-1v8-supply = <&vcca1v8_image>;
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-2.0-ports-on-ODROI.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-2.0-ports-on-ODROI.patch
new file mode 100644
index 000000000..c27944417
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-2.0-ports-on-ODROI.patch
@@ -0,0 +1,108 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:42 +0200
+Subject: [09/13] arm64: dts: rockchip: Enable the USB 2.0 ports on ODROID-M1
+Origin: https://git.kernel.org/linus/4685d7b68aaac199ab0d950d2047405bf551f964
+
+The Rockchip RK3568 has two USB OHCI/EHCI controllers connected to a PHY
+providing one host-only port and one OTG port. On the ODROID-M1, they
+are both used in host mode. The USB ports are powered by a DC/DC
+converter providing 5V and named VCC5V0_SYS on the schematics, followed
+by a power switch.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-10-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 61 +++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index e4b7699d3eea..2e4cc20bd676 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -105,6 +105,28 @@ vcc3v3_sys: vcc3v3-sys-regulator {
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&dc_12v>;
+ };
++
++ vcc5v0_sys: vcc5v0-sys-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v0_sys";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ vin-supply = <&dc_12v>;
++ };
++
++ vcc5v0_usb_host: vcc5v0-usb-host-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v0_usb_host";
++ enable-active-high;
++ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&vcc5v0_usb_host_en_pin>;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ vin-supply = <&vcc5v0_sys>;
++ };
+ };
+
+ &cpu0 {
+@@ -463,6 +485,15 @@ hp_det_pin: hp-det-pin {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
++
++ usb {
++ vcc5v0_usb_host_en_pin: vcc5v0-usb-host-en-pin {
++ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ vcc5v0_usb_otg_en_pin: vcc5v0-usb-otg-en-pin {
++ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
+ };
+
+ &pmu_io_domains {
+@@ -561,6 +592,36 @@ &uart2 {
+ status = "okay";
+ };
+
++&usb_host0_ehci {
++ status = "okay";
++};
++
++&usb_host0_ohci {
++ status = "okay";
++};
++
++&usb_host1_ehci {
++ status = "okay";
++};
++
++&usb_host1_ohci {
++ status = "okay";
++};
++
++&usb2phy1 {
++ status = "okay";
++};
++
++&usb2phy1_host {
++ phy-supply = <&vcc5v0_usb_host>;
++ status = "okay";
++};
++
++&usb2phy1_otg {
++ phy-supply = <&vcc5v0_usb_host>;
++ status = "okay";
++};
++
+ &vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-3.0-ports-on-ODROI.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-3.0-ports-on-ODROI.patch
new file mode 100644
index 000000000..bfcf9c523
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-the-USB-3.0-ports-on-ODROI.patch
@@ -0,0 +1,111 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:43 +0200
+Subject: [10/13] arm64: dts: rockchip: Enable the USB 3.0 ports on ODROID-M1
+Origin: https://git.kernel.org/linus/9984ef562653c8d0beb51021fc286706b6ec4802
+
+The Rockchip RK3568 has two USB XHCI controllers. The USB 2.0 signals
+are connected to a PHY providing one host-only port and one OTG port.
+The USB 3.0 signals are connected to two USB3.0/PCIE/SATA combo PHY.
+
+The ODROID M1 has 2 type A USB 3.0 connectors, with the USB 3.0 signals
+connected to the two combo PHYs. For the USB 2.0 signals, one connector
+is connected to the host-only PHY and uses the same power switch as the
+USB 2.0 ports. The other connector has its own power switch and is
+connected to the OTG PHY, which is also connected to a device only
+micro-USB connector. The purpose of this micro-USB connector is for
+firmware update using the Rockusb vendor specific USB class. Therefore
+it does not make sense to enable this port on Linux, and the PHY is
+forced to host mode.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-11-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 49 ++++++++++++++++++-
+ 1 file changed, 48 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 2e4cc20bd676..9a84a7e76d7a 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -127,6 +127,30 @@ vcc5v0_usb_host: vcc5v0-usb-host-regulator {
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
++
++ vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v0_usb_otg";
++ enable-active-high;
++ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&vcc5v0_usb_otg_en_pin>;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ vin-supply = <&vcc5v0_sys>;
++ };
++};
++
++&combphy0 {
++ /* Used for USB3 */
++ phy-supply = <&vcc5v0_usb_host>;
++ status = "okay";
++};
++
++&combphy1 {
++ /* Used for USB3 */
++ phy-supply = <&vcc5v0_usb_otg>;
++ status = "okay";
+ };
+
+ &cpu0 {
+@@ -490,7 +514,7 @@ usb {
+ vcc5v0_usb_host_en_pin: vcc5v0-usb-host-en-pin {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+- vcc5v0_usb_otg_en_pin: vcc5v0-usb-otg-en-pin {
++ vcc5v0_usb_otg_en_pin: vcc5v0-usb-dr-en-pin {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+@@ -600,6 +624,11 @@ &usb_host0_ohci {
+ status = "okay";
+ };
+
++&usb_host0_xhci {
++ dr_mode = "host";
++ status = "okay";
++};
++
+ &usb_host1_ehci {
+ status = "okay";
+ };
+@@ -608,6 +637,24 @@ &usb_host1_ohci {
+ status = "okay";
+ };
+
++&usb_host1_xhci {
++ status = "okay";
++};
++
++&usb2phy0 {
++ status = "okay";
++};
++
++&usb2phy0_host {
++ phy-supply = <&vcc5v0_usb_host>;
++ status = "okay";
++};
++
++&usb2phy0_otg {
++ phy-supply = <&vcc5v0_usb_otg>;
++ status = "okay";
++};
++
+ &usb2phy1 {
+ status = "okay";
+ };
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-Enable-vop2-and-hdmi-tx-on-ODROID.patch b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-vop2-and-hdmi-tx-on-ODROID.patch
new file mode 100644
index 000000000..48d1b3642
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-Enable-vop2-and-hdmi-tx-on-ODROID.patch
@@ -0,0 +1,94 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:39 +0200
+Subject: [06/13] arm64: dts: rockchip: Enable vop2 and hdmi tx on ODROID-M1
+Origin: https://git.kernel.org/linus/913404aa2e60610f9cae375069dae97e11d726ed
+
+Enable the RK356x Video Output Processor (VOP) 2 on ODROID M1.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-7-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3568-odroid-m1.dts | 47 +++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index 634c1bd80b4e..126b893048fe 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -8,6 +8,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/pinctrl/rockchip.h>
++#include <dt-bindings/soc/rockchip,vop2.h>
+ #include "rk3568.dtsi"
+
+ / {
+@@ -37,6 +38,17 @@ dc_12v: dc-12v-regulator {
+ regulator-max-microvolt = <12000000>;
+ };
+
++ hdmi-con {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi_con_in: endpoint {
++ remote-endpoint = <&hdmi_out_con>;
++ };
++ };
++ };
++
+ leds {
+ compatible = "gpio-leds";
+
+@@ -131,6 +143,24 @@ &gmac0_rgmii_clk
+ rx_delay = <0x2d>;
+ };
+
++&hdmi {
++ avdd-0v9-supply = <&vdda0v9_image>;
++ avdd-1v8-supply = <&vcca1v8_image>;
++ status = "okay";
++};
++
++&hdmi_in {
++ hdmi_in_vp0: endpoint {
++ remote-endpoint = <&vp0_out_hdmi>;
++ };
++};
++
++&hdmi_out {
++ hdmi_out_con: endpoint {
++ remote-endpoint = <&hdmi_con_in>;
++ };
++};
++
+ &i2c0 {
+ status = "okay";
+
+@@ -517,3 +547,20 @@ &tsadc {
+ &uart2 {
+ status = "okay";
+ };
++
++&vop {
++ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
++ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
++ status = "okay";
++};
++
++&vop_mmu {
++ status = "okay";
++};
++
++&vp0 {
++ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
++ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
++ remote-endpoint = <&hdmi_in_vp0>;
++ };
++};
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/arm64-dts-rockchip-add-thermal-support-to-ODROID-M1.patch b/debian/patches/features/arm64/arm64-dts-rockchip-add-thermal-support-to-ODROID-M1.patch
new file mode 100644
index 000000000..5e0970dba
--- /dev/null
+++ b/debian/patches/features/arm64/arm64-dts-rockchip-add-thermal-support-to-ODROID-M1.patch
@@ -0,0 +1,35 @@
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 30 Sep 2022 07:12:36 +0200
+Subject: [03/13] arm64: dts: rockchip: add thermal support to ODROID-M1
+Origin: https://git.kernel.org/linus/f5511bd8498da222b6455038a0cf3e7d2b2dfc7e
+
+Add the thermal nodes for the ODROID-M1.
+
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-4-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+index b3016437640b..112c65af3f55 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
+@@ -409,6 +409,12 @@ &sdmmc0 {
+ status = "okay";
+ };
+
++&tsadc {
++ rockchip,hw-tshut-mode = <1>;
++ rockchip,hw-tshut-polarity = <0>;
++ status = "okay";
++};
++
+ &uart2 {
+ status = "okay";
+ };
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/dt-bindings-rockchip-Add-Hardkernel-ODROID-M1-board.patch b/debian/patches/features/arm64/dt-bindings-rockchip-Add-Hardkernel-ODROID-M1-board.patch
new file mode 100644
index 000000000..54d0c6c20
--- /dev/null
+++ b/debian/patches/features/arm64/dt-bindings-rockchip-Add-Hardkernel-ODROID-M1-board.patch
@@ -0,0 +1,37 @@
+From: Dongjin Kim <tobetter@gmail.com>
+Date: Fri, 30 Sep 2022 07:12:34 +0200
+Subject: [01/13] dt-bindings: rockchip: Add Hardkernel ODROID-M1 board
+Origin: https://git.kernel.org/linus/19cc53eb2ce63c0e5adc2fd89494fb16f383ac10
+
+Add device tree binding for Hardkernel ODROID-M1 board based on RK3568
+SoC.
+
+Signed-off-by: Dongjin Kim <tobetter@gmail.com>
+Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Tested-by: Dan Johansen <strit@manjaro.org>
+Link: https://lore.kernel.org/r/20220930051246.391614-2-aurelien@aurel32.net
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ Documentation/devicetree/bindings/arm/rockchip.yaml | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
+index eee1e6b3f9cb..72bf2fbfe99d 100644
+--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
++++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
+@@ -468,6 +468,11 @@ properties:
+ - const: hardkernel,rk3326-odroid-go2
+ - const: rockchip,rk3326
+
++ - description: Hardkernel Odroid M1
++ items:
++ - const: rockchip,rk3568-odroid-m1
++ - const: rockchip,rk3568
++
+ - description: Hugsun X99 TV Box
+ items:
+ - const: hugsun,x99
+--
+2.35.1
+
diff --git a/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-Model-A-baseboard.patch b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-Model-A-baseboard.patch
new file mode 100644
index 000000000..ae644e05f
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-Model-A-baseboard.patch
@@ -0,0 +1,279 @@
+From: Andrew Powers-Holmes <aholmes@omnom.net>
+Date: Wed, 16 Nov 2022 12:53:37 +0100
+Subject: [4/4] arm64: dts: rockchip: Add SOQuartz Model A baseboard
+Origin: https://git.kernel.org/linus/afbaed737fb45bcae91e4606025fb31da71b9dfe
+
+This patch adds the device tree for the "Model A" baseboard for
+the SOQuartz CM4 SoM, which is not to be confused with the
+Quartz64 Model A, which is the same form factor and SoC, but is
+not a CM4 carrier board.
+
+The board features a PCIe 2 x1 slot, USB 2 host ports, CSI/DSI
+connectors, an eDP FFC connector, gigabit ethernet, HDMI, and a
+12V DC barrel jack. Also present is a microSD card slot, 40-pin
+GPIO, and a power and reset button.
+
+Signed-off-by: Andrew Powers-Holmes <aholmes@omnom.net>
+[rebase, misc fixes, reword]
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Link: https://lore.kernel.org/r/20221116115337.541601-5-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/Makefile | 1 +
+ .../dts/rockchip/rk3566-soquartz-model-a.dts | 232 ++++++++++++++++++
+ 2 files changed, 233 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
+
+diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
+index 071284a46bf7..0a76a2ebb5f6 100644
+--- a/arch/arm64/boot/dts/rockchip/Makefile
++++ b/arch/arm64/boot/dts/rockchip/Makefile
+@@ -70,6 +70,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-b.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-roc-pc.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-blade.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-cm4.dtb
++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-model-a.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-odroid-m1.dtb
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
+new file mode 100644
+index 000000000000..2208dbfb7f0a
+--- /dev/null
++++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
+@@ -0,0 +1,232 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/dts-v1/;
++
++#include "rk3566-soquartz.dtsi"
++
++/ {
++ model = "PINE64 RK3566 SOQuartz on Model A carrier board";
++ compatible = "pine64,soquartz-model-a", "pine64,soquartz", "rockchip,rk3566";
++
++ /* labeled DCIN_12V in schematic */
++ vcc12v_dcin: vcc12v-dcin-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc12v_dcin";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <12000000>;
++ regulator-max-microvolt = <12000000>;
++ };
++
++ vcc5v0_usb: vcc5v0-usb-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v0_usb";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ vin-supply = <&vcc12v_dcin>;
++ };
++
++ /*
++ * Labelled VCC3V0_SD in schematic to not conflict with PMIC
++ * regulator, it's 3.3v in actuality
++ */
++ vcc3v0_sd: vcc3v0-sd-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v0_sd";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <&vcc3v3_sys>;
++ };
++
++ vcc3v3_pcie: vcc3v3-pcie-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v3_pcie";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <&vcc12v_dcin>;
++ };
++
++ vcc12v_pcie: vcc12v-pcie-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc12v_pcie";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <12000000>;
++ regulator-max-microvolt = <12000000>;
++ vin-supply = <&vcc12v_dcin>;
++ };
++};
++
++/* phy for pcie */
++&combphy2 {
++ phy-supply = <&vcc3v3_sys>;
++ status = "okay";
++};
++
++&gmac1 {
++ status = "okay";
++};
++
++/*
++ * i2c1 is exposed on CM1 / Module1A
++ * pin 80 - SCL0 - i2c1_scl_m0, pullup to vcc3v3_pmu
++ * pin 82 - SDA0 - i2c1_sda_m0, pullup to vcc3v3_pmu
++ */
++&i2c1 {
++ status = "okay";
++
++ /*
++ * the rtc interrupt is tied to PMIC_PWRON,
++ * it will force reset the board if triggered.
++ */
++ pcf85063: rtc@51 {
++ compatible = "nxp,pcf85063";
++ reg = <0x51>;
++ };
++};
++
++/*
++ * i2c2 is exposed on CM1 / Module1A - to PI40
++ * pin 56 - GPIO3 - i2c2_scl_m1, pullup to vcc_3v3, shared with i2s1_8ch
++ * pin 58 - GPIO2 - i2c2_sda_m1, pullup to vcc_3v3
++ */
++&i2c2 {
++ status = "disabled";
++};
++
++/*
++ * i2c3 is exposed on CM1 / Module1A - to PI40
++ * pin 35 - ID_SC(GPIO28) - i2c3_scl_m0, pullup to vcc_3v3
++ * pin 36 - ID_SD(GPIO27) - i2c3_sda_m0, pullup to vcc_3v3
++ */
++&i2c3 {
++ status = "disabled";
++};
++
++/*
++ * i2c4 is exposed on CM2 / Module1B - to PI40
++ * pin 45 - GPIO24 - i2c4_scl_m1
++ * pin 47 - GPIO23 - i2c4_sda_m1
++ */
++&i2c4 {
++ status = "disabled";
++};
++
++/*
++ * i2s1_8ch is exposed on CM1 / Module1A - to PI40
++ * pin 24 - GPIO26 - i2s1_sdi1_m1
++ * pin 25 - GPIO21 - i2s1_sdo0_m1
++ * pin 26 - GPIO19 - i2s1_lrck_tx_m1
++ * pin 27 - GPIO20 - i2s1_sdi0_m1
++ * pin 29 - GPIO16 - i2s1_sdi3_m1
++ * pin 30 - GPIO6 - i2s1_sdi2_m1
++ * pin 40 - GPIO9 - i2s1_sdo1_m1, shared with spi3
++ * pin 41 - GPIO25 - i2s1_sdo2_m1
++ * pin 49 - GPIO18 - i2s1_sclk_tx_m1
++ * pin 50 - GPIO17 - i2s1_mclk_m1
++ * pin 56 - GPIO3 - i2s1_sdo3_m1, shared with i2c2
++ */
++&i2s1_8ch {
++ status = "disabled";
++};
++
++&led_diy {
++ status = "okay";
++};
++
++&led_work {
++ status = "okay";
++};
++
++&pcie2x1 {
++ vpcie3v3-supply = <&vcc3v3_pcie>;
++ status = "okay";
++};
++
++&rgmii_phy1 {
++ status = "okay";
++};
++
++&rgmii_phy1 {
++ status = "okay";
++};
++
++/*
++ * saradc is exposed on CM1 / Module1A - to J2
++ * pin 94 - AIN1 - saradc_vin3
++ * pin 96 - AIN0 - saradc_vin2
++ */
++&saradc {
++ status = "disabled";
++};
++
++/*
++ * vmmc-supply is vcc3v3_sd on v1.0 and vcc3v0_sd on v1.1+
++ * the soquartz SoM has SDMMC_PWR (CM1 pin 75) hardwired to vcc3v3_sys,
++ * so we use vcc3v3_sd here to ensure the regulator is enabled on older boards.
++ */
++&sdmmc0 {
++ vmmc-supply = <&vcc3v3_sd>;
++ status = "okay";
++};
++
++/*
++ * spi3 is exposed on CM1 / Module1A - to PI40
++ * pin 37 - GPIO7 - spi3_cs1_m0
++ * pin 38 - GPIO11 - spi3_clk_m0
++ * pin 39 - GPIO8 - spi3_cs0_m0
++ * pin 40 - GPIO9 - spi3_miso_m0, shared with i2s1_8ch
++ * pin 44 - GPIO10 - spi3_mosi_m0
++ */
++&spi3 {
++ status = "disabled";
++};
++
++/*
++ * uart2 is exposed on CM1 / Module1A - to PI40
++ * pin 51 - GPIO15 - uart2_rx_m0
++ * pin 55 - GPIO14 - uart2_tx_m0
++ */
++&uart2 {
++ status = "okay";
++};
++
++/*
++ * uart7 is exposed on CM1 / Module1A - to PI40
++ * pin 46 - GPIO22 - uart7_tx_m2
++ * pin 47 - GPIO23 - uart7_rx_m2
++ */
++&uart7 {
++ status = "okay";
++};
++
++&usb2phy0 {
++ status = "okay";
++};
++
++&usb2phy0_otg {
++ phy-supply = <&vcc5v0_usb>;
++ status = "okay";
++};
++
++&usb_host0_xhci {
++ status = "okay";
++};
++
++&vbus {
++ vin-supply = <&vcc5v0_usb>;
++};
++
++&vcc3v3_sd {
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ status = "okay";
++};
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-blade-board.patch b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-blade-board.patch
new file mode 100644
index 000000000..246d62c12
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-blade-board.patch
@@ -0,0 +1,242 @@
+From: Andrew Powers-Holmes <aholmes@omnom.net>
+Date: Wed, 16 Nov 2022 12:53:35 +0100
+Subject: [2/4] arm64: dts: rockchip: Add SOQuartz blade board
+Origin: https://git.kernel.org/linus/a5c826ecde5222f755e7d8a0c8d795189c5c1228
+
+This adds a device tree for the PINE64 SOQuartz blade baseboard,
+a 1U rack mountable baseboard for the CM4 form factor with PoE
+support designed for the SOQuartz CM4 System-on-Module.
+
+The board takes power from either PoE or a 5V DC input, and allows
+for mounting an M.2 SSD.
+
+The board also features one USB 2.0 host port, one HDMI output,
+a 3.5mm jack for UART, and the aforementioned gigabit networking
+port.
+
+Signed-off-by: Andrew Powers-Holmes <aholmes@omnom.net>
+[rebase, squash, reword, misc fixes]
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Link: https://lore.kernel.org/r/20221116115337.541601-3-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/Makefile | 1 +
+ .../dts/rockchip/rk3566-soquartz-blade.dts | 194 ++++++++++++++++++
+ 2 files changed, 195 insertions(+)
+ create mode 100644 arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
+
+diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
+index e14390277739..071284a46bf7 100644
+--- a/arch/arm64/boot/dts/rockchip/Makefile
++++ b/arch/arm64/boot/dts/rockchip/Makefile
+@@ -68,6 +68,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-b.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-roc-pc.dtb
++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-blade.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-cm4.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb
+ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
+new file mode 100644
+index 000000000000..4e49bebf548b
+--- /dev/null
++++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
+@@ -0,0 +1,194 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
++
++/dts-v1/;
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/pinctrl/rockchip.h>
++
++#include "rk3566-soquartz.dtsi"
++
++/ {
++ model = "PINE64 RK3566 SOQuartz on Blade carrier board";
++ compatible = "pine64,soquartz-blade", "pine64,soquartz", "rockchip,rk3566";
++
++ /* labeled VCC3V0_SD in schematic to not conflict with PMIC regulator */
++ vcc3v0_sd: vcc3v0-sd-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v0_sd";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <&vcc3v3_sys>;
++ };
++
++ /* labeled VCC_SSD in schematic */
++ vcc3v3_pcie_p: vcc3v3-pcie-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc3v3_pcie_p";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ vin-supply = <&vbus>;
++ };
++
++ vcc5v_dcin: vcc5v-dcin-regulator {
++ compatible = "regulator-fixed";
++ regulator-name = "vcc5v_dcin";
++ regulator-always-on;
++ regulator-boot-on;
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ };
++};
++
++&combphy2 {
++ phy-supply = <&vcc3v3_sys>;
++ status = "okay";
++};
++
++&gmac1 {
++ status = "okay";
++};
++
++/*
++ * i2c1 is exposed on CM1 / Module1A
++ * pin 80 - SCL0 - i2c1_scl_m0, pullup to vcc3v3_pmu
++ * pin 82 - SDA0 - i2c1_sda_m0, pullup to vcc3v3_pmu
++ */
++&i2c1 {
++ status = "okay";
++
++};
++
++/*
++ * i2c2 is exposed on CM1 / Module1A - to PI40
++ * pin 56 - GPIO3 - i2c2_scl_m1, pullup to vcc_3v3, shared with i2s1_8ch
++ * pin 58 - GPIO2 - i2c2_sda_m1, pullup to vcc_3v3
++ */
++&i2c2 {
++ status = "disabled";
++};
++
++/*
++ * i2c3 is exposed on CM1 / Module1A - to PI40
++ * pin 35 - ID_SC(GPIO28) - i2c3_scl_m0, pullup to vcc_3v3
++ * pin 36 - ID_SD(GPIO27) - i2c3_sda_m0, pullup to vcc_3v3
++ */
++&i2c3 {
++ status = "disabled";
++};
++
++/*
++ * i2c4 is exposed on CM2 / Module1B - to PI40
++ * pin 45 - GPIO24 - i2c4_scl_m1
++ * pin 47 - GPIO23 - i2c4_sda_m1
++ */
++&i2c4 {
++ status = "disabled";
++};
++
++/*
++ * i2s1_8ch is exposed on CM1 / Module1A - to PI40
++ * pin 24 - GPIO26 - i2s1_sdi1_m1
++ * pin 25 - GPIO21 - i2s1_sdo0_m1
++ * pin 26 - GPIO19 - i2s1_lrck_tx_m1
++ * pin 27 - GPIO20 - i2s1_sdi0_m1
++ * pin 29 - GPIO16 - i2s1_sdi3_m1
++ * pin 30 - GPIO6 - i2s1_sdi2_m1
++ * pin 40 - GPIO9 - i2s1_sdo1_m1, shared with spi3
++ * pin 41 - GPIO25 - i2s1_sdo2_m1
++ * pin 49 - GPIO18 - i2s1_sclk_tx_m1
++ * pin 50 - GPIO17 - i2s1_mclk_m1
++ * pin 56 - GPIO3 - i2s1_sdo3_m1, shared with i2c2
++ */
++&i2s1_8ch {
++ status = "disabled";
++};
++
++&led_diy {
++ color = <LED_COLOR_ID_RED>;
++ function = LED_FUNCTION_DISK_ACTIVITY;
++ linux,default-trigger = "disk-activity";
++ status = "okay";
++};
++
++&led_work {
++ color = <LED_COLOR_ID_GREEN>;
++ function = LED_FUNCTION_STATUS;
++ linux,default-trigger = "heartbeat";
++ status = "okay";
++};
++
++&pcie2x1 {
++ vpcie3v3-supply = <&vcc3v3_pcie_p>;
++ status = "okay";
++};
++
++&rgmii_phy1 {
++ status = "okay";
++};
++
++/*
++ * saradc is exposed on CM1 / Module1A - to J2
++ * pin 94 - AIN1 - saradc_vin3
++ * pin 96 - AIN0 - saradc_vin2
++ */
++&saradc {
++ status = "disabled";
++};
++
++&sdmmc0 {
++ vmmc-supply = <&vcc3v0_sd>;
++ status = "okay";
++};
++
++/*
++ * spi3 is exposed on CM1 / Module1A - to PI40
++ * pin 37 - GPIO7 - spi3_cs1_m0
++ * pin 38 - GPIO11 - spi3_clk_m0
++ * pin 39 - GPIO8 - spi3_cs0_m0
++ * pin 40 - GPIO9 - spi3_miso_m0, shared with i2s1_8ch
++ * pin 44 - GPIO10 - spi3_mosi_m0
++ */
++&spi3 {
++ status = "disabled";
++};
++
++/*
++ * uart2 is exposed on CM1 / Module1A - to PI40
++ * pin 51 - GPIO15 - uart2_rx_m0
++ * pin 55 - GPIO14 - uart2_tx_m0
++ */
++&uart2 {
++ status = "okay";
++};
++
++/*
++ * uart7 is exposed on CM1 / Module1A - to PI40
++ * pin 46 - GPIO22 - uart7_tx_m2
++ * pin 47 - GPIO23 - uart7_rx_m2
++ */
++&uart7 {
++ status = "okay";
++};
++
++&usb2phy0 {
++ status = "okay";
++};
++
++&usb2phy0_otg {
++ phy-supply = <&vbus>;
++ status = "okay";
++};
++
++&usb_host0_xhci {
++ status = "okay";
++};
++
++&vbus {
++ vin-supply = <&vcc5v_dcin>;
++};
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-HDMI-sound-on-SOQuartz.patch b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-HDMI-sound-on-SOQuartz.patch
new file mode 100644
index 000000000..d4df69e16
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-HDMI-sound-on-SOQuartz.patch
@@ -0,0 +1,44 @@
+From: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Date: Sat, 12 Nov 2022 17:04:00 +0100
+Subject: arm64: dts: rockchip: Enable HDMI sound on SOQuartz
+Origin: https://git.kernel.org/linus/70b620c4ba919a87c607b8d98b08478b213877bd
+
+This patch enables the i2s0 node on SOQuartz, which is responsible
+for hdmi audio, and adds an hdmi-sound node to enable said audio.
+
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Link: https://lore.kernel.org/r/20221112160404.70868-4-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+index 0bfb0cea7d6b..1b975822effa 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+@@ -178,6 +178,10 @@
+ };
+ };
+
++&hdmi_sound {
++ status = "okay";
++};
++
+ &i2c0 {
+ status = "okay";
+
+@@ -446,6 +450,10 @@
+ status = "disabled";
+ };
+
++&i2s0_8ch {
++ status = "okay";
++};
++
+ /*
+ * i2s1_8ch is exposed on CM1 / Module1A
+ * pin 24 - i2s1_sdi1_m1
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-PCIe-2-on-SOQuartz-CM4IO.patch b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-PCIe-2-on-SOQuartz-CM4IO.patch
new file mode 100644
index 000000000..1a8063e0f
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-PCIe-2-on-SOQuartz-CM4IO.patch
@@ -0,0 +1,82 @@
+From: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Date: Sat, 12 Nov 2022 17:04:01 +0100
+Subject: arm64: dts: rockchip: Enable PCIe 2 on SOQuartz CM4IO
+Origin: https://git.kernel.org/linus/3736aa7ecc4cd9b4abce30052bad00aba4f0362f
+
+This patch enables the PCIe2 on the CM4IO board when paired with
+a SOQuartz CM4 System-on-Module board. combphy2 also needs to be
+enabled in this case to make the PHY work for this.
+
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Link: https://lore.kernel.org/r/20221112160404.70868-5-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3566-soquartz-cm4.dts | 11 +++++++++++
+ arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi | 15 +++++++++++++++
+ 2 files changed, 26 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
+index e00568a6be5c..263ce40770dd 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
+@@ -30,6 +30,12 @@
+ };
+ };
+
++/* phy for pcie */
++&combphy2 {
++ phy-supply = <&vcc3v3_sys>;
++ status = "okay";
++};
++
+ &gmac1 {
+ status = "okay";
+ };
+@@ -105,6 +111,11 @@
+ status = "okay";
+ };
+
++&pcie2x1 {
++ vpcie3v3-supply = <&vcc_3v3>;
++ status = "okay";
++};
++
+ &rgmii_phy1 {
+ status = "okay";
+ };
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+index 1b975822effa..ce7165d7f1a1 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+@@ -487,6 +487,12 @@
+ };
+ };
+
++&pcie2x1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pcie_reset_h>;
++ reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
++};
++
+ &pinctrl {
+ bt {
+ bt_enable_h: bt-enable-h {
+@@ -512,6 +518,15 @@
+ };
+ };
+
++ pcie {
++ pcie_clkreq_h: pcie-clkreq-h {
++ rockchip,pins = <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ pcie_reset_h: pcie-reset-h {
++ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
++ };
++ };
++
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-video-output-and-HDMI-on-S.patch b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-video-output-and-HDMI-on-S.patch
new file mode 100644
index 000000000..37cfbdb23
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-Enable-video-output-and-HDMI-on-S.patch
@@ -0,0 +1,94 @@
+From: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Date: Sat, 12 Nov 2022 17:03:59 +0100
+Subject: arm64: dts: rockchip: Enable video output and HDMI on SOQuartz
+Origin: https://git.kernel.org/linus/36d7a605706d9648526a0574b8e7b0e02fa70c2a
+
+This patch adds and enables the necessary device tree nodes to
+enable video output and HDMI functionality on the SOQuartz module.
+
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Link: https://lore.kernel.org/r/20221112160404.70868-3-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ .../boot/dts/rockchip/rk3566-soquartz.dtsi | 47 +++++++++++++++++++
+ 1 file changed, 47 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+index 6e99f049501c..0bfb0cea7d6b 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+@@ -4,6 +4,7 @@
+
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/pinctrl/rockchip.h>
++#include <dt-bindings/soc/rockchip,vop2.h>
+ #include "rk3566.dtsi"
+
+ / {
+@@ -28,6 +29,17 @@
+ #clock-cells = <0>;
+ };
+
++ hdmi-con {
++ compatible = "hdmi-connector";
++ type = "a";
++
++ port {
++ hdmi_con_in: endpoint {
++ remote-endpoint = <&hdmi_out_con>;
++ };
++ };
++ };
++
+ leds {
+ compatible = "gpio-leds";
+
+@@ -148,6 +160,24 @@
+ status = "okay";
+ };
+
++&hdmi {
++ avdd-0v9-supply = <&vdda0v9_image>;
++ avdd-1v8-supply = <&vcca1v8_image>;
++ status = "okay";
++};
++
++&hdmi_in {
++ hdmi_in_vp0: endpoint {
++ remote-endpoint = <&vp0_out_hdmi>;
++ };
++};
++
++&hdmi_out {
++ hdmi_out_con: endpoint {
++ remote-endpoint = <&hdmi_con_in>;
++ };
++};
++
+ &i2c0 {
+ status = "okay";
+
+@@ -619,3 +649,20 @@
+ &usb_host0_xhci {
+ status = "disabled";
+ };
++
++&vop {
++ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
++ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
++ status = "okay";
++};
++
++&vop_mmu {
++ status = "okay";
++};
++
++&vp0 {
++ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
++ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
++ remote-endpoint = <&hdmi_in_vp0>;
++ };
++};
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-RK356x-Add-I2S2-device-node.patch b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-RK356x-Add-I2S2-device-node.patch
new file mode 100644
index 000000000..55c6af80b
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/arm64-dts-rockchip-RK356x-Add-I2S2-device-node.patch
@@ -0,0 +1,50 @@
+From: Shengyu Qu <wiagn233@outlook.com>
+Date: Sun, 30 Oct 2022 01:09:04 +0800
+Subject: arm64: dts: rockchip: RK356x: Add I2S2 device node
+Origin: https://git.kernel.org/linus/755f37010f3eac0bdfa41bdf2308e8380a93f10c
+
+This patch adds I2S2 device tree node for RK3566/RK3568.
+
+Signed-off-by: Shengyu Qu <wiagn233@outlook.com>
+Link: https://lore.kernel.org/r/OS3P286MB259771C12F2B15A4DDF435FE98359@OS3P286MB2597.JPNP286.PROD.OUTLOOK.COM
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ arch/arm64/boot/dts/rockchip/rk356x.dtsi | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+index 10e3a0862602..5706c3e24f0a 100644
+--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+@@ -1091,6 +1091,28 @@
+ status = "disabled";
+ };
+
++ i2s2_2ch: i2s@fe420000 {
++ compatible = "rockchip,rk3568-i2s-tdm";
++ reg = <0x0 0xfe420000 0x0 0x1000>;
++ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
++ assigned-clocks = <&cru CLK_I2S2_2CH_SRC>;
++ assigned-clock-rates = <1188000000>;
++ clocks = <&cru MCLK_I2S2_2CH>, <&cru MCLK_I2S2_2CH>, <&cru HCLK_I2S2_2CH>;
++ clock-names = "mclk_tx", "mclk_rx", "hclk";
++ dmas = <&dmac1 4>, <&dmac1 5>;
++ dma-names = "tx", "rx";
++ resets = <&cru SRST_M_I2S2_2CH>;
++ reset-names = "m";
++ rockchip,grf = <&grf>;
++ pinctrl-names = "default";
++ pinctrl-0 = <&i2s2m0_sclktx
++ &i2s2m0_lrcktx
++ &i2s2m0_sdi
++ &i2s2m0_sdo>;
++ #sound-dai-cells = <0>;
++ status = "disabled";
++ };
++
+ i2s3_2ch: i2s@fe430000 {
+ compatible = "rockchip,rk3568-i2s-tdm";
+ reg = <0x0 0xfe430000 0x0 0x1000>;
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Blade.patch b/debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Blade.patch
new file mode 100644
index 000000000..52fdca25d
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Blade.patch
@@ -0,0 +1,39 @@
+From: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Date: Wed, 16 Nov 2022 12:53:34 +0100
+Subject: [1/4] dt-bindings: arm: rockchip: Add SOQuartz Blade
+Origin: https://git.kernel.org/linus/8c84c2e51f3ee39b40e8078ebe3ad9c01fb17aff
+
+Add a compatible for the SOQuartz Blade base board to the rockchip
+platforms binding.
+
+The SOQuartz Blade is a PoE-capable carrier board for the CM4 SoM
+form factor, designed around the SOQuartz CM4 System-on-Module.
+
+The board features the usual connectivity (GPIO, USB, HDMI,
+Ethernet) and an M.2 slot for SSDs. It may also be powered from
+a 5V barrel jack input, and has a 3.5mm jack for UART debug
+output.
+
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20221116115337.541601-2-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ Documentation/devicetree/bindings/arm/rockchip.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
+index 3f31115ee99a..42f33240ade8 100644
+--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
++++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
+@@ -593,6 +593,7 @@ properties:
+ - description: Pine64 SoQuartz SoM
+ items:
+ - enum:
++ - pine64,soquartz-blade
+ - pine64,soquartz-cm4io
+ - const: pine64,soquartz
+ - const: rockchip,rk3566
+--
+2.39.0
+
diff --git a/debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Model-A.patch b/debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Model-A.patch
new file mode 100644
index 000000000..2983e8a88
--- /dev/null
+++ b/debian/patches/features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Model-A.patch
@@ -0,0 +1,39 @@
+From: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Date: Wed, 16 Nov 2022 12:53:36 +0100
+Subject: [3/4] dt-bindings: arm: rockchip: Add SOQuartz Model A
+Origin: https://git.kernel.org/linus/7441d8c437883581dddfb616a087b399338244f0
+
+The SOQuartz Model A base board is a carrier board for the CM4
+form factor, designed around the PINE64 SOQuartz CM4 SoM.
+
+The board sports "Model A" dimensions like the Quartz64 Model A,
+but is not to be confused with that.
+
+As for I/O, it features USB 2 ports, Gigabit Ethernet, a PCIe 2
+x1 slot, HDMI, a 40-pin GPIO header, CSI/DSI connectors, an eDP
+flat-flex cable connector, a 12V DC barrel jack for power input
+and power/reset buttons as well as a microSD card slot.
+
+Signed-off-by: Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20221116115337.541601-4-frattaroli.nicolas@gmail.com
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+---
+ Documentation/devicetree/bindings/arm/rockchip.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
+index 42f33240ade8..88ff4422a8c1 100644
+--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
++++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
+@@ -595,6 +595,7 @@ properties:
+ - enum:
+ - pine64,soquartz-blade
+ - pine64,soquartz-cm4io
++ - pine64,soquartz-model-a
+ - const: pine64,soquartz
+ - const: rockchip,rk3566
+
+--
+2.39.0
+
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 000000000..ff2fdadc4
--- /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
+@@ -282,14 +282,14 @@ static LIST_HEAD(dmar_satc_units);
+
+ static void device_block_translation(struct device *dev);
+
+-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;
+@@ -327,6 +327,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 000000000..a3543d90e
--- /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 000000000..44dd25261
--- /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
+@@ -5768,6 +5768,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.
++
+ sysfs.deprecated=0|1 [KNL]
+ Enable/disable old style sysfs layout for old udev
+ on older distributions. When this option is enabled
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2865,6 +2865,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;
+
+@@ -161,7 +164,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))
+
+ #if __USER32_DS != __USER_DS
+ # error "The following code assumes __USER32_DS == __USER_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 000000000..7a7952003
--- /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: http://thread.gmane.org/gmane.linux.kernel/1286471
+
+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 000000000..f31b433c2
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,175 @@
+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/vs6624-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
+
+# 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
+bugfix/all/wifi-mt76-do-not-run-mt76_unregister_device-on-unregistered-hw.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/arm64/dt-bindings-rockchip-Add-Hardkernel-ODROID-M1-board.patch
+features/arm64/arm64-dts-rockchip-Add-Hardkernel-ODROID-M1-board.patch
+features/arm64/arm64-dts-rockchip-add-thermal-support-to-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Add-NOR-flash-to-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Add-analog-audio-on-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Enable-vop2-and-hdmi-tx-on-ODROID.patch
+features/arm64/arm64-dts-rockchip-Enable-HDMI-audio-on-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Enable-the-GPU-on-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Enable-the-USB-2.0-ports-on-ODROI.patch
+features/arm64/arm64-dts-rockchip-Enable-the-USB-3.0-ports-on-ODROI.patch
+features/arm64/arm64-dts-rockchip-Add-SATA-support-to-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Add-PCIEe-v3-nodes-to-ODROID-M1.patch
+features/arm64/arm64-dts-rockchip-Add-IR-receiver-node-to-ODROID-M1.patch
+features/x86/x86-memtest-WARN-if-bad-RAM-found.patch
+features/x86/x86-make-x32-syscall-support-conditional.patch
+
+# Quartz64 bug fixes/patches
+bugfix/arm64/arm64-dts-rockchip-fix-spdif-fe460000-ordering-on-rk.patch
+features/arm64/quartz64/arm64-dts-rockchip-RK356x-Add-I2S2-device-node.patch
+features/arm64/quartz64/arm64-dts-rockchip-Enable-video-output-and-HDMI-on-S.patch
+features/arm64/quartz64/arm64-dts-rockchip-Enable-HDMI-sound-on-SOQuartz.patch
+features/arm64/quartz64/arm64-dts-rockchip-Enable-PCIe-2-on-SOQuartz-CM4IO.patch
+features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Blade.patch
+features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-blade-board.patch
+features/arm64/quartz64/dt-bindings-arm-rockchip-Add-SOQuartz-Model-A.patch
+features/arm64/quartz64/arm64-dts-rockchip-Add-SOQuartz-Model-A-baseboard.patch
+
+# Miscellaneous bug fixes
+bugfix/all/disable-some-marvell-phys.patch
+bugfix/all/fs-add-module_softdep-declarations-for-hard-coded-cr.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-bump-soname-version.patch
+bugfix/all/cpupower-fix-checks-for-cpu-existence.patch
+bugfix/all/tools-perf-pmu-events-fix-reproducibility.patch
+bugfix/all/libapi-define-_fortify_source-as-2-not-empty.patch
+bugfix/all/tools-perf-fix-missing-ldflags-for-some-programs.patch
+
+# debian-installer fixes
+bugfix/powerpc/fbdev-offb-Update-expected-device-name.patch
+
+# Backport of Microsoft Azure Network Adapter to 6.6
+features/all/ethernet-microsoft/0001-net-Remove-the-obsolte-u64_stats_fetch_-_irq-users-d.patch
+features/all/ethernet-microsoft/0002-net-mana-Assign-interrupts-to-CPUs-based-on-NUMA-nod.patch
+features/all/ethernet-microsoft/0003-net-mana-Add-support-for-auxiliary-device.patch
+features/all/ethernet-microsoft/0004-net-mana-Record-the-physical-address-for-doorbell-pa.patch
+features/all/ethernet-microsoft/0005-net-mana-Handle-vport-sharing-between-devices.patch
+features/all/ethernet-microsoft/0006-net-mana-Set-the-DMA-device-max-segment-size.patch
+features/all/ethernet-microsoft/0007-net-mana-Export-Work-Queue-functions-for-use-by-RDMA.patch
+features/all/ethernet-microsoft/0008-net-mana-Record-port-number-in-netdev.patch
+features/all/ethernet-microsoft/0009-net-mana-Move-header-files-to-a-common-location.patch
+features/all/ethernet-microsoft/0010-net-mana-Define-max-values-for-SGL-entries.patch
+features/all/ethernet-microsoft/0011-net-mana-Define-and-process-GDMA-response-code-GDMA_.patch
+features/all/ethernet-microsoft/0012-net-mana-Define-data-structures-for-protection-domai.patch
+features/all/ethernet-microsoft/0013-net-mana-Fix-return-type-of-mana_start_xmit.patch
+features/all/ethernet-microsoft/0014-net-mana-Fix-accessing-freed-irq-affinity_hint.patch
+features/all/ethernet-microsoft/0015-net-mana-Add-new-MANA-VF-performance-counters-for-ea.patch
+features/all/ethernet-microsoft/0016-net-mana-Remove-redundant-pci_clear_master.patch
+features/all/ethernet-microsoft/0017-net-mana-Use-napi_build_skb-in-RX-path.patch
+features/all/ethernet-microsoft/0018-net-mana-Refactor-RX-buffer-allocation-code-to-prepa.patch
+features/all/ethernet-microsoft/0019-net-mana-Enable-RX-path-to-handle-various-MTU-sizes.patch
+features/all/ethernet-microsoft/0020-net-mana-Add-support-for-jumbo-frame.patch
+features/all/ethernet-microsoft/0021-net-mana-Check-if-netdev-napi_alloc_frag-returns-sin.patch
+features/all/ethernet-microsoft/0022-net-mana-Fix-perf-regression-remove-rx_cqes-tx_cqes-.patch
+features/all/ethernet-microsoft/0023-net-mana-Add-support-for-vlan-tagging.patch
+features/all/ethernet-microsoft/0024-RDMA-mana_ib-Use-v2-version-of-cfg_rx_steer_req-to-e.patch
+features/all/ethernet-microsoft/0025-net-mana-use-vmalloc_array-and-vcalloc.patch
+features/all/ethernet-microsoft/0026-net-mana-Batch-ringing-RX-queue-doorbell-on-receivin.patch
+features/all/ethernet-microsoft/0027-net-mana-Use-the-correct-WQE-count-for-ringing-RQ-do.patch
+features/all/ethernet-microsoft/0028-net-mana-Configure-hwc-timeout-from-hardware.patch
+features/all/ethernet-microsoft/0029-net-mana-Rename-mana_refill_rxoob-and-remove-some-em.patch
+features/all/ethernet-microsoft/0030-net-mana-Add-gdma-stats-to-ethtool-output-for-mana.patch
+
+# ABI maintenance