From d7905a0422328f0ca6c3a3bd292b1daf86e5c842 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 6 Mar 2025 21:04:26 +0100 Subject: [PATCH 01/39] meta-digi: revert revisions to AUTOREV Signed-off-by: Arturo Buzarra --- .../recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend | 4 ++-- .../recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend | 4 ++-- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb | 2 +- .../recipes-digi/trustfence/trustfence-sign-tools.inc | 4 ++-- .../kernel-module-qualcomm/kernel-module-qualcomm.bb | 4 ++-- meta-digi-arm/recipes-kernel/linux/linux-dey.inc | 2 +- meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb | 4 ++-- meta-digi-dey/recipes-digi/cccs/cccs_git.bb | 4 ++-- meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc | 4 ++-- meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend index 7a28df3bc..4be084e74 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend @@ -8,10 +8,10 @@ TFA_URI_GITHUB = "${DIGI_GITHUB_GIT}/arm-trusted-firmware.git;protocol=https" TFA_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${TFA_URI_STASH}', '${TFA_URI_GITHUB}', d)}" SRCBRANCH = "v2.10/stm32mp/maint" -SRCREV = "87e6c6d0d7990c5c5d25aaf53da50aa322ed232c" +SRCREV = "${AUTOREV}" SRC_URI = " \ - ${TFA_GIT_URI};nobranch=1 \ + ${TFA_GIT_URI};branch=${SRCBRANCH} \ " TF_A_CONFIG[nand] = "${DEVICE_BOARD_ENABLE:NAND},STM32MP_RAW_NAND=1 ${@'STM32MP_FORCE_MTD_START_OFFSET=${TF_A_MTD_START_OFFSET_NAND}' if ${TF_A_MTD_START_OFFSET_NAND} else ''} STM32MP_USB_PROGRAMMER=1" diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend index 1037ba947..83a187760 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend @@ -8,10 +8,10 @@ OPTEE_URI_GITHUB = "${DIGI_GITHUB_GIT}/optee_os.git;protocol=https" OPTEE_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${OPTEE_URI_STASH}', '${OPTEE_URI_GITHUB}', d)}" SRCBRANCH = "4.0.0/stm/maint" -SRCREV = "5c00c71b64a32a4f4bd7266ae88d34b7a07ebe5a" +SRCREV = "${AUTOREV}" SRC_URI = " \ - ${OPTEE_GIT_URI};nobranch=1;name=os \ + ${OPTEE_GIT_URI};branch=${SRCBRANCH};name=os \ file://fonts.tar.gz;subdir=git;name=fonts \ " diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc index dc49afaa2..58f4abc40 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc @@ -27,7 +27,7 @@ INSTALL_FW_UBOOT_SCRIPTS = " \ " SRC_URI = " \ - ${UBOOT_GIT_URI};nobranch=1 \ + ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ file://boot.txt \ ${INSTALL_FW_UBOOT_SCRIPTS} \ " diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb index 2f21e9596..f354495ea 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb @@ -7,7 +7,7 @@ DEPENDS += "flex-native bison-native" DEPENDS += "python3-setuptools-native" SRCBRANCH = "v2023.10/maint" -SRCREV = "066683d260b3f225b7971db012e31eeeee734cfb" +SRCREV = "${AUTOREV}" SRC_URI += " \ ${@oe.utils.conditional('TRUSTFENCE_SIGN_FIT_STM', '1', 'file://fit_signature.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb index 57ca6cafe..9b381fff8 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb @@ -7,6 +7,6 @@ LIC_FILES_CHKSUM = "file://Licenses/README;md5=2ca5f2c35c8cc335f0a19756634782f1" DEPENDS += "flex-native bison-native" SRCBRANCH = "v2024.04/maint" -SRCREV = "f8357fd57e589bc0abbc754ce17a66f933402ff8" +SRCREV = "${AUTOREV}" COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8x|ccimx9)" diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc index 7e368689e..d27e2b2e6 100644 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc @@ -5,7 +5,7 @@ LICENSE = "GPL-2.0-only" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6" SRCBRANCH = "v2024.04/maint" -SRCREV = "f8357fd57e589bc0abbc754ce17a66f933402ff8" +SRCREV = "${AUTOREV}" S = "${WORKDIR}" @@ -15,7 +15,7 @@ UBOOT_URI_GITHUB = "${DIGI_GITHUB_GIT}/u-boot.git;protocol=https" UBOOT_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${UBOOT_URI_STASH}', '${UBOOT_URI_GITHUB}', d)}" SRC_URI = " \ - ${UBOOT_GIT_URI};nobranch=1 \ + ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ file://trustfence-sign-artifact-nxp.sh \ file://trustfence-sign-artifact-stm.sh \ file://trustfence-gen-pki-stm.sh \ diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index 47d37d0c8..6b2061aeb 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -9,12 +9,12 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca PV = "v4.0.11.213X" SRCBRANCH = "qca65X4/dey-5.0/maint" -SRCREV = "81f2e6d27c127f7bce54d348310919e6b3e3972a" +SRCREV = "${AUTOREV}" QCOM_GIT_URI = "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DIGI_MTK_GIT}/linux/qcacld-2.0.git;protocol=ssh', '${DIGI_GITHUB_GIT}/qcacld-2.0.git;protocol=https', d)}" SRC_URI = " \ - ${QCOM_GIT_URI};nobranch=1 \ + ${QCOM_GIT_URI};branch=${SRCBRANCH} \ " # Selects whether the interface is SDIO or PCI diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc index 22a814036..755704788 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc @@ -11,7 +11,7 @@ require ${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'recipes-kernel/linux/li DEPENDS += "${@oe.utils.conditional('DEY_SOC_VENDOR', 'NXP', 'lzop-native', '', d)}" SRC_URI = " \ - ${LINUX_GIT_URI};nobranch=1 \ + ${LINUX_GIT_URI};branch=${SRCBRANCH} \ ${@oe.utils.conditional('KERNEL_DEFCONFIG', '', 'file://defconfig', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'virtualization', 'file://docker_conf.cfg', '', d)} \ ${@oe.utils.vartrue('TRUSTFENCE_FILE_BASED_ENCRYPT', 'file://fscrypt.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb index 4c2b28426..84862071a 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb @@ -4,8 +4,8 @@ require recipes-kernel/linux/linux-dey.inc SRCBRANCH = "v6.6/nxp/dey-5.0/maint" SRCBRANCH:stm32mp2common = "v6.6/stm/dey-5.0/maint" -SRCREV = "87cedd7e8231fee5992dc8d27b6c1448dbfcb1ac" -SRCREV:stm32mp2common = "ff0c2b76588b0cf61cf12b6ebbb929ac84da9ebe" +SRCREV = "${AUTOREV}" +SRCREV:stm32mp2common = "${AUTOREV}" # Blacklist btnxpuart module. It will be managed by the bluetooth-init script KERNEL_MODULE_PROBECONF += "btnxpuart" diff --git a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb index ff0fa6672..694d2ac1c 100644 --- a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb +++ b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb @@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7 DEPENDS = "libconfuse libdigiapix openssl recovery-utils swupdate zlib json-c" SRCBRANCH = "dey-5.0/maint" -SRCREV = "5a5bf3f71df14855730bfbf3f4603d61bde3cbb2" +SRCREV = "${AUTOREV}" CC_STASH = "gitsm://git@stash.digi.com/cc/cc_dey.git;protocol=ssh" CC_GITHUB = "gitsm://github.com/digi-embedded/cc_dey.git;protocol=https" @@ -19,7 +19,7 @@ CCCS_DEVICE_TYPE ?= "${MACHINE}" CCCS_CONF_PATH ?= "" SRC_URI = " \ - ${CC_GIT_URI};nobranch=1 \ + ${CC_GIT_URI};branch=${SRCBRANCH} \ file://cccsd-init \ file://cccsd.service \ file://cccs-gs-demo-init \ diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc index 2c5733ce7..852a67bee 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc @@ -1,11 +1,11 @@ # Copyright (C) 2019-2025, Digi International Inc. SRCBRANCH = "dey-5.0/maint" -SRCREV = "46100efac498c4336baefcd8c7bde3217bac122e" +SRCREV = "${AUTOREV}" DEY_EXAMPLES_STASH = "${DIGI_MTK_GIT}/dey/dey-examples.git;protocol=ssh" DEY_EXAMPLES_GITHUB = "${DIGI_GITHUB_GIT}/dey-examples.git;protocol=https" DEY_EXAMPLES_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DEY_EXAMPLES_STASH}', '${DEY_EXAMPLES_GITHUB}', d)}" -SRC_URI = "${DEY_EXAMPLES_GIT_URI};nobranch=1" +SRC_URI = "${DEY_EXAMPLES_GIT_URI};branch=${SRCBRANCH}" diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb index ecb1ee014..3e4f5b7a8 100644 --- a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb @@ -7,7 +7,7 @@ LICENSE = "ISC" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d" SRCBRANCH ?= "dey-5.0/maint" -SRCREV = "b7d3156f55d9263ecee99201b9f1d997515d8858" +SRCREV = "${AUTOREV}" LIBDIGIAPIX_URI_STASH = "${DIGI_MTK_GIT}/dey/libdigiapix.git;protocol=ssh" LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" @@ -15,7 +15,7 @@ LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" LIBDIGIAPIX_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${LIBDIGIAPIX_URI_STASH}', '${LIBDIGIAPIX_URI_GITHUB}', d)}" SRC_URI = " \ - ${LIBDIGIAPIX_GIT_URI};nobranch=1 \ + ${LIBDIGIAPIX_GIT_URI};branch=${SRCBRANCH} \ file://99-digiapix.rules \ file://libdigiapix.conf \ file://digiapix.sh \ From 79444395f0a336ed39f1231e2f9e45351b401f2d Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Wed, 5 Mar 2025 12:00:57 +0100 Subject: [PATCH 02/39] meta-digi-dey: do not include hwlatdetect hwlatdetect is intended for monitoring hw latency on real time systems that rely on SMI interrupts (mainly x86 machines). As our devices that not support it, do not include the tool. Signed-off-by: Isaac Hermida --- .../recipes-core/packagegroups/packagegroup-dey-core.bb | 1 - 1 file changed, 1 deletion(-) diff --git a/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb b/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb index 65bf3e484..e20b04601 100644 --- a/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb +++ b/meta-digi-dey/recipes-core/packagegroups/packagegroup-dey-core.bb @@ -43,7 +43,6 @@ RDEPENDS:${PN} = "\ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'firmwared', '',d)} \ ${@bb.utils.contains("MACHINE_FEATURES", "keyboard", "${VIRTUAL-RUNTIME_keymaps}", "", d)} \ ${@bb.utils.contains("MACHINE_FEATURES", "touchscreen", "${VIRTUAL-RUNTIME_touchscreen}", "",d)} \ - ${@bb.utils.contains('DISTRO_FEATURES', 'rt', 'hwlatdetect', '',d)} \ init-ifupdown \ libdigiapix \ libgpiod \ From d09b04be600d8de22cb42c58f1281fc7b3944ce1 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Tue, 4 Mar 2025 11:54:28 +0100 Subject: [PATCH 03/39] linux-dey-6.6: add RT functionality to STM supported platforms This commit integrates the X-LINUX-RT expansion package from the meta-st-x-linux-rt layer, based on the tag "openstlinux-6.6-yocto-scarthgap-mpu-v24.11.06", for Yocto Scarthgap. Currently only the STM CCMP2 is supported in kernel 6.6. https://onedigi.atlassian.net/browse/DEL-9507 Signed-off-by: Isaac Hermida --- .../0010-Rebase-on-v6.6.48-rt40.patch | 15672 ++++++++++++++++ .../0011-v6.6-stm32mp-rt-r1.patch | 386 + .../fragment-08-deactivate-rng.config | 2 + .../recipes-kernel/linux/linux-dey_6.6.bb | 16 + 4 files changed, 16076 insertions(+) create mode 100644 meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0010-Rebase-on-v6.6.48-rt40.patch create mode 100644 meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0011-v6.6-stm32mp-rt-r1.patch create mode 100644 meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/fragment-08-deactivate-rng.config diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0010-Rebase-on-v6.6.48-rt40.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0010-Rebase-on-v6.6.48-rt40.patch new file mode 100644 index 000000000..622eac0f4 --- /dev/null +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0010-Rebase-on-v6.6.48-rt40.patch @@ -0,0 +1,15672 @@ +From 853262b793afb5b3b26b0fd0ed6467475328ee2c Mon Sep 17 00:00:00 2001 +From: Lionel VITTE +Date: Tue, 3 Dec 2024 14:40:54 +0100 +Subject: [PATCH 10/11] Rebase on v6.6.48-rt40 + +--- + arch/arm/Kconfig | 6 +- + arch/arm/mm/fault.c | 6 + + arch/arm/vfp/vfpmodule.c | 74 +- + arch/arm64/Kconfig | 1 + + arch/powerpc/Kconfig | 2 + + arch/powerpc/include/asm/stackprotector.h | 7 +- + arch/powerpc/kernel/traps.c | 7 +- + arch/powerpc/kvm/Kconfig | 1 + + arch/powerpc/platforms/pseries/Kconfig | 1 + + arch/powerpc/platforms/pseries/iommu.c | 31 +- + arch/riscv/Kconfig | 2 + + arch/riscv/include/asm/cpufeature.h | 2 - + arch/riscv/include/asm/thread_info.h | 2 + + arch/riscv/kernel/cpufeature.c | 92 +- + arch/riscv/kernel/smpboot.c | 1 - + arch/x86/Kconfig | 2 + + arch/x86/include/asm/thread_info.h | 6 +- + drivers/acpi/processor_idle.c | 2 +- + drivers/block/zram/zram_drv.c | 37 + + drivers/block/zram/zram_drv.h | 3 + + .../gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 53 +- + .../drm/amd/display/dc/dcn20/dcn20_resource.c | 10 +- + .../drm/amd/display/dc/dcn21/dcn21_resource.c | 10 +- + .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 23 +- + .../drm/amd/display/dc/dml/dcn20/dcn20_fpu.h | 10 +- + drivers/gpu/drm/i915/Kconfig | 1 - + drivers/gpu/drm/i915/display/intel_crtc.c | 15 +- + drivers/gpu/drm/i915/display/intel_vblank.c | 6 +- + drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 7 +- + .../drm/i915/gt/intel_execlists_submission.c | 17 +- + drivers/gpu/drm/i915/gt/intel_reset.c | 12 +- + drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 +- + drivers/gpu/drm/i915/i915_request.c | 2 - + drivers/gpu/drm/i915/i915_trace.h | 6 +- + drivers/gpu/drm/i915/i915_utils.h | 2 +- + drivers/tty/serial/21285.c | 8 +- + drivers/tty/serial/8250/8250_aspeed_vuart.c | 6 +- + drivers/tty/serial/8250/8250_bcm7271.c | 28 +- + drivers/tty/serial/8250/8250_core.c | 54 +- + drivers/tty/serial/8250/8250_dma.c | 8 +- + drivers/tty/serial/8250/8250_dw.c | 8 +- + drivers/tty/serial/8250/8250_exar.c | 4 +- + drivers/tty/serial/8250/8250_fsl.c | 6 +- + drivers/tty/serial/8250/8250_mtk.c | 8 +- + drivers/tty/serial/8250/8250_omap.c | 52 +- + drivers/tty/serial/8250/8250_pci1xxxx.c | 8 +- + drivers/tty/serial/8250/8250_port.c | 259 ++- + drivers/tty/serial/altera_jtaguart.c | 28 +- + drivers/tty/serial/altera_uart.c | 20 +- + drivers/tty/serial/amba-pl010.c | 20 +- + drivers/tty/serial/amba-pl011.c | 78 +- + drivers/tty/serial/apbuart.c | 8 +- + drivers/tty/serial/ar933x_uart.c | 26 +- + drivers/tty/serial/arc_uart.c | 16 +- + drivers/tty/serial/atmel_serial.c | 24 +- + drivers/tty/serial/bcm63xx_uart.c | 22 +- + drivers/tty/serial/cpm_uart.c | 8 +- + drivers/tty/serial/digicolor-usart.c | 18 +- + drivers/tty/serial/dz.c | 32 +- + drivers/tty/serial/fsl_linflexuart.c | 26 +- + drivers/tty/serial/fsl_lpuart.c | 88 +- + drivers/tty/serial/icom.c | 26 +- + drivers/tty/serial/imx.c | 84 +- + drivers/tty/serial/ip22zilog.c | 36 +- + drivers/tty/serial/jsm/jsm_neo.c | 4 +- + drivers/tty/serial/jsm/jsm_tty.c | 16 +- + drivers/tty/serial/liteuart.c | 20 +- + drivers/tty/serial/lpc32xx_hs.c | 26 +- + drivers/tty/serial/ma35d1_serial.c | 22 +- + drivers/tty/serial/mcf.c | 20 +- + drivers/tty/serial/men_z135_uart.c | 8 +- + drivers/tty/serial/meson_uart.c | 30 +- + drivers/tty/serial/milbeaut_usio.c | 16 +- + drivers/tty/serial/mpc52xx_uart.c | 12 +- + drivers/tty/serial/mps2-uart.c | 16 +- + drivers/tty/serial/msm_serial.c | 38 +- + drivers/tty/serial/mvebu-uart.c | 18 +- + drivers/tty/serial/omap-serial.c | 44 +- + drivers/tty/serial/owl-uart.c | 26 +- + drivers/tty/serial/pch_uart.c | 10 +- + drivers/tty/serial/pic32_uart.c | 20 +- + drivers/tty/serial/pmac_zilog.c | 52 +- + drivers/tty/serial/pxa.c | 30 +- + drivers/tty/serial/qcom_geni_serial.c | 8 +- + drivers/tty/serial/rda-uart.c | 34 +- + drivers/tty/serial/rp2.c | 20 +- + drivers/tty/serial/sa1100.c | 20 +- + drivers/tty/serial/samsung_tty.c | 50 +- + drivers/tty/serial/sb1250-duart.c | 12 +- + drivers/tty/serial/sc16is7xx.c | 5 + + drivers/tty/serial/serial-tegra.c | 32 +- + drivers/tty/serial/serial_core.c | 92 +- + drivers/tty/serial/serial_mctrl_gpio.c | 4 +- + drivers/tty/serial/serial_port.c | 4 +- + drivers/tty/serial/serial_txx9.c | 26 +- + drivers/tty/serial/sh-sci.c | 68 +- + drivers/tty/serial/sifive.c | 16 +- + drivers/tty/serial/sprd_serial.c | 30 +- + drivers/tty/serial/st-asc.c | 18 +- + drivers/tty/serial/stm32-usart.c | 38 +- + drivers/tty/serial/sunhv.c | 28 +- + drivers/tty/serial/sunplus-uart.c | 26 +- + drivers/tty/serial/sunsab.c | 34 +- + drivers/tty/serial/sunsu.c | 46 +- + drivers/tty/serial/sunzilog.c | 42 +- + drivers/tty/serial/timbuart.c | 8 +- + drivers/tty/serial/uartlite.c | 18 +- + drivers/tty/serial/ucc_uart.c | 4 +- + drivers/tty/serial/vt8500_serial.c | 8 +- + drivers/tty/serial/xilinx_uartps.c | 56 +- + drivers/tty/tty_io.c | 11 +- + fs/proc/consoles.c | 14 +- + include/linux/bottom_half.h | 2 + + include/linux/console.h | 150 ++ + include/linux/entry-common.h | 2 +- + include/linux/entry-kvm.h | 2 +- + include/linux/interrupt.h | 29 + + include/linux/netdevice.h | 4 + + include/linux/printk.h | 30 +- + include/linux/sched.h | 16 +- + include/linux/sched/idle.h | 8 +- + include/linux/sched/rt.h | 4 + + include/linux/serial_8250.h | 6 + + include/linux/serial_core.h | 43 +- + include/linux/thread_info.h | 24 + + include/linux/trace_events.h | 8 +- + kernel/Kconfig.preempt | 17 +- + kernel/entry/common.c | 4 +- + kernel/entry/kvm.c | 2 +- + kernel/futex/pi.c | 87 +- + kernel/futex/requeue.c | 6 +- + kernel/ksysfs.c | 12 + + kernel/locking/lockdep.c | 5 + + kernel/locking/rtmutex.c | 37 +- + kernel/locking/rwbase_rt.c | 8 + + kernel/locking/rwsem.c | 8 +- + kernel/locking/spinlock_rt.c | 6 + + kernel/locking/ww_rt_mutex.c | 2 +- + kernel/panic.c | 9 + + kernel/printk/Makefile | 2 +- + kernel/printk/internal.h | 121 ++ + kernel/printk/nbcon.c | 1665 +++++++++++++++++ + kernel/printk/printk.c | 750 ++++++-- + kernel/printk/printk_ringbuffer.c | 360 +++- + kernel/printk/printk_ringbuffer.h | 54 +- + kernel/printk/printk_safe.c | 12 + + kernel/rcu/rcutorture.c | 6 + + kernel/rcu/tree_stall.h | 5 + + kernel/sched/core.c | 127 +- + kernel/sched/debug.c | 19 + + kernel/sched/fair.c | 46 +- + kernel/sched/features.h | 2 + + kernel/sched/idle.c | 3 +- + kernel/sched/rt.c | 5 +- + kernel/sched/sched.h | 1 + + kernel/signal.c | 30 +- + kernel/softirq.c | 95 +- + kernel/time/hrtimer.c | 4 +- + kernel/time/tick-sched.c | 2 +- + kernel/time/timer.c | 11 +- + kernel/trace/trace.c | 2 + + kernel/trace/trace_output.c | 16 +- + localversion-rt | 1 + + net/core/dev.c | 39 +- + net/core/skbuff.c | 7 +- + 165 files changed, 5048 insertions(+), 1538 deletions(-) + create mode 100644 kernel/printk/nbcon.c + create mode 100644 localversion-rt + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 57c0448d0..e5a283851 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -34,6 +34,7 @@ config ARM + select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7 + select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE ++ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK + select ARCH_USE_BUILTIN_BSWAP + select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_USE_MEMTEST +@@ -73,7 +74,7 @@ config ARM + select HAS_IOPORT + select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT + select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 +- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU ++ select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && !PREEMPT_RT + select HAVE_ARCH_KFENCE if MMU && !XIP_KERNEL + select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU + select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL +@@ -96,7 +97,7 @@ config ARM + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE + select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU + select HAVE_EXIT_THREAD +- select HAVE_FAST_GUP if ARM_LPAE ++ select HAVE_FAST_GUP if ARM_LPAE && !(PREEMPT_RT && HIGHPTE) + select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL + select HAVE_FUNCTION_ERROR_INJECTION + select HAVE_FUNCTION_GRAPH_TRACER +@@ -118,6 +119,7 @@ config ARM + select HAVE_PERF_EVENTS + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP ++ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM + select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE + select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RSEQ +diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c +index fef62e4a9..622a30243 100644 +--- a/arch/arm/mm/fault.c ++++ b/arch/arm/mm/fault.c +@@ -404,6 +404,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; + +@@ -474,6 +477,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; + } +diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c +index 7e8773a2d..9fde36fcb 100644 +--- a/arch/arm/vfp/vfpmodule.c ++++ b/arch/arm/vfp/vfpmodule.c +@@ -55,6 +55,34 @@ extern unsigned int VFP_arch_feroceon __alias(VFP_arch); + */ + union vfp_state *vfp_current_hw_state[NR_CPUS]; + ++/* ++ * Claim ownership of the VFP unit. ++ * ++ * The caller may change VFP registers until vfp_unlock() is called. ++ * ++ * local_bh_disable() is used to disable preemption and to disable VFP ++ * processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is ++ * not sufficient because it only serializes soft interrupt related sections ++ * via a local lock, but stays preemptible. Disabling preemption is the right ++ * choice here as bottom half processing is always in thread context on RT ++ * kernels so it implicitly prevents bottom half processing as well. ++ */ ++static void vfp_lock(void) ++{ ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) ++ local_bh_disable(); ++ else ++ preempt_disable(); ++} ++ ++static void vfp_unlock(void) ++{ ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) ++ local_bh_enable(); ++ else ++ preempt_enable(); ++} ++ + /* + * Is 'thread's most up to date state stored in this CPUs hardware? + * Must be called from non-preemptible context. +@@ -240,7 +268,7 @@ static void vfp_panic(char *reason, u32 inst) + /* + * Process bitmask of exception conditions. + */ +-static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs) ++static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr) + { + int si_code = 0; + +@@ -248,8 +276,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_ + + if (exceptions == VFP_EXCEPTION_ERROR) { + vfp_panic("unhandled bounce", inst); +- vfp_raise_sigfpe(FPE_FLTINV, regs); +- return; ++ return FPE_FLTINV; + } + + /* +@@ -277,8 +304,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_ + RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); + RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV); + +- if (si_code) +- vfp_raise_sigfpe(si_code, regs); ++ return si_code; + } + + /* +@@ -324,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs) + static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + { + u32 fpscr, orig_fpscr, fpsid, exceptions; ++ int si_code2 = 0; ++ int si_code = 0; + + pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc); + +@@ -369,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + * unallocated VFP instruction but with FPSCR.IXE set and not + * on VFP subarch 1. + */ +- vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs); +- return; ++ si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr); ++ goto exit; + } + + /* +@@ -394,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + */ + exceptions = vfp_emulate_instruction(trigger, fpscr, regs); + if (exceptions) +- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); ++ si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr); + + /* + * If there isn't a second FP instruction, exit now. Note that + * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1. + */ + if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V)) +- return; ++ goto exit; + + /* + * The barrier() here prevents fpinst2 being read +@@ -413,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + emulate: + exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs); + if (exceptions) +- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); ++ si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr); ++exit: ++ vfp_unlock(); ++ if (si_code2) ++ vfp_raise_sigfpe(si_code2, regs); ++ if (si_code) ++ vfp_raise_sigfpe(si_code, regs); + } + + static void vfp_enable(void *unused) +@@ -512,11 +546,9 @@ static inline void vfp_pm_init(void) { } + */ + void vfp_sync_hwstate(struct thread_info *thread) + { +- unsigned int cpu = get_cpu(); ++ vfp_lock(); + +- local_bh_disable(); +- +- if (vfp_state_in_hw(cpu, thread)) { ++ if (vfp_state_in_hw(raw_smp_processor_id(), thread)) { + u32 fpexc = fmrx(FPEXC); + + /* +@@ -527,8 +559,7 @@ void vfp_sync_hwstate(struct thread_info *thread) + fmxr(FPEXC, fpexc); + } + +- local_bh_enable(); +- put_cpu(); ++ vfp_unlock(); + } + + /* Ensure that the thread reloads the hardware VFP state on the next use. */ +@@ -683,7 +714,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger) + if (!user_mode(regs)) + return vfp_kmode_exception(regs, trigger); + +- local_bh_disable(); ++ vfp_lock(); + fpexc = fmrx(FPEXC); + + /* +@@ -748,6 +779,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger) + * replay the instruction that trapped. + */ + fmxr(FPEXC, fpexc); ++ vfp_unlock(); + } else { + /* Check for synchronous or asynchronous exceptions */ + if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) { +@@ -762,17 +794,17 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger) + if (!(fpscr & FPSCR_IXE)) { + if (!(fpscr & FPSCR_LENGTH_MASK)) { + pr_debug("not VFP\n"); +- local_bh_enable(); ++ vfp_unlock(); + return -ENOEXEC; + } + fpexc |= FPEXC_DEX; + } + } + bounce: regs->ARM_pc += 4; ++ /* VFP_bounce() will invoke vfp_unlock() */ + VFP_bounce(trigger, fpexc, regs); + } + +- local_bh_enable(); + return 0; + } + +@@ -819,7 +851,7 @@ void kernel_neon_begin(void) + unsigned int cpu; + u32 fpexc; + +- local_bh_disable(); ++ vfp_lock(); + + /* + * Kernel mode NEON is only allowed outside of hardirq context with +@@ -850,7 +882,7 @@ void kernel_neon_end(void) + { + /* Disable the NEON/VFP unit. */ + fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); +- local_bh_enable(); ++ vfp_unlock(); + } + EXPORT_SYMBOL(kernel_neon_end); + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 9e0c1ac3d..6f7960fad 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -97,6 +97,7 @@ config ARM64 + select ARCH_SUPPORTS_NUMA_BALANCING + select ARCH_SUPPORTS_PAGE_TABLE_CHECK + select ARCH_SUPPORTS_PER_VMA_LOCK ++ select ARCH_SUPPORTS_RT + select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH + select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT + select ARCH_WANT_DEFAULT_BPF_JIT +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index 2fe51e0ad..116444551 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -166,6 +166,7 @@ config PPC + select ARCH_STACKWALK + select ARCH_SUPPORTS_ATOMIC_RMW + select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x ++ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK + select ARCH_USE_BUILTIN_BSWAP + select ARCH_USE_CMPXCHG_LOCKREF if PPC64 + select ARCH_USE_MEMTEST +@@ -268,6 +269,7 @@ config PPC + select HAVE_PERF_USER_STACK_DUMP + select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RELIABLE_STACKTRACE ++ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM + select HAVE_RSEQ + select HAVE_SETUP_PER_CPU_AREA if PPC64 + select HAVE_SOFTIRQ_ON_OWN_STACK +diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h +index 283c34647..4727f4005 100644 +--- a/arch/powerpc/include/asm/stackprotector.h ++++ b/arch/powerpc/include/asm/stackprotector.h +@@ -19,8 +19,13 @@ + */ + static __always_inline void boot_init_stack_canary(void) + { +- unsigned long canary = get_random_canary(); ++ unsigned long canary; + ++#ifndef CONFIG_PREEMPT_RT ++ canary = get_random_canary(); ++#else ++ canary = ((unsigned long)&canary) & CANARY_MASK; ++#endif + current->stack_canary = canary; + #ifdef CONFIG_PPC64 + get_paca()->canary = canary; +diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c +index 2de7f6dcd..739f5b179 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" : "", +diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig +index 902611954..2f188137f 100644 +--- a/arch/powerpc/kvm/Kconfig ++++ b/arch/powerpc/kvm/Kconfig +@@ -224,6 +224,7 @@ config KVM_E500MC + config KVM_MPIC + bool "KVM in-kernel MPIC emulation" + depends on KVM && PPC_E500 ++ depends on !PREEMPT_RT + select HAVE_KVM_IRQCHIP + select HAVE_KVM_IRQFD + select HAVE_KVM_IRQ_ROUTING +diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig +index 4ebf2ef28..381c3be3b 100644 +--- a/arch/powerpc/platforms/pseries/Kconfig ++++ b/arch/powerpc/platforms/pseries/Kconfig +@@ -2,6 +2,7 @@ + config PPC_PSERIES + depends on PPC64 && PPC_BOOK3S + bool "IBM pSeries & new (POWER5-based) iSeries" ++ select GENERIC_ALLOCATOR + select HAVE_PCSPKR_PLATFORM + select MPIC + select OF_DYNAMIC +diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c +index b1e6d275c..9a8d3970d 100644 +--- a/arch/powerpc/platforms/pseries/iommu.c ++++ b/arch/powerpc/platforms/pseries/iommu.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -206,7 +207,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, +@@ -229,9 +236,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}() +@@ -240,12 +248,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; +@@ -275,7 +283,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; +@@ -459,16 +467,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; +@@ -511,7 +520,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; + } + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index c785a0200..e05c17078 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -48,6 +48,7 @@ config RISCV + select ARCH_SUPPORTS_HUGETLBFS if MMU + select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU + select ARCH_SUPPORTS_PER_VMA_LOCK if MMU ++ select ARCH_SUPPORTS_RT + select ARCH_USE_MEMTEST + select ARCH_USE_QUEUED_RWLOCKS + select ARCH_USES_CFI_TRAPS if CFI_CLANG +@@ -135,6 +136,7 @@ config RISCV + select HAVE_PERF_USER_STACK_DUMP + select HAVE_POSIX_CPU_TIMERS_TASK_WORK + select HAVE_PREEMPT_DYNAMIC_KEY if !XIP_KERNEL ++ select HAVE_PREEMPT_AUTO + select HAVE_REGS_AND_STACK_ACCESS_API + select HAVE_RETHOOK if !XIP_KERNEL + select HAVE_RSEQ +diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h +index d0345bd65..23fed53b8 100644 +--- a/arch/riscv/include/asm/cpufeature.h ++++ b/arch/riscv/include/asm/cpufeature.h +@@ -30,6 +30,4 @@ DECLARE_PER_CPU(long, misaligned_access_speed); + /* Per-cpu ISA extensions. */ + extern struct riscv_isainfo hart_isa[NR_CPUS]; + +-void check_unaligned_access(int cpu); +- + #endif +diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h +index d18ce0113..e18710fe5 100644 +--- a/arch/riscv/include/asm/thread_info.h ++++ b/arch/riscv/include/asm/thread_info.h +@@ -82,6 +82,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); + * - pending work-to-be-done flags are in lowest half-word + * - other flags in upper half-word(s) + */ ++#define TIF_ARCH_RESCHED_LAZY 0 /* Lazy rescheduling */ + #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ + #define TIF_SIGPENDING 2 /* signal pending */ + #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +@@ -96,6 +97,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) + #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) + #define _TIF_UPROBE (1 << TIF_UPROBE) ++#define _TIF_ARCH_RESCHED_LAZY (1 << TIF_ARCH_RESCHED_LAZY) + + #define _TIF_WORK_MASK \ + (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c +index e39a905ac..347cdf56f 100644 +--- a/arch/riscv/kernel/cpufeature.c ++++ b/arch/riscv/kernel/cpufeature.c +@@ -8,6 +8,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -30,6 +31,7 @@ + + #define MISALIGNED_ACCESS_JIFFIES_LG2 1 + #define MISALIGNED_BUFFER_SIZE 0x4000 ++#define MISALIGNED_BUFFER_ORDER get_order(MISALIGNED_BUFFER_SIZE) + #define MISALIGNED_COPY_SIZE ((MISALIGNED_BUFFER_SIZE / 2) - 0x80) + + unsigned long elf_hwcap __read_mostly; +@@ -571,27 +573,22 @@ unsigned long riscv_get_elf_hwcap(void) + return hwcap; + } + +-void check_unaligned_access(int cpu) ++static int check_unaligned_access(void *param) + { ++ int cpu = smp_processor_id(); + u64 start_cycles, end_cycles; + u64 word_cycles; + u64 byte_cycles; + int ratio; + unsigned long start_jiffies, now; +- struct page *page; ++ struct page *page = param; + void *dst; + void *src; + long speed = RISCV_HWPROBE_MISALIGNED_SLOW; + + /* We are already set since the last check */ + if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_UNKNOWN) +- return; +- +- page = alloc_pages(GFP_NOWAIT, get_order(MISALIGNED_BUFFER_SIZE)); +- if (!page) { +- pr_warn("Can't alloc pages to measure memcpy performance"); +- return; +- } ++ return 0; + + /* Make an unaligned destination buffer. */ + dst = (void *)((unsigned long)page_address(page) | 0x1); +@@ -645,7 +642,7 @@ void check_unaligned_access(int cpu) + pr_warn("cpu%d: rdtime lacks granularity needed to measure unaligned access speed\n", + cpu); + +- goto out; ++ return 0; + } + + if (word_cycles < byte_cycles) +@@ -659,18 +656,83 @@ void check_unaligned_access(int cpu) + (speed == RISCV_HWPROBE_MISALIGNED_FAST) ? "fast" : "slow"); + + per_cpu(misaligned_access_speed, cpu) = speed; ++ return 0; ++} + +-out: +- __free_pages(page, get_order(MISALIGNED_BUFFER_SIZE)); ++static void check_unaligned_access_nonboot_cpu(void *param) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct page **pages = param; ++ ++ if (smp_processor_id() != 0) ++ check_unaligned_access(pages[cpu]); ++} ++ ++static int riscv_online_cpu(unsigned int cpu) ++{ ++ static struct page *buf; ++ ++ /* We are already set since the last check */ ++ if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_UNKNOWN) ++ return 0; ++ ++ buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); ++ if (!buf) { ++ pr_warn("Allocation failure, not measuring misaligned performance\n"); ++ return -ENOMEM; ++ } ++ ++ check_unaligned_access(buf); ++ __free_pages(buf, MISALIGNED_BUFFER_ORDER); ++ return 0; + } + +-static int check_unaligned_access_boot_cpu(void) ++/* Measure unaligned access on all CPUs present at boot in parallel. */ ++static int check_unaligned_access_all_cpus(void) + { +- check_unaligned_access(0); ++ unsigned int cpu; ++ unsigned int cpu_count = num_possible_cpus(); ++ struct page **bufs = kzalloc(cpu_count * sizeof(struct page *), ++ GFP_KERNEL); ++ ++ if (!bufs) { ++ pr_warn("Allocation failure, not measuring misaligned performance\n"); ++ return 0; ++ } ++ ++ /* ++ * Allocate separate buffers for each CPU so there's no fighting over ++ * cache lines. ++ */ ++ for_each_cpu(cpu, cpu_online_mask) { ++ bufs[cpu] = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER); ++ if (!bufs[cpu]) { ++ pr_warn("Allocation failure, not measuring misaligned performance\n"); ++ goto out; ++ } ++ } ++ ++ /* Check everybody except 0, who stays behind to tend jiffies. */ ++ on_each_cpu(check_unaligned_access_nonboot_cpu, bufs, 1); ++ ++ /* Check core 0. */ ++ smp_call_on_cpu(0, check_unaligned_access, bufs[0], true); ++ ++ /* Setup hotplug callback for any new CPUs that come online. */ ++ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "riscv:online", ++ riscv_online_cpu, NULL); ++ ++out: ++ for_each_cpu(cpu, cpu_online_mask) { ++ if (bufs[cpu]) ++ __free_pages(bufs[cpu], MISALIGNED_BUFFER_ORDER); ++ } ++ ++ kfree(bufs); + return 0; + } + +-arch_initcall(check_unaligned_access_boot_cpu); ++arch_initcall(check_unaligned_access_all_cpus); + + #ifdef CONFIG_RISCV_ALTERNATIVE + /* +diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c +index 1b8da4e40..2cb5e6514 100644 +--- a/arch/riscv/kernel/smpboot.c ++++ b/arch/riscv/kernel/smpboot.c +@@ -246,7 +246,6 @@ asmlinkage __visible void smp_callin(void) + + numa_add_cpu(curr_cpuid); + set_cpu_online(curr_cpuid, 1); +- check_unaligned_access(curr_cpuid); + + if (has_vector()) { + if (riscv_v_setup_vsize()) +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 82d12c93f..7bbf835fe 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -118,6 +118,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 +@@ -272,6 +273,7 @@ config X86 + select HAVE_STATIC_CALL + select HAVE_STATIC_CALL_INLINE if HAVE_OBJTOOL + select HAVE_PREEMPT_DYNAMIC_CALL ++ select HAVE_PREEMPT_AUTO + select HAVE_RSEQ + select HAVE_RUST if X86_64 + select HAVE_SYSCALL_TRACEPOINTS +diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h +index d63b02940..1ff38ebbd 100644 +--- a/arch/x86/include/asm/thread_info.h ++++ b/arch/x86/include/asm/thread_info.h +@@ -81,8 +81,9 @@ struct thread_info { + #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ + #define TIF_SIGPENDING 2 /* signal pending */ + #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +-#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ +-#define TIF_SSBD 5 /* Speculative store bypass disable */ ++#define TIF_ARCH_RESCHED_LAZY 4 /* Lazy rescheduling */ ++#define TIF_SINGLESTEP 5 /* reenable singlestep on user return*/ ++#define TIF_SSBD 6 /* Speculative store bypass disable */ + #define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */ + #define TIF_SPEC_L1D_FLUSH 10 /* Flush L1D on mm switches (processes) */ + #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ +@@ -104,6 +105,7 @@ struct thread_info { + #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) ++#define _TIF_ARCH_RESCHED_LAZY (1 << TIF_ARCH_RESCHED_LAZY) + #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) + #define _TIF_SSBD (1 << TIF_SSBD) + #define _TIF_SPEC_IB (1 << TIF_SPEC_IB) +diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c +index 831fa4a12..5af3ebec0 100644 +--- a/drivers/acpi/processor_idle.c ++++ b/drivers/acpi/processor_idle.c +@@ -107,7 +107,7 @@ static const struct dmi_system_id processor_power_dmi_table[] = { + */ + static void __cpuidle acpi_safe_halt(void) + { +- if (!tif_need_resched()) { ++ if (!need_resched()) { + raw_safe_halt(); + raw_local_irq_disable(); + } +diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c +index 06673c6ca..a5d0f7c06 100644 +--- a/drivers/block/zram/zram_drv.c ++++ b/drivers/block/zram/zram_drv.c +@@ -57,6 +57,41 @@ static void zram_free_page(struct zram *zram, size_t index); + static int zram_read_page(struct zram *zram, struct page *page, u32 index, + struct bio *parent); + ++#ifdef CONFIG_PREEMPT_RT ++static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages) ++{ ++ size_t index; ++ ++ for (index = 0; index < num_pages; index++) ++ spin_lock_init(&zram->table[index].lock); ++} ++ ++static int zram_slot_trylock(struct zram *zram, u32 index) ++{ ++ int ret; ++ ++ ret = spin_trylock(&zram->table[index].lock); ++ if (ret) ++ __set_bit(ZRAM_LOCK, &zram->table[index].flags); ++ return ret; ++} ++ ++static void zram_slot_lock(struct zram *zram, u32 index) ++{ ++ spin_lock(&zram->table[index].lock); ++ __set_bit(ZRAM_LOCK, &zram->table[index].flags); ++} ++ ++static void zram_slot_unlock(struct zram *zram, u32 index) ++{ ++ __clear_bit(ZRAM_LOCK, &zram->table[index].flags); ++ spin_unlock(&zram->table[index].lock); ++} ++ ++#else ++ ++static void zram_meta_init_table_locks(struct zram *zram, size_t num_pages) { } ++ + static int zram_slot_trylock(struct zram *zram, u32 index) + { + return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags); +@@ -71,6 +106,7 @@ static void zram_slot_unlock(struct zram *zram, u32 index) + { + bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags); + } ++#endif + + static inline bool init_done(struct zram *zram) + { +@@ -1245,6 +1281,7 @@ static bool zram_meta_alloc(struct zram *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 ca7a15bd4..e64eb607e 100644 +--- a/drivers/block/zram/zram_drv.h ++++ b/drivers/block/zram/zram_drv.h +@@ -69,6 +69,9 @@ struct zram_table_entry { + unsigned long element; + }; + unsigned long flags; ++#ifdef CONFIG_PREEMPT_RT ++ spinlock_t lock; ++#endif + #ifdef CONFIG_ZRAM_MEMORY_TRACKING + ktime_t ac_time; + #endif +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +index 172aa10a8..4ae472053 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +@@ -60,11 +60,9 @@ static DEFINE_PER_CPU(int, fpu_recursion_depth); + */ + inline void dc_assert_fp_enabled(void) + { +- int *pcpu, depth = 0; ++ int depth; + +- pcpu = get_cpu_ptr(&fpu_recursion_depth); +- depth = *pcpu; +- put_cpu_ptr(&fpu_recursion_depth); ++ depth = __this_cpu_read(fpu_recursion_depth); + + ASSERT(depth >= 1); + } +@@ -84,33 +82,28 @@ inline void dc_assert_fp_enabled(void) + */ + void dc_fpu_begin(const char *function_name, const int line) + { +- int *pcpu; ++ int depth; + +- pcpu = get_cpu_ptr(&fpu_recursion_depth); +- *pcpu += 1; ++ WARN_ON_ONCE(!in_task()); ++ preempt_disable(); ++ depth = __this_cpu_inc_return(fpu_recursion_depth); + +- if (*pcpu == 1) { ++ if (depth == 1) { + #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH) +- migrate_disable(); + kernel_fpu_begin(); + #elif defined(CONFIG_PPC64) +- if (cpu_has_feature(CPU_FTR_VSX_COMP)) { +- preempt_disable(); ++ if (cpu_has_feature(CPU_FTR_VSX_COMP)) + enable_kernel_vsx(); +- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { +- preempt_disable(); ++ else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) + enable_kernel_altivec(); +- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { +- preempt_disable(); ++ else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) + enable_kernel_fp(); +- } + #elif defined(CONFIG_ARM64) + kernel_neon_begin(); + #endif + } + +- TRACE_DCN_FPU(true, function_name, line, *pcpu); +- put_cpu_ptr(&fpu_recursion_depth); ++ TRACE_DCN_FPU(true, function_name, line, depth); + } + + /** +@@ -125,30 +118,26 @@ void dc_fpu_begin(const char *function_name, const int line) + */ + void dc_fpu_end(const char *function_name, const int line) + { +- int *pcpu; ++ int depth; + +- pcpu = get_cpu_ptr(&fpu_recursion_depth); +- *pcpu -= 1; +- if (*pcpu <= 0) { ++ depth = __this_cpu_dec_return(fpu_recursion_depth); ++ if (depth == 0) { + #if defined(CONFIG_X86) || defined(CONFIG_LOONGARCH) + kernel_fpu_end(); +- migrate_enable(); + #elif defined(CONFIG_PPC64) +- if (cpu_has_feature(CPU_FTR_VSX_COMP)) { ++ if (cpu_has_feature(CPU_FTR_VSX_COMP)) + disable_kernel_vsx(); +- preempt_enable(); +- } else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) { ++ else if (cpu_has_feature(CPU_FTR_ALTIVEC_COMP)) + disable_kernel_altivec(); +- preempt_enable(); +- } else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) { ++ else if (!cpu_has_feature(CPU_FTR_FPU_UNAVAILABLE)) + disable_kernel_fp(); +- preempt_enable(); +- } + #elif defined(CONFIG_ARM64) + kernel_neon_end(); + #endif ++ } else { ++ WARN_ON_ONCE(depth < 0); + } + +- TRACE_DCN_FPU(false, function_name, line, *pcpu); +- put_cpu_ptr(&fpu_recursion_depth); ++ TRACE_DCN_FPU(false, function_name, line, depth); ++ preempt_enable(); + } +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +index d587f807d..5036a3e60 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +@@ -2141,9 +2141,17 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) + { + bool voltage_supported; ++ display_e2e_pipe_params_st *pipes; ++ ++ pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL); ++ if (!pipes) ++ return false; ++ + DC_FP_START(); +- voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate); ++ voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes); + DC_FP_END(); ++ ++ kfree(pipes); + return voltage_supported; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +index d1a25fe6c..5674c3450 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +@@ -953,9 +953,17 @@ static bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, + bool fast_validate) + { + bool voltage_supported; ++ display_e2e_pipe_params_st *pipes; ++ ++ pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL); ++ if (!pipes) ++ return false; ++ + DC_FP_START(); +- voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate); ++ voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes); + DC_FP_END(); ++ ++ kfree(pipes); + return voltage_supported; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +index 8a5a038fd..68970d6cf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +@@ -2018,7 +2018,7 @@ void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st + } + + static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context, +- bool fast_validate) ++ bool fast_validate, display_e2e_pipe_params_st *pipes) + { + bool out = false; + +@@ -2027,7 +2027,6 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co + int vlevel = 0; + int pipe_split_from[MAX_PIPES]; + int pipe_cnt = 0; +- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); +@@ -2062,16 +2061,14 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co + out = false; + + validate_out: +- kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; + } + +-bool dcn20_validate_bandwidth_fp(struct dc *dc, +- struct dc_state *context, +- bool fast_validate) ++bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, ++ bool fast_validate, display_e2e_pipe_params_st *pipes) + { + bool voltage_supported = false; + bool full_pstate_supported = false; +@@ -2090,11 +2087,11 @@ bool dcn20_validate_bandwidth_fp(struct dc *dc, + ASSERT(context != dc->current_state); + + if (fast_validate) { +- return dcn20_validate_bandwidth_internal(dc, context, true); ++ return dcn20_validate_bandwidth_internal(dc, context, true, pipes); + } + + // Best case, we support full UCLK switch latency +- voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false); ++ voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes); + full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; + + if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 || +@@ -2106,7 +2103,8 @@ bool dcn20_validate_bandwidth_fp(struct dc *dc, + // Fallback: Try to only support G6 temperature read latency + context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us; + +- voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false); ++ memset(pipes, 0, dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st)); ++ voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false, pipes); + dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support; + + if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) { +@@ -2311,9 +2309,8 @@ static void dcn21_calculate_wm(struct dc *dc, struct dc_state *context, + &context->bw_ctx.dml, pipes, pipe_cnt); + } + +-bool dcn21_validate_bandwidth_fp(struct dc *dc, +- struct dc_state *context, +- bool fast_validate) ++bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, ++ bool fast_validate, display_e2e_pipe_params_st *pipes) + { + bool out = false; + +@@ -2322,7 +2319,6 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, + int vlevel = 0; + int pipe_split_from[MAX_PIPES]; + int pipe_cnt = 0; +- display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); +@@ -2362,7 +2358,6 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, + out = false; + + validate_out: +- kfree(pipes); + + BW_VAL_TRACE_FINISH(); + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h +index c51badf7b..b6c34198d 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h ++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h +@@ -61,9 +61,8 @@ void dcn20_update_bounding_box(struct dc *dc, + unsigned int num_states); + void dcn20_patch_bounding_box(struct dc *dc, + struct _vcs_dpi_soc_bounding_box_st *bb); +-bool dcn20_validate_bandwidth_fp(struct dc *dc, +- struct dc_state *context, +- bool fast_validate); ++bool dcn20_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, ++ bool fast_validate, display_e2e_pipe_params_st *pipes); + void dcn20_fpu_set_wm_ranges(int i, + struct pp_smu_wm_range_sets *ranges, + struct _vcs_dpi_soc_bounding_box_st *loaded_bb); +@@ -77,9 +76,8 @@ int dcn21_populate_dml_pipes_from_context(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + bool fast_validate); +-bool dcn21_validate_bandwidth_fp(struct dc *dc, +- struct dc_state *context, +- bool fast_validate); ++bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, bool ++ fast_validate, display_e2e_pipe_params_st *pipes); + void dcn21_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + + void dcn21_clk_mgr_set_bw_params_wm_table(struct clk_bw_params *bw_params); +diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig +index ce397a879..98c3f5328 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 +diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c +index cfbfbfed3..da2becfbc 100644 +--- a/drivers/gpu/drm/i915/display/intel_crtc.c ++++ b/drivers/gpu/drm/i915/display/intel_crtc.c +@@ -562,7 +562,8 @@ void intel_pipe_update_start(struct intel_atomic_state *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; +@@ -587,11 +588,13 @@ void intel_pipe_update_start(struct intel_atomic_state *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); +@@ -624,7 +627,8 @@ void intel_pipe_update_start(struct intel_atomic_state *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) +@@ -728,7 +732,8 @@ void intel_pipe_update_end(struct intel_atomic_state *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; +diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c +index f5659ebd0..5b6d2f555 100644 +--- a/drivers/gpu/drm/i915/display/intel_vblank.c ++++ b/drivers/gpu/drm/i915/display/intel_vblank.c +@@ -294,7 +294,8 @@ static bool i915_get_crtc_scanoutpos(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) +@@ -358,7 +359,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); + +diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +index f2973cd1a..aa77f8601 100644 +--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c ++++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +@@ -315,7 +315,12 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b) + return; + + /* Kick the work once more to drain the signalers, and disarm the irq */ +- irq_work_queue(&b->irq_work); ++ irq_work_sync(&b->irq_work); ++ while (READ_ONCE(b->irq_armed) && !atomic_read(&b->active)) { ++ irq_work_queue(&b->irq_work); ++ cond_resched(); ++ irq_work_sync(&b->irq_work); ++ } + } + + void intel_breadcrumbs_free(struct kref *kref) +diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +index 2065be5a1..73d815fc5 100644 +--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c ++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +@@ -1303,7 +1303,7 @@ static void execlists_dequeue(struct 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 +@@ -1403,7 +1403,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; + } + } +@@ -1429,7 +1429,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 */ + } + +@@ -1591,7 +1591,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 +@@ -1617,13 +1617,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); +@@ -2478,7 +2471,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); + } + +diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c +index 13fb8e504..b51fb0c97 100644 +--- a/drivers/gpu/drm/i915/gt/intel_reset.c ++++ b/drivers/gpu/drm/i915/gt/intel_reset.c +@@ -164,13 +164,13 @@ static int i915_do_reset(struct intel_gt *gt, + /* Assert reset for at least 20 usec, and wait for acknowledgement. */ + pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE); + udelay(50); +- err = wait_for_atomic(i915_in_reset(pdev), 50); ++ err = _wait_for_atomic(i915_in_reset(pdev), 50, 0); + + /* Clear the reset request. */ + pci_write_config_byte(pdev, I915_GDRST, 0); + udelay(50); + if (!err) +- err = wait_for_atomic(!i915_in_reset(pdev), 50); ++ err = _wait_for_atomic(!i915_in_reset(pdev), 50, 0); + + return err; + } +@@ -190,7 +190,7 @@ static int g33_do_reset(struct intel_gt *gt, + struct pci_dev *pdev = to_pci_dev(gt->i915->drm.dev); + + pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE); +- return wait_for_atomic(g4x_reset_complete(pdev), 50); ++ return _wait_for_atomic(g4x_reset_complete(pdev), 50, 0); + } + + static int g4x_do_reset(struct intel_gt *gt, +@@ -207,7 +207,7 @@ static int g4x_do_reset(struct intel_gt *gt, + + pci_write_config_byte(pdev, I915_GDRST, + GRDOM_MEDIA | GRDOM_RESET_ENABLE); +- ret = wait_for_atomic(g4x_reset_complete(pdev), 50); ++ ret = _wait_for_atomic(g4x_reset_complete(pdev), 50, 0); + if (ret) { + GT_TRACE(gt, "Wait for media reset failed\n"); + goto out; +@@ -215,7 +215,7 @@ static int g4x_do_reset(struct intel_gt *gt, + + pci_write_config_byte(pdev, I915_GDRST, + GRDOM_RENDER | GRDOM_RESET_ENABLE); +- ret = wait_for_atomic(g4x_reset_complete(pdev), 50); ++ ret = _wait_for_atomic(g4x_reset_complete(pdev), 50, 0); + if (ret) { + GT_TRACE(gt, "Wait for render reset failed\n"); + goto out; +@@ -785,9 +785,7 @@ int __intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t engine_mask) + reset_mask = wa_14015076503_start(gt, engine_mask, !retry); + + GT_TRACE(gt, "engine_mask=%x\n", reset_mask); +- preempt_disable(); + ret = reset(gt, reset_mask, retry); +- preempt_enable(); + + wa_14015076503_end(gt, reset_mask); + } +diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h +index 8dc291ff0..5b8d084c9 100644 +--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h ++++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h +@@ -317,7 +317,7 @@ static inline int intel_guc_send_busy_loop(struct intel_guc *guc, + { + int err; + unsigned int sleep_period_ms = 1; +- bool not_atomic = !in_atomic() && !irqs_disabled(); ++ bool not_atomic = !in_atomic() && !irqs_disabled() && !rcu_preempt_depth(); + + /* + * FIXME: Have caller pass in if we are in an atomic context to avoid +diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c +index f59081066..014d02029 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); + + /* +diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h +index ce1cbee1b..3c51620d0 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 + #include + #include +@@ -322,7 +326,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) +diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h +index c61066498..48e19e55d 100644 +--- a/drivers/gpu/drm/i915/i915_utils.h ++++ b/drivers/gpu/drm/i915/i915_utils.h +@@ -288,7 +288,7 @@ wait_remaining_ms_from_jiffies(unsigned 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) +diff --git a/drivers/tty/serial/21285.c b/drivers/tty/serial/21285.c +index d756fcc88..4de0c975e 100644 +--- a/drivers/tty/serial/21285.c ++++ b/drivers/tty/serial/21285.c +@@ -185,14 +185,14 @@ static void serial21285_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + unsigned int h_lcr; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + h_lcr = *CSR_H_UBRLCR; + if (break_state) + h_lcr |= H_UBRLCR_BREAK; + else + h_lcr &= ~H_UBRLCR_BREAK; + *CSR_H_UBRLCR = h_lcr; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int serial21285_startup(struct uart_port *port) +@@ -272,7 +272,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, + if (port->fifosize) + h_lcr |= H_UBRLCR_FIFO; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * Update the per-port timeout. +@@ -309,7 +309,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, + *CSR_H_UBRLCR = h_lcr; + *CSR_UARTCON = 1; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *serial21285_type(struct uart_port *port) +diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c +index 4a9e71b2d..021949f25 100644 +--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c ++++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c +@@ -288,9 +288,9 @@ static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle) + struct uart_8250_port *up = up_to_u8250p(port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + __aspeed_vuart_set_throttle(up, throttle); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void aspeed_vuart_throttle(struct uart_port *port) +@@ -340,7 +340,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port) + if (iir & UART_IIR_NO_INT) + return 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + lsr = serial_port_in(port, UART_LSR); + +diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c +index 9afd5979c..db23b3a02 100644 +--- a/drivers/tty/serial/8250/8250_bcm7271.c ++++ b/drivers/tty/serial/8250/8250_bcm7271.c +@@ -567,7 +567,7 @@ static irqreturn_t brcmuart_isr(int irq, void *dev_id) + if (interrupts == 0) + return IRQ_NONE; + +- spin_lock_irqsave(&up->lock, flags); ++ uart_port_lock_irqsave(up, &flags); + + /* Clear all interrupts */ + udma_writel(priv, REGS_DMA_ISR, UDMA_INTR_CLEAR, interrupts); +@@ -581,7 +581,7 @@ static irqreturn_t brcmuart_isr(int irq, void *dev_id) + if ((rval | tval) == 0) + dev_warn(dev, "Spurious interrupt: 0x%x\n", interrupts); + +- spin_unlock_irqrestore(&up->lock, flags); ++ uart_port_unlock_irqrestore(up, flags); + return IRQ_HANDLED; + } + +@@ -608,10 +608,10 @@ static int brcmuart_startup(struct uart_port *port) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + up->ier &= ~UART_IER_RDI; + serial_port_out(port, UART_IER, up->ier); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + + priv->tx_running = false; + priv->dma.rx_dma = NULL; +@@ -629,7 +629,7 @@ static void brcmuart_shutdown(struct uart_port *port) + struct brcmuart_priv *priv = up->port.private_data; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + priv->shutdown = true; + if (priv->dma_enabled) { + stop_rx_dma(up); +@@ -645,7 +645,7 @@ static void brcmuart_shutdown(struct uart_port *port) + */ + up->dma = NULL; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + serial8250_do_shutdown(port); + } + +@@ -807,7 +807,7 @@ static int brcmuart_handle_irq(struct uart_port *p) + * interrupt but there is no data ready. + */ + if (((iir & UART_IIR_ID) == UART_IIR_RX_TIMEOUT) && !(priv->shutdown)) { +- spin_lock_irqsave(&p->lock, flags); ++ uart_port_lock_irqsave(p, &flags); + status = serial_port_in(p, UART_LSR); + if ((status & UART_LSR_DR) == 0) { + +@@ -832,7 +832,7 @@ static int brcmuart_handle_irq(struct uart_port *p) + + handled = 1; + } +- spin_unlock_irqrestore(&p->lock, flags); ++ uart_port_unlock_irqrestore(p, flags); + if (handled) + return 1; + } +@@ -850,7 +850,7 @@ static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t) + if (priv->shutdown) + return HRTIMER_NORESTART; + +- spin_lock_irqsave(&p->lock, flags); ++ uart_port_lock_irqsave(p, &flags); + status = serial_port_in(p, UART_LSR); + + /* +@@ -874,7 +874,7 @@ static enum hrtimer_restart brcmuart_hrtimer_func(struct hrtimer *t) + status |= UART_MCR_RTS; + serial_port_out(p, UART_MCR, status); + } +- spin_unlock_irqrestore(&p->lock, flags); ++ uart_port_unlock_irqrestore(p, flags); + return HRTIMER_NORESTART; + } + +@@ -1173,10 +1173,10 @@ static int __maybe_unused brcmuart_suspend(struct device *dev) + * This will prevent resume from enabling RTS before the + * baud rate has been restored. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + priv->saved_mctrl = port->mctrl; + port->mctrl &= ~TIOCM_RTS; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + serial8250_suspend_port(priv->line); + clk_disable_unprepare(priv->baud_mux_clk); +@@ -1215,10 +1215,10 @@ static int __maybe_unused brcmuart_resume(struct device *dev) + + if (priv->saved_mctrl & TIOCM_RTS) { + /* Restore RTS */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + port->mctrl |= TIOCM_RTS; + port->ops->set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + return 0; +diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c +index 3449f8790..30434718f 100644 +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c +@@ -259,7 +259,7 @@ static void serial8250_backup_timeout(struct timer_list *t) + unsigned int iir, ier = 0, lsr; + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * Must disable interrupts or else we risk racing with the interrupt +@@ -292,7 +292,7 @@ static void serial8250_backup_timeout(struct timer_list *t) + if (up->port.irq) + serial_out(up, UART_IER, ier); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + /* Standard timer interval plus 0.2s to keep the port running */ + mod_timer(&up->timer, +@@ -592,6 +592,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) + + #ifdef CONFIG_SERIAL_8250_CONSOLE + ++#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE + static void univ8250_console_write(struct console *co, const char *s, + unsigned int count) + { +@@ -599,6 +600,37 @@ static void univ8250_console_write(struct console *co, const char *s, + + serial8250_console_write(up, s, count); + } ++#else ++static bool univ8250_console_write_atomic(struct console *co, ++ struct nbcon_write_context *wctxt) ++{ ++ struct uart_8250_port *up = &serial8250_ports[co->index]; ++ ++ return serial8250_console_write_atomic(up, wctxt); ++} ++ ++static bool univ8250_console_write_thread(struct console *co, ++ struct nbcon_write_context *wctxt) ++{ ++ struct uart_8250_port *up = &serial8250_ports[co->index]; ++ ++ return serial8250_console_write_thread(up, wctxt); ++} ++ ++static void univ8250_console_driver_enter(struct console *con, unsigned long *flags) ++{ ++ struct uart_port *up = &serial8250_ports[con->index].port; ++ ++ __uart_port_lock_irqsave(up, flags); ++} ++ ++static void univ8250_console_driver_exit(struct console *con, unsigned long flags) ++{ ++ struct uart_port *up = &serial8250_ports[con->index].port; ++ ++ __uart_port_unlock_irqrestore(up, flags); ++} ++#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */ + + static int univ8250_console_setup(struct console *co, char *options) + { +@@ -698,12 +730,20 @@ static int univ8250_console_match(struct console *co, char *name, int idx, + + static struct console univ8250_console = { + .name = "ttyS", ++#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE + .write = univ8250_console_write, ++ .flags = CON_PRINTBUFFER | CON_ANYTIME, ++#else ++ .write_atomic = univ8250_console_write_atomic, ++ .write_thread = univ8250_console_write_thread, ++ .driver_enter = univ8250_console_driver_enter, ++ .driver_exit = univ8250_console_driver_exit, ++ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON, ++#endif + .device = uart_console_device, + .setup = univ8250_console_setup, + .exit = univ8250_console_exit, + .match = univ8250_console_match, +- .flags = CON_PRINTBUFFER | CON_ANYTIME, + .index = -1, + .data = &serial8250_reg, + }; +@@ -992,11 +1032,11 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work) + struct uart_port *port = &up->port; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + up->port.read_status_mask |= UART_LSR_DR; + serial_out(up, UART_IER, up->ier); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /** +@@ -1194,9 +1234,9 @@ void serial8250_unregister_port(int line) + if (uart->em485) { + unsigned long flags; + +- spin_lock_irqsave(&uart->port.lock, flags); ++ uart_port_lock_irqsave(&uart->port, &flags); + serial8250_em485_destroy(uart); +- spin_unlock_irqrestore(&uart->port.lock, flags); ++ uart_port_unlock_irqrestore(&uart->port, flags); + } + + uart_remove_one_port(&serial8250_reg, &uart->port); +diff --git a/drivers/tty/serial/8250/8250_dma.c b/drivers/tty/serial/8250/8250_dma.c +index 7fa665017..8b30ca8fd 100644 +--- a/drivers/tty/serial/8250/8250_dma.c ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -22,7 +22,7 @@ static void __dma_tx_complete(void *param) + dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, + UART_XMIT_SIZE, DMA_TO_DEVICE); + +- spin_lock_irqsave(&p->port.lock, flags); ++ uart_port_lock_irqsave(&p->port, &flags); + + dma->tx_running = 0; + +@@ -35,7 +35,7 @@ static void __dma_tx_complete(void *param) + if (ret || !dma->tx_running) + serial8250_set_THRI(p); + +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + } + + static void __dma_rx_complete(struct uart_8250_port *p) +@@ -70,7 +70,7 @@ static void dma_rx_complete(void *param) + struct uart_8250_dma *dma = p->dma; + unsigned long flags; + +- spin_lock_irqsave(&p->port.lock, flags); ++ uart_port_lock_irqsave(&p->port, &flags); + if (dma->rx_running) + __dma_rx_complete(p); + +@@ -80,7 +80,7 @@ static void dma_rx_complete(void *param) + */ + if (!dma->rx_running && (serial_lsr_in(p) & UART_LSR_DR)) + p->dma->rx_dma(p); +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + } + + int serial8250_tx_dma(struct uart_8250_port *p) +diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c +index 8aed33be2..5367bcc62 100644 +--- a/drivers/tty/serial/8250/8250_dw.c ++++ b/drivers/tty/serial/8250/8250_dw.c +@@ -290,20 +290,20 @@ static int dw8250_handle_irq(struct uart_port *p) + * so we limit the workaround only to non-DMA mode. + */ + if (!up->dma && rx_timeout) { +- spin_lock_irqsave(&p->lock, flags); ++ uart_port_lock_irqsave(p, &flags); + status = serial_lsr_in(up); + + if (!(status & (UART_LSR_DR | UART_LSR_BI))) + (void) p->serial_in(p, UART_RX); + +- spin_unlock_irqrestore(&p->lock, flags); ++ uart_port_unlock_irqrestore(p, flags); + } + + /* Manually stop the Rx DMA transfer when acting as flow controller */ + if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) { +- spin_lock_irqsave(&p->lock, flags); ++ uart_port_lock_irqsave(p, &flags); + status = serial_lsr_in(up); +- spin_unlock_irqrestore(&p->lock, flags); ++ uart_port_unlock_irqrestore(p, flags); + + if (status & (UART_LSR_DR | UART_LSR_BI)) { + dw8250_writel_ext(p, RZN1_UART_RDMACR, 0); +diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c +index 27430fdd9..17be6ad24 100644 +--- a/drivers/tty/serial/8250/8250_exar.c ++++ b/drivers/tty/serial/8250/8250_exar.c +@@ -243,9 +243,9 @@ static int xr17v35x_startup(struct uart_port *port) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + serial_port_out(port, UART_IER, 0); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + + return serial8250_do_startup(port); + } +diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c +index 6af4e1c12..f522eb502 100644 +--- a/drivers/tty/serial/8250/8250_fsl.c ++++ b/drivers/tty/serial/8250/8250_fsl.c +@@ -30,11 +30,11 @@ int fsl8250_handle_irq(struct uart_port *port) + unsigned int iir; + struct uart_8250_port *up = up_to_u8250p(port); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + iir = port->serial_in(port, UART_IIR); + if (iir & UART_IIR_NO_INT) { +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + return 0; + } + +@@ -54,7 +54,7 @@ int fsl8250_handle_irq(struct uart_port *port) + if (unlikely(up->lsr_saved_flags & UART_LSR_BI)) { + up->lsr_saved_flags &= ~UART_LSR_BI; + port->serial_in(port, UART_RX); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + return 1; + } + +diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c +index 28f9a2679..33699e86e 100644 +--- a/drivers/tty/serial/8250/8250_mtk.c ++++ b/drivers/tty/serial/8250/8250_mtk.c +@@ -102,7 +102,7 @@ static void mtk8250_dma_rx_complete(void *param) + if (data->rx_status == DMA_RX_SHUTDOWN) + return; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); + total = dma->rx_size - state.residue; +@@ -128,7 +128,7 @@ static void mtk8250_dma_rx_complete(void *param) + + mtk8250_rx_dma(up); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static void mtk8250_rx_dma(struct uart_8250_port *up) +@@ -372,7 +372,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * Update the per-port timeout. +@@ -420,7 +420,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, + if (uart_console(port)) + up->port.cons->cflag = termios->c_cflag; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + /* Don't rewrite B0 */ + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); +diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c +index 8f472a208..78fc1f17d 100644 +--- a/drivers/tty/serial/8250/8250_omap.c ++++ b/drivers/tty/serial/8250/8250_omap.c +@@ -405,7 +405,7 @@ static void omap_8250_set_termios(struct uart_port *port, + * interrupts disabled. + */ + pm_runtime_get_sync(port->dev); +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + + /* + * Update the per-port timeout. +@@ -508,7 +508,7 @@ static void omap_8250_set_termios(struct uart_port *port, + } + omap8250_restore_regs(up); + +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); + +@@ -533,7 +533,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, + pm_runtime_get_sync(port->dev); + + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); + efr = serial_in(up, UART_EFR); +@@ -545,7 +545,7 @@ static void omap_8250_pm(struct uart_port *port, unsigned int state, + serial_out(up, UART_EFR, efr); + serial_out(up, UART_LCR, 0); + +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); +@@ -676,7 +676,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) + unsigned long delay; + + /* Synchronize UART_IER access against the console. */ +- spin_lock(&port->lock); ++ uart_port_lock(port); + up->ier = port->serial_in(port, UART_IER); + if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) { + port->ops->stop_rx(port); +@@ -686,7 +686,7 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) + */ + cancel_delayed_work(&up->overrun_backoff); + } +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + delay = msecs_to_jiffies(up->overrun_backoff_time_ms); + schedule_delayed_work(&up->overrun_backoff, delay); +@@ -733,10 +733,10 @@ static int omap_8250_startup(struct uart_port *port) + } + + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + up->ier = UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + + #ifdef CONFIG_PM + up->capabilities |= UART_CAP_RPM; +@@ -749,9 +749,9 @@ static int omap_8250_startup(struct uart_port *port) + serial_out(up, UART_OMAP_WER, priv->wer); + + if (up->dma && !(priv->habit & UART_HAS_EFR2)) { +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + up->dma->rx_dma(up); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } + + enable_irq(up->port.irq); +@@ -777,10 +777,10 @@ static void omap_8250_shutdown(struct uart_port *port) + serial_out(up, UART_OMAP_EFR2, 0x0); + + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + up->ier = 0; + serial_out(up, UART_IER, 0); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + disable_irq_nosync(up->port.irq); + dev_pm_clear_wake_irq(port->dev); + +@@ -805,10 +805,10 @@ static void omap_8250_throttle(struct uart_port *port) + + pm_runtime_get_sync(port->dev); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + port->ops->stop_rx(port); + priv->throttled = true; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); +@@ -823,14 +823,14 @@ static void omap_8250_unthrottle(struct uart_port *port) + pm_runtime_get_sync(port->dev); + + /* Synchronize UART_IER access against the console. */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + priv->throttled = false; + if (up->dma) + up->dma->rx_dma(up); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + port->read_status_mask |= UART_LSR_DR; + serial_out(up, UART_IER, up->ier); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + pm_runtime_mark_last_busy(port->dev); + pm_runtime_put_autosuspend(port->dev); +@@ -974,7 +974,7 @@ static void __dma_rx_complete(void *param) + unsigned long flags; + + /* Synchronize UART_IER access against the console. */ +- spin_lock_irqsave(&p->port.lock, flags); ++ uart_port_lock_irqsave(&p->port, &flags); + + /* + * If the tx status is not DMA_COMPLETE, then this is a delayed +@@ -983,7 +983,7 @@ static void __dma_rx_complete(void *param) + */ + if (dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state) != + DMA_COMPLETE) { +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + return; + } + __dma_rx_do_complete(p); +@@ -994,7 +994,7 @@ static void __dma_rx_complete(void *param) + omap_8250_rx_dma(p); + } + +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + } + + static void omap_8250_rx_dma_flush(struct uart_8250_port *p) +@@ -1099,7 +1099,7 @@ static void omap_8250_dma_tx_complete(void *param) + dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr, + UART_XMIT_SIZE, DMA_TO_DEVICE); + +- spin_lock_irqsave(&p->port.lock, flags); ++ uart_port_lock_irqsave(&p->port, &flags); + + dma->tx_running = 0; + +@@ -1128,7 +1128,7 @@ static void omap_8250_dma_tx_complete(void *param) + serial8250_set_THRI(p); + } + +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + } + + static int omap_8250_tx_dma(struct uart_8250_port *p) +@@ -1294,7 +1294,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port) + return IRQ_HANDLED; + } + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + status = serial_port_in(port, UART_LSR); + +@@ -1774,15 +1774,15 @@ static int omap8250_runtime_resume(struct device *dev) + up = serial8250_get_port(priv->line); + + if (up && omap8250_lost_context(up)) { +- spin_lock_irq(&up->port.lock); ++ uart_port_lock_irq(&up->port); + omap8250_restore_regs(up); +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + } + + if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) { +- spin_lock_irq(&up->port.lock); ++ uart_port_lock_irq(&up->port); + omap_8250_rx_dma(up); +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + } + + priv->latency = priv->calc_latency; +diff --git a/drivers/tty/serial/8250/8250_pci1xxxx.c b/drivers/tty/serial/8250/8250_pci1xxxx.c +index a3b25779d..53e238c8c 100644 +--- a/drivers/tty/serial/8250/8250_pci1xxxx.c ++++ b/drivers/tty/serial/8250/8250_pci1xxxx.c +@@ -225,10 +225,10 @@ static bool pci1xxxx_port_suspend(int line) + if (port->suspended == 0 && port->dev) { + wakeup_mask = readb(up->port.membase + UART_WAKE_MASK_REG); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + port->mctrl &= ~TIOCM_OUT2; + port->ops->set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + ret = (wakeup_mask & UART_WAKE_SRCS) != UART_WAKE_SRCS; + } +@@ -251,10 +251,10 @@ static void pci1xxxx_port_resume(int line) + writeb(UART_WAKE_SRCS, port->membase + UART_WAKE_REG); + + if (port->suspended == 0) { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + port->mctrl |= TIOCM_OUT2; + port->ops->set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + mutex_unlock(&tport->mutex); + } +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index a17803da8..2d4e775cd 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -557,6 +557,11 @@ static int serial8250_em485_init(struct uart_8250_port *p) + if (!p->em485) + return -ENOMEM; + ++#ifndef CONFIG_SERIAL_8250_LEGACY_CONSOLE ++ if (uart_console(&p->port)) ++ dev_warn(p->port.dev, "no atomic printing for rs485 consoles\n"); ++#endif ++ + hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC, +@@ -689,7 +694,7 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) + + if (p->capabilities & UART_CAP_SLEEP) { + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&p->port.lock); ++ uart_port_lock_irq(&p->port); + if (p->capabilities & UART_CAP_EFR) { + lcr = serial_in(p, UART_LCR); + efr = serial_in(p, UART_EFR); +@@ -703,13 +708,17 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) + serial_out(p, UART_EFR, efr); + serial_out(p, UART_LCR, lcr); + } +- spin_unlock_irq(&p->port.lock); ++ uart_port_unlock_irq(&p->port); + } + + serial8250_rpm_put(p); + } + +-static void serial8250_clear_IER(struct uart_8250_port *up) ++/* ++ * Only to be used by write_atomic() and the legacy write(), which do not ++ * require port lock. ++ */ ++static void __serial8250_clear_IER(struct uart_8250_port *up) + { + if (up->capabilities & UART_CAP_UUE) + serial_out(up, UART_IER, UART_IER_UUE); +@@ -717,6 +726,14 @@ static void serial8250_clear_IER(struct uart_8250_port *up) + serial_out(up, UART_IER, 0); + } + ++static inline void serial8250_clear_IER(struct uart_8250_port *up) ++{ ++ /* Port locked to synchronize UART_IER access against the console. */ ++ lockdep_assert_held_once(&up->port.lock); ++ ++ __serial8250_clear_IER(up); ++} ++ + #ifdef CONFIG_SERIAL_8250_RSA + /* + * Attempts to turn on the RSA FIFO. Returns zero on failure. +@@ -746,9 +763,9 @@ static void enable_rsa(struct uart_8250_port *up) + { + if (up->port.type == PORT_RSA) { + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { +- spin_lock_irq(&up->port.lock); ++ uart_port_lock_irq(&up->port); + __enable_rsa(up); +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + } + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) + serial_out(up, UART_RSA_FRR, 0); +@@ -768,7 +785,7 @@ static void disable_rsa(struct uart_8250_port *up) + + if (up->port.type == PORT_RSA && + up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { +- spin_lock_irq(&up->port.lock); ++ uart_port_lock_irq(&up->port); + + mode = serial_in(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); +@@ -781,7 +798,7 @@ static void disable_rsa(struct uart_8250_port *up) + + if (result) + up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + } + } + #endif /* CONFIG_SERIAL_8250_RSA */ +@@ -1172,7 +1189,7 @@ static void autoconfig(struct uart_8250_port *up) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + up->capabilities = 0; + up->bugs = 0; +@@ -1211,7 +1228,7 @@ static void autoconfig(struct uart_8250_port *up) + /* + * We failed; there's nothing here + */ +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + DEBUG_AUTOCONF("IER test failed (%02x, %02x) ", + scratch2, scratch3); + goto out; +@@ -1235,7 +1252,7 @@ static void autoconfig(struct uart_8250_port *up) + status1 = serial_in(up, UART_MSR) & UART_MSR_STATUS_BITS; + serial8250_out_MCR(up, save_mcr); + if (status1 != (UART_MSR_DCD | UART_MSR_CTS)) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + DEBUG_AUTOCONF("LOOP test failed (%02x) ", + status1); + goto out; +@@ -1304,7 +1321,7 @@ static void autoconfig(struct uart_8250_port *up) + serial8250_clear_IER(up); + + out_unlock: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* + * Check if the device is a Fintek F81216A +@@ -1341,9 +1358,9 @@ static void autoconfig_irq(struct uart_8250_port *up) + probe_irq_off(probe_irq_on()); + save_mcr = serial8250_in_MCR(up); + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + save_ier = serial_in(up, UART_IER); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + serial8250_out_MCR(up, UART_MCR_OUT1 | UART_MCR_OUT2); + + irqs = probe_irq_on(); +@@ -1356,9 +1373,9 @@ static void autoconfig_irq(struct uart_8250_port *up) + UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); + } + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + serial_out(up, UART_IER, UART_IER_ALL_INTR); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + serial_in(up, UART_LSR); + serial_in(up, UART_RX); + serial_in(up, UART_IIR); +@@ -1369,9 +1386,9 @@ static void autoconfig_irq(struct uart_8250_port *up) + + serial8250_out_MCR(up, save_mcr); + /* Synchronize UART_IER access against the console. */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + serial_out(up, UART_IER, save_ier); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + + if (port->flags & UPF_FOURPORT) + outb_p(save_ICP, ICP); +@@ -1436,13 +1453,13 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t) + unsigned long flags; + + serial8250_rpm_get(p); +- spin_lock_irqsave(&p->port.lock, flags); ++ uart_port_lock_irqsave(&p->port, &flags); + if (em485->active_timer == &em485->stop_tx_timer) { + p->rs485_stop_tx(p); + em485->active_timer = NULL; + em485->tx_stopped = true; + } +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + serial8250_rpm_put(p); + + return HRTIMER_NORESTART; +@@ -1624,12 +1641,12 @@ static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t) + struct uart_8250_port *p = em485->port; + unsigned long flags; + +- spin_lock_irqsave(&p->port.lock, flags); ++ uart_port_lock_irqsave(&p->port, &flags); + if (em485->active_timer == &em485->start_tx_timer) { + __start_tx(&p->port); + em485->active_timer = NULL; + } +- spin_unlock_irqrestore(&p->port.lock, flags); ++ uart_port_unlock_irqrestore(&p->port, flags); + + return HRTIMER_NORESTART; + } +@@ -1912,7 +1929,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) + if (iir & UART_IIR_NO_INT) + return 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + status = serial_lsr_in(up); + +@@ -1982,9 +1999,9 @@ static int serial8250_tx_threshold_handle_irq(struct uart_port *port) + if ((iir & UART_IIR_ID) == UART_IIR_THRI) { + struct uart_8250_port *up = up_to_u8250p(port); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + serial8250_tx_chars(up); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + iir = serial_port_in(port, UART_IIR); +@@ -1999,10 +2016,10 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) + + serial8250_rpm_get(up); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (!serial8250_tx_dma_running(up) && uart_lsr_tx_empty(serial_lsr_in(up))) + result = TIOCSER_TEMT; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + serial8250_rpm_put(up); + +@@ -2064,13 +2081,13 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + + serial8250_rpm_get(up); +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_port_out(port, UART_LCR, up->lcr); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + serial8250_rpm_put(up); + } + +@@ -2205,7 +2222,7 @@ int serial8250_do_startup(struct uart_port *port) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + up->acr = 0; + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); +@@ -2215,7 +2232,7 @@ int serial8250_do_startup(struct uart_port *port) + serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B); + serial_port_out(port, UART_EFR, UART_EFR_ECB); + serial_port_out(port, UART_LCR, 0); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + if (port->type == PORT_DA830) { +@@ -2224,10 +2241,10 @@ int serial8250_do_startup(struct uart_port *port) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + serial_port_out(port, UART_IER, 0); + serial_port_out(port, UART_DA830_PWREMU_MGMT, 0); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + mdelay(10); + + /* Enable Tx, Rx and free run mode */ +@@ -2341,7 +2358,7 @@ int serial8250_do_startup(struct uart_port *port) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + wait_for_xmitr(up, UART_LSR_THRE); + serial_port_out_sync(port, UART_IER, UART_IER_THRI); +@@ -2353,7 +2370,7 @@ int serial8250_do_startup(struct uart_port *port) + iir = serial_port_in(port, UART_IIR); + serial_port_out(port, UART_IER, 0); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (port->irqflags & IRQF_SHARED) + enable_irq(port->irq); +@@ -2376,7 +2393,7 @@ int serial8250_do_startup(struct uart_port *port) + */ + serial_port_out(port, UART_LCR, UART_LCR_WLEN8); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (up->port.flags & UPF_FOURPORT) { + if (!up->port.irq) + up->port.mctrl |= TIOCM_OUT1; +@@ -2422,7 +2439,7 @@ int serial8250_do_startup(struct uart_port *port) + } + + dont_test_tx_en: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* + * Clear the interrupt registers again for luck, and clear the +@@ -2493,17 +2510,17 @@ void serial8250_do_shutdown(struct uart_port *port) + * + * Synchronize UART_IER access against the console. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + up->ier = 0; + serial_port_out(port, UART_IER, 0); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + synchronize_irq(port->irq); + + if (up->dma) + serial8250_release_dma(up); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (port->flags & UPF_FOURPORT) { + /* reset interrupts on the AST Fourport board */ + inb((port->iobase & 0xfe0) | 0x1f); +@@ -2512,7 +2529,7 @@ void serial8250_do_shutdown(struct uart_port *port) + port->mctrl &= ~TIOCM_OUT2; + + serial8250_set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* + * Disable break condition and FIFOs +@@ -2748,14 +2765,14 @@ void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk) + quot = serial8250_get_divisor(port, baud, &frac); + + serial8250_rpm_get(up); +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_update_timeout(port, termios->c_cflag, baud); + + serial8250_set_divisor(port, baud, quot, frac); + serial_port_out(port, UART_LCR, up->lcr); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + serial8250_rpm_put(up); + + out_unlock: +@@ -2792,7 +2809,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + * Synchronize UART_IER access against the console. + */ + serial8250_rpm_get(up); +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + up->lcr = cval; /* Save computed LCR */ + +@@ -2895,7 +2912,7 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, + serial_port_out(port, UART_FCR, up->fcr); /* set fcr */ + } + serial8250_set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + serial8250_rpm_put(up); + + /* Don't rewrite B0 */ +@@ -2918,15 +2935,15 @@ void serial8250_do_set_ldisc(struct uart_port *port, struct ktermios *termios) + { + if (termios->c_line == N_PPS) { + port->flags |= UPF_HARDPPS_CD; +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + serial8250_enable_ms(port); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } else { + port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + serial8250_disable_ms(port); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } + } + } +@@ -3322,6 +3339,11 @@ static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) + + wait_for_xmitr(up, UART_LSR_THRE); + serial_port_out(port, UART_TX, ch); ++ ++ if (ch == '\n') ++ up->console_newline_needed = false; ++ else ++ up->console_newline_needed = true; + } + + /* +@@ -3350,6 +3372,7 @@ static void serial8250_console_restore(struct uart_8250_port *up) + serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); + } + ++#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE + /* + * Print a string to the serial port using the device FIFO + * +@@ -3400,15 +3423,15 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, + touch_nmi_watchdog(); + + if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * First save the IER then disable the interrupts + */ + ier = serial_port_in(port, UART_IER); +- serial8250_clear_IER(up); ++ __serial8250_clear_IER(up); + + /* check scratch reg to see if port powered off during system sleep */ + if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { +@@ -3472,8 +3495,137 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, + serial8250_modem_status(up); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } ++#else ++bool serial8250_console_write_thread(struct uart_8250_port *up, ++ struct nbcon_write_context *wctxt) ++{ ++ struct uart_8250_em485 *em485 = up->em485; ++ struct uart_port *port = &up->port; ++ bool done = false; ++ unsigned int ier; ++ ++ touch_nmi_watchdog(); ++ ++ if (!nbcon_enter_unsafe(wctxt)) ++ return false; ++ ++ /* First save IER then disable the interrupts. */ ++ ier = serial_port_in(port, UART_IER); ++ serial8250_clear_IER(up); ++ ++ /* Check scratch reg if port powered off during system sleep. */ ++ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { ++ serial8250_console_restore(up); ++ up->canary = 0; ++ } ++ ++ if (em485) { ++ if (em485->tx_stopped) ++ up->rs485_start_tx(up); ++ mdelay(port->rs485.delay_rts_before_send); ++ } ++ ++ if (nbcon_exit_unsafe(wctxt)) { ++ int len = READ_ONCE(wctxt->len); ++ int i; ++ ++ /* ++ * Write out the message. Toggle unsafe for each byte in order ++ * to give another (higher priority) context the opportunity ++ * for a friendly takeover. If such a takeover occurs, this ++ * context must reacquire ownership in order to perform final ++ * actions (such as re-enabling the interrupts). ++ * ++ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid ++ * after a reacquire so writing the message must be ++ * aborted. ++ */ ++ for (i = 0; i < len; i++) { ++ if (!nbcon_enter_unsafe(wctxt)) { ++ nbcon_reacquire(wctxt); ++ break; ++ } ++ ++ uart_console_write(port, wctxt->outbuf + i, 1, serial8250_console_putchar); ++ ++ if (!nbcon_exit_unsafe(wctxt)) { ++ nbcon_reacquire(wctxt); ++ break; ++ } ++ } ++ done = (i == len); ++ } else { ++ nbcon_reacquire(wctxt); ++ } ++ ++ while (!nbcon_enter_unsafe(wctxt)) ++ nbcon_reacquire(wctxt); ++ ++ /* Finally, wait for transmitter to become empty and restore IER. */ ++ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); ++ if (em485) { ++ mdelay(port->rs485.delay_rts_after_send); ++ if (em485->tx_stopped) ++ up->rs485_stop_tx(up); ++ } ++ serial_port_out(port, UART_IER, ier); ++ ++ /* ++ * The receive handling will happen properly because the receive ready ++ * bit will still be set; it is not cleared on read. However, modem ++ * control will not, we must call it if we have saved something in the ++ * saved flags while processing with interrupts off. ++ */ ++ if (up->msr_saved_flags) ++ serial8250_modem_status(up); ++ ++ /* Success if no handover/takeover and message fully printed. */ ++ return (nbcon_exit_unsafe(wctxt) && done); ++} ++ ++bool serial8250_console_write_atomic(struct uart_8250_port *up, ++ struct nbcon_write_context *wctxt) ++{ ++ struct uart_port *port = &up->port; ++ unsigned int ier; ++ ++ /* Atomic console not supported for rs485 mode. */ ++ if (up->em485) ++ return false; ++ ++ touch_nmi_watchdog(); ++ ++ if (!nbcon_enter_unsafe(wctxt)) ++ return false; ++ ++ /* ++ * First save IER then disable the interrupts. The special variant to ++ * clear IER is used because atomic printing may occur without holding ++ * the port lock. ++ */ ++ ier = serial_port_in(port, UART_IER); ++ __serial8250_clear_IER(up); ++ ++ /* Check scratch reg if port powered off during system sleep. */ ++ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { ++ serial8250_console_restore(up); ++ up->canary = 0; ++ } ++ ++ if (up->console_newline_needed) ++ uart_console_write(port, "\n", 1, serial8250_console_putchar); ++ uart_console_write(port, wctxt->outbuf, wctxt->len, serial8250_console_putchar); ++ ++ /* Finally, wait for transmitter to become empty and restore IER. */ ++ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); ++ serial_port_out(port, UART_IER, ier); ++ ++ /* Success if no handover/takeover. */ ++ return nbcon_exit_unsafe(wctxt); ++} ++#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */ + + static unsigned int probe_baud(struct uart_port *port) + { +@@ -3492,6 +3644,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'; +@@ -3501,6 +3654,8 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe) + if (!port->iobase && !port->membase) + return -ENODEV; + ++ up->console_newline_needed = false; ++ + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else if (probe) +diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c +index 5fab4c978..7090b251d 100644 +--- a/drivers/tty/serial/altera_jtaguart.c ++++ b/drivers/tty/serial/altera_jtaguart.c +@@ -147,14 +147,14 @@ static irqreturn_t altera_jtaguart_interrupt(int irq, void *data) + isr = (readl(port->membase + ALTERA_JTAGUART_CONTROL_REG) >> + ALTERA_JTAGUART_CONTROL_RI_OFF) & port->read_status_mask; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + if (isr & ALTERA_JTAGUART_CONTROL_RE_MSK) + altera_jtaguart_rx_chars(port); + if (isr & ALTERA_JTAGUART_CONTROL_WE_MSK) + altera_jtaguart_tx_chars(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_RETVAL(isr); + } +@@ -180,14 +180,14 @@ static int altera_jtaguart_startup(struct uart_port *port) + return ret; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Enable RX interrupts now */ + port->read_status_mask = ALTERA_JTAGUART_CONTROL_RE_MSK; + writel(port->read_status_mask, + port->membase + ALTERA_JTAGUART_CONTROL_REG); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -196,14 +196,14 @@ static void altera_jtaguart_shutdown(struct uart_port *port) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable all interrupts now */ + port->read_status_mask = 0; + writel(port->read_status_mask, + port->membase + ALTERA_JTAGUART_CONTROL_REG); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + free_irq(port->irq, port); + } +@@ -264,33 +264,33 @@ static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c + unsigned long flags; + u32 status; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + while (!altera_jtaguart_tx_space(port, &status)) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) { + return; /* no connection activity */ + } + + cpu_relax(); +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + } + writel(c, port->membase + ALTERA_JTAGUART_DATA_REG); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + #else + static void altera_jtaguart_console_putc(struct uart_port *port, unsigned char c) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + while (!altera_jtaguart_tx_space(port, NULL)) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + cpu_relax(); +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + } + writel(c, port->membase + ALTERA_JTAGUART_DATA_REG); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + #endif + +diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c +index a9c419421..77835ac68 100644 +--- a/drivers/tty/serial/altera_uart.c ++++ b/drivers/tty/serial/altera_uart.c +@@ -164,13 +164,13 @@ static void altera_uart_break_ctl(struct uart_port *port, int break_state) + struct altera_uart *pp = container_of(port, struct altera_uart, port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (break_state == -1) + pp->imr |= ALTERA_UART_CONTROL_TRBK_MSK; + else + pp->imr &= ~ALTERA_UART_CONTROL_TRBK_MSK; + altera_uart_update_ctrl_reg(pp); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void altera_uart_set_termios(struct uart_port *port, +@@ -187,10 +187,10 @@ static void altera_uart_set_termios(struct uart_port *port, + tty_termios_copy_hw(termios, old); + tty_termios_encode_baud_rate(termios, baud, baud); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + uart_update_timeout(port, termios->c_cflag, baud); + altera_uart_writel(port, baudclk, ALTERA_UART_DIVISOR_REG); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* + * FIXME: port->read_status_mask and port->ignore_status_mask +@@ -264,12 +264,12 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) + + isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (isr & ALTERA_UART_STATUS_RRDY_MSK) + altera_uart_rx_chars(port); + if (isr & ALTERA_UART_STATUS_TRDY_MSK) + altera_uart_tx_chars(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_RETVAL(isr); + } +@@ -313,13 +313,13 @@ static int altera_uart_startup(struct uart_port *port) + } + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Enable RX interrupts now */ + pp->imr = ALTERA_UART_CONTROL_RRDY_MSK; + altera_uart_update_ctrl_reg(pp); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -329,13 +329,13 @@ static void altera_uart_shutdown(struct uart_port *port) + struct altera_uart *pp = container_of(port, struct altera_uart, port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable all interrupts now */ + pp->imr = 0; + altera_uart_update_ctrl_reg(pp); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (port->irq) + free_irq(port->irq, port); +diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c +index b5a7404cb..eabbf8afc 100644 +--- a/drivers/tty/serial/amba-pl010.c ++++ b/drivers/tty/serial/amba-pl010.c +@@ -207,7 +207,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id) + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; + int handled = 0; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + status = readb(port->membase + UART010_IIR); + if (status) { +@@ -228,7 +228,7 @@ static irqreturn_t pl010_int(int irq, void *dev_id) + handled = 1; + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_RETVAL(handled); + } +@@ -270,14 +270,14 @@ static void pl010_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + unsigned int lcr_h; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + lcr_h = readb(port->membase + UART010_LCRH); + if (break_state == -1) + lcr_h |= UART01x_LCRH_BRK; + else + lcr_h &= ~UART01x_LCRH_BRK; + writel(lcr_h, port->membase + UART010_LCRH); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int pl010_startup(struct uart_port *port) +@@ -385,7 +385,7 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, + if (port->fifosize > 1) + lcr_h |= UART01x_LCRH_FEN; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * Update the per-port timeout. +@@ -438,22 +438,22 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, + writel(lcr_h, port->membase + UART010_LCRH); + writel(old_cr, port->membase + UART010_CR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void pl010_set_ldisc(struct uart_port *port, struct ktermios *termios) + { + if (termios->c_line == N_PPS) { + port->flags |= UPF_HARDPPS_CD; +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + pl010_enable_ms(port); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } else { + port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + pl010_disable_ms(port); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } + } + } +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 362bbcdec..9cd660edb 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -347,9 +347,9 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap) + flag = TTY_FRAME; + } + +- spin_unlock(&uap->port.lock); ++ uart_port_unlock(&uap->port); + sysrq = uart_handle_sysrq_char(&uap->port, ch & 255); +- spin_lock(&uap->port.lock); ++ uart_port_lock(&uap->port); + + if (!sysrq) + uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag); +@@ -544,7 +544,7 @@ static void pl011_dma_tx_callback(void *data) + unsigned long flags; + u16 dmacr; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + if (uap->dmatx.queued) + dma_unmap_single(dmatx->chan->device->dev, dmatx->dma, + dmatx->len, DMA_TO_DEVICE); +@@ -565,7 +565,7 @@ static void pl011_dma_tx_callback(void *data) + if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) || + uart_circ_empty(&uap->port.state->xmit)) { + uap->dmatx.queued = false; +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + return; + } + +@@ -576,7 +576,7 @@ static void pl011_dma_tx_callback(void *data) + */ + pl011_start_tx_pio(uap); + +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + } + + /* +@@ -1004,7 +1004,7 @@ static void pl011_dma_rx_callback(void *data) + * routine to flush out the secondary DMA buffer while + * we immediately trigger the next DMA job. + */ +- spin_lock_irq(&uap->port.lock); ++ uart_port_lock_irq(&uap->port); + /* + * Rx data can be taken by the UART interrupts during + * the DMA irq handler. So we check the residue here. +@@ -1020,7 +1020,7 @@ static void pl011_dma_rx_callback(void *data) + ret = pl011_dma_rx_trigger_dma(uap); + + pl011_dma_rx_chars(uap, pending, lastbuf, false); +- spin_unlock_irq(&uap->port.lock); ++ uart_port_unlock_irq(&uap->port); + /* + * Do this check after we picked the DMA chars so we don't + * get some IRQ immediately from RX. +@@ -1086,11 +1086,11 @@ static void pl011_dma_rx_poll(struct timer_list *t) + if (jiffies_to_msecs(jiffies - dmarx->last_jiffies) + > uap->dmarx.poll_timeout) { + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + pl011_dma_rx_stop(uap); + uap->im |= UART011_RXIM; + pl011_write(uap->im, uap, REG_IMSC); +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + + uap->dmarx.running = false; + dmaengine_terminate_all(rxchan); +@@ -1186,10 +1186,10 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) + while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy) + cpu_relax(); + +- spin_lock_irq(&uap->port.lock); ++ uart_port_lock_irq(&uap->port); + uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); + pl011_write(uap->dmacr, uap, REG_DMACR); +- spin_unlock_irq(&uap->port.lock); ++ uart_port_unlock_irq(&uap->port); + + if (uap->using_tx_dma) { + /* In theory, this should already be done by pl011_dma_flush_buffer */ +@@ -1400,9 +1400,9 @@ static void pl011_throttle_rx(struct uart_port *port) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + pl011_stop_rx(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void pl011_enable_ms(struct uart_port *port) +@@ -1420,7 +1420,7 @@ __acquires(&uap->port.lock) + { + pl011_fifo_to_tty(uap); + +- spin_unlock(&uap->port.lock); ++ uart_port_unlock(&uap->port); + tty_flip_buffer_push(&uap->port.state->port); + /* + * If we were temporarily out of DMA mode for a while, +@@ -1445,7 +1445,7 @@ __acquires(&uap->port.lock) + #endif + } + } +- spin_lock(&uap->port.lock); ++ uart_port_lock(&uap->port); + } + + static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c, +@@ -1551,7 +1551,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) + unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; + int handled = 0; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + status = pl011_read(uap, REG_RIS) & uap->im; + if (status) { + do { +@@ -1581,7 +1581,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id) + handled = 1; + } + +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + + return IRQ_RETVAL(handled); + } +@@ -1653,14 +1653,14 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + unsigned int lcr_h; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + lcr_h = pl011_read(uap, REG_LCRH_TX); + if (break_state == -1) + lcr_h |= UART01x_LCRH_BRK; + else + lcr_h &= ~UART01x_LCRH_BRK; + pl011_write(lcr_h, uap, REG_LCRH_TX); +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + } + + #ifdef CONFIG_CONSOLE_POLL +@@ -1799,7 +1799,7 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) + unsigned long flags; + unsigned int i; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + + /* Clear out any spuriously appearing RX interrupts */ + pl011_write(UART011_RTIS | UART011_RXIS, uap, REG_ICR); +@@ -1821,7 +1821,7 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) + if (!pl011_dma_rx_running(uap)) + uap->im |= UART011_RXIM; + pl011_write(uap->im, uap, REG_IMSC); +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + } + + static void pl011_unthrottle_rx(struct uart_port *port) +@@ -1829,7 +1829,7 @@ static void pl011_unthrottle_rx(struct uart_port *port) + struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); + unsigned long flags; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + + uap->im = UART011_RTIM; + if (!pl011_dma_rx_running(uap)) +@@ -1837,7 +1837,7 @@ static void pl011_unthrottle_rx(struct uart_port *port) + + pl011_write(uap->im, uap, REG_IMSC); + +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + } + + static int pl011_startup(struct uart_port *port) +@@ -1857,7 +1857,7 @@ static int pl011_startup(struct uart_port *port) + + pl011_write(uap->vendor->ifls, uap, REG_IFLS); + +- spin_lock_irq(&uap->port.lock); ++ uart_port_lock_irq(&uap->port); + + cr = pl011_read(uap, REG_CR); + cr &= UART011_CR_RTS | UART011_CR_DTR; +@@ -1868,7 +1868,7 @@ static int pl011_startup(struct uart_port *port) + + pl011_write(cr, uap, REG_CR); + +- spin_unlock_irq(&uap->port.lock); ++ uart_port_unlock_irq(&uap->port); + + /* + * initialise the old status of the modem signals +@@ -1929,12 +1929,12 @@ static void pl011_disable_uart(struct uart_amba_port *uap) + unsigned int cr; + + uap->port.status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS); +- spin_lock_irq(&uap->port.lock); ++ uart_port_lock_irq(&uap->port); + cr = pl011_read(uap, REG_CR); + cr &= UART011_CR_RTS | UART011_CR_DTR; + cr |= UART01x_CR_UARTEN | UART011_CR_TXE; + pl011_write(cr, uap, REG_CR); +- spin_unlock_irq(&uap->port.lock); ++ uart_port_unlock_irq(&uap->port); + + /* + * disable break condition and fifos +@@ -1946,14 +1946,14 @@ static void pl011_disable_uart(struct uart_amba_port *uap) + + static void pl011_disable_interrupts(struct uart_amba_port *uap) + { +- spin_lock_irq(&uap->port.lock); ++ uart_port_lock_irq(&uap->port); + + /* mask all interrupts and clear all pending ones */ + uap->im = 0; + pl011_write(uap->im, uap, REG_IMSC); + pl011_write(0xffff, uap, REG_ICR); + +- spin_unlock_irq(&uap->port.lock); ++ uart_port_unlock_irq(&uap->port); + } + + static void pl011_shutdown(struct uart_port *port) +@@ -2098,7 +2098,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, + + bits = tty_get_frame_size(termios->c_cflag); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * Update the per-port timeout. +@@ -2172,7 +2172,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, + old_cr |= UART011_CR_RXE; + pl011_write(old_cr, uap, REG_CR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void +@@ -2190,10 +2190,10 @@ sbsa_uart_set_termios(struct uart_port *port, struct ktermios *termios, + termios->c_cflag &= ~(CMSPAR | CRTSCTS); + termios->c_cflag |= CS8 | CLOCAL; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + uart_update_timeout(port, CS8, uap->fixed_baud); + pl011_setup_status_masks(port, termios); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *pl011_type(struct uart_port *port) +@@ -2328,13 +2328,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) + + clk_enable(uap->clk); + +- local_irq_save(flags); +- if (uap->port.sysrq) +- locked = 0; +- else if (oops_in_progress) +- locked = spin_trylock(&uap->port.lock); ++ if (uap->port.sysrq || oops_in_progress) ++ locked = uart_port_trylock_irqsave(&uap->port, &flags); + else +- spin_lock(&uap->port.lock); ++ uart_port_lock_irqsave(&uap->port, &flags); + + /* + * First save the CR then disable the interrupts +@@ -2360,8 +2357,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); ++ uart_port_unlock_irqrestore(&uap->port, flags); + + clk_disable(uap->clk); + } +diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c +index d3cb341f2..364599f25 100644 +--- a/drivers/tty/serial/apbuart.c ++++ b/drivers/tty/serial/apbuart.c +@@ -133,7 +133,7 @@ static irqreturn_t apbuart_int(int irq, void *dev_id) + struct uart_port *port = dev_id; + unsigned int status; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + status = UART_GET_STATUS(port); + if (status & UART_STATUS_DR) +@@ -141,7 +141,7 @@ static irqreturn_t apbuart_int(int irq, void *dev_id) + if (status & UART_STATUS_THE) + apbuart_tx_chars(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -228,7 +228,7 @@ static void apbuart_set_termios(struct uart_port *port, + if (termios->c_cflag & CRTSCTS) + cr |= UART_CTRL_FL; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Update the per-port timeout. */ + uart_update_timeout(port, termios->c_cflag, baud); +@@ -251,7 +251,7 @@ static void apbuart_set_termios(struct uart_port *port, + UART_PUT_SCAL(port, quot); + UART_PUT_CTRL(port, cr); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *apbuart_type(struct uart_port *port) +diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c +index 924c1a893..ffd234673 100644 +--- a/drivers/tty/serial/ar933x_uart.c ++++ b/drivers/tty/serial/ar933x_uart.c +@@ -133,9 +133,9 @@ static unsigned int ar933x_uart_tx_empty(struct uart_port *port) + unsigned long flags; + unsigned int rdata; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + rdata = ar933x_uart_read(up, AR933X_UART_DATA_REG); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return (rdata & AR933X_UART_DATA_TX_CSR) ? 0 : TIOCSER_TEMT; + } +@@ -220,14 +220,14 @@ static void ar933x_uart_break_ctl(struct uart_port *port, int break_state) + container_of(port, struct ar933x_uart_port, port); + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + if (break_state == -1) + ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, + AR933X_UART_CS_TX_BREAK); + else + ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG, + AR933X_UART_CS_TX_BREAK); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + /* +@@ -318,7 +318,7 @@ static void ar933x_uart_set_termios(struct uart_port *port, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* disable the UART */ + ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG, +@@ -352,7 +352,7 @@ static void ar933x_uart_set_termios(struct uart_port *port, + AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S, + AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + if (tty_termios_baud_rate(new)) + tty_termios_encode_baud_rate(new, baud, baud); +@@ -450,7 +450,7 @@ static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id) + if ((status & AR933X_UART_CS_HOST_INT) == 0) + return IRQ_NONE; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + + status = ar933x_uart_read(up, AR933X_UART_INT_REG); + status &= ar933x_uart_read(up, AR933X_UART_INT_EN_REG); +@@ -468,7 +468,7 @@ static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id) + ar933x_uart_tx_chars(up); + } + +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + return IRQ_HANDLED; + } +@@ -485,7 +485,7 @@ static int ar933x_uart_startup(struct uart_port *port) + if (ret) + return ret; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* Enable HOST interrupts */ + ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, +@@ -498,7 +498,7 @@ static int ar933x_uart_startup(struct uart_port *port) + /* Enable RX interrupts */ + ar933x_uart_start_rx_interrupt(up); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return 0; + } +@@ -632,9 +632,9 @@ static void ar933x_uart_console_write(struct console *co, const char *s, + if (up->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&up->port.lock); ++ locked = uart_port_trylock(&up->port); + else +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + + /* + * First save the IER then disable the interrupts +@@ -654,7 +654,7 @@ static void ar933x_uart_console_write(struct console *co, const char *s, + ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_ALLINTS); + + if (locked) +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + local_irq_restore(flags); + } +diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c +index ad4ae19b6..1aa5b2b49 100644 +--- a/drivers/tty/serial/arc_uart.c ++++ b/drivers/tty/serial/arc_uart.c +@@ -279,9 +279,9 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id) + if (status & RXIENB) { + + /* already in ISR, no need of xx_irqsave */ +- spin_lock(&port->lock); ++ uart_port_lock(port); + arc_serial_rx_chars(port, status); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + } + + if ((status & TXIENB) && (status & TXEMPTY)) { +@@ -291,12 +291,12 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id) + */ + UART_TX_IRQ_DISABLE(port); + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + if (!uart_tx_stopped(port)) + arc_serial_tx_chars(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + } + + return IRQ_HANDLED; +@@ -366,7 +366,7 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new, + uartl = hw_val & 0xFF; + uarth = (hw_val >> 8) & 0xFF; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + UART_ALL_IRQ_DISABLE(port); + +@@ -391,7 +391,7 @@ arc_serial_set_termios(struct uart_port *port, struct ktermios *new, + + uart_update_timeout(port, new->c_cflag, baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *arc_serial_type(struct uart_port *port) +@@ -521,9 +521,9 @@ static void arc_serial_console_write(struct console *co, const char *s, + struct uart_port *port = &arc_uart_ports[co->index].port; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + uart_console_write(port, s, count, arc_serial_console_putchar); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static struct console arc_console = { +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index bcca5627a..5a3f2fc47 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -861,7 +861,7 @@ static void atmel_complete_tx_dma(void *arg) + struct dma_chan *chan = atmel_port->chan_tx; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (chan) + dmaengine_terminate_all(chan); +@@ -893,7 +893,7 @@ static void atmel_complete_tx_dma(void *arg) + atmel_port->tx_done_mask); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void atmel_release_tx_dma(struct uart_port *port) +@@ -1711,9 +1711,9 @@ static void atmel_tasklet_rx_func(struct tasklet_struct *t) + struct uart_port *port = &atmel_port->uart; + + /* The interrupt handler does not take the lock */ +- spin_lock(&port->lock); ++ uart_port_lock(port); + atmel_port->schedule_rx(port); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + } + + static void atmel_tasklet_tx_func(struct tasklet_struct *t) +@@ -1723,9 +1723,9 @@ static void atmel_tasklet_tx_func(struct tasklet_struct *t) + struct uart_port *port = &atmel_port->uart; + + /* The interrupt handler does not take the lock */ +- spin_lock(&port->lock); ++ uart_port_lock(port); + atmel_port->schedule_tx(port); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + } + + static void atmel_init_property(struct atmel_uart_port *atmel_port, +@@ -2175,7 +2175,7 @@ static void atmel_set_termios(struct uart_port *port, + } else + mode |= ATMEL_US_PAR_NONE; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + port->read_status_mask = ATMEL_US_OVRE; + if (termios->c_iflag & INPCK) +@@ -2377,22 +2377,22 @@ static void atmel_set_termios(struct uart_port *port, + else + atmel_disable_ms(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void atmel_set_ldisc(struct uart_port *port, struct ktermios *termios) + { + if (termios->c_line == N_PPS) { + port->flags |= UPF_HARDPPS_CD; +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + atmel_enable_ms(port); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } else { + port->flags &= ~UPF_HARDPPS_CD; + if (!UART_ENABLE_MS(port, termios->c_cflag)) { +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + atmel_disable_ms(port); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } + } + } +diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c +index 44c27e5ce..b104c36ce 100644 +--- a/drivers/tty/serial/bcm63xx_uart.c ++++ b/drivers/tty/serial/bcm63xx_uart.c +@@ -201,7 +201,7 @@ static void bcm_uart_break_ctl(struct uart_port *port, int ctl) + unsigned long flags; + unsigned int val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = bcm_uart_readl(port, UART_CTL_REG); + if (ctl) +@@ -210,7 +210,7 @@ static void bcm_uart_break_ctl(struct uart_port *port, int ctl) + val &= ~UART_CTL_XMITBRK_MASK; + bcm_uart_writel(port, val, UART_CTL_REG); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* +@@ -335,7 +335,7 @@ static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id) + unsigned int irqstat; + + port = dev_id; +- spin_lock(&port->lock); ++ uart_port_lock(port); + + irqstat = bcm_uart_readl(port, UART_IR_REG); + if (irqstat & UART_RX_INT_STAT) +@@ -356,7 +356,7 @@ static irqreturn_t bcm_uart_interrupt(int irq, void *dev_id) + estat & UART_EXTINP_DCD_MASK); + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + return IRQ_HANDLED; + } + +@@ -454,9 +454,9 @@ static void bcm_uart_shutdown(struct uart_port *port) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + bcm_uart_writel(port, 0, UART_IR_REG); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + bcm_uart_disable(port); + bcm_uart_flush(port); +@@ -473,7 +473,7 @@ static void bcm_uart_set_termios(struct uart_port *port, struct ktermios *new, + unsigned long flags; + int tries; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Drain the hot tub fully before we power it off for the winter. */ + for (tries = 3; !bcm_uart_tx_empty(port) && tries; tries--) +@@ -549,7 +549,7 @@ static void bcm_uart_set_termios(struct uart_port *port, struct ktermios *new, + + uart_update_timeout(port, new->c_cflag, baud); + bcm_uart_enable(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* +@@ -715,9 +715,9 @@ static void bcm_console_write(struct console *co, const char *s, + /* bcm_uart_interrupt() already took the lock */ + locked = 0; + } else if (oops_in_progress) { +- locked = spin_trylock(&port->lock); ++ locked = uart_port_trylock(port); + } else { +- spin_lock(&port->lock); ++ uart_port_lock(port); + locked = 1; + } + +@@ -728,7 +728,7 @@ static void bcm_console_write(struct console *co, const char *s, + wait_for_xmitr(port); + + if (locked) +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + local_irq_restore(flags); + } + +diff --git a/drivers/tty/serial/cpm_uart.c b/drivers/tty/serial/cpm_uart.c +index 626423022..be4af6eda 100644 +--- a/drivers/tty/serial/cpm_uart.c ++++ b/drivers/tty/serial/cpm_uart.c +@@ -569,7 +569,7 @@ static void cpm_uart_set_termios(struct uart_port *port, + if ((termios->c_cflag & CREAD) == 0) + port->read_status_mask &= ~BD_SC_EMPTY; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (IS_SMC(pinfo)) { + unsigned int bits = tty_get_frame_size(termios->c_cflag); +@@ -609,7 +609,7 @@ static void cpm_uart_set_termios(struct uart_port *port, + clk_set_rate(pinfo->clk, baud); + else + cpm_setbrg(pinfo->brg - 1, baud); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *cpm_uart_type(struct uart_port *port) +@@ -1386,9 +1386,9 @@ static void cpm_uart_console_write(struct console *co, const char *s, + cpm_uart_early_write(pinfo, s, count, true); + local_irq_restore(flags); + } else { +- spin_lock_irqsave(&pinfo->port.lock, flags); ++ uart_port_lock_irqsave(&pinfo->port, &flags); + cpm_uart_early_write(pinfo, s, count, true); +- spin_unlock_irqrestore(&pinfo->port.lock, flags); ++ uart_port_unlock_irqrestore(&pinfo->port, flags); + } + } + +diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c +index 128b5479e..5004125f3 100644 +--- a/drivers/tty/serial/digicolor-usart.c ++++ b/drivers/tty/serial/digicolor-usart.c +@@ -133,7 +133,7 @@ static void digicolor_uart_rx(struct uart_port *port) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + while (1) { + u8 status, ch, ch_flag; +@@ -172,7 +172,7 @@ static void digicolor_uart_rx(struct uart_port *port) + ch_flag); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + tty_flip_buffer_push(&port->state->port); + } +@@ -185,7 +185,7 @@ static void digicolor_uart_tx(struct uart_port *port) + if (digicolor_uart_tx_full(port)) + return; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (port->x_char) { + writeb_relaxed(port->x_char, port->membase + UA_EMI_REC); +@@ -211,7 +211,7 @@ static void digicolor_uart_tx(struct uart_port *port) + uart_write_wakeup(port); + + out: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static irqreturn_t digicolor_uart_int(int irq, void *dev_id) +@@ -333,7 +333,7 @@ static void digicolor_uart_set_termios(struct uart_port *port, + port->ignore_status_mask |= UA_STATUS_OVERRUN_ERR + | UA_STATUS_PARITY_ERR | UA_STATUS_FRAME_ERR; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_update_timeout(port, termios->c_cflag, baud); + +@@ -341,7 +341,7 @@ static void digicolor_uart_set_termios(struct uart_port *port, + writeb_relaxed(divisor & 0xff, port->membase + UA_HBAUD_LO); + writeb_relaxed(divisor >> 8, port->membase + UA_HBAUD_HI); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *digicolor_uart_type(struct uart_port *port) +@@ -398,14 +398,14 @@ static void digicolor_uart_console_write(struct console *co, const char *c, + int locked = 1; + + if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_console_write(port, c, n, digicolor_uart_console_putchar); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Wait for transmitter to become empty */ + do { +diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c +index 667f52e83..6df7af9ed 100644 +--- a/drivers/tty/serial/dz.c ++++ b/drivers/tty/serial/dz.c +@@ -268,9 +268,9 @@ static inline void dz_transmit_chars(struct dz_mux *mux) + } + /* If nothing to do or stopped or hardware stopped. */ + if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { +- spin_lock(&dport->port.lock); ++ uart_port_lock(&dport->port); + dz_stop_tx(&dport->port); +- spin_unlock(&dport->port.lock); ++ uart_port_unlock(&dport->port); + return; + } + +@@ -287,9 +287,9 @@ static inline void dz_transmit_chars(struct dz_mux *mux) + + /* Are we are done. */ + if (uart_circ_empty(xmit)) { +- spin_lock(&dport->port.lock); ++ uart_port_lock(&dport->port); + dz_stop_tx(&dport->port); +- spin_unlock(&dport->port.lock); ++ uart_port_unlock(&dport->port); + } + } + +@@ -415,14 +415,14 @@ static int dz_startup(struct uart_port *uport) + return ret; + } + +- spin_lock_irqsave(&dport->port.lock, flags); ++ uart_port_lock_irqsave(&dport->port, &flags); + + /* Enable interrupts. */ + tmp = dz_in(dport, DZ_CSR); + tmp |= DZ_RIE | DZ_TIE; + dz_out(dport, DZ_CSR, tmp); + +- spin_unlock_irqrestore(&dport->port.lock, flags); ++ uart_port_unlock_irqrestore(&dport->port, flags); + + return 0; + } +@@ -443,9 +443,9 @@ static void dz_shutdown(struct uart_port *uport) + int irq_guard; + u16 tmp; + +- spin_lock_irqsave(&dport->port.lock, flags); ++ uart_port_lock_irqsave(&dport->port, &flags); + dz_stop_tx(&dport->port); +- spin_unlock_irqrestore(&dport->port.lock, flags); ++ uart_port_unlock_irqrestore(&dport->port, flags); + + irq_guard = atomic_add_return(-1, &mux->irq_guard); + if (!irq_guard) { +@@ -491,14 +491,14 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) + unsigned long flags; + unsigned short tmp, mask = 1 << dport->port.line; + +- spin_lock_irqsave(&uport->lock, flags); ++ uart_port_lock_irqsave(uport, &flags); + tmp = dz_in(dport, DZ_TCR); + if (break_state) + tmp |= mask; + else + tmp &= ~mask; + dz_out(dport, DZ_TCR, tmp); +- spin_unlock_irqrestore(&uport->lock, flags); ++ uart_port_unlock_irqrestore(uport, flags); + } + + static int dz_encode_baud_rate(unsigned int baud) +@@ -608,7 +608,7 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, + if (termios->c_cflag & CREAD) + cflag |= DZ_RXENAB; + +- spin_lock_irqsave(&dport->port.lock, flags); ++ uart_port_lock_irqsave(&dport->port, &flags); + + uart_update_timeout(uport, termios->c_cflag, baud); + +@@ -631,7 +631,7 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, + if (termios->c_iflag & IGNBRK) + dport->port.ignore_status_mask |= DZ_BREAK; + +- spin_unlock_irqrestore(&dport->port.lock, flags); ++ uart_port_unlock_irqrestore(&dport->port, flags); + } + + /* +@@ -645,12 +645,12 @@ static void dz_pm(struct uart_port *uport, unsigned int state, + struct dz_port *dport = to_dport(uport); + unsigned long flags; + +- spin_lock_irqsave(&dport->port.lock, flags); ++ uart_port_lock_irqsave(&dport->port, &flags); + if (state < 3) + dz_start_tx(&dport->port); + else + dz_stop_tx(&dport->port); +- spin_unlock_irqrestore(&dport->port.lock, flags); ++ uart_port_unlock_irqrestore(&dport->port, flags); + } + + +@@ -811,7 +811,7 @@ static void dz_console_putchar(struct uart_port *uport, unsigned char ch) + unsigned short csr, tcr, trdy, mask; + int loops = 10000; + +- spin_lock_irqsave(&dport->port.lock, flags); ++ uart_port_lock_irqsave(&dport->port, &flags); + csr = dz_in(dport, DZ_CSR); + dz_out(dport, DZ_CSR, csr & ~DZ_TIE); + tcr = dz_in(dport, DZ_TCR); +@@ -819,7 +819,7 @@ static void dz_console_putchar(struct uart_port *uport, unsigned char ch) + mask = tcr; + dz_out(dport, DZ_TCR, mask); + iob(); +- spin_unlock_irqrestore(&dport->port.lock, flags); ++ uart_port_unlock_irqrestore(&dport->port, flags); + + do { + trdy = dz_in(dport, DZ_CSR); +diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c +index 249cb380c..7fa809a40 100644 +--- a/drivers/tty/serial/fsl_linflexuart.c ++++ b/drivers/tty/serial/fsl_linflexuart.c +@@ -203,7 +203,7 @@ static irqreturn_t linflex_txint(int irq, void *dev_id) + struct circ_buf *xmit = &sport->state->xmit; + unsigned long flags; + +- spin_lock_irqsave(&sport->lock, flags); ++ uart_port_lock_irqsave(sport, &flags); + + if (sport->x_char) { + linflex_put_char(sport, sport->x_char); +@@ -217,7 +217,7 @@ static irqreturn_t linflex_txint(int irq, void *dev_id) + + linflex_transmit_buffer(sport); + out: +- spin_unlock_irqrestore(&sport->lock, flags); ++ uart_port_unlock_irqrestore(sport, flags); + return IRQ_HANDLED; + } + +@@ -230,7 +230,7 @@ static irqreturn_t linflex_rxint(int irq, void *dev_id) + unsigned char rx; + bool brk; + +- spin_lock_irqsave(&sport->lock, flags); ++ uart_port_lock_irqsave(sport, &flags); + + status = readl(sport->membase + UARTSR); + while (status & LINFLEXD_UARTSR_RMB) { +@@ -266,7 +266,7 @@ static irqreturn_t linflex_rxint(int irq, void *dev_id) + } + } + +- spin_unlock_irqrestore(&sport->lock, flags); ++ uart_port_unlock_irqrestore(sport, flags); + + tty_flip_buffer_push(port); + +@@ -369,11 +369,11 @@ static int linflex_startup(struct uart_port *port) + int ret = 0; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + linflex_setup_watermark(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + ret = devm_request_irq(port->dev, port->irq, linflex_int, 0, + DRIVER_NAME, port); +@@ -386,14 +386,14 @@ static void linflex_shutdown(struct uart_port *port) + unsigned long ier; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* disable interrupts */ + ier = readl(port->membase + LINIER); + ier &= ~(LINFLEXD_LINIER_DRIE | LINFLEXD_LINIER_DTIE); + writel(ier, port->membase + LINIER); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + devm_free_irq(port->dev, port->irq, port); + } +@@ -474,7 +474,7 @@ linflex_set_termios(struct uart_port *port, struct ktermios *termios, + cr &= ~LINFLEXD_UARTCR_PCE; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + port->read_status_mask = 0; + +@@ -507,7 +507,7 @@ linflex_set_termios(struct uart_port *port, struct ktermios *termios, + + writel(cr1, port->membase + LINCR1); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *linflex_type(struct uart_port *port) +@@ -646,14 +646,14 @@ linflex_console_write(struct console *co, const char *s, unsigned int count) + if (sport->sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&sport->lock, flags); ++ locked = uart_port_trylock_irqsave(sport, &flags); + else +- spin_lock_irqsave(&sport->lock, flags); ++ uart_port_lock_irqsave(sport, &flags); + + linflex_string_write(sport, s, count); + + if (locked) +- spin_unlock_irqrestore(&sport->lock, flags); ++ uart_port_unlock_irqrestore(sport, flags); + } + + /* +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index 8bd0f8e45..58c2c460c 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -532,9 +532,9 @@ static void lpuart_dma_tx_complete(void *arg) + struct dma_chan *chan = sport->dma_tx_chan; + unsigned long flags; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (!sport->dma_tx_in_progress) { +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + return; + } + +@@ -543,7 +543,7 @@ static void lpuart_dma_tx_complete(void *arg) + + uart_xmit_advance(&sport->port, sport->dma_tx_bytes); + sport->dma_tx_in_progress = false; +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&sport->port); +@@ -553,12 +553,12 @@ static void lpuart_dma_tx_complete(void *arg) + return; + } + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + if (!lpuart_stopped_or_empty(&sport->port)) + lpuart_dma_tx(sport); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static dma_addr_t lpuart_dma_datareg_addr(struct lpuart_port *sport) +@@ -651,7 +651,7 @@ static int lpuart_poll_init(struct uart_port *port) + + sport->port.fifosize = 0; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + /* Disable Rx & Tx */ + writeb(0, sport->port.membase + UARTCR2); + +@@ -675,7 +675,7 @@ static int lpuart_poll_init(struct uart_port *port) + + /* Enable Rx and Tx */ + writeb(UARTCR2_RE | UARTCR2_TE, sport->port.membase + UARTCR2); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + return 0; + } +@@ -703,7 +703,7 @@ static int lpuart32_poll_init(struct uart_port *port) + + sport->port.fifosize = 0; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* Disable Rx & Tx */ + lpuart32_write(&sport->port, 0, UARTCTRL); +@@ -724,7 +724,7 @@ static int lpuart32_poll_init(struct uart_port *port) + + /* Enable Rx and Tx */ + lpuart32_write(&sport->port, UARTCTRL_RE | UARTCTRL_TE, UARTCTRL); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + return 0; + } +@@ -879,9 +879,9 @@ static unsigned int lpuart32_tx_empty(struct uart_port *port) + + static void lpuart_txint(struct lpuart_port *sport) + { +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + lpuart_transmit_buffer(sport); +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + } + + static void lpuart_rxint(struct lpuart_port *sport) +@@ -890,7 +890,7 @@ static void lpuart_rxint(struct lpuart_port *sport) + struct tty_port *port = &sport->port.state->port; + unsigned char rx, sr; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + + while (!(readb(sport->port.membase + UARTSFIFO) & UARTSFIFO_RXEMPT)) { + flg = TTY_NORMAL; +@@ -956,9 +956,9 @@ static void lpuart_rxint(struct lpuart_port *sport) + + static void lpuart32_txint(struct lpuart_port *sport) + { +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + lpuart32_transmit_buffer(sport); +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + } + + static void lpuart32_rxint(struct lpuart_port *sport) +@@ -968,7 +968,7 @@ static void lpuart32_rxint(struct lpuart_port *sport) + unsigned long rx, sr; + bool is_break; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + + while (!(lpuart32_read(&sport->port, UARTFIFO) & UARTFIFO_RXEMPT)) { + flg = TTY_NORMAL; +@@ -1170,12 +1170,12 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) + + async_tx_ack(sport->dma_rx_desc); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state); + if (dmastat == DMA_ERROR) { + dev_err(sport->port.dev, "Rx DMA transfer failed!\n"); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + return; + } + +@@ -1244,7 +1244,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport) + dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1, + DMA_FROM_DEVICE); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + tty_flip_buffer_push(port); + if (!sport->dma_idle_int) +@@ -1335,9 +1335,9 @@ static void lpuart_timer_func(struct timer_list *t) + mod_timer(&sport->lpuart_timer, + jiffies + sport->dma_rx_timeout); + +- if (spin_trylock_irqsave(&sport->port.lock, flags)) { ++ if (uart_port_trylock_irqsave(&sport->port, &flags)) { + sport->last_residue = state.residue; +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + } + +@@ -1802,14 +1802,14 @@ static void lpuart_hw_setup(struct lpuart_port *sport) + { + unsigned long flags; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + lpuart_setup_watermark_enable(sport); + + lpuart_rx_dma_startup(sport); + lpuart_tx_dma_startup(sport); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static int lpuart_startup(struct uart_port *port) +@@ -1859,7 +1859,7 @@ static void lpuart32_hw_setup(struct lpuart_port *sport) + { + unsigned long flags; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + lpuart32_hw_disable(sport); + +@@ -1869,7 +1869,7 @@ static void lpuart32_hw_setup(struct lpuart_port *sport) + lpuart32_setup_watermark_enable(sport); + lpuart32_configure(sport); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static int lpuart32_startup(struct uart_port *port) +@@ -1932,7 +1932,7 @@ static void lpuart_shutdown(struct uart_port *port) + unsigned char temp; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* disable Rx/Tx and interrupts */ + temp = readb(port->membase + UARTCR2); +@@ -1940,7 +1940,7 @@ static void lpuart_shutdown(struct uart_port *port) + UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_RIE); + writeb(temp, port->membase + UARTCR2); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + lpuart_dma_shutdown(sport); + } +@@ -1952,7 +1952,7 @@ static void lpuart32_shutdown(struct uart_port *port) + unsigned long temp; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* clear status */ + temp = lpuart32_read(&sport->port, UARTSTAT); +@@ -1969,7 +1969,7 @@ static void lpuart32_shutdown(struct uart_port *port) + UARTCTRL_TIE | UARTCTRL_TCIE | UARTCTRL_RIE | UARTCTRL_SBK); + lpuart32_write(port, temp, UARTCTRL); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + lpuart_dma_shutdown(sport); + } +@@ -2069,7 +2069,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, + if (old && sport->lpuart_dma_rx_use) + lpuart_dma_rx_free(&sport->port); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + sport->port.read_status_mask = 0; + if (termios->c_iflag & INPCK) +@@ -2124,7 +2124,7 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios, + sport->lpuart_dma_rx_use = false; + } + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static void __lpuart32_serial_setbrg(struct uart_port *port, +@@ -2304,7 +2304,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, + if (old && sport->lpuart_dma_rx_use) + lpuart_dma_rx_free(&sport->port); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + sport->port.read_status_mask = 0; + if (termios->c_iflag & INPCK) +@@ -2362,7 +2362,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios, + sport->lpuart_dma_rx_use = false; + } + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static const char *lpuart_type(struct uart_port *port) +@@ -2480,9 +2480,9 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count) + int locked = 1; + + if (oops_in_progress) +- locked = spin_trylock_irqsave(&sport->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&sport->port, &flags); + else +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* first save CR2 and then disable interrupts */ + cr2 = old_cr2 = readb(sport->port.membase + UARTCR2); +@@ -2498,7 +2498,7 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count) + writeb(old_cr2, sport->port.membase + UARTCR2); + + if (locked) +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static void +@@ -2510,9 +2510,9 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count) + int locked = 1; + + if (oops_in_progress) +- locked = spin_trylock_irqsave(&sport->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&sport->port, &flags); + else +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* first save CR2 and then disable interrupts */ + cr = old_cr = lpuart32_read(&sport->port, UARTCTRL); +@@ -2528,7 +2528,7 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count) + lpuart32_write(&sport->port, old_cr, UARTCTRL); + + if (locked) +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + /* +@@ -3093,7 +3093,7 @@ static int lpuart_suspend(struct device *dev) + uart_suspend_port(&lpuart_reg, &sport->port); + + if (lpuart_uport_is_active(sport)) { +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (lpuart_is_32(sport)) { + /* disable Rx/Tx and interrupts */ + temp = lpuart32_read(&sport->port, UARTCTRL); +@@ -3105,7 +3105,7 @@ static int lpuart_suspend(struct device *dev) + temp &= ~(UARTCR2_TE | UARTCR2_TIE | UARTCR2_TCIE); + writeb(temp, sport->port.membase + UARTCR2); + } +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + if (sport->lpuart_dma_rx_use) { + /* +@@ -3118,7 +3118,7 @@ static int lpuart_suspend(struct device *dev) + lpuart_dma_rx_free(&sport->port); + + /* Disable Rx DMA to use UART port as wakeup source */ +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (lpuart_is_32(sport)) { + temp = lpuart32_read(&sport->port, UARTBAUD); + lpuart32_write(&sport->port, temp & ~UARTBAUD_RDMAE, +@@ -3127,11 +3127,11 @@ static int lpuart_suspend(struct device *dev) + writeb(readb(sport->port.membase + UARTCR5) & + ~UARTCR5_RDMAS, sport->port.membase + UARTCR5); + } +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + if (sport->lpuart_dma_tx_use) { +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (lpuart_is_32(sport)) { + temp = lpuart32_read(&sport->port, UARTBAUD); + temp &= ~UARTBAUD_TDMAE; +@@ -3141,7 +3141,7 @@ static int lpuart_suspend(struct device *dev) + temp &= ~UARTCR5_TDMAS; + writeb(temp, sport->port.membase + UARTCR5); + } +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + sport->dma_tx_in_progress = false; + dmaengine_terminate_sync(sport->dma_tx_chan); + } +diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c +index 819f957b6..a75eafbcb 100644 +--- a/drivers/tty/serial/icom.c ++++ b/drivers/tty/serial/icom.c +@@ -929,7 +929,7 @@ static inline void check_modem_status(struct icom_port *icom_port) + char delta_status; + unsigned char status; + +- spin_lock(&icom_port->uart_port.lock); ++ uart_port_lock(&icom_port->uart_port); + + /*modem input register */ + status = readb(&icom_port->dram->isr); +@@ -951,7 +951,7 @@ static inline void check_modem_status(struct icom_port *icom_port) + port.delta_msr_wait); + old_status = status; + } +- spin_unlock(&icom_port->uart_port.lock); ++ uart_port_unlock(&icom_port->uart_port); + } + + static void xmit_interrupt(u16 port_int_reg, struct icom_port *icom_port) +@@ -1093,7 +1093,7 @@ static void process_interrupt(u16 port_int_reg, + struct icom_port *icom_port) + { + +- spin_lock(&icom_port->uart_port.lock); ++ uart_port_lock(&icom_port->uart_port); + trace(icom_port, "INTERRUPT", port_int_reg); + + if (port_int_reg & (INT_XMIT_COMPLETED | INT_XMIT_DISABLED)) +@@ -1102,7 +1102,7 @@ static void process_interrupt(u16 port_int_reg, + if (port_int_reg & INT_RCV_COMPLETED) + recv_interrupt(port_int_reg, icom_port); + +- spin_unlock(&icom_port->uart_port.lock); ++ uart_port_unlock(&icom_port->uart_port); + } + + static irqreturn_t icom_interrupt(int irq, void *dev_id) +@@ -1186,14 +1186,14 @@ static unsigned int icom_tx_empty(struct uart_port *port) + int ret; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (le16_to_cpu(icom_port->statStg->xmit[0].flags) & + SA_FLAGS_READY_TO_XMIT) + ret = TIOCSER_TEMT; + else + ret = 0; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return ret; + } + +@@ -1276,7 +1276,7 @@ static void icom_send_xchar(struct uart_port *port, char ch) + + /* wait .1 sec to send char */ + for (index = 0; index < 10; index++) { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + xdata = readb(&icom_port->dram->xchar); + if (xdata == 0x00) { + trace(icom_port, "QUICK_WRITE", 0); +@@ -1284,10 +1284,10 @@ static void icom_send_xchar(struct uart_port *port, char ch) + + /* flush write operation */ + xdata = readb(&icom_port->dram->xchar); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + break; + } +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + msleep(10); + } + } +@@ -1307,7 +1307,7 @@ static void icom_break(struct uart_port *port, int break_state) + unsigned char cmdReg; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + trace(icom_port, "BREAK", 0); + cmdReg = readb(&icom_port->dram->CmdReg); + if (break_state == -1) { +@@ -1315,7 +1315,7 @@ static void icom_break(struct uart_port *port, int break_state) + } else { + writeb(cmdReg & ~CMD_SND_BREAK, &icom_port->dram->CmdReg); + } +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int icom_open(struct uart_port *port) +@@ -1365,7 +1365,7 @@ static void icom_set_termios(struct uart_port *port, struct ktermios *termios, + unsigned long offset; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + trace(icom_port, "CHANGE_SPEED", 0); + + cflag = termios->c_cflag; +@@ -1516,7 +1516,7 @@ static void icom_set_termios(struct uart_port *port, struct ktermios *termios, + trace(icom_port, "XR_ENAB", 0); + writeb(CMD_XMIT_RCV_ENABLE, &icom_port->dram->CmdReg); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *icom_type(struct uart_port *port) +diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c +index a5d0df2ba..267c9af4b 100644 +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -586,7 +586,7 @@ static void imx_uart_dma_tx_callback(void *data) + unsigned long flags; + u32 ucr1; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + +@@ -611,7 +611,7 @@ static void imx_uart_dma_tx_callback(void *data) + imx_uart_writel(sport, ucr4, UCR4); + } + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + /* called with port.lock taken and irqs off */ +@@ -782,11 +782,11 @@ static irqreturn_t imx_uart_rtsint(int irq, void *dev_id) + struct imx_port *sport = dev_id; + irqreturn_t ret; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + + ret = __imx_uart_rtsint(irq, dev_id); + +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + + return ret; + } +@@ -795,9 +795,9 @@ static irqreturn_t imx_uart_txint(int irq, void *dev_id) + { + struct imx_port *sport = dev_id; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + imx_uart_transmit_buffer(sport); +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + return IRQ_HANDLED; + } + +@@ -911,11 +911,11 @@ static irqreturn_t imx_uart_rxint(int irq, void *dev_id) + struct imx_port *sport = dev_id; + irqreturn_t ret; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + + ret = __imx_uart_rxint(irq, dev_id); + +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + + return ret; + } +@@ -978,7 +978,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) + unsigned int usr1, usr2, ucr1, ucr2, ucr3, ucr4; + irqreturn_t ret = IRQ_NONE; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + + usr1 = imx_uart_readl(sport, USR1); + usr2 = imx_uart_readl(sport, USR2); +@@ -1048,7 +1048,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id) + ret = IRQ_HANDLED; + } + +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + + return ret; + } +@@ -1131,7 +1131,7 @@ static void imx_uart_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + u32 ucr1; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + ucr1 = imx_uart_readl(sport, UCR1) & ~UCR1_SNDBRK; + +@@ -1140,7 +1140,7 @@ static void imx_uart_break_ctl(struct uart_port *port, int break_state) + + imx_uart_writel(sport, ucr1, UCR1); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + /* +@@ -1153,9 +1153,9 @@ static void imx_uart_timeout(struct timer_list *t) + unsigned long flags; + + if (sport->port.state) { +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + imx_uart_mctrl_check(sport); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); + } +@@ -1185,9 +1185,9 @@ static void imx_uart_dma_rx_callback(void *data) + status = dmaengine_tx_status(chan, sport->rx_cookie, &state); + + if (status == DMA_ERROR) { +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + imx_uart_clear_rx_errors(sport); +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + return; + } + +@@ -1216,9 +1216,9 @@ static void imx_uart_dma_rx_callback(void *data) + r_bytes = rx_ring->head - rx_ring->tail; + + /* If we received something, check for 0xff flood */ +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + imx_uart_check_flood(sport, imx_uart_readl(sport, USR2)); +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + + if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) { + +@@ -1476,7 +1476,7 @@ static int imx_uart_startup(struct uart_port *port) + if (!uart_console(port) && imx_uart_dma_init(sport) == 0) + dma_is_inited = 1; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* Reset fifo's and state machines */ + imx_uart_soft_reset(sport); +@@ -1549,7 +1549,7 @@ static int imx_uart_startup(struct uart_port *port) + + imx_uart_disable_loopback_rs485(sport); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + return 0; + } +@@ -1574,21 +1574,21 @@ static void imx_uart_shutdown(struct uart_port *port) + sport->dma_is_rxing = 0; + } + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + imx_uart_stop_tx(port); + imx_uart_stop_rx(port); + imx_uart_disable_dma(sport); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + imx_uart_dma_exit(sport); + } + + mctrl_gpio_disable_ms(sport->gpios); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + ucr2 = imx_uart_readl(sport, UCR2); + ucr2 &= ~(UCR2_TXEN | UCR2_ATEN); + imx_uart_writel(sport, ucr2, UCR2); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + /* + * Stop our timer. +@@ -1599,7 +1599,7 @@ static void imx_uart_shutdown(struct uart_port *port) + * Disable all interrupts, port and break condition. + */ + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + ucr1 = imx_uart_readl(sport, UCR1); + ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_RXDMAEN | +@@ -1621,7 +1621,7 @@ static void imx_uart_shutdown(struct uart_port *port) + ucr4 &= ~UCR4_TCEN; + imx_uart_writel(sport, ucr4, UCR4); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + clk_disable_unprepare(sport->clk_per); + clk_disable_unprepare(sport->clk_ipg); +@@ -1684,7 +1684,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, + baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16); + quot = uart_get_divisor(port, baud); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* + * Read current UCR2 and save it for future use, then clear all the bits +@@ -1812,7 +1812,7 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, + if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) + imx_uart_enable_ms(&sport->port); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static const char *imx_uart_type(struct uart_port *port) +@@ -1874,7 +1874,7 @@ static int imx_uart_poll_init(struct uart_port *port) + + imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* + * Be careful about the order of enabling bits here. First enable the +@@ -1902,7 +1902,7 @@ static int imx_uart_poll_init(struct uart_port *port) + imx_uart_writel(sport, ucr1 | UCR1_RRDYEN, UCR1); + imx_uart_writel(sport, ucr2 | UCR2_ATEN, UCR2); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + return 0; + } +@@ -2022,9 +2022,9 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) + if (sport->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&sport->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&sport->port, &flags); + else +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + /* + * First, save UCR1/2/3 and then disable interrupts +@@ -2052,7 +2052,7 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) + imx_uart_ucrs_restore(sport, &old_ucr); + + if (locked) +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + /* +@@ -2210,10 +2210,10 @@ static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t) + struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx); + unsigned long flags; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (sport->tx_state == WAIT_AFTER_RTS) + imx_uart_start_tx(&sport->port); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + return HRTIMER_NORESTART; + } +@@ -2223,10 +2223,10 @@ static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t) + struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx); + unsigned long flags; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (sport->tx_state == WAIT_AFTER_SEND) + imx_uart_stop_tx(&sport->port); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + return HRTIMER_NORESTART; + } +@@ -2493,9 +2493,9 @@ static void imx_uart_restore_context(struct imx_port *sport) + { + unsigned long flags; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + if (!sport->context_saved) { +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + return; + } + +@@ -2510,7 +2510,7 @@ static void imx_uart_restore_context(struct imx_port *sport) + imx_uart_writel(sport, sport->saved_reg[2], UCR3); + imx_uart_writel(sport, sport->saved_reg[3], UCR4); + sport->context_saved = false; +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static void imx_uart_save_context(struct imx_port *sport) +@@ -2518,7 +2518,7 @@ static void imx_uart_save_context(struct imx_port *sport) + unsigned long flags; + + /* Save necessary regs */ +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + sport->saved_reg[0] = imx_uart_readl(sport, UCR1); + sport->saved_reg[1] = imx_uart_readl(sport, UCR2); + sport->saved_reg[2] = imx_uart_readl(sport, UCR3); +@@ -2530,7 +2530,7 @@ static void imx_uart_save_context(struct imx_port *sport) + sport->saved_reg[8] = imx_uart_readl(sport, UBMR); + sport->saved_reg[9] = imx_uart_readl(sport, IMX21_UTS); + sport->context_saved = true; +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static void imx_uart_enable_wakeup(struct imx_port *sport, bool on) +diff --git a/drivers/tty/serial/ip22zilog.c b/drivers/tty/serial/ip22zilog.c +index 845ff706b..320b29cd4 100644 +--- a/drivers/tty/serial/ip22zilog.c ++++ b/drivers/tty/serial/ip22zilog.c +@@ -432,7 +432,7 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) + unsigned char r3; + bool push = false; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + r3 = read_zsreg(channel, R3); + + /* Channel A */ +@@ -448,7 +448,7 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) + if (r3 & CHATxIP) + ip22zilog_transmit_chars(up, channel); + } +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + if (push) + tty_flip_buffer_push(&up->port.state->port); +@@ -458,7 +458,7 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + push = false; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { + writeb(RES_H_IUS, &channel->control); + ZSDELAY(); +@@ -471,7 +471,7 @@ static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id) + if (r3 & CHBTxIP) + ip22zilog_transmit_chars(up, channel); + } +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + if (push) + tty_flip_buffer_push(&up->port.state->port); +@@ -504,11 +504,11 @@ static unsigned int ip22zilog_tx_empty(struct uart_port *port) + unsigned char status; + unsigned int ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + status = ip22zilog_read_channel_status(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (status & Tx_BUF_EMP) + ret = TIOCSER_TEMT; +@@ -664,7 +664,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) + else + clear_bits |= SND_BRK; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; + if (new_reg != up->curregs[R5]) { +@@ -674,7 +674,7 @@ static void ip22zilog_break_ctl(struct uart_port *port, int break_state) + write_zsreg(channel, R5, up->curregs[R5]); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void __ip22zilog_reset(struct uart_ip22zilog_port *up) +@@ -735,9 +735,9 @@ static int ip22zilog_startup(struct uart_port *port) + if (ZS_IS_CONS(up)) + return 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + __ip22zilog_startup(up); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return 0; + } + +@@ -775,7 +775,7 @@ static void ip22zilog_shutdown(struct uart_port *port) + if (ZS_IS_CONS(up)) + return; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + channel = ZILOG_CHANNEL_FROM_PORT(port); + +@@ -788,7 +788,7 @@ static void ip22zilog_shutdown(struct uart_port *port) + up->curregs[R5] &= ~SND_BRK; + ip22zilog_maybe_update_regs(up, channel); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* Shared by TTY driver and serial console setup. The port lock is held +@@ -880,7 +880,7 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, + + baud = uart_get_baud_rate(port, termios, old, 1200, 76800); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + +@@ -894,7 +894,7 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, + ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static const char *ip22zilog_type(struct uart_port *port) +@@ -1016,10 +1016,10 @@ ip22zilog_console_write(struct console *con, const char *s, unsigned int count) + struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + uart_console_write(&up->port, s, count, ip22zilog_put_char); + udelay(2); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int __init ip22zilog_console_setup(struct console *con, char *options) +@@ -1034,13 +1034,13 @@ static int __init ip22zilog_console_setup(struct console *con, char *options) + + printk(KERN_INFO "Console: ttyS%d (IP22-Zilog)\n", con->index); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + up->curregs[R15] |= BRKIE; + + __ip22zilog_startup(up); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); +diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c +index 0c78f6627..2bd640428 100644 +--- a/drivers/tty/serial/jsm/jsm_neo.c ++++ b/drivers/tty/serial/jsm/jsm_neo.c +@@ -816,9 +816,9 @@ static void neo_parse_isr(struct jsm_board *brd, u32 port) + /* Parse any modem signal changes */ + jsm_dbg(INTR, &ch->ch_bd->pci_dev, + "MOD_STAT: sending to parse_modem_sigs\n"); +- spin_lock_irqsave(&ch->uart_port.lock, lock_flags); ++ uart_port_lock_irqsave(&ch->uart_port, &lock_flags); + neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); +- spin_unlock_irqrestore(&ch->uart_port.lock, lock_flags); ++ uart_port_unlock_irqrestore(&ch->uart_port, lock_flags); + } + } + +diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c +index 222afc270..ce0fef7e2 100644 +--- a/drivers/tty/serial/jsm/jsm_tty.c ++++ b/drivers/tty/serial/jsm/jsm_tty.c +@@ -152,14 +152,14 @@ static void jsm_tty_send_xchar(struct uart_port *port, char ch) + container_of(port, struct jsm_channel, uart_port); + struct ktermios *termios; + +- spin_lock_irqsave(&port->lock, lock_flags); ++ uart_port_lock_irqsave(port, &lock_flags); + termios = &port->state->port.tty->termios; + if (ch == termios->c_cc[VSTART]) + channel->ch_bd->bd_ops->send_start_character(channel); + + if (ch == termios->c_cc[VSTOP]) + channel->ch_bd->bd_ops->send_stop_character(channel); +- spin_unlock_irqrestore(&port->lock, lock_flags); ++ uart_port_unlock_irqrestore(port, lock_flags); + } + + static void jsm_tty_stop_rx(struct uart_port *port) +@@ -176,13 +176,13 @@ static void jsm_tty_break(struct uart_port *port, int break_state) + struct jsm_channel *channel = + container_of(port, struct jsm_channel, uart_port); + +- spin_lock_irqsave(&port->lock, lock_flags); ++ uart_port_lock_irqsave(port, &lock_flags); + if (break_state == -1) + channel->ch_bd->bd_ops->send_break(channel); + else + channel->ch_bd->bd_ops->clear_break(channel); + +- spin_unlock_irqrestore(&port->lock, lock_flags); ++ uart_port_unlock_irqrestore(port, lock_flags); + } + + static int jsm_tty_open(struct uart_port *port) +@@ -241,7 +241,7 @@ static int jsm_tty_open(struct uart_port *port) + channel->ch_cached_lsr = 0; + channel->ch_stops_sent = 0; + +- spin_lock_irqsave(&port->lock, lock_flags); ++ uart_port_lock_irqsave(port, &lock_flags); + termios = &port->state->port.tty->termios; + channel->ch_c_cflag = termios->c_cflag; + channel->ch_c_iflag = termios->c_iflag; +@@ -261,7 +261,7 @@ static int jsm_tty_open(struct uart_port *port) + jsm_carrier(channel); + + channel->ch_open_count++; +- spin_unlock_irqrestore(&port->lock, lock_flags); ++ uart_port_unlock_irqrestore(port, lock_flags); + + jsm_dbg(OPEN, &channel->ch_bd->pci_dev, "finish\n"); + return 0; +@@ -307,7 +307,7 @@ static void jsm_tty_set_termios(struct uart_port *port, + struct jsm_channel *channel = + container_of(port, struct jsm_channel, uart_port); + +- spin_lock_irqsave(&port->lock, lock_flags); ++ uart_port_lock_irqsave(port, &lock_flags); + channel->ch_c_cflag = termios->c_cflag; + channel->ch_c_iflag = termios->c_iflag; + channel->ch_c_oflag = termios->c_oflag; +@@ -317,7 +317,7 @@ static void jsm_tty_set_termios(struct uart_port *port, + + channel->ch_bd->bd_ops->param(channel); + jsm_carrier(channel); +- spin_unlock_irqrestore(&port->lock, lock_flags); ++ uart_port_unlock_irqrestore(port, lock_flags); + } + + static const char *jsm_tty_type(struct uart_port *port) +diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c +index d881cdd2a..a25ab1efe 100644 +--- a/drivers/tty/serial/liteuart.c ++++ b/drivers/tty/serial/liteuart.c +@@ -139,13 +139,13 @@ static irqreturn_t liteuart_interrupt(int irq, void *data) + * if polling, the context would be "in_serving_softirq", so use + * irq[save|restore] spin_lock variants to cover all possibilities + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + isr = litex_read8(port->membase + OFF_EV_PENDING) & uart->irq_reg; + if (isr & EV_RX) + liteuart_rx_chars(port); + if (isr & EV_TX) + liteuart_tx_chars(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_RETVAL(isr); + } +@@ -195,10 +195,10 @@ static int liteuart_startup(struct uart_port *port) + } + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + /* only enabling rx irqs during startup */ + liteuart_update_irq_reg(port, true, EV_RX); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (!port->irq) { + timer_setup(&uart->timer, liteuart_timer, 0); +@@ -213,9 +213,9 @@ static void liteuart_shutdown(struct uart_port *port) + struct liteuart_port *uart = to_liteuart_port(port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + liteuart_update_irq_reg(port, false, EV_RX | EV_TX); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (port->irq) + free_irq(port->irq, port); +@@ -229,13 +229,13 @@ static void liteuart_set_termios(struct uart_port *port, struct ktermios *new, + unsigned int baud; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* update baudrate */ + baud = uart_get_baud_rate(port, new, old, 0, 460800); + uart_update_timeout(port, new->c_cflag, baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *liteuart_type(struct uart_port *port) +@@ -382,9 +382,9 @@ static void liteuart_console_write(struct console *co, const char *s, + uart = (struct liteuart_port *)xa_load(&liteuart_array, co->index); + port = &uart->port; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + uart_console_write(port, s, count, liteuart_putchar); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int liteuart_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c +index b38fe4728..5149a947b 100644 +--- a/drivers/tty/serial/lpc32xx_hs.c ++++ b/drivers/tty/serial/lpc32xx_hs.c +@@ -140,15 +140,15 @@ static void lpc32xx_hsuart_console_write(struct console *co, const char *s, + if (up->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&up->port.lock); ++ locked = uart_port_trylock(&up->port); + else +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + + uart_console_write(&up->port, s, count, lpc32xx_hsuart_console_putchar); + wait_for_xmit_empty(&up->port); + + if (locked) +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + local_irq_restore(flags); + } + +@@ -298,7 +298,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) + struct tty_port *tport = &port->state->port; + u32 status; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + /* Read UART status and clear latched interrupts */ + status = readl(LPC32XX_HSUART_IIR(port->membase)); +@@ -333,7 +333,7 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id) + __serial_lpc32xx_tx(port); + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -404,14 +404,14 @@ static void serial_lpc32xx_break_ctl(struct uart_port *port, + unsigned long flags; + u32 tmp; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); + if (break_state != 0) + tmp |= LPC32XX_HSU_BREAK; + else + tmp &= ~LPC32XX_HSU_BREAK; + writel(tmp, LPC32XX_HSUART_CTRL(port->membase)); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* port->lock is not held. */ +@@ -421,7 +421,7 @@ static int serial_lpc32xx_startup(struct uart_port *port) + unsigned long flags; + u32 tmp; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + __serial_uart_flush(port); + +@@ -441,7 +441,7 @@ static int serial_lpc32xx_startup(struct uart_port *port) + + lpc32xx_loopback_set(port->mapbase, 0); /* get out of loopback mode */ + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + retval = request_irq(port->irq, serial_lpc32xx_interrupt, + 0, MODNAME, port); +@@ -458,7 +458,7 @@ static void serial_lpc32xx_shutdown(struct uart_port *port) + u32 tmp; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + tmp = LPC32XX_HSU_TX_TL8B | LPC32XX_HSU_RX_TL32B | + LPC32XX_HSU_OFFSET(20) | LPC32XX_HSU_TMO_INACT_4B; +@@ -466,7 +466,7 @@ static void serial_lpc32xx_shutdown(struct uart_port *port) + + lpc32xx_loopback_set(port->mapbase, 1); /* go to loopback mode */ + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + free_irq(port->irq, port); + } +@@ -491,7 +491,7 @@ static void serial_lpc32xx_set_termios(struct uart_port *port, + + quot = __serial_get_clock_div(port->uartclk, baud); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Ignore characters? */ + tmp = readl(LPC32XX_HSUART_CTRL(port->membase)); +@@ -505,7 +505,7 @@ static void serial_lpc32xx_set_termios(struct uart_port *port, + + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Don't rewrite B0 */ + if (tty_termios_baud_rate(termios)) +diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c +index 99225f1e0..faccd772c 100644 +--- a/drivers/tty/serial/ma35d1_serial.c ++++ b/drivers/tty/serial/ma35d1_serial.c +@@ -269,16 +269,16 @@ static void receive_chars(struct uart_ma35d1_port *up) + if (uart_handle_sysrq_char(&up->port, ch)) + continue; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + uart_insert_char(&up->port, fsr, MA35_FSR_RX_OVER_IF, ch, flag); +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + fsr = serial_in(up, MA35_FSR_REG); + } while (!(fsr & MA35_FSR_RX_EMPTY) && (max_count-- > 0)); + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + tty_flip_buffer_push(&up->port.state->port); +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + } + + static irqreturn_t ma35d1serial_interrupt(int irq, void *dev_id) +@@ -364,14 +364,14 @@ static void ma35d1serial_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + u32 lcr; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + lcr = serial_in(up, MA35_LCR_REG); + if (break_state != 0) + lcr |= MA35_LCR_BREAK; + else + lcr &= ~MA35_LCR_BREAK; + serial_out(up, MA35_LCR_REG, lcr); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int ma35d1serial_startup(struct uart_port *port) +@@ -441,7 +441,7 @@ static void ma35d1serial_set_termios(struct uart_port *port, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + up->port.read_status_mask = MA35_FSR_RX_OVER_IF; + if (termios->c_iflag & INPCK) +@@ -475,7 +475,7 @@ static void ma35d1serial_set_termios(struct uart_port *port, + + serial_out(up, MA35_LCR_REG, lcr); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static const char *ma35d1serial_type(struct uart_port *port) +@@ -568,9 +568,9 @@ static void ma35d1serial_console_write(struct console *co, const char *s, u32 co + if (up->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&up->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&up->port, &flags); + else +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * First save the IER then disable the interrupts +@@ -584,7 +584,7 @@ static void ma35d1serial_console_write(struct console *co, const char *s, u32 co + serial_out(up, MA35_IER_REG, ier); + + if (locked) +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int __init ma35d1serial_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c +index aea29b4e6..ee40af20a 100644 +--- a/drivers/tty/serial/mcf.c ++++ b/drivers/tty/serial/mcf.c +@@ -135,12 +135,12 @@ static void mcf_break_ctl(struct uart_port *port, int break_state) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (break_state == -1) + writeb(MCFUART_UCR_CMDBREAKSTART, port->membase + MCFUART_UCR); + else + writeb(MCFUART_UCR_CMDBREAKSTOP, port->membase + MCFUART_UCR); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /****************************************************************************/ +@@ -150,7 +150,7 @@ static int mcf_startup(struct uart_port *port) + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Reset UART, get it into known state... */ + writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); +@@ -164,7 +164,7 @@ static int mcf_startup(struct uart_port *port) + pp->imr = MCFUART_UIR_RXREADY; + writeb(pp->imr, port->membase + MCFUART_UIMR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -176,7 +176,7 @@ static void mcf_shutdown(struct uart_port *port) + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable all interrupts now */ + pp->imr = 0; +@@ -186,7 +186,7 @@ static void mcf_shutdown(struct uart_port *port) + writeb(MCFUART_UCR_CMDRESETRX, port->membase + MCFUART_UCR); + writeb(MCFUART_UCR_CMDRESETTX, port->membase + MCFUART_UCR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /****************************************************************************/ +@@ -252,7 +252,7 @@ static void mcf_set_termios(struct uart_port *port, struct ktermios *termios, + mr2 |= MCFUART_MR2_TXCTS; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (port->rs485.flags & SER_RS485_ENABLED) { + dev_dbg(port->dev, "Setting UART to RS485\n"); + mr2 |= MCFUART_MR2_TXRTS; +@@ -273,7 +273,7 @@ static void mcf_set_termios(struct uart_port *port, struct ktermios *termios, + port->membase + MCFUART_UCSR); + writeb(MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE, + port->membase + MCFUART_UCR); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /****************************************************************************/ +@@ -350,7 +350,7 @@ static irqreturn_t mcf_interrupt(int irq, void *data) + + isr = readb(port->membase + MCFUART_UISR) & pp->imr; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + if (isr & MCFUART_UIR_RXREADY) { + mcf_rx_chars(pp); + ret = IRQ_HANDLED; +@@ -359,7 +359,7 @@ static irqreturn_t mcf_interrupt(int irq, void *data) + mcf_tx_chars(pp); + ret = IRQ_HANDLED; + } +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return ret; + } +diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c +index d2502aaa3..8048fa542 100644 +--- a/drivers/tty/serial/men_z135_uart.c ++++ b/drivers/tty/serial/men_z135_uart.c +@@ -392,7 +392,7 @@ static irqreturn_t men_z135_intr(int irq, void *data) + if (!irq_id) + goto out; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + /* It's save to write to IIR[7:6] RXC[9:8] */ + iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG); + +@@ -418,7 +418,7 @@ static irqreturn_t men_z135_intr(int irq, void *data) + handled = true; + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + out: + return IRQ_RETVAL(handled); + } +@@ -708,7 +708,7 @@ static void men_z135_set_termios(struct uart_port *port, + + baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16); + +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); + +@@ -716,7 +716,7 @@ static void men_z135_set_termios(struct uart_port *port, + iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG); + + uart_update_timeout(port, termios->c_cflag, baud); +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + } + + static const char *men_z135_type(struct uart_port *port) +diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c +index 9388b9dde..4c1d2089a 100644 +--- a/drivers/tty/serial/meson_uart.c ++++ b/drivers/tty/serial/meson_uart.c +@@ -129,14 +129,14 @@ static void meson_uart_shutdown(struct uart_port *port) + + free_irq(port->irq, port); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = readl(port->membase + AML_UART_CONTROL); + val &= ~AML_UART_RX_EN; + val &= ~(AML_UART_RX_INT_EN | AML_UART_TX_INT_EN); + writel(val, port->membase + AML_UART_CONTROL); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void meson_uart_start_tx(struct uart_port *port) +@@ -238,7 +238,7 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id) + { + struct uart_port *port = (struct uart_port *)dev_id; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + if (!(readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY)) + meson_receive_chars(port); +@@ -248,7 +248,7 @@ static irqreturn_t meson_uart_interrupt(int irq, void *dev_id) + meson_uart_start_tx(port); + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -284,7 +284,7 @@ static int meson_uart_startup(struct uart_port *port) + u32 val; + int ret = 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = readl(port->membase + AML_UART_CONTROL); + val |= AML_UART_CLEAR_ERR; +@@ -301,7 +301,7 @@ static int meson_uart_startup(struct uart_port *port) + val = (AML_UART_RECV_IRQ(1) | AML_UART_XMIT_IRQ(port->fifosize / 2)); + writel(val, port->membase + AML_UART_MISC); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + ret = request_irq(port->irq, meson_uart_interrupt, 0, + port->name, port); +@@ -341,7 +341,7 @@ static void meson_uart_set_termios(struct uart_port *port, + unsigned long flags; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + cflags = termios->c_cflag; + iflags = termios->c_iflag; +@@ -405,7 +405,7 @@ static void meson_uart_set_termios(struct uart_port *port, + AML_UART_FRAME_ERR; + + uart_update_timeout(port, termios->c_cflag, baud); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int meson_uart_verify_port(struct uart_port *port, +@@ -464,14 +464,14 @@ static int meson_uart_poll_get_char(struct uart_port *port) + u32 c; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (readl(port->membase + AML_UART_STATUS) & AML_UART_RX_EMPTY) + c = NO_POLL_CHAR; + else + c = readl(port->membase + AML_UART_RFIFO); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return c; + } +@@ -482,7 +482,7 @@ static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c) + u32 reg; + int ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Wait until FIFO is empty or timeout */ + ret = readl_poll_timeout_atomic(port->membase + AML_UART_STATUS, reg, +@@ -506,7 +506,7 @@ static void meson_uart_poll_put_char(struct uart_port *port, unsigned char c) + dev_err(port->dev, "Timeout waiting for UART TX EMPTY\n"); + + out: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + #endif /* CONFIG_CONSOLE_POLL */ +@@ -563,9 +563,9 @@ static void meson_serial_port_write(struct uart_port *port, const char *s, + if (port->sysrq) { + locked = 0; + } else if (oops_in_progress) { +- locked = spin_trylock(&port->lock); ++ locked = uart_port_trylock(port); + } else { +- spin_lock(&port->lock); ++ uart_port_lock(port); + locked = 1; + } + +@@ -577,7 +577,7 @@ static void meson_serial_port_write(struct uart_port *port, const char *s, + writel(val, port->membase + AML_UART_CONTROL); + + if (locked) +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + local_irq_restore(flags); + } + +diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbeaut_usio.c +index 70a910085..db3b81f2a 100644 +--- a/drivers/tty/serial/milbeaut_usio.c ++++ b/drivers/tty/serial/milbeaut_usio.c +@@ -207,9 +207,9 @@ static irqreturn_t mlb_usio_rx_irq(int irq, void *dev_id) + { + struct uart_port *port = dev_id; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + mlb_usio_rx_chars(port); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -218,10 +218,10 @@ static irqreturn_t mlb_usio_tx_irq(int irq, void *dev_id) + { + struct uart_port *port = dev_id; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + if (readb(port->membase + MLB_USIO_REG_SSR) & MLB_USIO_SSR_TBI) + mlb_usio_tx_chars(port); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -267,7 +267,7 @@ static int mlb_usio_startup(struct uart_port *port) + escr = readb(port->membase + MLB_USIO_REG_ESCR); + if (of_property_read_bool(port->dev->of_node, "auto-flow-control")) + escr |= MLB_USIO_ESCR_FLWEN; +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + writeb(0, port->membase + MLB_USIO_REG_SCR); + writeb(escr, port->membase + MLB_USIO_REG_ESCR); + writeb(MLB_USIO_SCR_UPCL, port->membase + MLB_USIO_REG_SCR); +@@ -282,7 +282,7 @@ static int mlb_usio_startup(struct uart_port *port) + + writeb(MLB_USIO_SCR_TXE | MLB_USIO_SCR_RIE | MLB_USIO_SCR_TBIE | + MLB_USIO_SCR_RXE, port->membase + MLB_USIO_REG_SCR); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -337,7 +337,7 @@ static void mlb_usio_set_termios(struct uart_port *port, + else + quot = 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + uart_update_timeout(port, termios->c_cflag, baud); + port->read_status_mask = MLB_USIO_SSR_ORE | MLB_USIO_SSR_RDRF | + MLB_USIO_SSR_TDRE; +@@ -367,7 +367,7 @@ static void mlb_usio_set_termios(struct uart_port *port, + writew(BIT(12), port->membase + MLB_USIO_REG_FBYTE); + writeb(MLB_USIO_SCR_RIE | MLB_USIO_SCR_RXE | MLB_USIO_SCR_TBIE | + MLB_USIO_SCR_TXE, port->membase + MLB_USIO_REG_SCR); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *mlb_usio_type(struct uart_port *port) +diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c +index 916507b8f..a252465e7 100644 +--- a/drivers/tty/serial/mpc52xx_uart.c ++++ b/drivers/tty/serial/mpc52xx_uart.c +@@ -1096,14 +1096,14 @@ static void + mpc52xx_uart_break_ctl(struct uart_port *port, int ctl) + { + unsigned long flags; +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (ctl == -1) + psc_ops->command(port, MPC52xx_PSC_START_BRK); + else + psc_ops->command(port, MPC52xx_PSC_STOP_BRK); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int +@@ -1214,7 +1214,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, + } + + /* Get the lock */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Do our best to flush TX & RX, so we don't lose anything */ + /* But we don't wait indefinitely ! */ +@@ -1250,7 +1250,7 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, + psc_ops->command(port, MPC52xx_PSC_RX_ENABLE); + + /* We're all set, release the lock */ +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char * +@@ -1477,11 +1477,11 @@ mpc52xx_uart_int(int irq, void *dev_id) + struct uart_port *port = dev_id; + irqreturn_t ret; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + ret = psc_ops->handle_irq(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return ret; + } +diff --git a/drivers/tty/serial/mps2-uart.c b/drivers/tty/serial/mps2-uart.c +index ea5a7911c..2a4c09f3a 100644 +--- a/drivers/tty/serial/mps2-uart.c ++++ b/drivers/tty/serial/mps2-uart.c +@@ -188,12 +188,12 @@ static irqreturn_t mps2_uart_rxirq(int irq, void *data) + if (unlikely(!(irqflag & UARTn_INT_RX))) + return IRQ_NONE; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + mps2_uart_write8(port, UARTn_INT_RX, UARTn_INT); + mps2_uart_rx_chars(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -206,12 +206,12 @@ static irqreturn_t mps2_uart_txirq(int irq, void *data) + if (unlikely(!(irqflag & UARTn_INT_TX))) + return IRQ_NONE; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + mps2_uart_write8(port, UARTn_INT_TX, UARTn_INT); + mps2_uart_tx_chars(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -222,7 +222,7 @@ static irqreturn_t mps2_uart_oerrirq(int irq, void *data) + struct uart_port *port = data; + u8 irqflag = mps2_uart_read8(port, UARTn_INT); + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + if (irqflag & UARTn_INT_RX_OVERRUN) { + struct tty_port *tport = &port->state->port; +@@ -244,7 +244,7 @@ static irqreturn_t mps2_uart_oerrirq(int irq, void *data) + handled = IRQ_HANDLED; + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return handled; + } +@@ -356,12 +356,12 @@ mps2_uart_set_termios(struct uart_port *port, struct ktermios *termios, + + bauddiv = DIV_ROUND_CLOSEST(port->uartclk, baud); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_update_timeout(port, termios->c_cflag, baud); + mps2_uart_write32(port, bauddiv, UARTn_BAUDDIV); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); +diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c +index 90953e679..597264b54 100644 +--- a/drivers/tty/serial/msm_serial.c ++++ b/drivers/tty/serial/msm_serial.c +@@ -444,7 +444,7 @@ static void msm_complete_tx_dma(void *args) + unsigned int count; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Already stopped */ + if (!dma->count) +@@ -476,7 +476,7 @@ static void msm_complete_tx_dma(void *args) + + msm_handle_tx(port); + done: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int msm_handle_tx_dma(struct msm_port *msm_port, unsigned int count) +@@ -549,7 +549,7 @@ static void msm_complete_rx_dma(void *args) + unsigned long flags; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Already stopped */ + if (!dma->count) +@@ -587,16 +587,16 @@ static void msm_complete_rx_dma(void *args) + if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) + flag = TTY_NORMAL; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + sysrq = uart_handle_sysrq_char(port, dma->virt[i]); +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (!sysrq) + tty_insert_flip_char(tport, dma->virt[i], flag); + } + + msm_start_rx_dma(msm_port); + done: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (count) + tty_flip_buffer_push(tport); +@@ -762,9 +762,9 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) + if (!(port->read_status_mask & MSM_UART_SR_RX_BREAK)) + flag = TTY_NORMAL; + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + sysrq = uart_handle_sysrq_char(port, buf[i]); +- spin_lock(&port->lock); ++ uart_port_lock(port); + if (!sysrq) + tty_insert_flip_char(tport, buf[i], flag); + } +@@ -824,9 +824,9 @@ static void msm_handle_rx(struct uart_port *port) + else if (sr & MSM_UART_SR_PAR_FRAME_ERR) + flag = TTY_FRAME; + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + sysrq = uart_handle_sysrq_char(port, c); +- spin_lock(&port->lock); ++ uart_port_lock(port); + if (!sysrq) + tty_insert_flip_char(tport, c, flag); + } +@@ -951,7 +951,7 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) + unsigned int misr; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + misr = msm_read(port, MSM_UART_MISR); + msm_write(port, 0, MSM_UART_IMR); /* disable interrupt */ + +@@ -983,7 +983,7 @@ static irqreturn_t msm_uart_irq(int irq, void *dev_id) + msm_handle_delta_cts(port); + + msm_write(port, msm_port->imr, MSM_UART_IMR); /* restore interrupt */ +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -1128,13 +1128,13 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud, + unsigned long flags, rate; + + flags = *saved_flags; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + entry = msm_find_best_baud(port, baud, &rate); + clk_set_rate(msm_port->clk, rate); + baud = rate / 16 / entry->divisor; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + *saved_flags = flags; + port->uartclk = rate; + +@@ -1266,7 +1266,7 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios, + unsigned long flags; + unsigned int baud, mr; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (dma->chan) /* Terminate if any */ + msm_stop_dma(port, dma); +@@ -1338,7 +1338,7 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios, + /* Try to use DMA */ + msm_start_rx_dma(msm_port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *msm_type(struct uart_port *port) +@@ -1620,9 +1620,9 @@ static void __msm_console_write(struct uart_port *port, const char *s, + if (port->sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&port->lock); ++ locked = uart_port_trylock(port); + else +- spin_lock(&port->lock); ++ uart_port_lock(port); + + if (is_uartdm) + msm_reset_dm_count(port, count); +@@ -1661,7 +1661,7 @@ static void __msm_console_write(struct uart_port *port, const char *s, + } + + if (locked) +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + local_irq_restore(flags); + } +diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c +index ea924e9b9..0255646bc 100644 +--- a/drivers/tty/serial/mvebu-uart.c ++++ b/drivers/tty/serial/mvebu-uart.c +@@ -187,9 +187,9 @@ static unsigned int mvebu_uart_tx_empty(struct uart_port *port) + unsigned long flags; + unsigned int st; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + st = readl(port->membase + UART_STAT); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return (st & STAT_TX_EMP) ? TIOCSER_TEMT : 0; + } +@@ -249,14 +249,14 @@ static void mvebu_uart_break_ctl(struct uart_port *port, int brk) + unsigned int ctl; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ctl = readl(port->membase + UART_CTRL(port)); + if (brk == -1) + ctl |= CTRL_SND_BRK_SEQ; + else + ctl &= ~CTRL_SND_BRK_SEQ; + writel(ctl, port->membase + UART_CTRL(port)); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void mvebu_uart_rx_chars(struct uart_port *port, unsigned int status) +@@ -540,7 +540,7 @@ static void mvebu_uart_set_termios(struct uart_port *port, + unsigned long flags; + unsigned int baud, min_baud, max_baud; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + port->read_status_mask = STAT_RX_RDY(port) | STAT_OVR_ERR | + STAT_TX_RDY(port) | STAT_TX_FIFO_FUL; +@@ -589,7 +589,7 @@ static void mvebu_uart_set_termios(struct uart_port *port, + uart_update_timeout(port, termios->c_cflag, baud); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *mvebu_uart_type(struct uart_port *port) +@@ -735,9 +735,9 @@ static void mvebu_uart_console_write(struct console *co, const char *s, + int locked = 1; + + if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ier = readl(port->membase + UART_CTRL(port)) & CTRL_BRK_INT; + intr = readl(port->membase + UART_INTR(port)) & +@@ -758,7 +758,7 @@ static void mvebu_uart_console_write(struct console *co, const char *s, + } + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int mvebu_uart_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c +index 135a838f5..1097fca22 100644 +--- a/drivers/tty/serial/omap-serial.c ++++ b/drivers/tty/serial/omap-serial.c +@@ -390,10 +390,10 @@ static void serial_omap_throttle(struct uart_port *port) + struct uart_omap_port *up = to_uart_omap_port(port); + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + serial_out(up, UART_IER, up->ier); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static void serial_omap_unthrottle(struct uart_port *port) +@@ -401,10 +401,10 @@ static void serial_omap_unthrottle(struct uart_port *port) + struct uart_omap_port *up = to_uart_omap_port(port); + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + up->ier |= UART_IER_RLSI | UART_IER_RDI; + serial_out(up, UART_IER, up->ier); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static unsigned int check_modem_status(struct uart_omap_port *up) +@@ -527,7 +527,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) + irqreturn_t ret = IRQ_NONE; + int max_count = 256; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + + do { + iir = serial_in(up, UART_IIR); +@@ -563,7 +563,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) + } + } while (max_count--); + +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + tty_flip_buffer_push(&up->port.state->port); + +@@ -579,9 +579,9 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port) + unsigned int ret = 0; + + dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line); +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return ret; + } +@@ -647,13 +647,13 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + + dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line); +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_out(up, UART_LCR, up->lcr); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int serial_omap_startup(struct uart_port *port) +@@ -701,13 +701,13 @@ static int serial_omap_startup(struct uart_port *port) + * Now, initialize the UART + */ + serial_out(up, UART_LCR, UART_LCR_WLEN8); +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + /* + * Most PC uarts need OUT2 raised to enable interrupts. + */ + up->port.mctrl |= TIOCM_OUT2; + serial_omap_set_mctrl(&up->port, up->port.mctrl); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + up->msr_saved_flags = 0; + /* +@@ -742,10 +742,10 @@ static void serial_omap_shutdown(struct uart_port *port) + up->ier = 0; + serial_out(up, UART_IER, 0); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + up->port.mctrl &= ~TIOCM_OUT2; + serial_omap_set_mctrl(&up->port, up->port.mctrl); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + /* + * Disable break condition and FIFOs +@@ -815,7 +815,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * Update the per-port timeout. +@@ -1013,7 +1013,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, + + serial_omap_set_mctrl(&up->port, up->port.mctrl); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line); + } + +@@ -1212,13 +1212,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 = uart_port_trylock_irqsave(&up->port, &flags); + else +- spin_lock(&up->port.lock); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * First save the IER then disable the interrupts +@@ -1245,8 +1242,7 @@ serial_omap_console_write(struct console *co, const char *s, + check_modem_status(up); + + if (locked) +- spin_unlock(&up->port.lock); +- local_irq_restore(flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int __init +diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c +index e99970a94..919f5e5aa 100644 +--- a/drivers/tty/serial/owl-uart.c ++++ b/drivers/tty/serial/owl-uart.c +@@ -125,12 +125,12 @@ static unsigned int owl_uart_tx_empty(struct uart_port *port) + u32 val; + unsigned int ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = owl_uart_read(port, OWL_UART_STAT); + ret = (val & OWL_UART_STAT_TFES) ? TIOCSER_TEMT : 0; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return ret; + } +@@ -232,7 +232,7 @@ static irqreturn_t owl_uart_irq(int irq, void *dev_id) + unsigned long flags; + u32 stat; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + stat = owl_uart_read(port, OWL_UART_STAT); + +@@ -246,7 +246,7 @@ static irqreturn_t owl_uart_irq(int irq, void *dev_id) + stat |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP; + owl_uart_write(port, stat, OWL_UART_STAT); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -256,14 +256,14 @@ static void owl_uart_shutdown(struct uart_port *port) + u32 val; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = owl_uart_read(port, OWL_UART_CTL); + val &= ~(OWL_UART_CTL_TXIE | OWL_UART_CTL_RXIE + | OWL_UART_CTL_TXDE | OWL_UART_CTL_RXDE | OWL_UART_CTL_EN); + owl_uart_write(port, val, OWL_UART_CTL); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + free_irq(port->irq, port); + } +@@ -279,7 +279,7 @@ static int owl_uart_startup(struct uart_port *port) + if (ret) + return ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = owl_uart_read(port, OWL_UART_STAT); + val |= OWL_UART_STAT_RIP | OWL_UART_STAT_TIP +@@ -291,7 +291,7 @@ static int owl_uart_startup(struct uart_port *port) + val |= OWL_UART_CTL_EN; + owl_uart_write(port, val, OWL_UART_CTL); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -311,7 +311,7 @@ static void owl_uart_set_termios(struct uart_port *port, + u32 ctl; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ctl = owl_uart_read(port, OWL_UART_CTL); + +@@ -371,7 +371,7 @@ static void owl_uart_set_termios(struct uart_port *port, + + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void owl_uart_release_port(struct uart_port *port) +@@ -515,9 +515,9 @@ static void owl_uart_port_write(struct uart_port *port, const char *s, + if (port->sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&port->lock); ++ locked = uart_port_trylock(port); + else { +- spin_lock(&port->lock); ++ uart_port_lock(port); + locked = 1; + } + +@@ -541,7 +541,7 @@ static void owl_uart_port_write(struct uart_port *port, const char *s, + owl_uart_write(port, old_ctl, OWL_UART_CTL); + + if (locked) +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + local_irq_restore(flags); + } +diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c +index cc83b772b..436cc6d52 100644 +--- a/drivers/tty/serial/pch_uart.c ++++ b/drivers/tty/serial/pch_uart.c +@@ -1347,7 +1347,7 @@ static void pch_uart_set_termios(struct uart_port *port, + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); + + spin_lock_irqsave(&priv->lock, flags); +- spin_lock(&port->lock); ++ uart_port_lock(port); + + uart_update_timeout(port, termios->c_cflag, baud); + rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); +@@ -1360,7 +1360,7 @@ static void pch_uart_set_termios(struct uart_port *port, + tty_termios_encode_baud_rate(termios, baud, baud); + + out: +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + spin_unlock_irqrestore(&priv->lock, flags); + } + +@@ -1581,10 +1581,10 @@ pch_console_write(struct console *co, const char *s, unsigned int count) + port_locked = 0; + } else if (oops_in_progress) { + priv_locked = spin_trylock(&priv->lock); +- port_locked = spin_trylock(&priv->port.lock); ++ port_locked = uart_port_trylock(&priv->port); + } else { + spin_lock(&priv->lock); +- spin_lock(&priv->port.lock); ++ uart_port_lock(&priv->port); + } + + /* +@@ -1604,7 +1604,7 @@ pch_console_write(struct console *co, const char *s, unsigned int count) + iowrite8(ier, priv->membase + UART_IER); + + if (port_locked) +- spin_unlock(&priv->port.lock); ++ uart_port_unlock(&priv->port); + if (priv_locked) + spin_unlock(&priv->lock); + local_irq_restore(flags); +diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c +index e308d5022..3a95bf5d5 100644 +--- a/drivers/tty/serial/pic32_uart.c ++++ b/drivers/tty/serial/pic32_uart.c +@@ -243,7 +243,7 @@ static void pic32_uart_break_ctl(struct uart_port *port, int ctl) + struct pic32_sport *sport = to_pic32_sport(port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (ctl) + pic32_uart_writel(sport, PIC32_SET(PIC32_UART_STA), +@@ -252,7 +252,7 @@ static void pic32_uart_break_ctl(struct uart_port *port, int ctl) + pic32_uart_writel(sport, PIC32_CLR(PIC32_UART_STA), + PIC32_UART_STA_UTXBRK); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* get port type in string format */ +@@ -274,7 +274,7 @@ static void pic32_uart_do_rx(struct uart_port *port) + */ + max_count = PIC32_UART_RX_FIFO_DEPTH; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + tty = &port->state->port; + +@@ -331,7 +331,7 @@ static void pic32_uart_do_rx(struct uart_port *port) + + } while (--max_count); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + tty_flip_buffer_push(tty); + } +@@ -410,9 +410,9 @@ static irqreturn_t pic32_uart_tx_interrupt(int irq, void *dev_id) + struct uart_port *port = dev_id; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + pic32_uart_do_tx(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -580,9 +580,9 @@ static void pic32_uart_shutdown(struct uart_port *port) + unsigned long flags; + + /* disable uart */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + pic32_uart_dsbl_and_mask(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + clk_disable_unprepare(sport->clk); + + /* free all 3 interrupts for this UART */ +@@ -604,7 +604,7 @@ static void pic32_uart_set_termios(struct uart_port *port, + unsigned int quot; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* disable uart and mask all interrupts while changing speed */ + pic32_uart_dsbl_and_mask(port); +@@ -672,7 +672,7 @@ static void pic32_uart_set_termios(struct uart_port *port, + /* enable uart */ + pic32_uart_en_and_unmask(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* serial core request to claim uart iomem */ +diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c +index 29bc80d39..77691fbbf 100644 +--- a/drivers/tty/serial/pmac_zilog.c ++++ b/drivers/tty/serial/pmac_zilog.c +@@ -245,9 +245,9 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap) + #endif /* USE_CTRL_O_SYSRQ */ + if (uap->port.sysrq) { + int swallow; +- spin_unlock(&uap->port.lock); ++ uart_port_unlock(&uap->port); + swallow = uart_handle_sysrq_char(&uap->port, ch); +- spin_lock(&uap->port.lock); ++ uart_port_lock(&uap->port); + if (swallow) + goto next_char; + } +@@ -421,7 +421,7 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id) + uap_a = pmz_get_port_A(uap); + uap_b = uap_a->mate; + +- spin_lock(&uap_a->port.lock); ++ uart_port_lock(&uap_a->port); + r3 = read_zsreg(uap_a, R3); + + /* Channel A */ +@@ -442,14 +442,14 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id) + rc = IRQ_HANDLED; + } + skip_a: +- spin_unlock(&uap_a->port.lock); ++ uart_port_unlock(&uap_a->port); + if (push) + tty_flip_buffer_push(&uap->port.state->port); + + if (!uap_b) + goto out; + +- spin_lock(&uap_b->port.lock); ++ uart_port_lock(&uap_b->port); + push = false; + if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { + if (!ZS_IS_OPEN(uap_b)) { +@@ -467,7 +467,7 @@ static irqreturn_t pmz_interrupt(int irq, void *dev_id) + rc = IRQ_HANDLED; + } + skip_b: +- spin_unlock(&uap_b->port.lock); ++ uart_port_unlock(&uap_b->port); + if (push) + tty_flip_buffer_push(&uap->port.state->port); + +@@ -483,9 +483,9 @@ static inline u8 pmz_peek_status(struct uart_pmac_port *uap) + unsigned long flags; + u8 status; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + status = read_zsreg(uap, R0); +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + + return status; + } +@@ -671,7 +671,7 @@ static void pmz_break_ctl(struct uart_port *port, int break_state) + else + clear_bits |= SND_BRK; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits; + if (new_reg != uap->curregs[R5]) { +@@ -679,7 +679,7 @@ static void pmz_break_ctl(struct uart_port *port, int break_state) + write_zsreg(uap, R5, uap->curregs[R5]); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + #ifdef CONFIG_PPC_PMAC +@@ -851,18 +851,18 @@ static void pmz_irda_reset(struct uart_pmac_port *uap) + { + unsigned long flags; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + uap->curregs[R5] |= DTR; + write_zsreg(uap, R5, uap->curregs[R5]); + zssync(uap); +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + msleep(110); + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + uap->curregs[R5] &= ~DTR; + write_zsreg(uap, R5, uap->curregs[R5]); + zssync(uap); +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + msleep(10); + } + +@@ -882,9 +882,9 @@ static int pmz_startup(struct uart_port *port) + * initialize the chip + */ + if (!ZS_IS_CONS(uap)) { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + pwr_delay = __pmz_startup(uap); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + sprintf(uap->irq_name, PMACZILOG_NAME"%d", uap->port.line); + if (request_irq(uap->port.irq, pmz_interrupt, IRQF_SHARED, +@@ -907,9 +907,9 @@ static int pmz_startup(struct uart_port *port) + pmz_irda_reset(uap); + + /* Enable interrupt requests for the channel */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + pmz_interrupt_control(uap, 1); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -919,7 +919,7 @@ static void pmz_shutdown(struct uart_port *port) + struct uart_pmac_port *uap = to_pmz(port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable interrupt requests for the channel */ + pmz_interrupt_control(uap, 0); +@@ -934,19 +934,19 @@ static void pmz_shutdown(struct uart_port *port) + pmz_maybe_update_regs(uap); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Release interrupt handler */ + free_irq(uap->port.irq, uap); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uap->flags &= ~PMACZILOG_FLAG_IS_OPEN; + + if (!ZS_IS_CONS(uap)) + pmz_set_scc_power(uap, 0); /* Shut the chip down */ + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* Shared by TTY driver and serial console setup. The port lock is held +@@ -1233,7 +1233,7 @@ static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + struct uart_pmac_port *uap = to_pmz(port); + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable IRQs on the port */ + pmz_interrupt_control(uap, 0); +@@ -1245,7 +1245,7 @@ static void pmz_set_termios(struct uart_port *port, struct ktermios *termios, + if (ZS_IS_OPEN(uap)) + pmz_interrupt_control(uap, 1); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *pmz_type(struct uart_port *port) +@@ -1882,7 +1882,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c + struct uart_pmac_port *uap = &pmz_ports[con->index]; + unsigned long flags; + +- spin_lock_irqsave(&uap->port.lock, flags); ++ uart_port_lock_irqsave(&uap->port, &flags); + + /* Turn of interrupts and enable the transmitter. */ + write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); +@@ -1894,7 +1894,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c + write_zsreg(uap, R1, uap->curregs[1]); + /* Don't disable the transmitter. */ + +- spin_unlock_irqrestore(&uap->port.lock, flags); ++ uart_port_unlock_irqrestore(&uap->port, flags); + } + + /* +diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c +index 73c60f5ea..46e70e155 100644 +--- a/drivers/tty/serial/pxa.c ++++ b/drivers/tty/serial/pxa.c +@@ -225,14 +225,14 @@ static inline irqreturn_t serial_pxa_irq(int irq, void *dev_id) + iir = serial_in(up, UART_IIR); + if (iir & UART_IIR_NO_INT) + return IRQ_NONE; +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + lsr = serial_in(up, UART_LSR); + if (lsr & UART_LSR_DR) + receive_chars(up, &lsr); + check_modem_status(up); + if (lsr & UART_LSR_THRE) + transmit_chars(up); +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + return IRQ_HANDLED; + } + +@@ -242,9 +242,9 @@ static unsigned int serial_pxa_tx_empty(struct uart_port *port) + unsigned long flags; + unsigned int ret; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return ret; + } +@@ -295,13 +295,13 @@ static void serial_pxa_break_ctl(struct uart_port *port, int break_state) + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_out(up, UART_LCR, up->lcr); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int serial_pxa_startup(struct uart_port *port) +@@ -346,10 +346,10 @@ static int serial_pxa_startup(struct uart_port *port) + */ + serial_out(up, UART_LCR, UART_LCR_WLEN8); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + up->port.mctrl |= TIOCM_OUT2; + serial_pxa_set_mctrl(&up->port, up->port.mctrl); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + /* + * Finally, enable interrupts. Note: Modem status interrupts +@@ -383,10 +383,10 @@ static void serial_pxa_shutdown(struct uart_port *port) + up->ier = 0; + serial_out(up, UART_IER, 0); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + up->port.mctrl &= ~TIOCM_OUT2; + serial_pxa_set_mctrl(&up->port, up->port.mctrl); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + /* + * Disable break condition and FIFOs +@@ -434,7 +434,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * Ensure the port will be enabled. +@@ -504,7 +504,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, + up->lcr = cval; /* Save LCR */ + serial_pxa_set_mctrl(&up->port, up->port.mctrl); + serial_out(up, UART_FCR, fcr); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static void +@@ -608,9 +608,9 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) + if (up->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&up->port.lock); ++ locked = uart_port_trylock(&up->port); + else +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + + /* + * First save the IER then disable the interrupts +@@ -628,7 +628,7 @@ serial_pxa_console_write(struct console *co, const char *s, unsigned int count) + serial_out(up, UART_IER, ier); + + if (locked) +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + local_irq_restore(flags); + clk_disable(up->clk); + +diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c +index 2e1b1c827..549909644 100644 +--- a/drivers/tty/serial/qcom_geni_serial.c ++++ b/drivers/tty/serial/qcom_geni_serial.c +@@ -482,9 +482,9 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + + uport = &port->uport; + if (oops_in_progress) +- locked = spin_trylock_irqsave(&uport->lock, flags); ++ locked = uart_port_trylock_irqsave(uport, &flags); + else +- spin_lock_irqsave(&uport->lock, flags); ++ uart_port_lock_irqsave(uport, &flags); + + geni_status = readl(uport->membase + SE_GENI_STATUS); + +@@ -520,7 +520,7 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s, + qcom_geni_serial_setup_tx(uport, port->tx_remaining); + + if (locked) +- spin_unlock_irqrestore(&uport->lock, flags); ++ uart_port_unlock_irqrestore(uport, flags); + } + + static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop) +@@ -972,7 +972,7 @@ static irqreturn_t qcom_geni_serial_isr(int isr, void *dev) + if (uport->suspended) + return IRQ_NONE; + +- spin_lock(&uport->lock); ++ uart_port_lock(uport); + + m_irq_status = readl(uport->membase + SE_GENI_M_IRQ_STATUS); + s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS); +diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c +index be5c842b5..d824c8318 100644 +--- a/drivers/tty/serial/rda-uart.c ++++ b/drivers/tty/serial/rda-uart.c +@@ -139,12 +139,12 @@ static unsigned int rda_uart_tx_empty(struct uart_port *port) + unsigned int ret; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = rda_uart_read(port, RDA_UART_STATUS); + ret = (val & RDA_UART_TX_FIFO_MASK) ? TIOCSER_TEMT : 0; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return ret; + } +@@ -246,7 +246,7 @@ static void rda_uart_set_termios(struct uart_port *port, + unsigned int baud; + u32 irq_mask; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + baud = uart_get_baud_rate(port, termios, old, 9600, port->uartclk / 4); + rda_uart_change_baudrate(rda_port, baud); +@@ -325,7 +325,7 @@ static void rda_uart_set_termios(struct uart_port *port, + /* update the per-port timeout */ + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void rda_uart_send_chars(struct uart_port *port) +@@ -408,7 +408,7 @@ static irqreturn_t rda_interrupt(int irq, void *dev_id) + unsigned long flags; + u32 val, irq_mask; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Clear IRQ cause */ + val = rda_uart_read(port, RDA_UART_IRQ_CAUSE); +@@ -425,7 +425,7 @@ static irqreturn_t rda_interrupt(int irq, void *dev_id) + rda_uart_send_chars(port); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -436,16 +436,16 @@ static int rda_uart_startup(struct uart_port *port) + int ret; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + rda_uart_write(port, 0, RDA_UART_IRQ_MASK); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + ret = request_irq(port->irq, rda_interrupt, IRQF_NO_SUSPEND, + "rda-uart", port); + if (ret) + return ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + val = rda_uart_read(port, RDA_UART_CTRL); + val |= RDA_UART_ENABLE; +@@ -456,7 +456,7 @@ static int rda_uart_startup(struct uart_port *port) + val |= (RDA_UART_RX_DATA_AVAILABLE | RDA_UART_RX_TIMEOUT); + rda_uart_write(port, val, RDA_UART_IRQ_MASK); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -466,7 +466,7 @@ static void rda_uart_shutdown(struct uart_port *port) + unsigned long flags; + u32 val; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + rda_uart_stop_tx(port); + rda_uart_stop_rx(port); +@@ -475,7 +475,7 @@ static void rda_uart_shutdown(struct uart_port *port) + val &= ~RDA_UART_ENABLE; + rda_uart_write(port, val, RDA_UART_CTRL); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *rda_uart_type(struct uart_port *port) +@@ -515,7 +515,7 @@ static void rda_uart_config_port(struct uart_port *port, int flags) + rda_uart_request_port(port); + } + +- spin_lock_irqsave(&port->lock, irq_flags); ++ uart_port_lock_irqsave(port, &irq_flags); + + /* Clear mask, so no surprise interrupts. */ + rda_uart_write(port, 0, RDA_UART_IRQ_MASK); +@@ -523,7 +523,7 @@ static void rda_uart_config_port(struct uart_port *port, int flags) + /* Clear status register */ + rda_uart_write(port, 0, RDA_UART_STATUS); + +- spin_unlock_irqrestore(&port->lock, irq_flags); ++ uart_port_unlock_irqrestore(port, irq_flags); + } + + static void rda_uart_release_port(struct uart_port *port) +@@ -597,9 +597,9 @@ static void rda_uart_port_write(struct uart_port *port, const char *s, + if (port->sysrq) { + locked = 0; + } else if (oops_in_progress) { +- locked = spin_trylock(&port->lock); ++ locked = uart_port_trylock(port); + } else { +- spin_lock(&port->lock); ++ uart_port_lock(port); + locked = 1; + } + +@@ -615,7 +615,7 @@ static void rda_uart_port_write(struct uart_port *port, const char *s, + rda_uart_write(port, old_irq_mask, RDA_UART_IRQ_MASK); + + if (locked) +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + local_irq_restore(flags); + } +diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c +index de220ac8c..d46a81cdd 100644 +--- a/drivers/tty/serial/rp2.c ++++ b/drivers/tty/serial/rp2.c +@@ -276,9 +276,9 @@ static unsigned int rp2_uart_tx_empty(struct uart_port *port) + * But the TXEMPTY bit doesn't seem to work unless the TX IRQ is + * enabled. + */ +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + tx_fifo_bytes = readw(up->base + RP2_TX_FIFO_COUNT); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return tx_fifo_bytes ? 0 : TIOCSER_TEMT; + } +@@ -323,10 +323,10 @@ static void rp2_uart_break_ctl(struct uart_port *port, int break_state) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + rp2_rmw(port_to_up(port), RP2_TXRX_CTL, RP2_TXRX_CTL_BREAK_m, + break_state ? RP2_TXRX_CTL_BREAK_m : 0); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void rp2_uart_enable_ms(struct uart_port *port) +@@ -383,7 +383,7 @@ static void rp2_uart_set_termios(struct uart_port *port, struct ktermios *new, + if (tty_termios_baud_rate(new)) + tty_termios_encode_baud_rate(new, baud, baud); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* ignore all characters if CREAD is not set */ + port->ignore_status_mask = (new->c_cflag & CREAD) ? 0 : RP2_DUMMY_READ; +@@ -391,7 +391,7 @@ static void rp2_uart_set_termios(struct uart_port *port, struct ktermios *new, + __rp2_uart_set_termios(up, new->c_cflag, new->c_iflag, baud_div); + uart_update_timeout(port, new->c_cflag, baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void rp2_rx_chars(struct rp2_uart_port *up) +@@ -440,7 +440,7 @@ static void rp2_ch_interrupt(struct rp2_uart_port *up) + { + u32 status; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + + /* + * The IRQ status bits are clear-on-write. Other status bits in +@@ -456,7 +456,7 @@ static void rp2_ch_interrupt(struct rp2_uart_port *up) + if (status & RP2_CHAN_STAT_MS_CHANGED_MASK) + wake_up_interruptible(&up->port.state->port.delta_msr_wait); + +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + } + + static int rp2_asic_interrupt(struct rp2_card *card, unsigned int asic_id) +@@ -516,10 +516,10 @@ static void rp2_uart_shutdown(struct uart_port *port) + + rp2_uart_break_ctl(port, 0); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + rp2_mask_ch_irq(up, up->idx, 0); + rp2_rmw(up, RP2_CHAN_STAT, 0, 0); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *rp2_uart_type(struct uart_port *port) +diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c +index ad011f1e2..be7bcd75d 100644 +--- a/drivers/tty/serial/sa1100.c ++++ b/drivers/tty/serial/sa1100.c +@@ -115,9 +115,9 @@ static void sa1100_timeout(struct timer_list *t) + unsigned long flags; + + if (sport->port.state) { +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + sa1100_mctrl_check(sport); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + + mod_timer(&sport->timer, jiffies + MCTRL_TIMEOUT); + } +@@ -247,7 +247,7 @@ static irqreturn_t sa1100_int(int irq, void *dev_id) + struct sa1100_port *sport = dev_id; + unsigned int status, pass_counter = 0; + +- spin_lock(&sport->port.lock); ++ uart_port_lock(&sport->port); + status = UART_GET_UTSR0(sport); + status &= SM_TO_UTSR0(sport->port.read_status_mask) | ~UTSR0_TFS; + do { +@@ -276,7 +276,7 @@ static irqreturn_t sa1100_int(int irq, void *dev_id) + status &= SM_TO_UTSR0(sport->port.read_status_mask) | + ~UTSR0_TFS; + } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID)); +- spin_unlock(&sport->port.lock); ++ uart_port_unlock(&sport->port); + + return IRQ_HANDLED; + } +@@ -321,14 +321,14 @@ static void sa1100_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + unsigned int utcr3; + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + utcr3 = UART_GET_UTCR3(sport); + if (break_state == -1) + utcr3 |= UTCR3_BRK; + else + utcr3 &= ~UTCR3_BRK; + UART_PUT_UTCR3(sport, utcr3); +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static int sa1100_startup(struct uart_port *port) +@@ -354,9 +354,9 @@ static int sa1100_startup(struct uart_port *port) + /* + * Enable modem status interrupts + */ +- spin_lock_irq(&sport->port.lock); ++ uart_port_lock_irq(&sport->port); + sa1100_enable_ms(&sport->port); +- spin_unlock_irq(&sport->port.lock); ++ uart_port_unlock_irq(&sport->port); + + return 0; + } +@@ -423,7 +423,7 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios, + + del_timer_sync(&sport->timer); + +- spin_lock_irqsave(&sport->port.lock, flags); ++ uart_port_lock_irqsave(&sport->port, &flags); + + sport->port.read_status_mask &= UTSR0_TO_SM(UTSR0_TFS); + sport->port.read_status_mask |= UTSR1_TO_SM(UTSR1_ROR); +@@ -485,7 +485,7 @@ sa1100_set_termios(struct uart_port *port, struct ktermios *termios, + if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) + sa1100_enable_ms(&sport->port); + +- spin_unlock_irqrestore(&sport->port.lock, flags); ++ uart_port_unlock_irqrestore(&sport->port, flags); + } + + static const char *sa1100_type(struct uart_port *port) +diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c +index 5a4d88e13..a82b65155 100644 +--- a/drivers/tty/serial/samsung_tty.c ++++ b/drivers/tty/serial/samsung_tty.c +@@ -248,7 +248,7 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port) + unsigned int ucon, ufcon; + int count = 10000; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + while (--count && !s3c24xx_serial_txempty_nofifo(port)) + udelay(100); +@@ -262,7 +262,7 @@ static void s3c24xx_serial_rx_enable(struct uart_port *port) + wr_regl(port, S3C2410_UCON, ucon); + + ourport->rx_enabled = 1; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void s3c24xx_serial_rx_disable(struct uart_port *port) +@@ -271,14 +271,14 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) + unsigned long flags; + unsigned int ucon; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ucon = rd_regl(port, S3C2410_UCON); + ucon &= ~S3C2410_UCON_RXIRQMODE; + wr_regl(port, S3C2410_UCON, ucon); + + ourport->rx_enabled = 0; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void s3c24xx_serial_stop_tx(struct uart_port *port) +@@ -344,7 +344,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args) + dma->tx_transfer_addr, dma->tx_size, + DMA_TO_DEVICE); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_xmit_advance(port, count); + ourport->tx_in_progress = 0; +@@ -353,7 +353,7 @@ static void s3c24xx_serial_tx_dma_complete(void *args) + uart_write_wakeup(port); + + s3c24xx_serial_start_next_tx(ourport); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void enable_tx_dma(struct s3c24xx_uart_port *ourport) +@@ -619,7 +619,7 @@ static void s3c24xx_serial_rx_dma_complete(void *args) + received = dma->rx_bytes_requested - state.residue; + async_tx_ack(dma->rx_desc); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + if (received) + s3c24xx_uart_copy_rx_to_tty(ourport, t, received); +@@ -631,7 +631,7 @@ static void s3c24xx_serial_rx_dma_complete(void *args) + + s3c64xx_start_rx_dma(ourport); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void s3c64xx_start_rx_dma(struct s3c24xx_uart_port *ourport) +@@ -722,7 +722,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) + utrstat = rd_regl(port, S3C2410_UTRSTAT); + rd_regl(port, S3C2410_UFSTAT); + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + if (!(utrstat & S3C2410_UTRSTAT_TIMEOUT)) { + s3c64xx_start_rx_dma(ourport); +@@ -751,7 +751,7 @@ static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id) + wr_regl(port, S3C2410_UTRSTAT, S3C2410_UTRSTAT_TIMEOUT); + + finish: +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -849,9 +849,9 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id) + struct s3c24xx_uart_port *ourport = dev_id; + struct uart_port *port = &ourport->port; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + s3c24xx_serial_rx_drain_fifo(ourport); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -932,11 +932,11 @@ static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id) + struct s3c24xx_uart_port *ourport = id; + struct uart_port *port = &ourport->port; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + s3c24xx_serial_tx_chars(ourport); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + return IRQ_HANDLED; + } + +@@ -1032,7 +1032,7 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + unsigned int ucon; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ucon = rd_regl(port, S3C2410_UCON); + +@@ -1043,7 +1043,7 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state) + + wr_regl(port, S3C2410_UCON, ucon); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p) +@@ -1302,7 +1302,7 @@ static int s3c64xx_serial_startup(struct uart_port *port) + ourport->rx_enabled = 1; + ourport->tx_enabled = 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ufcon = rd_regl(port, S3C2410_UFCON); + ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8; +@@ -1312,7 +1312,7 @@ static int s3c64xx_serial_startup(struct uart_port *port) + + enable_rx_pio(ourport); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Enable Rx Interrupt */ + s3c24xx_clear_bit(port, S3C64XX_UINTM_RXD, S3C64XX_UINTM); +@@ -1340,7 +1340,7 @@ static int apple_s5l_serial_startup(struct uart_port *port) + ourport->rx_enabled = 1; + ourport->tx_enabled = 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ufcon = rd_regl(port, S3C2410_UFCON); + ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8; +@@ -1350,7 +1350,7 @@ static int apple_s5l_serial_startup(struct uart_port *port) + + enable_rx_pio(ourport); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Enable Rx Interrupt */ + s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON); +@@ -1625,7 +1625,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, + ulcon |= S3C2410_LCON_PNONE; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + dev_dbg(port->dev, + "setting ulcon to %08x, brddiv to %d, udivslot %08x\n", +@@ -1683,7 +1683,7 @@ static void s3c24xx_serial_set_termios(struct uart_port *port, + if ((termios->c_cflag & CREAD) == 0) + port->ignore_status_mask |= RXSTAT_DUMMY_READ; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *s3c24xx_serial_type(struct uart_port *port) +@@ -2375,14 +2375,14 @@ s3c24xx_serial_console_write(struct console *co, const char *s, + if (cons_uart->sysrq) + locked = false; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&cons_uart->lock, flags); ++ locked = uart_port_trylock_irqsave(cons_uart, &flags); + else +- spin_lock_irqsave(&cons_uart->lock, flags); ++ uart_port_lock_irqsave(cons_uart, &flags); + + uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar); + + if (locked) +- spin_unlock_irqrestore(&cons_uart->lock, flags); ++ uart_port_unlock_irqrestore(cons_uart, flags); + } + + /* Shouldn't be __init, as it can be instantiated from other module */ +diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c +index f3cd69346..dbec29d9a 100644 +--- a/drivers/tty/serial/sb1250-duart.c ++++ b/drivers/tty/serial/sb1250-duart.c +@@ -610,7 +610,7 @@ static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios, + else + aux &= ~M_DUART_CTS_CHNG_ENA; + +- spin_lock(&uport->lock); ++ uart_port_lock(uport); + + if (sport->tx_stopped) + command |= M_DUART_TX_DIS; +@@ -632,7 +632,7 @@ static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios, + + write_sbdchn(sport, R_DUART_CMD, command); + +- spin_unlock(&uport->lock); ++ uart_port_unlock(uport); + } + + +@@ -839,22 +839,22 @@ static void sbd_console_write(struct console *co, const char *s, + unsigned int mask; + + /* Disable transmit interrupts and enable the transmitter. */ +- spin_lock_irqsave(&uport->lock, flags); ++ uart_port_lock_irqsave(uport, &flags); + mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2)); + write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), + mask & ~M_DUART_IMR_TX); + write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN); +- spin_unlock_irqrestore(&uport->lock, flags); ++ uart_port_unlock_irqrestore(uport, flags); + + uart_console_write(&sport->port, s, count, sbd_console_putchar); + + /* Restore transmit interrupts and the transmitter enable. */ +- spin_lock_irqsave(&uport->lock, flags); ++ uart_port_lock_irqsave(uport, &flags); + sbd_line_drain(sport); + if (sport->tx_stopped) + write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS); + write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask); +- spin_unlock_irqrestore(&uport->lock, flags); ++ uart_port_unlock_irqrestore(uport, flags); + } + + static int __init sbd_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c +index 7a9924d9b..be9ae5cdd 100644 +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -817,6 +817,7 @@ static void sc16is7xx_tx_proc(struct kthread_work *ws) + { + struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port); + struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); ++ unsigned long flags; + + if ((port->rs485.flags & SER_RS485_ENABLED) && + (port->rs485.delay_rts_before_send > 0)) +@@ -825,6 +826,10 @@ static void sc16is7xx_tx_proc(struct kthread_work *ws) + mutex_lock(&one->efr_lock); + sc16is7xx_handle_tx(port); + mutex_unlock(&one->efr_lock); ++ ++ uart_port_lock_irqsave(port, &flags); ++ sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void sc16is7xx_reconf_rs485(struct uart_port *port) +diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c +index d4ec943cb..6d4006b41 100644 +--- a/drivers/tty/serial/serial-tegra.c ++++ b/drivers/tty/serial/serial-tegra.c +@@ -411,7 +411,7 @@ static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) + divisor = DIV_ROUND_CLOSEST(rate, baud * 16); + } + +- spin_lock_irqsave(&tup->uport.lock, flags); ++ uart_port_lock_irqsave(&tup->uport, &flags); + lcr = tup->lcr_shadow; + lcr |= UART_LCR_DLAB; + tegra_uart_write(tup, lcr, UART_LCR); +@@ -424,7 +424,7 @@ static int tegra_set_baudrate(struct tegra_uart_port *tup, unsigned int baud) + + /* Dummy read to ensure the write is posted */ + tegra_uart_read(tup, UART_SCR); +- spin_unlock_irqrestore(&tup->uport.lock, flags); ++ uart_port_unlock_irqrestore(&tup->uport, flags); + + tup->current_baud = baud; + +@@ -522,13 +522,13 @@ static void tegra_uart_tx_dma_complete(void *args) + dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state); + count = tup->tx_bytes_requested - state.residue; + async_tx_ack(tup->tx_dma_desc); +- spin_lock_irqsave(&tup->uport.lock, flags); ++ uart_port_lock_irqsave(&tup->uport, &flags); + uart_xmit_advance(&tup->uport, count); + tup->tx_in_progress = 0; + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&tup->uport); + tegra_uart_start_next_tx(tup); +- spin_unlock_irqrestore(&tup->uport.lock, flags); ++ uart_port_unlock_irqrestore(&tup->uport, flags); + } + + static int tegra_uart_start_tx_dma(struct tegra_uart_port *tup, +@@ -598,13 +598,13 @@ static unsigned int tegra_uart_tx_empty(struct uart_port *u) + unsigned int ret = 0; + unsigned long flags; + +- spin_lock_irqsave(&u->lock, flags); ++ uart_port_lock_irqsave(u, &flags); + if (!tup->tx_in_progress) { + unsigned long lsr = tegra_uart_read(tup, UART_LSR); + if ((lsr & TX_EMPTY_STATUS) == TX_EMPTY_STATUS) + ret = TIOCSER_TEMT; + } +- spin_unlock_irqrestore(&u->lock, flags); ++ uart_port_unlock_irqrestore(u, flags); + return ret; + } + +@@ -727,7 +727,7 @@ static void tegra_uart_rx_dma_complete(void *args) + struct dma_tx_state state; + enum dma_status status; + +- spin_lock_irqsave(&u->lock, flags); ++ uart_port_lock_irqsave(u, &flags); + + status = dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); + +@@ -749,7 +749,7 @@ static void tegra_uart_rx_dma_complete(void *args) + set_rts(tup, true); + + done: +- spin_unlock_irqrestore(&u->lock, flags); ++ uart_port_unlock_irqrestore(u, flags); + } + + static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup) +@@ -836,7 +836,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) + bool is_rx_int = false; + unsigned long flags; + +- spin_lock_irqsave(&u->lock, flags); ++ uart_port_lock_irqsave(u, &flags); + while (1) { + iir = tegra_uart_read(tup, UART_IIR); + if (iir & UART_IIR_NO_INT) { +@@ -852,7 +852,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) + } else if (is_rx_start) { + tegra_uart_start_rx_dma(tup); + } +- spin_unlock_irqrestore(&u->lock, flags); ++ uart_port_unlock_irqrestore(u, flags); + return IRQ_HANDLED; + } + +@@ -969,11 +969,11 @@ static void tegra_uart_hw_deinit(struct tegra_uart_port *tup) + } + } + +- spin_lock_irqsave(&tup->uport.lock, flags); ++ uart_port_lock_irqsave(&tup->uport, &flags); + /* Reset the Rx and Tx FIFOs */ + tegra_uart_fifo_reset(tup, UART_FCR_CLEAR_XMIT | UART_FCR_CLEAR_RCVR); + tup->current_baud = 0; +- spin_unlock_irqrestore(&tup->uport.lock, flags); ++ uart_port_unlock_irqrestore(&tup->uport, flags); + + tup->rx_in_progress = 0; + tup->tx_in_progress = 0; +@@ -1292,7 +1292,7 @@ static void tegra_uart_set_termios(struct uart_port *u, + int ret; + + max_divider *= 16; +- spin_lock_irqsave(&u->lock, flags); ++ uart_port_lock_irqsave(u, &flags); + + /* Changing configuration, it is safe to stop any rx now */ + if (tup->rts_active) +@@ -1341,7 +1341,7 @@ static void tegra_uart_set_termios(struct uart_port *u, + baud = uart_get_baud_rate(u, termios, oldtermios, + parent_clk_rate/max_divider, + parent_clk_rate/16); +- spin_unlock_irqrestore(&u->lock, flags); ++ uart_port_unlock_irqrestore(u, flags); + ret = tegra_set_baudrate(tup, baud); + if (ret < 0) { + dev_err(tup->uport.dev, "Failed to set baud rate\n"); +@@ -1349,7 +1349,7 @@ static void tegra_uart_set_termios(struct uart_port *u, + } + if (tty_termios_baud_rate(termios)) + tty_termios_encode_baud_rate(termios, baud, baud); +- spin_lock_irqsave(&u->lock, flags); ++ uart_port_lock_irqsave(u, &flags); + + /* Flow control */ + if (termios->c_cflag & CRTSCTS) { +@@ -1382,7 +1382,7 @@ static void tegra_uart_set_termios(struct uart_port *u, + if (termios->c_iflag & IGNBRK) + tup->uport.ignore_status_mask |= UART_LSR_BI; + +- spin_unlock_irqrestore(&u->lock, flags); ++ uart_port_unlock_irqrestore(u, flags); + } + + static const char *tegra_uart_type(struct uart_port *u) +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c +index ed8798fdf..f0cd976e2 100644 +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -79,7 +79,7 @@ static inline void uart_port_deref(struct uart_port *uport) + ({ \ + struct uart_port *__uport = uart_port_ref(state); \ + if (__uport) \ +- spin_lock_irqsave(&__uport->lock, flags); \ ++ uart_port_lock_irqsave(__uport, &flags); \ + __uport; \ + }) + +@@ -87,7 +87,7 @@ static inline void uart_port_deref(struct uart_port *uport) + ({ \ + struct uart_port *__uport = uport; \ + if (__uport) { \ +- spin_unlock_irqrestore(&__uport->lock, flags); \ ++ uart_port_unlock_irqrestore(__uport, flags); \ + uart_port_deref(__uport); \ + } \ + }) +@@ -179,12 +179,12 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) + unsigned long flags; + unsigned int old; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + old = port->mctrl; + port->mctrl = (old & ~clear) | set; + if (old != port->mctrl && !(port->rs485.flags & SER_RS485_ENABLED)) + port->ops->set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + #define uart_set_mctrl(port, set) uart_update_mctrl(port, set, 0) +@@ -219,7 +219,7 @@ static void uart_change_line_settings(struct tty_struct *tty, struct uart_state + /* + * Set modem status enables based on termios cflag + */ +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + if (termios->c_cflag & CRTSCTS) + uport->status |= UPSTAT_CTS_ENABLE; + else +@@ -240,7 +240,7 @@ static void uart_change_line_settings(struct tty_struct *tty, struct uart_state + else + __uart_start(state); + } +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + } + + /* +@@ -715,11 +715,11 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) + if (port->ops->send_xchar) + port->ops->send_xchar(port, ch); + else { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + port->x_char = ch; + if (ch) + port->ops->start_tx(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + uart_port_deref(port); + } +@@ -1106,9 +1106,9 @@ static int uart_tiocmget(struct tty_struct *tty) + + if (!tty_io_error(tty)) { + result = uport->mctrl; +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + result |= uport->ops->get_mctrl(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + } + out: + mutex_unlock(&port->mutex); +@@ -1244,16 +1244,16 @@ static int uart_wait_modem_status(struct uart_state *state, unsigned long arg) + uport = uart_port_ref(state); + if (!uport) + return -EIO; +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + memcpy(&cprev, &uport->icount, sizeof(struct uart_icount)); + uart_enable_ms(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + + add_wait_queue(&port->delta_msr_wait, &wait); + for (;;) { +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + + set_current_state(TASK_INTERRUPTIBLE); + +@@ -1298,9 +1298,9 @@ static int uart_get_icount(struct tty_struct *tty, + uport = uart_port_ref(state); + if (!uport) + return -EIO; +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + uart_port_deref(uport); + + icount->cts = cnow.cts; +@@ -1453,9 +1453,9 @@ static int uart_rs485_config(struct uart_port *port) + uart_set_rs485_termination(port, rs485); + uart_set_rs485_rx_during_tx(port, rs485); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ret = port->rs485_config(port, NULL, rs485); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + if (ret) { + memset(rs485, 0, sizeof(*rs485)); + /* unset GPIOs */ +@@ -1472,9 +1472,9 @@ static int uart_get_rs485_config(struct uart_port *port, + unsigned long flags; + struct serial_rs485 aux; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + aux = port->rs485; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (copy_to_user(rs485, &aux, sizeof(aux))) + return -EFAULT; +@@ -1502,7 +1502,7 @@ static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port, + uart_set_rs485_termination(port, &rs485); + uart_set_rs485_rx_during_tx(port, &rs485); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ret = port->rs485_config(port, &tty->termios, &rs485); + if (!ret) { + port->rs485 = rs485; +@@ -1511,7 +1511,7 @@ static int uart_set_rs485_config(struct tty_struct *tty, struct uart_port *port, + if (!(rs485.flags & SER_RS485_ENABLED)) + port->ops->set_mctrl(port, port->mctrl); + } +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + if (ret) { + /* restore old GPIO settings */ + gpiod_set_value_cansleep(port->rs485_term_gpio, +@@ -1536,9 +1536,9 @@ static int uart_get_iso7816_config(struct uart_port *port, + if (!port->iso7816_config) + return -ENOTTY; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + aux = port->iso7816; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (copy_to_user(iso7816, &aux, sizeof(aux))) + return -EFAULT; +@@ -1567,9 +1567,9 @@ static int uart_set_iso7816_config(struct uart_port *port, + if (iso7816.reserved[i]) + return -EINVAL; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ret = port->iso7816_config(port, &iso7816); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + if (ret) + return ret; + +@@ -1786,9 +1786,9 @@ static void uart_tty_port_shutdown(struct tty_port *port) + if (WARN(!uport, "detached port still initialized!\n")) + return; + +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + uport->ops->stop_rx(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + + serial_base_port_shutdown(uport); + uart_port_shutdown(port); +@@ -1803,11 +1803,11 @@ static void uart_tty_port_shutdown(struct tty_port *port) + /* + * Free the transmit buffer. + */ +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + uart_circ_clear(&state->xmit); + buf = state->xmit.buf; + state->xmit.buf = NULL; +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + + free_page((unsigned long)buf); + +@@ -1950,10 +1950,10 @@ static bool uart_carrier_raised(struct tty_port *port) + */ + if (WARN_ON(!uport)) + return true; +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + uart_enable_ms(uport); + mctrl = uport->ops->get_mctrl(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + uart_port_deref(uport); + + return mctrl & TIOCM_CAR; +@@ -2070,9 +2070,9 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) + pm_state = state->pm_state; + if (pm_state != UART_PM_STATE_ON) + uart_change_pm(state, UART_PM_STATE_ON); +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + status = uport->ops->get_mctrl(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + if (pm_state != UART_PM_STATE_ON) + uart_change_pm(state, pm_state); + +@@ -2411,9 +2411,9 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) + */ + if (!console_suspend_enabled && uart_console(uport)) { + if (uport->ops->start_rx) { +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + uport->ops->stop_rx(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + } + goto unlock; + } +@@ -2428,7 +2428,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) + tty_port_set_suspended(port, true); + tty_port_set_initialized(port, false); + +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + ops->stop_tx(uport); + if (!(uport->rs485.flags & SER_RS485_ENABLED)) + ops->set_mctrl(uport, 0); +@@ -2436,7 +2436,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) + mctrl = uport->mctrl; + uport->mctrl = 0; + ops->stop_rx(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + + /* + * Wait for the transmitter to empty. +@@ -2508,9 +2508,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) + uart_change_pm(state, UART_PM_STATE_ON); + uport->ops->set_termios(uport, &termios, NULL); + if (!console_suspend_enabled && uport->ops->start_rx) { +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + uport->ops->start_rx(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + } + if (console_suspend_enabled) + console_start(uport->cons); +@@ -2521,10 +2521,10 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) + int ret; + + uart_change_pm(state, UART_PM_STATE_ON); +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + if (!(uport->rs485.flags & SER_RS485_ENABLED)) + ops->set_mctrl(uport, 0); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + if (console_suspend_enabled || !uart_console(uport)) { + /* Protected by port mutex for now */ + struct tty_struct *tty = port->tty; +@@ -2534,11 +2534,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) + if (tty) + uart_change_line_settings(tty, state, NULL); + uart_rs485_config(uport); +- spin_lock_irq(&uport->lock); ++ uart_port_lock_irq(uport); + if (!(uport->rs485.flags & SER_RS485_ENABLED)) + ops->set_mctrl(uport, uport->mctrl); + ops->start_tx(uport); +- spin_unlock_irq(&uport->lock); ++ uart_port_unlock_irq(uport); + tty_port_set_initialized(port, true); + } else { + /* +@@ -2650,11 +2650,11 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, + * keep the DTR setting that is set in uart_set_options() + * We probably don't need a spinlock around this, but + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + port->mctrl &= TIOCM_DTR; + if (!(port->rs485.flags & SER_RS485_ENABLED)) + port->ops->set_mctrl(port, port->mctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + uart_rs485_config(port); + +diff --git a/drivers/tty/serial/serial_mctrl_gpio.c b/drivers/tty/serial/serial_mctrl_gpio.c +index 7d5aaa8d4..e51ca593a 100644 +--- a/drivers/tty/serial/serial_mctrl_gpio.c ++++ b/drivers/tty/serial/serial_mctrl_gpio.c +@@ -184,7 +184,7 @@ static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context) + + mctrl_gpio_get(gpios, &mctrl); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + mctrl_diff = mctrl ^ gpios->mctrl_prev; + gpios->mctrl_prev = mctrl; +@@ -205,7 +205,7 @@ static irqreturn_t mctrl_gpio_irq_handle(int irq, void *context) + wake_up_interruptible(&port->state->port.delta_msr_wait); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_port.c +index 469ad26cd..66fd117d8 100644 +--- a/drivers/tty/serial/serial_port.c ++++ b/drivers/tty/serial/serial_port.c +@@ -38,14 +38,14 @@ static int serial_port_runtime_resume(struct device *dev) + goto out; + + /* Flush any pending TX for the port */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (!port_dev->tx_enabled) + goto unlock; + if (__serial_port_busy(port)) + port->ops->start_tx(port); + + unlock: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + out: + pm_runtime_mark_last_busy(dev); +diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c +index be08fb6f7..eaa980722 100644 +--- a/drivers/tty/serial/serial_txx9.c ++++ b/drivers/tty/serial/serial_txx9.c +@@ -335,13 +335,13 @@ static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id) + unsigned int status; + + while (1) { +- spin_lock(&up->lock); ++ uart_port_lock(up); + status = sio_in(up, TXX9_SIDISR); + if (!(sio_in(up, TXX9_SIDICR) & TXX9_SIDICR_TIE)) + status &= ~TXX9_SIDISR_TDIS; + if (!(status & (TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS | + TXX9_SIDISR_TOUT))) { +- spin_unlock(&up->lock); ++ uart_port_unlock(up); + break; + } + +@@ -353,7 +353,7 @@ static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id) + sio_mask(up, TXX9_SIDISR, + TXX9_SIDISR_TDIS | TXX9_SIDISR_RDIS | + TXX9_SIDISR_TOUT); +- spin_unlock(&up->lock); ++ uart_port_unlock(up); + + if (pass_counter++ > PASS_LIMIT) + break; +@@ -367,9 +367,9 @@ static unsigned int serial_txx9_tx_empty(struct uart_port *up) + unsigned long flags; + unsigned int ret; + +- spin_lock_irqsave(&up->lock, flags); ++ uart_port_lock_irqsave(up, &flags); + ret = (sio_in(up, TXX9_SICISR) & TXX9_SICISR_TXALS) ? TIOCSER_TEMT : 0; +- spin_unlock_irqrestore(&up->lock, flags); ++ uart_port_unlock_irqrestore(up, flags); + + return ret; + } +@@ -399,12 +399,12 @@ static void serial_txx9_break_ctl(struct uart_port *up, int break_state) + { + unsigned long flags; + +- spin_lock_irqsave(&up->lock, flags); ++ uart_port_lock_irqsave(up, &flags); + if (break_state == -1) + sio_set(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK); + else + sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_TBRK); +- spin_unlock_irqrestore(&up->lock, flags); ++ uart_port_unlock_irqrestore(up, flags); + } + + #if defined(CONFIG_SERIAL_TXX9_CONSOLE) || defined(CONFIG_CONSOLE_POLL) +@@ -517,9 +517,9 @@ static int serial_txx9_startup(struct uart_port *up) + /* + * Now, initialize the UART + */ +- spin_lock_irqsave(&up->lock, flags); ++ uart_port_lock_irqsave(up, &flags); + serial_txx9_set_mctrl(up, up->mctrl); +- spin_unlock_irqrestore(&up->lock, flags); ++ uart_port_unlock_irqrestore(up, flags); + + /* Enable RX/TX */ + sio_mask(up, TXX9_SIFLCR, TXX9_SIFLCR_RSDE | TXX9_SIFLCR_TSDE); +@@ -541,9 +541,9 @@ static void serial_txx9_shutdown(struct uart_port *up) + */ + sio_out(up, TXX9_SIDICR, 0); /* disable all intrs */ + +- spin_lock_irqsave(&up->lock, flags); ++ uart_port_lock_irqsave(up, &flags); + serial_txx9_set_mctrl(up, up->mctrl); +- spin_unlock_irqrestore(&up->lock, flags); ++ uart_port_unlock_irqrestore(up, flags); + + /* + * Disable break condition +@@ -625,7 +625,7 @@ serial_txx9_set_termios(struct uart_port *up, struct ktermios *termios, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&up->lock, flags); ++ uart_port_lock_irqsave(up, &flags); + + /* + * Update the per-port timeout. +@@ -676,7 +676,7 @@ serial_txx9_set_termios(struct uart_port *up, struct ktermios *termios, + sio_out(up, TXX9_SIFCR, fcr); + + serial_txx9_set_mctrl(up, up->mctrl); +- spin_unlock_irqrestore(&up->lock, flags); ++ uart_port_unlock_irqrestore(up, flags); + } + + static void +diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c +index f793624fd..2559c9781 100644 +--- a/drivers/tty/serial/sh-sci.c ++++ b/drivers/tty/serial/sh-sci.c +@@ -1205,7 +1205,7 @@ static void sci_dma_tx_complete(void *arg) + + dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_xmit_advance(port, s->tx_dma_len); + +@@ -1229,7 +1229,7 @@ static void sci_dma_tx_complete(void *arg) + } + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* Locking: called with port lock held */ +@@ -1325,7 +1325,7 @@ static void sci_dma_rx_complete(void *arg) + dev_dbg(port->dev, "%s(%d) active cookie %d\n", __func__, port->line, + s->active_rx); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + active = sci_dma_rx_find_active(s); + if (active >= 0) +@@ -1352,20 +1352,20 @@ static void sci_dma_rx_complete(void *arg) + + dma_async_issue_pending(chan); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + dev_dbg(port->dev, "%s: cookie %d #%d, new active cookie %d\n", + __func__, s->cookie_rx[active], active, s->active_rx); + return; + + fail: +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n"); + /* Switch to PIO */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + dmaengine_terminate_async(chan); + sci_dma_rx_chan_invalidate(s); + sci_dma_rx_reenable_irq(s); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void sci_dma_tx_release(struct sci_port *s) +@@ -1414,13 +1414,13 @@ static int sci_dma_rx_submit(struct sci_port *s, bool port_lock_held) + fail: + /* Switch to PIO */ + if (!port_lock_held) +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + if (i) + dmaengine_terminate_async(chan); + sci_dma_rx_chan_invalidate(s); + sci_start_rx(port); + if (!port_lock_held) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return -EAGAIN; + } + +@@ -1442,14 +1442,14 @@ static void sci_dma_tx_work_fn(struct work_struct *work) + * transmit till the end, and then the rest. Take the port lock to get a + * consistent xmit buffer state. + */ +- spin_lock_irq(&port->lock); ++ uart_port_lock_irq(port); + head = xmit->head; + tail = xmit->tail; + buf = s->tx_dma_addr + tail; + s->tx_dma_len = CIRC_CNT_TO_END(head, tail, UART_XMIT_SIZE); + if (!s->tx_dma_len) { + /* Transmit buffer has been flushed */ +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + return; + } + +@@ -1457,7 +1457,7 @@ static void sci_dma_tx_work_fn(struct work_struct *work) + DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + dev_warn(port->dev, "Failed preparing Tx DMA descriptor\n"); + goto switch_to_pio; + } +@@ -1469,12 +1469,12 @@ static void sci_dma_tx_work_fn(struct work_struct *work) + desc->callback_param = s; + s->cookie_tx = dmaengine_submit(desc); + if (dma_submit_error(s->cookie_tx)) { +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n"); + goto switch_to_pio; + } + +- spin_unlock_irq(&port->lock); ++ uart_port_unlock_irq(port); + dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", + __func__, xmit->buf, tail, head, s->cookie_tx); + +@@ -1482,10 +1482,10 @@ static void sci_dma_tx_work_fn(struct work_struct *work) + return; + + switch_to_pio: +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + s->chan_tx = NULL; + sci_start_tx(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return; + } + +@@ -1502,17 +1502,17 @@ static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t) + + dev_dbg(port->dev, "DMA Rx timed out\n"); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + active = sci_dma_rx_find_active(s); + if (active < 0) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return HRTIMER_NORESTART; + } + + status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state); + if (status == DMA_COMPLETE) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + dev_dbg(port->dev, "Cookie %d #%d has already completed\n", + s->active_rx, active); + +@@ -1530,7 +1530,7 @@ static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t) + */ + status = dmaengine_tx_status(s->chan_rx, s->active_rx, &state); + if (status == DMA_COMPLETE) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + dev_dbg(port->dev, "Transaction complete after DMA engine was stopped"); + return HRTIMER_NORESTART; + } +@@ -1551,7 +1551,7 @@ static enum hrtimer_restart sci_dma_rx_timer_fn(struct hrtimer *t) + + sci_dma_rx_reenable_irq(s); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return HRTIMER_NORESTART; + } +@@ -1775,9 +1775,9 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr) + struct uart_port *port = ptr; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + sci_transmit_chars(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -1791,11 +1791,11 @@ static irqreturn_t sci_tx_end_interrupt(int irq, void *ptr) + if (port->type != PORT_SCI) + return sci_tx_interrupt(irq, ptr); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ctrl = serial_port_in(port, SCSCR); + ctrl &= ~(SCSCR_TE | SCSCR_TEIE); + serial_port_out(port, SCSCR, ctrl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return IRQ_HANDLED; + } +@@ -2192,7 +2192,7 @@ static void sci_break_ctl(struct uart_port *port, int break_state) + return; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + scsptr = serial_port_in(port, SCSPTR); + scscr = serial_port_in(port, SCSCR); + +@@ -2206,7 +2206,7 @@ static void sci_break_ctl(struct uart_port *port, int break_state) + + serial_port_out(port, SCSPTR, scsptr); + serial_port_out(port, SCSCR, scscr); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int sci_startup(struct uart_port *port) +@@ -2238,7 +2238,7 @@ static void sci_shutdown(struct uart_port *port) + s->autorts = false; + mctrl_gpio_disable_ms(to_sci_port(port)->gpios); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + sci_stop_rx(port); + sci_stop_tx(port); + /* +@@ -2248,7 +2248,7 @@ static void sci_shutdown(struct uart_port *port) + scr = serial_port_in(port, SCSCR); + serial_port_out(port, SCSCR, scr & + (SCSCR_CKE1 | SCSCR_CKE0 | s->hscif_tot)); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + #ifdef CONFIG_SERIAL_SH_SCI_DMA + if (s->chan_rx_saved) { +@@ -2550,7 +2550,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + serial_port_out(port, SCCKS, sccks); + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + sci_reset(port); + +@@ -2672,7 +2672,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, + if ((termios->c_cflag & CREAD) != 0) + sci_start_rx(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + sci_port_disable(s); + +@@ -3057,9 +3057,9 @@ static void serial_console_write(struct console *co, const char *s, + if (port->sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* first save SCSCR then disable interrupts, keep clock source */ + ctrl = serial_port_in(port, SCSCR); +@@ -3079,7 +3079,7 @@ static void serial_console_write(struct console *co, const char *s, + serial_port_out(port, SCSCR, ctrl); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int serial_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c +index d195c5de5..b296e57a9 100644 +--- a/drivers/tty/serial/sifive.c ++++ b/drivers/tty/serial/sifive.c +@@ -521,11 +521,11 @@ static irqreturn_t sifive_serial_irq(int irq, void *dev_id) + struct sifive_serial_port *ssp = dev_id; + u32 ip; + +- spin_lock(&ssp->port.lock); ++ uart_port_lock(&ssp->port); + + ip = __ssp_readl(ssp, SIFIVE_SERIAL_IP_OFFS); + if (!ip) { +- spin_unlock(&ssp->port.lock); ++ uart_port_unlock(&ssp->port); + return IRQ_NONE; + } + +@@ -534,7 +534,7 @@ static irqreturn_t sifive_serial_irq(int irq, void *dev_id) + if (ip & SIFIVE_SERIAL_IP_TXWM_MASK) + __ssp_transmit_chars(ssp); + +- spin_unlock(&ssp->port.lock); ++ uart_port_unlock(&ssp->port); + + return IRQ_HANDLED; + } +@@ -653,7 +653,7 @@ static void sifive_serial_set_termios(struct uart_port *port, + ssp->port.uartclk / 16); + __ssp_update_baud_rate(ssp, rate); + +- spin_lock_irqsave(&ssp->port.lock, flags); ++ uart_port_lock_irqsave(&ssp->port, &flags); + + /* Update the per-port timeout */ + uart_update_timeout(port, termios->c_cflag, rate); +@@ -670,7 +670,7 @@ static void sifive_serial_set_termios(struct uart_port *port, + if (v != old_v) + __ssp_writel(v, SIFIVE_SERIAL_RXCTRL_OFFS, ssp); + +- spin_unlock_irqrestore(&ssp->port.lock, flags); ++ uart_port_unlock_irqrestore(&ssp->port, flags); + } + + static void sifive_serial_release_port(struct uart_port *port) +@@ -795,9 +795,9 @@ static void sifive_serial_console_write(struct console *co, const char *s, + if (ssp->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&ssp->port.lock); ++ locked = uart_port_trylock(&ssp->port); + else +- spin_lock(&ssp->port.lock); ++ uart_port_lock(&ssp->port); + + ier = __ssp_readl(ssp, SIFIVE_SERIAL_IE_OFFS); + __ssp_writel(0, SIFIVE_SERIAL_IE_OFFS, ssp); +@@ -807,7 +807,7 @@ static void sifive_serial_console_write(struct console *co, const char *s, + __ssp_writel(ier, SIFIVE_SERIAL_IE_OFFS, ssp); + + if (locked) +- spin_unlock(&ssp->port.lock); ++ uart_port_unlock(&ssp->port); + local_irq_restore(flags); + } + +diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c +index f328fa572..f257525f9 100644 +--- a/drivers/tty/serial/sprd_serial.c ++++ b/drivers/tty/serial/sprd_serial.c +@@ -247,7 +247,7 @@ static void sprd_complete_tx_dma(void *data) + struct circ_buf *xmit = &port->state->xmit; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + dma_unmap_single(port->dev, sp->tx_dma.phys_addr, + sp->tx_dma.trans_len, DMA_TO_DEVICE); + +@@ -260,7 +260,7 @@ static void sprd_complete_tx_dma(void *data) + sprd_tx_dma_config(port)) + sp->tx_dma.trans_len = 0; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int sprd_uart_dma_submit(struct uart_port *port, +@@ -429,13 +429,13 @@ static void sprd_complete_rx_dma(void *data) + enum dma_status status; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + status = dmaengine_tx_status(sp->rx_dma.chn, + sp->rx_dma.cookie, &state); + if (status != DMA_COMPLETE) { + sprd_stop_rx(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return; + } + +@@ -449,7 +449,7 @@ static void sprd_complete_rx_dma(void *data) + if (sprd_start_dma_rx(port)) + sprd_stop_rx(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int sprd_start_dma_rx(struct uart_port *port) +@@ -638,12 +638,12 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id) + struct uart_port *port = dev_id; + unsigned int ims; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + ims = serial_in(port, SPRD_IMSR); + + if (!ims) { +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + return IRQ_NONE; + } + +@@ -660,7 +660,7 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id) + if (ims & SPRD_IMSR_TX_FIFO_EMPTY) + sprd_tx(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -727,13 +727,13 @@ static int sprd_startup(struct uart_port *port) + serial_out(port, SPRD_CTL1, fc); + + /* enable interrupt */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ien = serial_in(port, SPRD_IEN); + ien |= SPRD_IEN_BREAK_DETECT | SPRD_IEN_TIMEOUT; + if (!sp->rx_dma.enable) + ien |= SPRD_IEN_RX_FULL; + serial_out(port, SPRD_IEN, ien); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -793,7 +793,7 @@ static void sprd_set_termios(struct uart_port *port, struct ktermios *termios, + lcr |= SPRD_LCR_EVEN_PAR; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* update the per-port timeout */ + uart_update_timeout(port, termios->c_cflag, baud); +@@ -837,7 +837,7 @@ static void sprd_set_termios(struct uart_port *port, struct ktermios *termios, + fc |= RX_TOUT_THLD_DEF | RX_HFC_THLD_DEF; + serial_out(port, SPRD_CTL1, fc); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Don't rewrite B0 */ + if (tty_termios_baud_rate(termios)) +@@ -974,9 +974,9 @@ static void sprd_console_write(struct console *co, const char *s, + if (port->sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_console_write(port, s, count, sprd_console_putchar); + +@@ -984,7 +984,7 @@ static void sprd_console_write(struct console *co, const char *s, + wait_for_xmitr(port); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int sprd_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c +index 92b9f6894..a821f5d76 100644 +--- a/drivers/tty/serial/st-asc.c ++++ b/drivers/tty/serial/st-asc.c +@@ -319,7 +319,7 @@ static irqreturn_t asc_interrupt(int irq, void *ptr) + struct uart_port *port = ptr; + u32 status; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + status = asc_in(port, ASC_STA); + +@@ -334,7 +334,7 @@ static irqreturn_t asc_interrupt(int irq, void *ptr) + asc_transmit_chars(port); + } + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -452,10 +452,10 @@ static void asc_pm(struct uart_port *port, unsigned int state, + * we can come to turning it off. Note this is not called with + * the port spinlock held. + */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN; + asc_out(port, ASC_CTL, ctl); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + clk_disable_unprepare(ascport->clk); + break; + } +@@ -480,7 +480,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + cflag = termios->c_cflag; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* read control register */ + ctrl_val = asc_in(port, ASC_CTL); +@@ -594,7 +594,7 @@ static void asc_set_termios(struct uart_port *port, struct ktermios *termios, + /* write final value and enable port */ + asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *asc_type(struct uart_port *port) +@@ -849,9 +849,9 @@ static void asc_console_write(struct console *co, const char *s, unsigned count) + if (port->sysrq) + locked = 0; /* asc_interrupt has already claimed the lock */ + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * Disable interrupts so we don't get the IRQ line bouncing +@@ -869,7 +869,7 @@ static void asc_console_write(struct console *co, const char *s, unsigned count) + asc_out(port, ASC_INTEN, intenable); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int asc_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index 48cd2d8d6..96daedd8d 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -693,7 +693,7 @@ static void stm32_usart_rx_dma_complete(void *arg) + unsigned int size; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + size = stm32_usart_receive_chars(port, false); + uart_unlock_and_check_sysrq_irqrestore(port, flags); + if (size) +@@ -813,9 +813,9 @@ static void stm32_usart_tx_dma_complete(void *arg) + stm32_usart_tx_dma_terminate(stm32port); + + /* Let's see if we have pending data to send */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + stm32_usart_transmit_chars(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void stm32_usart_tx_interrupt_enable(struct uart_port *port) +@@ -1095,7 +1095,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) + if (!stm32_port->throttled) { + if (((sr & USART_SR_RXNE) && !stm32_usart_rx_dma_started(stm32_port)) || + ((sr & USART_SR_ERR_MASK) && stm32_usart_rx_dma_started(stm32_port))) { +- spin_lock(&port->lock); ++ uart_port_lock(port); + size = stm32_usart_receive_chars(port, false); + uart_unlock_and_check_sysrq(port); + if (size) +@@ -1106,15 +1106,15 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) + } + + if ((sr & USART_SR_TXE) && !(stm32_port->tx_ch)) { +- spin_lock(&port->lock); ++ uart_port_lock(port); + stm32_usart_transmit_chars(port); +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + ret = IRQ_HANDLED; + } + + /* Receiver timeout irq for DMA RX */ + if (stm32_usart_rx_dma_started(stm32_port) && !stm32_port->throttled) { +- spin_lock(&port->lock); ++ uart_port_lock(port); + size = stm32_usart_receive_chars(port, false); + uart_unlock_and_check_sysrq(port); + if (size) +@@ -1203,7 +1203,7 @@ static void stm32_usart_throttle(struct uart_port *port) + const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* + * Pause DMA transfer, so the RX data gets queued into the FIFO. +@@ -1216,7 +1216,7 @@ static void stm32_usart_throttle(struct uart_port *port) + stm32_usart_clr_bits(port, ofs->cr3, stm32_port->cr3_irq); + + stm32_port->throttled = true; +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* Unthrottle the remote, the input buffer can now accept data. */ +@@ -1226,7 +1226,7 @@ static void stm32_usart_unthrottle(struct uart_port *port) + const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + stm32_usart_set_bits(port, ofs->cr1, stm32_port->cr1_irq); + if (stm32_port->cr3_irq) + stm32_usart_set_bits(port, ofs->cr3, stm32_port->cr3_irq); +@@ -1240,7 +1240,7 @@ static void stm32_usart_unthrottle(struct uart_port *port) + if (stm32_port->rx_ch) + stm32_usart_rx_dma_start_or_resume(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* Receive stop */ +@@ -1379,7 +1379,7 @@ static void stm32_usart_set_termios(struct uart_port *port, + + uart_clk = clk_get_rate(stm32_port->clk); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + ret = readl_relaxed_poll_timeout_atomic(port->membase + ofs->isr, + isr, +@@ -1599,7 +1599,7 @@ static void stm32_usart_set_termios(struct uart_port *port, + writel_relaxed(cr1, port->membase + ofs->cr1); + + stm32_usart_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + /* Handle modem control interrupts */ + if (UART_ENABLE_MS(port, termios->c_cflag)) +@@ -1649,9 +1649,9 @@ static void stm32_usart_pm(struct uart_port *port, unsigned int state, + pm_runtime_get_sync(port->dev); + break; + case UART_PM_STATE_OFF: +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + stm32_usart_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit)); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + pm_runtime_put_sync(port->dev); + break; + } +@@ -2204,9 +2204,9 @@ static void stm32_usart_console_write(struct console *co, const char *s, + int locked = 1; + + if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Save and disable interrupts, enable the transmitter */ + old_cr1 = readl_relaxed(port->membase + ofs->cr1); +@@ -2220,7 +2220,7 @@ static void stm32_usart_console_write(struct console *co, const char *s, + writel_relaxed(old_cr1, port->membase + ofs->cr1); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int stm32_usart_console_setup(struct console *co, char *options) +@@ -2357,7 +2357,7 @@ static int __maybe_unused stm32_usart_serial_en_wakeup(struct uart_port *port, + * low-power mode. + */ + if (stm32_port->rx_ch) { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + /* Poll data from DMA RX buffer if any */ + if (!stm32_usart_rx_dma_pause(stm32_port)) + size += stm32_usart_receive_chars(port, true); +diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c +index c671d674b..5bfc0040f 100644 +--- a/drivers/tty/serial/sunhv.c ++++ b/drivers/tty/serial/sunhv.c +@@ -217,10 +217,10 @@ static irqreturn_t sunhv_interrupt(int irq, void *dev_id) + struct tty_port *tport; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + tport = receive_chars(port); + transmit_chars(port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (tport) + tty_flip_buffer_push(tport); +@@ -271,7 +271,7 @@ static void sunhv_send_xchar(struct uart_port *port, char ch) + if (ch == __DISABLED_CHAR) + return; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + while (limit-- > 0) { + long status = sun4v_con_putchar(ch); +@@ -280,7 +280,7 @@ static void sunhv_send_xchar(struct uart_port *port, char ch) + udelay(1); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* port->lock held by caller. */ +@@ -295,7 +295,7 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + int limit = 10000; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + while (limit-- > 0) { + long status = sun4v_con_putchar(CON_BREAK); +@@ -304,7 +304,7 @@ static void sunhv_break_ctl(struct uart_port *port, int break_state) + udelay(1); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + } + +@@ -328,7 +328,7 @@ static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios, + unsigned int iflag, cflag; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + iflag = termios->c_iflag; + cflag = termios->c_cflag; +@@ -343,7 +343,7 @@ static void sunhv_set_termios(struct uart_port *port, struct ktermios *termios, + uart_update_timeout(port, cflag, + (port->uartclk / (16 * quot))); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *sunhv_type(struct uart_port *port) +@@ -437,9 +437,9 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign + int locked = 1; + + if (port->sysrq || oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + while (n > 0) { + unsigned long ra = __pa(con_write_page); +@@ -470,7 +470,7 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign + } + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static inline void sunhv_console_putchar(struct uart_port *port, char c) +@@ -492,9 +492,9 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig + int i, locked = 1; + + if (port->sysrq || oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + for (i = 0; i < n; i++) { + if (*s == '\n') +@@ -503,7 +503,7 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig + } + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static struct console sunhv_console = { +diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus-uart.c +index 3aacd5eb4..4251f4e1b 100644 +--- a/drivers/tty/serial/sunplus-uart.c ++++ b/drivers/tty/serial/sunplus-uart.c +@@ -184,7 +184,7 @@ static void sunplus_break_ctl(struct uart_port *port, int ctl) + unsigned long flags; + unsigned int lcr; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + lcr = readl(port->membase + SUP_UART_LCR); + +@@ -195,7 +195,7 @@ static void sunplus_break_ctl(struct uart_port *port, int ctl) + + writel(lcr, port->membase + SUP_UART_LCR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void transmit_chars(struct uart_port *port) +@@ -277,7 +277,7 @@ static irqreturn_t sunplus_uart_irq(int irq, void *args) + struct uart_port *port = args; + unsigned int isc; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + isc = readl(port->membase + SUP_UART_ISC); + +@@ -287,7 +287,7 @@ static irqreturn_t sunplus_uart_irq(int irq, void *args) + if (isc & SUP_UART_ISC_TX) + transmit_chars(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -302,14 +302,14 @@ static int sunplus_startup(struct uart_port *port) + if (ret) + return ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + /* isc define Bit[7:4] int setting, Bit[3:0] int status + * isc register will clean Bit[3:0] int status after read + * only do a write to Bit[7:4] int setting + */ + isc |= SUP_UART_ISC_RXM; + writel(isc, port->membase + SUP_UART_ISC); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return 0; + } +@@ -318,13 +318,13 @@ static void sunplus_shutdown(struct uart_port *port) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + /* isc define Bit[7:4] int setting, Bit[3:0] int status + * isc register will clean Bit[3:0] int status after read + * only do a write to Bit[7:4] int setting + */ + writel(0, port->membase + SUP_UART_ISC); /* disable all interrupt */ +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + free_irq(port->irq, port); + } +@@ -372,7 +372,7 @@ static void sunplus_set_termios(struct uart_port *port, + lcr |= UART_LCR_EPAR; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + uart_update_timeout(port, termios->c_cflag, baud); + +@@ -407,7 +407,7 @@ static void sunplus_set_termios(struct uart_port *port, + writel(div_l, port->membase + SUP_UART_DIV_L); + writel(lcr, port->membase + SUP_UART_LCR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void sunplus_set_ldisc(struct uart_port *port, struct ktermios *termios) +@@ -517,15 +517,15 @@ static void sunplus_console_write(struct console *co, + if (sunplus_console_ports[co->index]->port.sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock(&sunplus_console_ports[co->index]->port.lock); ++ locked = uart_port_trylock(&sunplus_console_ports[co->index]->port); + else +- spin_lock(&sunplus_console_ports[co->index]->port.lock); ++ uart_port_lock(&sunplus_console_ports[co->index]->port); + + uart_console_write(&sunplus_console_ports[co->index]->port, s, count, + sunplus_uart_console_putchar); + + if (locked) +- spin_unlock(&sunplus_console_ports[co->index]->port.lock); ++ uart_port_unlock(&sunplus_console_ports[co->index]->port); + + local_irq_restore(flags); + } +diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c +index 40eeaf835..6aa51a6f8 100644 +--- a/drivers/tty/serial/sunsab.c ++++ b/drivers/tty/serial/sunsab.c +@@ -310,7 +310,7 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id) + unsigned long flags; + unsigned char gis; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + status.stat = 0; + gis = readb(&up->regs->r.gis) >> up->gis_shift; +@@ -331,7 +331,7 @@ static irqreturn_t sunsab_interrupt(int irq, void *dev_id) + transmit_chars(up, &status); + } + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + if (port) + tty_flip_buffer_push(port); +@@ -473,12 +473,12 @@ static void sunsab_send_xchar(struct uart_port *port, char ch) + if (ch == __DISABLED_CHAR) + return; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + sunsab_tec_wait(up); + writeb(ch, &up->regs->w.tic); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + /* port->lock held by caller. */ +@@ -499,7 +499,7 @@ static void sunsab_break_ctl(struct uart_port *port, int break_state) + unsigned long flags; + unsigned char val; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + val = up->cached_dafo; + if (break_state) +@@ -512,7 +512,7 @@ static void sunsab_break_ctl(struct uart_port *port, int break_state) + if (test_bit(SAB82532_XPR, &up->irqflags)) + sunsab_tx_idle(up); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + /* port->lock is not held. */ +@@ -527,7 +527,7 @@ static int sunsab_startup(struct uart_port *port) + if (err) + return err; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * Wait for any commands or immediate characters +@@ -582,7 +582,7 @@ static int sunsab_startup(struct uart_port *port) + set_bit(SAB82532_ALLS, &up->irqflags); + set_bit(SAB82532_XPR, &up->irqflags); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return 0; + } +@@ -594,7 +594,7 @@ static void sunsab_shutdown(struct uart_port *port) + container_of(port, struct uart_sunsab_port, port); + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* Disable Interrupts */ + up->interrupt_mask0 = 0xff; +@@ -628,7 +628,7 @@ static void sunsab_shutdown(struct uart_port *port) + writeb(tmp, &up->regs->rw.ccr0); + #endif + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + free_irq(up->port.irq, up); + } + +@@ -779,9 +779,9 @@ static void sunsab_set_termios(struct uart_port *port, struct ktermios *termios, + unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); + unsigned int quot = uart_get_divisor(port, baud); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + sunsab_convert_to_sab(up, termios->c_cflag, termios->c_iflag, baud, quot); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static const char *sunsab_type(struct uart_port *port) +@@ -857,15 +857,15 @@ static void sunsab_console_write(struct console *con, const char *s, unsigned n) + int locked = 1; + + if (up->port.sysrq || oops_in_progress) +- locked = spin_trylock_irqsave(&up->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&up->port, &flags); + else +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + uart_console_write(&up->port, s, n, sunsab_console_putchar); + sunsab_tec_wait(up); + + if (locked) +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int sunsab_console_setup(struct console *con, char *options) +@@ -914,7 +914,7 @@ static int sunsab_console_setup(struct console *con, char *options) + */ + sunsab_startup(&up->port); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * Finally, enable interrupts +@@ -932,7 +932,7 @@ static int sunsab_console_setup(struct console *con, char *options) + sunsab_convert_to_sab(up, con->cflag, 0, baud, quot); + sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return 0; + } +diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c +index 58a4342ad..1e051cc25 100644 +--- a/drivers/tty/serial/sunsu.c ++++ b/drivers/tty/serial/sunsu.c +@@ -212,9 +212,9 @@ static void enable_rsa(struct uart_sunsu_port *up) + { + if (up->port.type == PORT_RSA) { + if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) { +- spin_lock_irq(&up->port.lock); ++ uart_port_lock_irq(&up->port); + __enable_rsa(up); +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + } + if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) + serial_outp(up, UART_RSA_FRR, 0); +@@ -234,7 +234,7 @@ static void disable_rsa(struct uart_sunsu_port *up) + + if (up->port.type == PORT_RSA && + up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) { +- spin_lock_irq(&up->port.lock); ++ uart_port_lock_irq(&up->port); + + mode = serial_inp(up, UART_RSA_MSR); + result = !(mode & UART_RSA_MSR_FIFO); +@@ -247,7 +247,7 @@ static void disable_rsa(struct uart_sunsu_port *up) + + if (result) + up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16; +- spin_unlock_irq(&up->port.lock); ++ uart_port_unlock_irq(&up->port); + } + } + #endif /* CONFIG_SERIAL_8250_RSA */ +@@ -311,10 +311,10 @@ static void sunsu_enable_ms(struct uart_port *port) + container_of(port, struct uart_sunsu_port, port); + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + up->ier |= UART_IER_MSI; + serial_out(up, UART_IER, up->ier); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static void +@@ -456,7 +456,7 @@ static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) + unsigned long flags; + unsigned char status; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + do { + status = serial_inp(up, UART_LSR); +@@ -470,7 +470,7 @@ static irqreturn_t sunsu_serial_interrupt(int irq, void *dev_id) + + } while (!(serial_in(up, UART_IIR) & UART_IIR_NO_INT)); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return IRQ_HANDLED; + } +@@ -545,9 +545,9 @@ static unsigned int sunsu_tx_empty(struct uart_port *port) + unsigned long flags; + unsigned int ret; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return ret; + } +@@ -599,13 +599,13 @@ static void sunsu_break_ctl(struct uart_port *port, int break_state) + container_of(port, struct uart_sunsu_port, port); + unsigned long flags; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_out(up, UART_LCR, up->lcr); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int sunsu_startup(struct uart_port *port) +@@ -683,12 +683,12 @@ static int sunsu_startup(struct uart_port *port) + */ + serial_outp(up, UART_LCR, UART_LCR_WLEN8); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + up->port.mctrl |= TIOCM_OUT2; + + sunsu_set_mctrl(&up->port, up->port.mctrl); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + /* + * Finally, enable interrupts. Note: Modem status interrupts +@@ -731,7 +731,7 @@ static void sunsu_shutdown(struct uart_port *port) + up->ier = 0; + serial_outp(up, UART_IER, 0); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + if (up->port.flags & UPF_FOURPORT) { + /* reset interrupts on the AST Fourport board */ + inb((up->port.iobase & 0xfe0) | 0x1f); +@@ -740,7 +740,7 @@ static void sunsu_shutdown(struct uart_port *port) + up->port.mctrl &= ~TIOCM_OUT2; + + sunsu_set_mctrl(&up->port, up->port.mctrl); +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + /* + * Disable break condition and FIFOs +@@ -826,7 +826,7 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * Update the per-port timeout. +@@ -891,7 +891,7 @@ sunsu_change_speed(struct uart_port *port, unsigned int cflag, + + up->cflag = cflag; + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static void +@@ -1038,7 +1038,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) + up->type_probed = PORT_UNKNOWN; + up->port.iotype = UPIO_MEM; + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + if (!(up->port.flags & UPF_BUGGY_UART)) { + /* +@@ -1173,7 +1173,7 @@ static void sunsu_autoconfig(struct uart_sunsu_port *up) + serial_outp(up, UART_IER, 0); + + out: +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static struct uart_driver sunsu_reg = { +@@ -1298,9 +1298,9 @@ static void sunsu_console_write(struct console *co, const char *s, + int locked = 1; + + if (up->port.sysrq || oops_in_progress) +- locked = spin_trylock_irqsave(&up->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&up->port, &flags); + else +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + /* + * First save the UER then disable the interrupts +@@ -1318,7 +1318,7 @@ static void sunsu_console_write(struct console *co, const char *s, + serial_out(up, UART_IER, ier); + + if (locked) +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + /* +diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c +index c8c71c562..d3b5e864b 100644 +--- a/drivers/tty/serial/sunzilog.c ++++ b/drivers/tty/serial/sunzilog.c +@@ -531,7 +531,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) + struct tty_port *port; + unsigned char r3; + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + r3 = read_zsreg(channel, R3); + + /* Channel A */ +@@ -548,7 +548,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) + if (r3 & CHATxIP) + sunzilog_transmit_chars(up, channel); + } +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + if (port) + tty_flip_buffer_push(port); +@@ -557,7 +557,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) + up = up->next; + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + +- spin_lock(&up->port.lock); ++ uart_port_lock(&up->port); + port = NULL; + if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { + writeb(RES_H_IUS, &channel->control); +@@ -571,7 +571,7 @@ static irqreturn_t sunzilog_interrupt(int irq, void *dev_id) + if (r3 & CHBTxIP) + sunzilog_transmit_chars(up, channel); + } +- spin_unlock(&up->port.lock); ++ uart_port_unlock(&up->port); + + if (port) + tty_flip_buffer_push(port); +@@ -604,11 +604,11 @@ static unsigned int sunzilog_tx_empty(struct uart_port *port) + unsigned char status; + unsigned int ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + status = sunzilog_read_channel_status(port); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (status & Tx_BUF_EMP) + ret = TIOCSER_TEMT; +@@ -764,7 +764,7 @@ static void sunzilog_break_ctl(struct uart_port *port, int break_state) + else + clear_bits |= SND_BRK; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; + if (new_reg != up->curregs[R5]) { +@@ -774,7 +774,7 @@ static void sunzilog_break_ctl(struct uart_port *port, int break_state) + write_zsreg(channel, R5, up->curregs[R5]); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static void __sunzilog_startup(struct uart_sunzilog_port *up) +@@ -800,9 +800,9 @@ static int sunzilog_startup(struct uart_port *port) + if (ZS_IS_CONS(up)) + return 0; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + __sunzilog_startup(up); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return 0; + } + +@@ -840,7 +840,7 @@ static void sunzilog_shutdown(struct uart_port *port) + if (ZS_IS_CONS(up)) + return; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + channel = ZILOG_CHANNEL_FROM_PORT(port); + +@@ -853,7 +853,7 @@ static void sunzilog_shutdown(struct uart_port *port) + up->curregs[R5] &= ~SND_BRK; + sunzilog_maybe_update_regs(up, channel); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* Shared by TTY driver and serial console setup. The port lock is held +@@ -945,7 +945,7 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, + + baud = uart_get_baud_rate(port, termios, old, 1200, 76800); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + +@@ -962,7 +962,7 @@ sunzilog_set_termios(struct uart_port *port, struct ktermios *termios, + + uart_update_timeout(port, termios->c_cflag, baud); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static const char *sunzilog_type(struct uart_port *port) +@@ -1201,15 +1201,15 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count) + int locked = 1; + + if (up->port.sysrq || oops_in_progress) +- locked = spin_trylock_irqsave(&up->port.lock, flags); ++ locked = uart_port_trylock_irqsave(&up->port, &flags); + else +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + uart_console_write(&up->port, s, count, sunzilog_putchar); + udelay(2); + + if (locked) +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + } + + static int __init sunzilog_console_setup(struct console *con, char *options) +@@ -1244,7 +1244,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) + + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + + up->curregs[R15] |= BRKIE; + sunzilog_convert_to_zs(up, con->cflag, 0, brg); +@@ -1252,7 +1252,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options) + sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS); + __sunzilog_startup(up); + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + return 0; + } +@@ -1333,7 +1333,7 @@ static void sunzilog_init_hw(struct uart_sunzilog_port *up) + + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + +- spin_lock_irqsave(&up->port.lock, flags); ++ uart_port_lock_irqsave(&up->port, &flags); + if (ZS_IS_CHANNEL_A(up)) { + write_zsreg(channel, R9, FHWRES); + ZSDELAY_LONG(); +@@ -1383,7 +1383,7 @@ static void sunzilog_init_hw(struct uart_sunzilog_port *up) + write_zsreg(channel, R9, up->curregs[R9]); + } + +- spin_unlock_irqrestore(&up->port.lock, flags); ++ uart_port_unlock_irqrestore(&up->port, flags); + + #ifdef CONFIG_SERIO + if (up->flags & (SUNZILOG_FLAG_CONS_KEYB | +diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c +index 0859394a7..0cc6524f5 100644 +--- a/drivers/tty/serial/timbuart.c ++++ b/drivers/tty/serial/timbuart.c +@@ -174,7 +174,7 @@ static void timbuart_tasklet(struct tasklet_struct *t) + struct timbuart_port *uart = from_tasklet(uart, t, tasklet); + u32 isr, ier = 0; + +- spin_lock(&uart->port.lock); ++ uart_port_lock(&uart->port); + + isr = ioread32(uart->port.membase + TIMBUART_ISR); + dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr); +@@ -189,7 +189,7 @@ static void timbuart_tasklet(struct tasklet_struct *t) + + iowrite32(ier, uart->port.membase + TIMBUART_IER); + +- spin_unlock(&uart->port.lock); ++ uart_port_unlock(&uart->port); + dev_dbg(uart->port.dev, "%s leaving\n", __func__); + } + +@@ -295,10 +295,10 @@ static void timbuart_set_termios(struct uart_port *port, + tty_termios_copy_hw(termios, old); + tty_termios_encode_baud_rate(termios, baud, baud); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE); + uart_update_timeout(port, termios->c_cflag, baud); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *timbuart_type(struct uart_port *port) +diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c +index b225a78f6..404c14aca 100644 +--- a/drivers/tty/serial/uartlite.c ++++ b/drivers/tty/serial/uartlite.c +@@ -216,11 +216,11 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) + unsigned long flags; + + do { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + stat = uart_in32(ULITE_STATUS, port); + busy = ulite_receive(port, stat); + busy |= ulite_transmit(port, stat); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + n++; + } while (busy); + +@@ -238,9 +238,9 @@ static unsigned int ulite_tx_empty(struct uart_port *port) + unsigned long flags; + unsigned int ret; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + ret = uart_in32(ULITE_STATUS, port); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return ret & ULITE_STATUS_TXEMPTY ? TIOCSER_TEMT : 0; + } +@@ -323,7 +323,7 @@ static void ulite_set_termios(struct uart_port *port, + termios->c_cflag |= pdata->cflags & (PARENB | PARODD | CSIZE); + tty_termios_encode_baud_rate(termios, pdata->baud, pdata->baud); + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + port->read_status_mask = ULITE_STATUS_RXVALID | ULITE_STATUS_OVERRUN + | ULITE_STATUS_TXFULL; +@@ -346,7 +346,7 @@ static void ulite_set_termios(struct uart_port *port, + /* update timeout */ + uart_update_timeout(port, termios->c_cflag, pdata->baud); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *ulite_type(struct uart_port *port) +@@ -495,9 +495,9 @@ static void ulite_console_write(struct console *co, const char *s, + int locked = 1; + + if (oops_in_progress) { +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + } else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* save and disable interrupt */ + ier = uart_in32(ULITE_STATUS, port) & ULITE_STATUS_IE; +@@ -512,7 +512,7 @@ static void ulite_console_write(struct console *co, const char *s, + uart_out32(ULITE_CONTROL_IE, ULITE_CONTROL, port); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static int ulite_console_setup(struct console *co, char *options) +diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c +index b06661b80..ed7a6bb55 100644 +--- a/drivers/tty/serial/ucc_uart.c ++++ b/drivers/tty/serial/ucc_uart.c +@@ -931,7 +931,7 @@ static void qe_uart_set_termios(struct uart_port *port, + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); + + /* Do we really need a spinlock here? */ +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Update the per-port timeout. */ + uart_update_timeout(port, termios->c_cflag, baud); +@@ -949,7 +949,7 @@ static void qe_uart_set_termios(struct uart_port *port, + qe_setbrg(qe_port->us_info.tx_clock, baud, 16); + } + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* +diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c +index c5d5c2765..78a1c1eea 100644 +--- a/drivers/tty/serial/vt8500_serial.c ++++ b/drivers/tty/serial/vt8500_serial.c +@@ -227,7 +227,7 @@ static irqreturn_t vt8500_irq(int irq, void *dev_id) + struct uart_port *port = dev_id; + unsigned long isr; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + isr = vt8500_read(port, VT8500_URISR); + + /* Acknowledge active status bits */ +@@ -240,7 +240,7 @@ static irqreturn_t vt8500_irq(int irq, void *dev_id) + if (isr & TCTS) + handle_delta_cts(port); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + return IRQ_HANDLED; + } +@@ -342,7 +342,7 @@ static void vt8500_set_termios(struct uart_port *port, + unsigned int baud, lcr; + unsigned int loops = 1000; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* calculate and set baud rate */ + baud = uart_get_baud_rate(port, termios, old, 900, 921600); +@@ -410,7 +410,7 @@ static void vt8500_set_termios(struct uart_port *port, + vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR); + vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + static const char *vt8500_type(struct uart_port *port) +diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c +index 2e5e86a00..9c13dac1d 100644 +--- a/drivers/tty/serial/xilinx_uartps.c ++++ b/drivers/tty/serial/xilinx_uartps.c +@@ -346,7 +346,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) + struct uart_port *port = (struct uart_port *)dev_id; + unsigned int isrstatus; + +- spin_lock(&port->lock); ++ uart_port_lock(port); + + /* Read the interrupt status register to determine which + * interrupt(s) is/are active and clear them. +@@ -369,7 +369,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) + !(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_RX_DIS)) + cdns_uart_handle_rx(dev_id, isrstatus); + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + return IRQ_HANDLED; + } + +@@ -506,14 +506,14 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, + return NOTIFY_BAD; + } + +- spin_lock_irqsave(&cdns_uart->port->lock, flags); ++ uart_port_lock_irqsave(cdns_uart->port, &flags); + + /* Disable the TX and RX to set baud rate */ + ctrl_reg = readl(port->membase + CDNS_UART_CR); + ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; + writel(ctrl_reg, port->membase + CDNS_UART_CR); + +- spin_unlock_irqrestore(&cdns_uart->port->lock, flags); ++ uart_port_unlock_irqrestore(cdns_uart->port, flags); + + return NOTIFY_OK; + } +@@ -523,7 +523,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, + * frequency. + */ + +- spin_lock_irqsave(&cdns_uart->port->lock, flags); ++ uart_port_lock_irqsave(cdns_uart->port, &flags); + + locked = 1; + port->uartclk = ndata->new_rate; +@@ -533,7 +533,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, + fallthrough; + case ABORT_RATE_CHANGE: + if (!locked) +- spin_lock_irqsave(&cdns_uart->port->lock, flags); ++ uart_port_lock_irqsave(cdns_uart->port, &flags); + + /* Set TX/RX Reset */ + ctrl_reg = readl(port->membase + CDNS_UART_CR); +@@ -555,7 +555,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, + ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; + writel(ctrl_reg, port->membase + CDNS_UART_CR); + +- spin_unlock_irqrestore(&cdns_uart->port->lock, flags); ++ uart_port_unlock_irqrestore(cdns_uart->port, flags); + + return NOTIFY_OK; + default: +@@ -652,7 +652,7 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl) + unsigned int status; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + status = readl(port->membase + CDNS_UART_CR); + +@@ -664,7 +664,7 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl) + writel(CDNS_UART_CR_STOPBRK | status, + port->membase + CDNS_UART_CR); + } +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /** +@@ -683,7 +683,7 @@ static void cdns_uart_set_termios(struct uart_port *port, + unsigned long flags; + unsigned int ctrl_reg, mode_reg; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable the TX and RX to set baud rate */ + ctrl_reg = readl(port->membase + CDNS_UART_CR); +@@ -794,7 +794,7 @@ static void cdns_uart_set_termios(struct uart_port *port, + cval &= ~CDNS_UART_MODEMCR_FCM; + writel(cval, port->membase + CDNS_UART_MODEMCR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /** +@@ -813,7 +813,7 @@ static int cdns_uart_startup(struct uart_port *port) + + is_brk_support = cdns_uart->quirks & CDNS_UART_RXBS_SUPPORT; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable the TX and RX */ + writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, +@@ -861,7 +861,7 @@ static int cdns_uart_startup(struct uart_port *port) + writel(readl(port->membase + CDNS_UART_ISR), + port->membase + CDNS_UART_ISR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + ret = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, port); + if (ret) { +@@ -889,7 +889,7 @@ static void cdns_uart_shutdown(struct uart_port *port) + int status; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Disable interrupts */ + status = readl(port->membase + CDNS_UART_IMR); +@@ -900,7 +900,7 @@ static void cdns_uart_shutdown(struct uart_port *port) + writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, + port->membase + CDNS_UART_CR); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + free_irq(port->irq, port); + } +@@ -1050,7 +1050,7 @@ static int cdns_uart_poll_get_char(struct uart_port *port) + int c; + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Check if FIFO is empty */ + if (readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY) +@@ -1058,7 +1058,7 @@ static int cdns_uart_poll_get_char(struct uart_port *port) + else /* Read a character */ + c = (unsigned char) readl(port->membase + CDNS_UART_FIFO); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + return c; + } +@@ -1067,7 +1067,7 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) + { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Wait until FIFO is empty */ + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) +@@ -1080,7 +1080,7 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) + cpu_relax(); + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + #endif + +@@ -1232,9 +1232,9 @@ static void cdns_uart_console_write(struct console *co, const char *s, + if (port->sysrq) + locked = 0; + else if (oops_in_progress) +- locked = spin_trylock_irqsave(&port->lock, flags); ++ locked = uart_port_trylock_irqsave(port, &flags); + else +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* save and disable interrupt */ + imr = readl(port->membase + CDNS_UART_IMR); +@@ -1257,7 +1257,7 @@ static void cdns_uart_console_write(struct console *co, const char *s, + writel(imr, port->membase + CDNS_UART_IER); + + if (locked) +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /** +@@ -1325,7 +1325,7 @@ static int cdns_uart_suspend(struct device *device) + if (console_suspend_enabled && uart_console(port) && may_wake) { + unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + /* Empty the receive FIFO 1st before making changes */ + while (!(readl(port->membase + CDNS_UART_SR) & + CDNS_UART_SR_RXEMPTY)) +@@ -1334,7 +1334,7 @@ static int cdns_uart_suspend(struct device *device) + writel(1, port->membase + CDNS_UART_RXWM); + /* disable RX timeout interrups */ + writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IDR); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + /* +@@ -1372,7 +1372,7 @@ static int cdns_uart_resume(struct device *device) + return ret; + } + +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + + /* Set TX/RX Reset */ + ctrl_reg = readl(port->membase + CDNS_UART_CR); +@@ -1392,14 +1392,14 @@ static int cdns_uart_resume(struct device *device) + + clk_disable(cdns_uart->uartclk); + clk_disable(cdns_uart->pclk); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } else { +- spin_lock_irqsave(&port->lock, flags); ++ uart_port_lock_irqsave(port, &flags); + /* restore original rx trigger level */ + writel(rx_trigger_level, port->membase + CDNS_UART_RXWM); + /* enable RX timeout interrupt */ + writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER); +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + + return uart_resume_port(cdns_uart->cdns_uart_driver, port); +diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c +index 493fc4742..afa52883c 100644 +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -3543,8 +3543,15 @@ static ssize_t show_cons_active(struct device *dev, + for_each_console(c) { + if (!c->device) + continue; +- if (!c->write) +- continue; ++ if (c->flags & CON_NBCON) { ++ if (!c->write_atomic && ++ !(c->write_thread && c->kthread)) { ++ continue; ++ } ++ } else { ++ if (!c->write) ++ continue; ++ } + if ((c->flags & CON_ENABLED) == 0) + continue; + cs[i++] = c; +diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c +index e0758fe79..270367654 100644 +--- a/fs/proc/consoles.c ++++ b/fs/proc/consoles.c +@@ -21,12 +21,14 @@ static int show_console_dev(struct seq_file *m, void *v) + { CON_ENABLED, 'E' }, + { CON_CONSDEV, 'C' }, + { CON_BOOT, 'B' }, ++ { CON_NBCON, 'N' }, + { CON_PRINTBUFFER, 'p' }, + { CON_BRL, 'b' }, + { CON_ANYTIME, 'a' }, + }; + char flags[ARRAY_SIZE(con_flags) + 1]; + struct console *con = v; ++ char con_write = '-'; + unsigned int a; + dev_t dev = 0; + +@@ -57,9 +59,15 @@ static int show_console_dev(struct seq_file *m, void *v) + seq_setwidth(m, 21 - 1); + seq_printf(m, "%s%d", con->name, con->index); + seq_pad(m, ' '); +- seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-', +- con->write ? 'W' : '-', con->unblank ? 'U' : '-', +- flags); ++ if (con->flags & CON_NBCON) { ++ if (con->write_atomic || con->write_thread) ++ con_write = 'W'; ++ } else { ++ if (con->write) ++ con_write = 'W'; ++ } ++ seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-', con_write, ++ con->unblank ? 'U' : '-', flags); + if (dev) + seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev)); + +diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h +index fc53e0ad5..448bbef47 100644 +--- a/include/linux/bottom_half.h ++++ b/include/linux/bottom_half.h +@@ -35,8 +35,10 @@ static inline void local_bh_enable(void) + + #ifdef CONFIG_PREEMPT_RT + extern bool local_bh_blocked(void); ++extern void softirq_preempt(void); + #else + static inline bool local_bh_blocked(void) { return false; } ++static inline void softirq_preempt(void) { } + #endif + + #endif /* _LINUX_BH_H */ +diff --git a/include/linux/console.h b/include/linux/console.h +index 7de11c763..1eb9580e9 100644 +--- a/include/linux/console.h ++++ b/include/linux/console.h +@@ -16,7 +16,9 @@ + + #include + #include ++#include + #include ++#include + #include + + struct vc_data; +@@ -156,6 +158,8 @@ static inline int con_debug_leave(void) + * /dev/kmesg which requires a larger output buffer. + * @CON_SUSPENDED: Indicates if a console is suspended. If true, the + * printing callbacks must not be called. ++ * @CON_NBCON: Console can operate outside of the legacy style console_lock ++ * constraints. + */ + enum cons_flags { + CON_PRINTBUFFER = BIT(0), +@@ -166,6 +170,111 @@ enum cons_flags { + CON_BRL = BIT(5), + CON_EXTENDED = BIT(6), + CON_SUSPENDED = BIT(7), ++ CON_NBCON = BIT(8), ++}; ++ ++/** ++ * struct nbcon_state - console state for nbcon consoles ++ * @atom: Compound of the state fields for atomic operations ++ * ++ * @req_prio: The priority of a handover request ++ * @prio: The priority of the current owner ++ * @unsafe: Console is busy in a non takeover region ++ * @unsafe_takeover: A hostile takeover in an unsafe state happened in the ++ * past. The console cannot be safe until re-initialized. ++ * @cpu: The CPU on which the owner runs ++ * ++ * To be used for reading and preparing of the value stored in the nbcon ++ * state variable @console::nbcon_state. ++ * ++ * The @prio and @req_prio fields are particularly important to allow ++ * spin-waiting to timeout and give up without the risk of a waiter being ++ * assigned the lock after giving up. ++ */ ++struct nbcon_state { ++ union { ++ unsigned int atom; ++ struct { ++ unsigned int prio : 2; ++ unsigned int req_prio : 2; ++ unsigned int unsafe : 1; ++ unsigned int unsafe_takeover : 1; ++ unsigned int cpu : 24; ++ }; ++ }; ++}; ++ ++/* ++ * The nbcon_state struct is used to easily create and interpret values that ++ * are stored in the @console::nbcon_state variable. Ensure this struct stays ++ * within the size boundaries of the atomic variable's underlying type in ++ * order to avoid any accidental truncation. ++ */ ++static_assert(sizeof(struct nbcon_state) <= sizeof(int)); ++ ++/** ++ * nbcon_prio - console owner priority for nbcon consoles ++ * @NBCON_PRIO_NONE: Unused ++ * @NBCON_PRIO_NORMAL: Normal (non-emergency) usage ++ * @NBCON_PRIO_EMERGENCY: Emergency output (WARN/OOPS...) ++ * @NBCON_PRIO_PANIC: Panic output ++ * @NBCON_PRIO_MAX: The number of priority levels ++ * ++ * A higher priority context can takeover the console when it is ++ * in the safe state. The final attempt to flush consoles in panic() ++ * can be allowed to do so even in an unsafe state (Hope and pray). ++ */ ++enum nbcon_prio { ++ NBCON_PRIO_NONE = 0, ++ NBCON_PRIO_NORMAL, ++ NBCON_PRIO_EMERGENCY, ++ NBCON_PRIO_PANIC, ++ NBCON_PRIO_MAX, ++}; ++ ++struct console; ++struct printk_buffers; ++ ++/** ++ * struct nbcon_context - Context for console acquire/release ++ * @console: The associated console ++ * @spinwait_max_us: Limit for spin-wait acquire ++ * @prio: Priority of the context ++ * @allow_unsafe_takeover: Allow performing takeover even if unsafe. Can ++ * be used only with NBCON_PRIO_PANIC @prio. It ++ * might cause a system freeze when the console ++ * is used later. ++ * @backlog: Ringbuffer has pending records ++ * @pbufs: Pointer to the text buffer for this context ++ * @seq: The sequence number to print for this context ++ */ ++struct nbcon_context { ++ /* members set by caller */ ++ struct console *console; ++ unsigned int spinwait_max_us; ++ enum nbcon_prio prio; ++ unsigned int allow_unsafe_takeover : 1; ++ ++ /* members set by emit */ ++ unsigned int backlog : 1; ++ ++ /* members set by acquire */ ++ struct printk_buffers *pbufs; ++ u64 seq; ++}; ++ ++/** ++ * struct nbcon_write_context - Context handed to the nbcon write callbacks ++ * @ctxt: The core console context ++ * @outbuf: Pointer to the text buffer for output ++ * @len: Length to write ++ * @unsafe_takeover: If a hostile takeover in an unsafe state has occurred ++ */ ++struct nbcon_write_context { ++ struct nbcon_context __private ctxt; ++ char *outbuf; ++ unsigned int len; ++ bool unsafe_takeover; + }; + + /** +@@ -187,6 +296,17 @@ enum cons_flags { + * @dropped: Number of unreported dropped ringbuffer records + * @data: Driver private data + * @node: hlist node for the console list ++ * ++ * @write_atomic: Write callback for atomic context ++ * @write_thread: Write callback for non-atomic context ++ * @driver_enter: Callback to begin synchronization with driver code ++ * @driver_exit: Callback to finish synchronization with driver code ++ * @nbcon_state: State for nbcon consoles ++ * @nbcon_seq: Sequence number of the next record for nbcon to print ++ * @pbufs: Pointer to nbcon private buffer ++ * @kthread: Printer kthread for this console ++ * @rcuwait: RCU-safe wait object for @kthread waking ++ * @irq_work: Defer @kthread waking to IRQ work context + */ + struct console { + char name[16]; +@@ -206,6 +326,20 @@ struct console { + unsigned long dropped; + void *data; + struct hlist_node node; ++ ++ /* nbcon console specific members */ ++ bool (*write_atomic)(struct console *con, ++ struct nbcon_write_context *wctxt); ++ bool (*write_thread)(struct console *con, ++ struct nbcon_write_context *wctxt); ++ void (*driver_enter)(struct console *con, unsigned long *flags); ++ void (*driver_exit)(struct console *con, unsigned long flags); ++ atomic_t __private nbcon_state; ++ atomic_long_t __private nbcon_seq; ++ struct printk_buffers *pbufs; ++ struct task_struct *kthread; ++ struct rcuwait rcuwait; ++ struct irq_work irq_work; + }; + + #ifdef CONFIG_LOCKDEP +@@ -332,6 +466,22 @@ static inline bool console_is_registered(const struct console *con) + lockdep_assert_console_list_lock_held(); \ + hlist_for_each_entry(con, &console_list, node) + ++#ifdef CONFIG_PRINTK ++extern void nbcon_cpu_emergency_enter(void); ++extern void nbcon_cpu_emergency_exit(void); ++extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); ++extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); ++extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); ++extern void nbcon_reacquire(struct nbcon_write_context *wctxt); ++#else ++static inline void nbcon_cpu_emergency_enter(void) { } ++static inline void nbcon_cpu_emergency_exit(void) { } ++static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } ++static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } ++static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } ++static inline void nbcon_reacquire(struct nbcon_write_context *wctxt) { } ++#endif ++ + extern int console_set_on_cmdline; + extern struct console *early_console; + +diff --git a/include/linux/entry-common.h b/include/linux/entry-common.h +index d95ab85f9..8b3ab0cc1 100644 +--- a/include/linux/entry-common.h ++++ b/include/linux/entry-common.h +@@ -60,7 +60,7 @@ + #define EXIT_TO_USER_MODE_WORK \ + (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ + _TIF_NEED_RESCHED | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \ +- ARCH_EXIT_TO_USER_MODE_WORK) ++ _TIF_NEED_RESCHED_LAZY | ARCH_EXIT_TO_USER_MODE_WORK) + + /** + * arch_enter_from_user_mode - Architecture specific sanity check for user mode regs +diff --git a/include/linux/entry-kvm.h b/include/linux/entry-kvm.h +index 6813171af..674a622c9 100644 +--- a/include/linux/entry-kvm.h ++++ b/include/linux/entry-kvm.h +@@ -18,7 +18,7 @@ + + #define XFER_TO_GUEST_MODE_WORK \ + (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \ +- _TIF_NOTIFY_RESUME | ARCH_XFER_TO_GUEST_MODE_WORK) ++ _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED_LAZY | ARCH_XFER_TO_GUEST_MODE_WORK) + + struct kvm_vcpu; + +diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h +index 4a1dc88dd..a5091ac97 100644 +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -609,6 +609,35 @@ 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 ++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) ++{ ++ raise_softirq(TIMER_SOFTIRQ); ++} ++ ++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); + + static inline struct task_struct *this_cpu_ksoftirqd(void) +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index b8e60a204..ffa5248a9 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -3258,7 +3258,11 @@ struct softnet_data { + int defer_count; + int defer_ipi_scheduled; + struct sk_buff *defer_list; ++#ifndef CONFIG_PREEMPT_RT + call_single_data_t defer_csd; ++#else ++ struct work_struct defer_work; ++#endif + }; + + static inline void input_queue_head_incr(struct softnet_data *sd) +diff --git a/include/linux/printk.h b/include/linux/printk.h +index e4878bb58..ebebc32e7 100644 +--- a/include/linux/printk.h ++++ b/include/linux/printk.h +@@ -9,6 +9,8 @@ + #include + #include + ++struct uart_port; ++ + extern const char linux_banner[]; + extern const char linux_proc_banner[]; + +@@ -159,13 +161,16 @@ __printf(1, 2) __cold int _printk_deferred(const char *fmt, ...); + + extern void __printk_safe_enter(void); + extern void __printk_safe_exit(void); ++extern void __printk_deferred_enter(void); ++extern void __printk_deferred_exit(void); ++ + /* + * The printk_deferred_enter/exit macros are available only as a hack for + * some code paths that need to defer all printk console printing. Interrupts + * must be disabled for the deferred duration. + */ +-#define printk_deferred_enter __printk_safe_enter +-#define printk_deferred_exit __printk_safe_exit ++#define printk_deferred_enter() __printk_deferred_enter() ++#define printk_deferred_exit() __printk_deferred_exit() + + /* + * Please don't use printk_ratelimit(), because it shares ratelimiting state +@@ -192,6 +197,10 @@ void show_regs_print_info(const char *log_lvl); + extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold; + extern asmlinkage void dump_stack(void) __cold; + void printk_trigger_flush(void); ++void printk_legacy_allow_panic_sync(void); ++extern void nbcon_acquire(struct uart_port *up); ++extern void nbcon_release(struct uart_port *up); ++void nbcon_atomic_flush_unsafe(void); + #else + static inline __printf(1, 0) + int vprintk(const char *s, va_list args) +@@ -271,6 +280,23 @@ static inline void dump_stack(void) + static inline void printk_trigger_flush(void) + { + } ++ ++static inline void printk_legacy_allow_panic_sync(void) ++{ ++} ++ ++static inline void nbcon_acquire(struct uart_port *up) ++{ ++} ++ ++static inline void nbcon_release(struct uart_port *up) ++{ ++} ++ ++static inline void nbcon_atomic_flush_unsafe(void) ++{ ++} ++ + #endif + + #ifdef CONFIG_SMP +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 77f01ac38..c02fd12b4 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -911,6 +911,9 @@ struct task_struct { + * ->sched_remote_wakeup gets used, so it can be in this word. + */ + unsigned sched_remote_wakeup:1; ++#ifdef CONFIG_RT_MUTEXES ++ unsigned sched_rt_mutex:1; ++#endif + + /* Bit to tell LSMs we're in execve(): */ + unsigned in_execve:1; +@@ -1902,6 +1905,7 @@ static inline int dl_task_check_affinity(struct task_struct *p, const struct cpu + } + #endif + ++extern bool task_is_pi_boosted(const struct task_struct *p); + extern int yield_to(struct task_struct *p, bool preempt); + extern void set_user_nice(struct task_struct *p, long nice); + extern int task_prio(const struct task_struct *p); +@@ -2046,17 +2050,17 @@ static inline void update_tsk_thread_flag(struct task_struct *tsk, int flag, + update_ti_thread_flag(task_thread_info(tsk), flag, value); + } + +-static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) ++static inline bool test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) + { + return test_and_set_ti_thread_flag(task_thread_info(tsk), flag); + } + +-static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) ++static inline bool test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) + { + return test_and_clear_ti_thread_flag(task_thread_info(tsk), flag); + } + +-static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) ++static inline bool test_tsk_thread_flag(struct task_struct *tsk, int flag) + { + return test_ti_thread_flag(task_thread_info(tsk), flag); + } +@@ -2069,9 +2073,11 @@ static inline void set_tsk_need_resched(struct task_struct *tsk) + static inline void clear_tsk_need_resched(struct task_struct *tsk) + { + clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED); ++ if (IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO)) ++ clear_tsk_thread_flag(tsk, TIF_NEED_RESCHED_LAZY); + } + +-static inline int test_tsk_need_resched(struct task_struct *tsk) ++static inline bool test_tsk_need_resched(struct task_struct *tsk) + { + return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED)); + } +@@ -2252,7 +2258,7 @@ static inline int rwlock_needbreak(rwlock_t *lock) + + static __always_inline bool need_resched(void) + { +- return unlikely(tif_need_resched()); ++ return unlikely(tif_need_resched_lazy() || tif_need_resched()); + } + + /* +diff --git a/include/linux/sched/idle.h b/include/linux/sched/idle.h +index 478084f91..719416fe8 100644 +--- a/include/linux/sched/idle.h ++++ b/include/linux/sched/idle.h +@@ -63,7 +63,7 @@ static __always_inline bool __must_check current_set_polling_and_test(void) + */ + smp_mb__after_atomic(); + +- return unlikely(tif_need_resched()); ++ return unlikely(need_resched()); + } + + static __always_inline bool __must_check current_clr_polling_and_test(void) +@@ -76,7 +76,7 @@ static __always_inline bool __must_check current_clr_polling_and_test(void) + */ + smp_mb__after_atomic(); + +- return unlikely(tif_need_resched()); ++ return unlikely(need_resched()); + } + + #else +@@ -85,11 +85,11 @@ static inline void __current_clr_polling(void) { } + + static inline bool __must_check current_set_polling_and_test(void) + { +- return unlikely(tif_need_resched()); ++ return unlikely(need_resched()); + } + static inline bool __must_check current_clr_polling_and_test(void) + { +- return unlikely(tif_need_resched()); ++ return unlikely(need_resched()); + } + #endif + +diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h +index 994c25640..b2b9e6eb9 100644 +--- a/include/linux/sched/rt.h ++++ b/include/linux/sched/rt.h +@@ -30,6 +30,10 @@ static inline bool task_is_realtime(struct task_struct *tsk) + } + + #ifdef CONFIG_RT_MUTEXES ++extern void rt_mutex_pre_schedule(void); ++extern void rt_mutex_schedule(void); ++extern void rt_mutex_post_schedule(void); ++ + /* + * Must hold either p->pi_lock or task_rq(p)->lock. + */ +diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h +index be65de65f..ec46e3b49 100644 +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -153,6 +153,8 @@ struct uart_8250_port { + #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA + unsigned char msr_saved_flags; + ++ bool console_newline_needed; ++ + struct uart_8250_dma *dma; + const struct uart_8250_ops *ops; + +@@ -204,6 +206,10 @@ void serial8250_init_port(struct uart_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); ++bool serial8250_console_write_atomic(struct uart_8250_port *up, ++ struct nbcon_write_context *wctxt); ++bool serial8250_console_write_thread(struct uart_8250_port *up, ++ struct nbcon_write_context *wctxt); + int serial8250_console_setup(struct uart_port *port, char *options, bool probe); + int serial8250_console_exit(struct uart_port *port); + +diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h +index 052df85df..6de3d7aab 100644 +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -489,6 +489,7 @@ struct uart_port { + struct uart_icount icount; /* statistics */ + + struct console *cons; /* struct console, if any */ ++ bool nbcon_locked_port; /* True, if the port is locked by nbcon */ + /* flags must be updated while holding port mutex */ + upf_t flags; + +@@ -596,6 +597,7 @@ struct uart_port { + static inline void uart_port_lock(struct uart_port *up) + { + spin_lock(&up->lock); ++ nbcon_acquire(up); + } + + /** +@@ -605,6 +607,7 @@ static inline void uart_port_lock(struct uart_port *up) + static inline void uart_port_lock_irq(struct uart_port *up) + { + spin_lock_irq(&up->lock); ++ nbcon_acquire(up); + } + + /** +@@ -615,6 +618,7 @@ static inline void uart_port_lock_irq(struct uart_port *up) + static inline void uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags) + { + spin_lock_irqsave(&up->lock, *flags); ++ nbcon_acquire(up); + } + + /** +@@ -625,7 +629,11 @@ static inline void uart_port_lock_irqsave(struct uart_port *up, unsigned long *f + */ + static inline bool uart_port_trylock(struct uart_port *up) + { +- return spin_trylock(&up->lock); ++ if (!spin_trylock(&up->lock)) ++ return false; ++ ++ nbcon_acquire(up); ++ return true; + } + + /** +@@ -637,7 +645,11 @@ static inline bool uart_port_trylock(struct uart_port *up) + */ + static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned long *flags) + { +- return spin_trylock_irqsave(&up->lock, *flags); ++ if (!spin_trylock_irqsave(&up->lock, *flags)) ++ return false; ++ ++ nbcon_acquire(up); ++ return true; + } + + /** +@@ -646,6 +658,7 @@ static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned long + */ + static inline void uart_port_unlock(struct uart_port *up) + { ++ nbcon_release(up); + spin_unlock(&up->lock); + } + +@@ -655,6 +668,7 @@ static inline void uart_port_unlock(struct uart_port *up) + */ + static inline void uart_port_unlock_irq(struct uart_port *up) + { ++ nbcon_release(up); + spin_unlock_irq(&up->lock); + } + +@@ -664,6 +678,19 @@ static inline void uart_port_unlock_irq(struct uart_port *up) + * @flags: The saved interrupt flags for restore + */ + static inline void uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags) ++{ ++ nbcon_release(up); ++ spin_unlock_irqrestore(&up->lock, flags); ++} ++ ++/* Only for use in the console->driver_enter() callback. */ ++static inline void __uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags) ++{ ++ spin_lock_irqsave(&up->lock, *flags); ++} ++ ++/* Only for use in the console->driver_exit() callback. */ ++static inline void __uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags) + { + spin_unlock_irqrestore(&up->lock, flags); + } +@@ -1078,14 +1105,14 @@ static inline void uart_unlock_and_check_sysrq(struct uart_port *port) + u8 sysrq_ch; + + if (!port->has_sysrq) { +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + return; + } + + sysrq_ch = port->sysrq_ch; + port->sysrq_ch = 0; + +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + + if (sysrq_ch) + handle_sysrq(sysrq_ch); +@@ -1097,14 +1124,14 @@ static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port + u8 sysrq_ch; + + if (!port->has_sysrq) { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + return; + } + + sysrq_ch = port->sysrq_ch; + port->sysrq_ch = 0; + +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + + if (sysrq_ch) + handle_sysrq(sysrq_ch); +@@ -1120,12 +1147,12 @@ static inline int uart_prepare_sysrq_char(struct uart_port *port, u8 ch) + } + static inline void uart_unlock_and_check_sysrq(struct uart_port *port) + { +- spin_unlock(&port->lock); ++ uart_port_unlock(port); + } + static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port, + unsigned long flags) + { +- spin_unlock_irqrestore(&port->lock, flags); ++ uart_port_unlock_irqrestore(port, flags); + } + #endif /* CONFIG_MAGIC_SYSRQ_SERIAL */ + +diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h +index 9ea0b2806..5ded1450a 100644 +--- a/include/linux/thread_info.h ++++ b/include/linux/thread_info.h +@@ -59,6 +59,16 @@ enum syscall_work_bit { + + #include + ++#ifdef CONFIG_PREEMPT_BUILD_AUTO ++# define TIF_NEED_RESCHED_LAZY TIF_ARCH_RESCHED_LAZY ++# define _TIF_NEED_RESCHED_LAZY _TIF_ARCH_RESCHED_LAZY ++# define TIF_NEED_RESCHED_LAZY_OFFSET (TIF_NEED_RESCHED_LAZY - TIF_NEED_RESCHED) ++#else ++# define TIF_NEED_RESCHED_LAZY TIF_NEED_RESCHED ++# define _TIF_NEED_RESCHED_LAZY _TIF_NEED_RESCHED ++# define TIF_NEED_RESCHED_LAZY_OFFSET 0 ++#endif ++ + #ifdef __KERNEL__ + + #ifndef arch_set_restart_data +@@ -185,6 +195,13 @@ static __always_inline bool tif_need_resched(void) + (unsigned long *)(¤t_thread_info()->flags)); + } + ++static __always_inline bool tif_need_resched_lazy(void) ++{ ++ return IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && ++ arch_test_bit(TIF_NEED_RESCHED_LAZY, ++ (unsigned long *)(¤t_thread_info()->flags)); ++} ++ + #else + + static __always_inline bool tif_need_resched(void) +@@ -193,6 +210,13 @@ static __always_inline bool tif_need_resched(void) + (unsigned long *)(¤t_thread_info()->flags)); + } + ++static __always_inline bool tif_need_resched_lazy(void) ++{ ++ return IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && ++ test_bit(TIF_NEED_RESCHED_LAZY, ++ (unsigned long *)(¤t_thread_info()->flags)); ++} ++ + #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */ + + #ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES +diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h +index cb8bd759e..ce1fefc37 100644 +--- a/include/linux/trace_events.h ++++ b/include/linux/trace_events.h +@@ -178,8 +178,8 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status); + + enum trace_flag_type { + TRACE_FLAG_IRQS_OFF = 0x01, +- TRACE_FLAG_IRQS_NOSUPPORT = 0x02, +- TRACE_FLAG_NEED_RESCHED = 0x04, ++ TRACE_FLAG_NEED_RESCHED = 0x02, ++ TRACE_FLAG_NEED_RESCHED_LAZY = 0x04, + TRACE_FLAG_HARDIRQ = 0x08, + TRACE_FLAG_SOFTIRQ = 0x10, + TRACE_FLAG_PREEMPT_RESCHED = 0x20, +@@ -205,11 +205,11 @@ static inline unsigned int tracing_gen_ctx(void) + + static inline unsigned int tracing_gen_ctx_flags(unsigned long irqflags) + { +- return tracing_gen_ctx_irq_test(TRACE_FLAG_IRQS_NOSUPPORT); ++ return tracing_gen_ctx_irq_test(0); + } + static inline unsigned int tracing_gen_ctx(void) + { +- return tracing_gen_ctx_irq_test(TRACE_FLAG_IRQS_NOSUPPORT); ++ return tracing_gen_ctx_irq_test(0); + } + #endif + +diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt +index c2f1fd95a..0f3d4c2a4 100644 +--- a/kernel/Kconfig.preempt ++++ b/kernel/Kconfig.preempt +@@ -11,6 +11,13 @@ config PREEMPT_BUILD + select PREEMPTION + select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK + ++config PREEMPT_BUILD_AUTO ++ bool ++ select PREEMPT_BUILD ++ ++config HAVE_PREEMPT_AUTO ++ bool ++ + choice + prompt "Preemption Model" + default PREEMPT_NONE +@@ -67,9 +74,17 @@ config PREEMPT + embedded system with latency requirements in the milliseconds + range. + ++config PREEMPT_AUTO ++ bool "Automagic preemption mode with runtime tweaking support" ++ depends on HAVE_PREEMPT_AUTO ++ select PREEMPT_BUILD_AUTO ++ help ++ Add some sensible blurb here ++ + config PREEMPT_RT + bool "Fully Preemptible Kernel (Real-Time)" + depends on EXPERT && ARCH_SUPPORTS_RT ++ select PREEMPT_BUILD_AUTO if HAVE_PREEMPT_AUTO + select PREEMPTION + help + This option turns the kernel into a real-time kernel by replacing +@@ -95,7 +110,7 @@ config PREEMPTION + + config PREEMPT_DYNAMIC + bool "Preemption behaviour defined on boot" +- depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT ++ depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT && !PREEMPT_AUTO + select JUMP_LABEL if HAVE_PREEMPT_DYNAMIC_KEY + select PREEMPT_BUILD + default y if HAVE_PREEMPT_DYNAMIC_CALL +diff --git a/kernel/entry/common.c b/kernel/entry/common.c +index 5ff4f1cd3..fd42f0b17 100644 +--- a/kernel/entry/common.c ++++ b/kernel/entry/common.c +@@ -161,7 +161,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 | _TIF_NEED_RESCHED_LAZY)) + schedule(); + + if (ti_work & _TIF_UPROBE) +@@ -391,7 +391,7 @@ void raw_irqentry_exit_cond_resched(void) + rcu_irq_exit_check_preempt(); + if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) + WARN_ON_ONCE(!on_thread_stack()); +- if (need_resched()) ++ if (test_tsk_need_resched(current)) + preempt_schedule_irq(); + } + } +diff --git a/kernel/entry/kvm.c b/kernel/entry/kvm.c +index 2e0f75bcb..d952fa5ee 100644 +--- a/kernel/entry/kvm.c ++++ b/kernel/entry/kvm.c +@@ -13,7 +13,7 @@ static int xfer_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work) + return -EINTR; + } + +- if (ti_work & _TIF_NEED_RESCHED) ++ if (ti_work & (_TIF_NEED_RESCHED | TIF_NEED_RESCHED_LAZY)) + schedule(); + + if (ti_work & _TIF_NOTIFY_RESUME) +diff --git a/kernel/futex/pi.c b/kernel/futex/pi.c +index ce2889f12..d636a1bbd 100644 +--- a/kernel/futex/pi.c ++++ b/kernel/futex/pi.c +@@ -1,6 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-or-later + + #include ++#include + #include + + #include "futex.h" +@@ -610,29 +611,16 @@ int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, + /* + * Caller must hold a reference on @pi_state. + */ +-static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_state) ++static int wake_futex_pi(u32 __user *uaddr, u32 uval, ++ struct futex_pi_state *pi_state, ++ struct rt_mutex_waiter *top_waiter) + { +- struct rt_mutex_waiter *top_waiter; + struct task_struct *new_owner; + bool postunlock = false; + DEFINE_RT_WAKE_Q(wqh); + u32 curval, newval; + int ret = 0; + +- top_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex); +- if (WARN_ON_ONCE(!top_waiter)) { +- /* +- * As per the comment in futex_unlock_pi() this should not happen. +- * +- * When this happens, give up our locks and try again, giving +- * the futex_lock_pi() instance time to complete, either by +- * waiting on the rtmutex or removing itself from the futex +- * queue. +- */ +- ret = -EAGAIN; +- goto out_unlock; +- } +- + new_owner = top_waiter->task; + + /* +@@ -1002,6 +990,12 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl + goto no_block; + } + ++ /* ++ * Must be done before we enqueue the waiter, here is unfortunately ++ * under the hb lock, but that *should* work because it does nothing. ++ */ ++ rt_mutex_pre_schedule(); ++ + rt_mutex_init_waiter(&rt_waiter); + + /* +@@ -1039,19 +1033,37 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl + ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter); + + cleanup: +- spin_lock(q.lock_ptr); + /* + * If we failed to acquire the lock (deadlock/signal/timeout), we must +- * first acquire the hb->lock before removing the lock from the +- * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait +- * lists consistent. ++ * must unwind the above, however we canont lock hb->lock because ++ * rt_mutex already has a waiter enqueued and hb->lock can itself try ++ * and enqueue an rt_waiter through rtlock. ++ * ++ * Doing the cleanup without holding hb->lock can cause inconsistent ++ * state between hb and pi_state, but only in the direction of not ++ * seeing a waiter that is leaving. ++ * ++ * See futex_unlock_pi(), it deals with this inconsistency. ++ * ++ * There be dragons here, since we must deal with the inconsistency on ++ * the way out (here), it is impossible to detect/warn about the race ++ * the other way around (missing an incoming waiter). + * +- * In particular; it is important that futex_unlock_pi() can not +- * observe this inconsistency. ++ * What could possibly go wrong... + */ + if (ret && !rt_mutex_cleanup_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter)) + ret = 0; + ++ /* ++ * Now that the rt_waiter has been dequeued, it is safe to use ++ * spinlock/rtlock (which might enqueue its own rt_waiter) and fix up ++ * the ++ */ ++ spin_lock(q.lock_ptr); ++ /* ++ * Waiter is unqueued. ++ */ ++ rt_mutex_post_schedule(); + no_block: + /* + * Fixup the pi_state owner and possibly acquire the lock if we +@@ -1132,6 +1144,7 @@ int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) + top_waiter = futex_top_waiter(hb, &key); + if (top_waiter) { + struct futex_pi_state *pi_state = top_waiter->pi_state; ++ struct rt_mutex_waiter *rt_waiter; + + ret = -EINVAL; + if (!pi_state) +@@ -1144,22 +1157,39 @@ int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) + if (pi_state->owner != current) + goto out_unlock; + +- get_pi_state(pi_state); + /* + * By taking wait_lock while still holding hb->lock, we ensure +- * there is no point where we hold neither; and therefore +- * wake_futex_p() must observe a state consistent with what we +- * observed. ++ * there is no point where we hold neither; and thereby ++ * wake_futex_pi() must observe any new waiters. ++ * ++ * Since the cleanup: case in futex_lock_pi() removes the ++ * rt_waiter without holding hb->lock, it is possible for ++ * wake_futex_pi() to not find a waiter while the above does, ++ * in this case the waiter is on the way out and it can be ++ * ignored. + * + * In particular; this forces __rt_mutex_start_proxy() to + * complete such that we're guaranteed to observe the +- * rt_waiter. Also see the WARN in wake_futex_pi(). ++ * rt_waiter. + */ + raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); ++ ++ /* ++ * Futex vs rt_mutex waiter state -- if there are no rt_mutex ++ * waiters even though futex thinks there are, then the waiter ++ * is leaving and the uncontended path is safe to take. ++ */ ++ rt_waiter = rt_mutex_top_waiter(&pi_state->pi_mutex); ++ if (!rt_waiter) { ++ raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); ++ goto do_uncontended; ++ } ++ ++ get_pi_state(pi_state); + spin_unlock(&hb->lock); + + /* drops pi_state->pi_mutex.wait_lock */ +- ret = wake_futex_pi(uaddr, uval, pi_state); ++ ret = wake_futex_pi(uaddr, uval, pi_state, rt_waiter); + + put_pi_state(pi_state); + +@@ -1187,6 +1217,7 @@ int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) + return ret; + } + ++do_uncontended: + /* + * We have no kernel internal state, i.e. no waiters in the + * kernel. Waiters which are about to queue themselves are stuck +diff --git a/kernel/futex/requeue.c b/kernel/futex/requeue.c +index cba8b1a6a..4c73e0b81 100644 +--- a/kernel/futex/requeue.c ++++ b/kernel/futex/requeue.c +@@ -850,11 +850,13 @@ int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + pi_mutex = &q.pi_state->pi_mutex; + ret = rt_mutex_wait_proxy_lock(pi_mutex, to, &rt_waiter); + +- /* Current is not longer pi_blocked_on */ +- spin_lock(q.lock_ptr); ++ /* ++ * See futex_unlock_pi()'s cleanup: comment. ++ */ + if (ret && !rt_mutex_cleanup_proxy_lock(pi_mutex, &rt_waiter)) + ret = 0; + ++ spin_lock(q.lock_ptr); + debug_rt_mutex_free_waiter(&rt_waiter); + /* + * Fixup the pi_state owner and possibly acquire the lock if we +diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c +index 1d4bc493b..486c68c11 100644 +--- a/kernel/ksysfs.c ++++ b/kernel/ksysfs.c +@@ -179,6 +179,15 @@ KERNEL_ATTR_RO(crash_elfcorehdr_size); + + #endif /* CONFIG_CRASH_CORE */ + ++#if defined(CONFIG_PREEMPT_RT) ++static ssize_t realtime_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%d\n", 1); ++} ++KERNEL_ATTR_RO(realtime); ++#endif ++ + /* whether file capabilities are enabled */ + static ssize_t fscaps_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +@@ -274,6 +283,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 + }; +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index 151bd3de5..5c21ba41e 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -56,6 +56,7 @@ + #include + #include + #include ++#include + + #include + +@@ -3971,6 +3972,8 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this, + if (!debug_locks_off() || debug_locks_silent) + return; + ++ nbcon_cpu_emergency_enter(); ++ + pr_warn("\n"); + pr_warn("================================\n"); + pr_warn("WARNING: inconsistent lock state\n"); +@@ -3999,6 +4002,8 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this, + + pr_warn("\nstack backtrace:\n"); + dump_stack(); ++ ++ nbcon_cpu_emergency_exit(); + } + + /* +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index 21db0df0e..4a10e8c16 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -218,6 +218,11 @@ static __always_inline bool rt_mutex_cmpxchg_acquire(struct rt_mutex_base *lock, + return try_cmpxchg_acquire(&lock->owner, &old, new); + } + ++static __always_inline bool rt_mutex_try_acquire(struct rt_mutex_base *lock) ++{ ++ return rt_mutex_cmpxchg_acquire(lock, NULL, current); ++} ++ + static __always_inline bool rt_mutex_cmpxchg_release(struct rt_mutex_base *lock, + struct task_struct *old, + struct task_struct *new) +@@ -297,6 +302,20 @@ static __always_inline bool rt_mutex_cmpxchg_acquire(struct rt_mutex_base *lock, + + } + ++static int __sched rt_mutex_slowtrylock(struct rt_mutex_base *lock); ++ ++static __always_inline bool rt_mutex_try_acquire(struct rt_mutex_base *lock) ++{ ++ /* ++ * With debug enabled rt_mutex_cmpxchg trylock() will always fail. ++ * ++ * Avoid unconditionally taking the slow path by using ++ * rt_mutex_slow_trylock() which is covered by the debug code and can ++ * acquire a non-contended rtmutex. ++ */ ++ return rt_mutex_slowtrylock(lock); ++} ++ + static __always_inline bool rt_mutex_cmpxchg_release(struct rt_mutex_base *lock, + struct task_struct *old, + struct task_struct *new) +@@ -1613,7 +1632,7 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock, + raw_spin_unlock_irq(&lock->wait_lock); + + if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner)) +- schedule(); ++ rt_mutex_schedule(); + + raw_spin_lock_irq(&lock->wait_lock); + set_current_state(state); +@@ -1642,7 +1661,7 @@ static void __sched rt_mutex_handle_deadlock(int res, int detect_deadlock, + WARN(1, "rtmutex deadlock detected\n"); + while (1) { + set_current_state(TASK_INTERRUPTIBLE); +- schedule(); ++ rt_mutex_schedule(); + } + } + +@@ -1737,6 +1756,15 @@ static int __sched rt_mutex_slowlock(struct rt_mutex_base *lock, + unsigned long flags; + int ret; + ++ /* ++ * Do all pre-schedule work here, before we queue a waiter and invoke ++ * PI -- any such work that trips on rtlock (PREEMPT_RT spinlock) would ++ * otherwise recurse back into task_blocks_on_rt_mutex() through ++ * rtlock_slowlock() and will then enqueue a second waiter for this ++ * same task and things get really confusing real fast. ++ */ ++ rt_mutex_pre_schedule(); ++ + /* + * Technically we could use raw_spin_[un]lock_irq() here, but this can + * be called in early boot if the cmpxchg() fast path is disabled +@@ -1748,6 +1776,7 @@ static int __sched rt_mutex_slowlock(struct rt_mutex_base *lock, + raw_spin_lock_irqsave(&lock->wait_lock, flags); + ret = __rt_mutex_slowlock_locked(lock, ww_ctx, state); + raw_spin_unlock_irqrestore(&lock->wait_lock, flags); ++ rt_mutex_post_schedule(); + + return ret; + } +@@ -1755,7 +1784,9 @@ static int __sched rt_mutex_slowlock(struct rt_mutex_base *lock, + static __always_inline int __rt_mutex_lock(struct rt_mutex_base *lock, + unsigned int state) + { +- if (likely(rt_mutex_cmpxchg_acquire(lock, NULL, current))) ++ lockdep_assert(!current->pi_blocked_on); ++ ++ if (likely(rt_mutex_try_acquire(lock))) + return 0; + + return rt_mutex_slowlock(lock, NULL, state); +diff --git a/kernel/locking/rwbase_rt.c b/kernel/locking/rwbase_rt.c +index 25ec02394..34a59569d 100644 +--- a/kernel/locking/rwbase_rt.c ++++ b/kernel/locking/rwbase_rt.c +@@ -71,6 +71,7 @@ static int __sched __rwbase_read_lock(struct rwbase_rt *rwb, + struct rt_mutex_base *rtm = &rwb->rtmutex; + int ret; + ++ rwbase_pre_schedule(); + raw_spin_lock_irq(&rtm->wait_lock); + + /* +@@ -125,12 +126,15 @@ static int __sched __rwbase_read_lock(struct rwbase_rt *rwb, + rwbase_rtmutex_unlock(rtm); + + trace_contention_end(rwb, ret); ++ rwbase_post_schedule(); + return ret; + } + + static __always_inline int rwbase_read_lock(struct rwbase_rt *rwb, + unsigned int state) + { ++ lockdep_assert(!current->pi_blocked_on); ++ + if (rwbase_read_trylock(rwb)) + return 0; + +@@ -237,6 +241,8 @@ static int __sched rwbase_write_lock(struct rwbase_rt *rwb, + /* Force readers into slow path */ + atomic_sub(READER_BIAS, &rwb->readers); + ++ rwbase_pre_schedule(); ++ + raw_spin_lock_irqsave(&rtm->wait_lock, flags); + if (__rwbase_write_trylock(rwb)) + goto out_unlock; +@@ -248,6 +254,7 @@ static int __sched rwbase_write_lock(struct rwbase_rt *rwb, + if (rwbase_signal_pending_state(state, current)) { + rwbase_restore_current_state(); + __rwbase_write_unlock(rwb, 0, flags); ++ rwbase_post_schedule(); + trace_contention_end(rwb, -EINTR); + return -EINTR; + } +@@ -266,6 +273,7 @@ static int __sched rwbase_write_lock(struct rwbase_rt *rwb, + + out_unlock: + raw_spin_unlock_irqrestore(&rtm->wait_lock, flags); ++ rwbase_post_schedule(); + return 0; + } + +diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c +index 11ed7ce65..62eac9fd8 100644 +--- a/kernel/locking/rwsem.c ++++ b/kernel/locking/rwsem.c +@@ -1427,8 +1427,14 @@ static inline void __downgrade_write(struct rw_semaphore *sem) + #define rwbase_signal_pending_state(state, current) \ + signal_pending_state(state, current) + ++#define rwbase_pre_schedule() \ ++ rt_mutex_pre_schedule() ++ + #define rwbase_schedule() \ +- schedule() ++ rt_mutex_schedule() ++ ++#define rwbase_post_schedule() \ ++ rt_mutex_post_schedule() + + #include "rwbase_rt.c" + +diff --git a/kernel/locking/spinlock_rt.c b/kernel/locking/spinlock_rt.c +index 48a19ed84..38e292454 100644 +--- a/kernel/locking/spinlock_rt.c ++++ b/kernel/locking/spinlock_rt.c +@@ -37,6 +37,8 @@ + + static __always_inline void rtlock_lock(struct rt_mutex_base *rtm) + { ++ lockdep_assert(!current->pi_blocked_on); ++ + if (unlikely(!rt_mutex_cmpxchg_acquire(rtm, NULL, current))) + rtlock_slowlock(rtm); + } +@@ -184,9 +186,13 @@ static __always_inline int rwbase_rtmutex_trylock(struct rt_mutex_base *rtm) + + #define rwbase_signal_pending_state(state, current) (0) + ++#define rwbase_pre_schedule() ++ + #define rwbase_schedule() \ + schedule_rtlock() + ++#define rwbase_post_schedule() ++ + #include "rwbase_rt.c" + /* + * The common functions which get wrapped into the rwlock API. +diff --git a/kernel/locking/ww_rt_mutex.c b/kernel/locking/ww_rt_mutex.c +index d1473c624..c7196de83 100644 +--- a/kernel/locking/ww_rt_mutex.c ++++ b/kernel/locking/ww_rt_mutex.c +@@ -62,7 +62,7 @@ __ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx, + } + mutex_acquire_nest(&rtm->dep_map, 0, 0, nest_lock, ip); + +- if (likely(rt_mutex_cmpxchg_acquire(&rtm->rtmutex, NULL, current))) { ++ if (likely(rt_mutex_try_acquire(&rtm->rtmutex))) { + if (ww_ctx) + ww_mutex_set_context_fastpath(lock, ww_ctx); + return 0; +diff --git a/kernel/panic.c b/kernel/panic.c +index ef9f9a4e9..9215df21d 100644 +--- a/kernel/panic.c ++++ b/kernel/panic.c +@@ -366,6 +366,8 @@ void panic(const char *fmt, ...) + */ + atomic_notifier_call_chain(&panic_notifier_list, 0, buf); + ++ printk_legacy_allow_panic_sync(); ++ + panic_print_sys_info(false); + + kmsg_dump(KMSG_DUMP_PANIC); +@@ -449,6 +451,7 @@ void panic(const char *fmt, ...) + * Explicitly flush the kernel log buffer one last time. + */ + console_flush_on_panic(CONSOLE_FLUSH_PENDING); ++ nbcon_atomic_flush_unsafe(); + + local_irq_enable(); + for (i = 0; ; i += PANIC_TIMER_STEP) { +@@ -627,6 +630,7 @@ bool oops_may_print(void) + */ + void oops_enter(void) + { ++ nbcon_cpu_emergency_enter(); + tracing_off(); + /* can't trust the integrity of the kernel anymore: */ + debug_locks_off(); +@@ -649,6 +653,7 @@ void oops_exit(void) + { + do_oops_enter_exit(); + print_oops_end_marker(); ++ nbcon_cpu_emergency_exit(); + kmsg_dump(KMSG_DUMP_OOPS); + } + +@@ -660,6 +665,8 @@ struct warn_args { + void __warn(const char *file, int line, void *caller, unsigned taint, + struct pt_regs *regs, struct warn_args *args) + { ++ nbcon_cpu_emergency_enter(); ++ + disable_trace_on_warning(); + + if (file) +@@ -690,6 +697,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); ++ ++ nbcon_cpu_emergency_exit(); + } + + #ifdef CONFIG_BUG +diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile +index f5b388e81..39a2b61c7 100644 +--- a/kernel/printk/Makefile ++++ b/kernel/printk/Makefile +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-y = printk.o +-obj-$(CONFIG_PRINTK) += printk_safe.o ++obj-$(CONFIG_PRINTK) += printk_safe.o nbcon.o + obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o + obj-$(CONFIG_PRINTK_INDEX) += index.o + +diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h +index 7d4979d5c..7db6992c5 100644 +--- a/kernel/printk/internal.h ++++ b/kernel/printk/internal.h +@@ -3,6 +3,8 @@ + * internal.h - printk internal definitions + */ + #include ++#include ++#include "printk_ringbuffer.h" + + #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL) + void __init printk_sysctl_init(void); +@@ -12,6 +14,12 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, + #define printk_sysctl_init() do { } while (0) + #endif + ++#define con_printk(lvl, con, fmt, ...) \ ++ printk(lvl pr_fmt("%s%sconsole [%s%d] " fmt), \ ++ (con->flags & CON_NBCON) ? "" : "legacy ", \ ++ (con->flags & CON_BOOT) ? "boot" : "", \ ++ con->name, con->index, ##__VA_ARGS__) ++ + #ifdef CONFIG_PRINTK + + #ifdef CONFIG_PRINTK_CALLER +@@ -35,6 +43,19 @@ enum printk_info_flags { + LOG_CONT = 8, /* text is a fragment of a continuation line */ + }; + ++extern struct printk_ringbuffer *prb; ++extern bool printk_threads_enabled; ++extern bool have_legacy_console; ++extern bool have_boot_console; ++ ++/* ++ * Specifies if the console lock/unlock dance is needed for console ++ * printing. If @have_boot_console is true, the nbcon consoles will ++ * be printed serially along with the legacy consoles because nbcon ++ * consoles cannot print simultaneously with boot consoles. ++ */ ++#define printing_via_unlock (have_legacy_console || have_boot_console) ++ + __printf(4, 0) + int vprintk_store(int facility, int level, + const struct dev_printk_info *dev_info, +@@ -61,12 +82,90 @@ void defer_console_output(void); + + u16 printk_parse_prefix(const char *text, int *level, + enum printk_info_flags *flags); ++void console_lock_spinning_enable(void); ++int console_lock_spinning_disable_and_check(int cookie); ++ ++u64 nbcon_seq_read(struct console *con); ++void nbcon_seq_force(struct console *con, u64 seq); ++bool nbcon_alloc(struct console *con); ++void nbcon_init(struct console *con); ++void nbcon_free(struct console *con); ++enum nbcon_prio nbcon_get_default_prio(void); ++void nbcon_atomic_flush_all(void); ++bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie); ++void nbcon_kthread_create(struct console *con); ++void nbcon_wake_threads(void); ++void nbcon_legacy_kthread_create(void); ++ ++/* ++ * Check if the given console is currently capable and allowed to print ++ * records. Note that this function does not consider the current context, ++ * which can also play a role in deciding if @con can be used to print ++ * records. ++ */ ++static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) ++{ ++ if (!(flags & CON_ENABLED)) ++ return false; ++ ++ if ((flags & CON_SUSPENDED)) ++ return false; ++ ++ if (flags & CON_NBCON) { ++ if (use_atomic) { ++ if (!con->write_atomic) ++ return false; ++ } else { ++ if (!con->write_thread || !con->kthread) ++ return false; ++ } ++ } else { ++ if (!con->write) ++ return false; ++ } ++ ++ /* ++ * Console drivers may assume that per-cpu resources have been ++ * allocated. So unless they're explicitly marked as being able to ++ * cope (CON_ANYTIME) don't call them until this CPU is officially up. ++ */ ++ if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) ++ return false; ++ ++ return true; ++} ++ ++/** ++ * nbcon_kthread_wake - Wake up a printk thread ++ * @con: Console to operate on ++ */ ++static inline void nbcon_kthread_wake(struct console *con) ++{ ++ /* ++ * Guarantee any new records can be seen by tasks preparing to wait ++ * before this context checks if the rcuwait is empty. ++ * ++ * The full memory barrier in rcuwait_wake_up() pairs with the full ++ * memory barrier within set_current_state() of ++ * ___rcuwait_wait_event(), which is called after prepare_to_rcuwait() ++ * adds the waiter but before it has checked the wait condition. ++ * ++ * This pairs with nbcon_kthread_func:A. ++ */ ++ rcuwait_wake_up(&con->rcuwait); /* LMM(nbcon_kthread_wake:A) */ ++} ++ + #else + + #define PRINTK_PREFIX_MAX 0 + #define PRINTK_MESSAGE_MAX 0 + #define PRINTKRB_RECORD_MAX 0 + ++static inline void nbcon_kthread_wake(struct console *con) { } ++static inline void nbcon_kthread_create(struct console *con) { } ++#define printk_threads_enabled (false) ++#define printing_via_unlock (false) ++ + /* + * In !PRINTK builds we still export console_sem + * semaphore and some of console functions (console_unlock()/etc.), so +@@ -76,8 +175,23 @@ u16 printk_parse_prefix(const char *text, int *level, + #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags) + + static inline bool printk_percpu_data_ready(void) { return false; } ++static inline u64 nbcon_seq_read(struct console *con) { return 0; } ++static inline void nbcon_seq_force(struct console *con, u64 seq) { } ++static inline bool nbcon_alloc(struct console *con) { return false; } ++static inline void nbcon_init(struct console *con) { } ++static inline void nbcon_free(struct console *con) { } ++static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; } ++static inline void nbcon_atomic_flush_all(void) { } ++static inline bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, ++ int cookie) { return false; } ++ ++static inline bool console_is_usable(struct console *con, short flags, ++ bool use_atomic) { return false; } ++ + #endif /* CONFIG_PRINTK */ + ++extern struct printk_buffers printk_shared_pbufs; ++ + /** + * struct printk_buffers - Buffers to read/format/output printk messages. + * @outbuf: After formatting, contains text to output. +@@ -105,3 +219,10 @@ struct printk_message { + }; + + bool other_cpu_in_panic(void); ++bool this_cpu_in_panic(void); ++bool printk_get_next_message(struct printk_message *pmsg, u64 seq, ++ bool is_extended, bool may_supress); ++ ++#ifdef CONFIG_PRINTK ++void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped); ++#endif +diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c +new file mode 100644 +index 000000000..b941039ee +--- /dev/null ++++ b/kernel/printk/nbcon.c +@@ -0,0 +1,1665 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++// Copyright (C) 2022 Linutronix GmbH, John Ogness ++// Copyright (C) 2022 Intel, Thomas Gleixner ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "printk_ringbuffer.h" ++#include "internal.h" ++/* ++ * Printk console printing implementation for consoles which does not depend ++ * on the legacy style console_lock mechanism. ++ * ++ * The state of the console is maintained in the "nbcon_state" atomic ++ * variable. ++ * ++ * The console is locked when: ++ * ++ * - The 'prio' field contains the priority of the context that owns the ++ * console. Only higher priority contexts are allowed to take over the ++ * lock. A value of 0 (NBCON_PRIO_NONE) means the console is not locked. ++ * ++ * - The 'cpu' field denotes on which CPU the console is locked. It is used ++ * to prevent busy waiting on the same CPU. Also it informs the lock owner ++ * that it has lost the lock in a more complex scenario when the lock was ++ * taken over by a higher priority context, released, and taken on another ++ * CPU with the same priority as the interrupted owner. ++ * ++ * The acquire mechanism uses a few more fields: ++ * ++ * - The 'req_prio' field is used by the handover approach to make the ++ * current owner aware that there is a context with a higher priority ++ * waiting for the friendly handover. ++ * ++ * - The 'unsafe' field allows to take over the console in a safe way in the ++ * middle of emitting a message. The field is set only when accessing some ++ * shared resources or when the console device is manipulated. It can be ++ * cleared, for example, after emitting one character when the console ++ * device is in a consistent state. ++ * ++ * - The 'unsafe_takeover' field is set when a hostile takeover took the ++ * console in an unsafe state. The console will stay in the unsafe state ++ * until re-initialized. ++ * ++ * The acquire mechanism uses three approaches: ++ * ++ * 1) Direct acquire when the console is not owned or is owned by a lower ++ * priority context and is in a safe state. ++ * ++ * 2) Friendly handover mechanism uses a request/grant handshake. It is used ++ * when the current owner has lower priority and the console is in an ++ * unsafe state. ++ * ++ * The requesting context: ++ * ++ * a) Sets its priority into the 'req_prio' field. ++ * ++ * b) Waits (with a timeout) for the owning context to unlock the ++ * console. ++ * ++ * c) Takes the lock and clears the 'req_prio' field. ++ * ++ * The owning context: ++ * ++ * a) Observes the 'req_prio' field set on exit from the unsafe ++ * console state. ++ * ++ * b) Gives up console ownership by clearing the 'prio' field. ++ * ++ * 3) Unsafe hostile takeover allows to take over the lock even when the ++ * console is an unsafe state. It is used only in panic() by the final ++ * attempt to flush consoles in a try and hope mode. ++ * ++ * Note that separate record buffers are used in panic(). As a result, ++ * the messages can be read and formatted without any risk even after ++ * using the hostile takeover in unsafe state. ++ * ++ * The release function simply clears the 'prio' field. ++ * ++ * All operations on @console::nbcon_state are atomic cmpxchg based to ++ * handle concurrency. ++ * ++ * The acquire/release functions implement only minimal policies: ++ * ++ * - Preference for higher priority contexts. ++ * - Protection of the panic CPU. ++ * ++ * All other policy decisions must be made at the call sites: ++ * ++ * - What is marked as an unsafe section. ++ * - Whether to spin-wait if there is already an owner and the console is ++ * in an unsafe state. ++ * - Whether to attempt an unsafe hostile takeover. ++ * ++ * The design allows to implement the well known: ++ * ++ * acquire() ++ * output_one_printk_record() ++ * release() ++ * ++ * The output of one printk record might be interrupted with a higher priority ++ * context. The new owner is supposed to reprint the entire interrupted record ++ * from scratch. ++ */ ++ ++/** ++ * nbcon_state_set - Helper function to set the console state ++ * @con: Console to update ++ * @new: The new state to write ++ * ++ * Only to be used when the console is not yet or no longer visible in the ++ * system. Otherwise use nbcon_state_try_cmpxchg(). ++ */ ++static inline void nbcon_state_set(struct console *con, struct nbcon_state *new) ++{ ++ atomic_set(&ACCESS_PRIVATE(con, nbcon_state), new->atom); ++} ++ ++/** ++ * nbcon_state_read - Helper function to read the console state ++ * @con: Console to read ++ * @state: The state to store the result ++ */ ++static inline void nbcon_state_read(struct console *con, struct nbcon_state *state) ++{ ++ state->atom = atomic_read(&ACCESS_PRIVATE(con, nbcon_state)); ++} ++ ++/** ++ * nbcon_state_try_cmpxchg() - Helper function for atomic_try_cmpxchg() on console state ++ * @con: Console to update ++ * @cur: Old/expected state ++ * @new: New state ++ * ++ * Return: True on success. False on fail and @cur is updated. ++ */ ++static inline bool nbcon_state_try_cmpxchg(struct console *con, struct nbcon_state *cur, ++ struct nbcon_state *new) ++{ ++ return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom); ++} ++ ++/** ++ * nbcon_seq_read - Read the current console sequence ++ * @con: Console to read the sequence of ++ * ++ * Return: Sequence number of the next record to print on @con. ++ */ ++u64 nbcon_seq_read(struct console *con) ++{ ++ unsigned long nbcon_seq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_seq)); ++ ++ return __ulseq_to_u64seq(prb, nbcon_seq); ++} ++ ++/** ++ * nbcon_seq_force - Force console sequence to a specific value ++ * @con: Console to work on ++ * @seq: Sequence number value to set ++ * ++ * Only to be used during init (before registration) or in extreme situations ++ * (such as panic with CONSOLE_REPLAY_ALL). ++ */ ++void nbcon_seq_force(struct console *con, u64 seq) ++{ ++ /* ++ * If the specified record no longer exists, the oldest available record ++ * is chosen. This is especially important on 32bit systems because only ++ * the lower 32 bits of the sequence number are stored. The upper 32 bits ++ * are derived from the sequence numbers available in the ringbuffer. ++ */ ++ u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb)); ++ ++ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __u64seq_to_ulseq(valid_seq)); ++ ++ /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */ ++ con->seq = 0; ++} ++ ++/** ++ * nbcon_seq_try_update - Try to update the console sequence number ++ * @ctxt: Pointer to an acquire context that contains ++ * all information about the acquire mode ++ * @new_seq: The new sequence number to set ++ * ++ * @ctxt->seq is updated to the new value of @con::nbcon_seq (expanded to ++ * the 64bit value). This could be a different value than @new_seq if ++ * nbcon_seq_force() was used or the current context no longer owns the ++ * console. In the later case, it will stop printing anyway. ++ */ ++static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq) ++{ ++ unsigned long nbcon_seq = __u64seq_to_ulseq(ctxt->seq); ++ struct console *con = ctxt->console; ++ ++ if (atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_seq), &nbcon_seq, ++ __u64seq_to_ulseq(new_seq))) { ++ ctxt->seq = new_seq; ++ } else { ++ ctxt->seq = nbcon_seq_read(con); ++ } ++} ++ ++bool printk_threads_enabled __ro_after_init; ++ ++/** ++ * nbcon_context_try_acquire_direct - Try to acquire directly ++ * @ctxt: The context of the caller ++ * @cur: The current console state ++ * ++ * Acquire the console when it is released. Also acquire the console when ++ * the current owner has a lower priority and the console is in a safe state. ++ * ++ * Return: 0 on success. Otherwise, an error code on failure. Also @cur ++ * is updated to the latest state when failed to modify it. ++ * ++ * Errors: ++ * ++ * -EPERM: A panic is in progress and this is not the panic CPU. ++ * Or the current owner or waiter has the same or higher ++ * priority. No acquire method can be successful in ++ * this case. ++ * ++ * -EBUSY: The current owner has a lower priority but the console ++ * in an unsafe state. The caller should try using ++ * the handover acquire method. ++ */ ++static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt, ++ struct nbcon_state *cur) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct console *con = ctxt->console; ++ struct nbcon_state new; ++ ++ do { ++ if (other_cpu_in_panic()) ++ return -EPERM; ++ ++ if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio) ++ return -EPERM; ++ ++ if (cur->unsafe) ++ return -EBUSY; ++ ++ /* ++ * The console should never be safe for a direct acquire ++ * if an unsafe hostile takeover has ever happened. ++ */ ++ WARN_ON_ONCE(cur->unsafe_takeover); ++ ++ new.atom = cur->atom; ++ new.prio = ctxt->prio; ++ new.req_prio = NBCON_PRIO_NONE; ++ new.unsafe = cur->unsafe_takeover; ++ new.cpu = cpu; ++ ++ } while (!nbcon_state_try_cmpxchg(con, cur, &new)); ++ ++ return 0; ++} ++ ++static bool nbcon_waiter_matches(struct nbcon_state *cur, int expected_prio) ++{ ++ /* ++ * The request context is well defined by the @req_prio because: ++ * ++ * - Only a context with a higher priority can take over the request. ++ * - There are only three priorities. ++ * - Only one CPU is allowed to request PANIC priority. ++ * - Lower priorities are ignored during panic() until reboot. ++ * ++ * As a result, the following scenario is *not* possible: ++ * ++ * 1. Another context with a higher priority directly takes ownership. ++ * 2. The higher priority context releases the ownership. ++ * 3. A lower priority context takes the ownership. ++ * 4. Another context with the same priority as this context ++ * creates a request and starts waiting. ++ */ ++ ++ return (cur->req_prio == expected_prio); ++} ++ ++/** ++ * nbcon_context_try_acquire_requested - Try to acquire after having ++ * requested a handover ++ * @ctxt: The context of the caller ++ * @cur: The current console state ++ * ++ * This is a helper function for nbcon_context_try_acquire_handover(). ++ * It is called when the console is in an unsafe state. The current ++ * owner will release the console on exit from the unsafe region. ++ * ++ * Return: 0 on success and @cur is updated to the new console state. ++ * Otherwise an error code on failure. ++ * ++ * Errors: ++ * ++ * -EPERM: A panic is in progress and this is not the panic CPU ++ * or this context is no longer the waiter. ++ * ++ * -EBUSY: The console is still locked. The caller should ++ * continue waiting. ++ * ++ * Note: The caller must still remove the request when an error has occurred ++ * except when this context is no longer the waiter. ++ */ ++static int nbcon_context_try_acquire_requested(struct nbcon_context *ctxt, ++ struct nbcon_state *cur) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct console *con = ctxt->console; ++ struct nbcon_state new; ++ ++ /* Note that the caller must still remove the request! */ ++ if (other_cpu_in_panic()) ++ return -EPERM; ++ ++ /* ++ * Note that the waiter will also change if there was an unsafe ++ * hostile takeover. ++ */ ++ if (!nbcon_waiter_matches(cur, ctxt->prio)) ++ return -EPERM; ++ ++ /* If still locked, caller should continue waiting. */ ++ if (cur->prio != NBCON_PRIO_NONE) ++ return -EBUSY; ++ ++ /* ++ * The previous owner should have never released ownership ++ * in an unsafe region. ++ */ ++ WARN_ON_ONCE(cur->unsafe); ++ ++ new.atom = cur->atom; ++ new.prio = ctxt->prio; ++ new.req_prio = NBCON_PRIO_NONE; ++ new.unsafe = cur->unsafe_takeover; ++ new.cpu = cpu; ++ ++ if (!nbcon_state_try_cmpxchg(con, cur, &new)) { ++ /* ++ * The acquire could fail only when it has been taken ++ * over by a higher priority context. ++ */ ++ WARN_ON_ONCE(nbcon_waiter_matches(cur, ctxt->prio)); ++ return -EPERM; ++ } ++ ++ /* Handover success. This context now owns the console. */ ++ return 0; ++} ++ ++/** ++ * nbcon_context_try_acquire_handover - Try to acquire via handover ++ * @ctxt: The context of the caller ++ * @cur: The current console state ++ * ++ * The function must be called only when the context has higher priority ++ * than the current owner and the console is in an unsafe state. ++ * It is the case when nbcon_context_try_acquire_direct() returns -EBUSY. ++ * ++ * The function sets "req_prio" field to make the current owner aware of ++ * the request. Then it waits until the current owner releases the console, ++ * or an even higher context takes over the request, or timeout expires. ++ * ++ * The current owner checks the "req_prio" field on exit from the unsafe ++ * region and releases the console. It does not touch the "req_prio" field ++ * so that the console stays reserved for the waiter. ++ * ++ * Return: 0 on success. Otherwise, an error code on failure. Also @cur ++ * is updated to the latest state when failed to modify it. ++ * ++ * Errors: ++ * ++ * -EPERM: A panic is in progress and this is not the panic CPU. ++ * Or a higher priority context has taken over the ++ * console or the handover request. ++ * ++ * -EBUSY: The current owner is on the same CPU so that the hand ++ * shake could not work. Or the current owner is not ++ * willing to wait (zero timeout). Or the console does ++ * not enter the safe state before timeout passed. The ++ * caller might still use the unsafe hostile takeover ++ * when allowed. ++ * ++ * -EAGAIN: @cur has changed when creating the handover request. ++ * The caller should retry with direct acquire. ++ */ ++static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt, ++ struct nbcon_state *cur) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct console *con = ctxt->console; ++ struct nbcon_state new; ++ int timeout; ++ int request_err = -EBUSY; ++ ++ /* ++ * Check that the handover is called when the direct acquire failed ++ * with -EBUSY. ++ */ ++ WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio); ++ WARN_ON_ONCE(!cur->unsafe); ++ ++ /* Handover is not possible on the same CPU. */ ++ if (cur->cpu == cpu) ++ return -EBUSY; ++ ++ /* ++ * Console stays unsafe after an unsafe takeover until re-initialized. ++ * Waiting is not going to help in this case. ++ */ ++ if (cur->unsafe_takeover) ++ return -EBUSY; ++ ++ /* Is the caller willing to wait? */ ++ if (ctxt->spinwait_max_us == 0) ++ return -EBUSY; ++ ++ /* ++ * Setup a request for the handover. The caller should try to acquire ++ * the console directly when the current state has been modified. ++ */ ++ new.atom = cur->atom; ++ new.req_prio = ctxt->prio; ++ if (!nbcon_state_try_cmpxchg(con, cur, &new)) ++ return -EAGAIN; ++ ++ cur->atom = new.atom; ++ ++ /* Wait until there is no owner and then acquire the console. */ ++ for (timeout = ctxt->spinwait_max_us; timeout >= 0; timeout--) { ++ /* On successful acquire, this request is cleared. */ ++ request_err = nbcon_context_try_acquire_requested(ctxt, cur); ++ if (!request_err) ++ return 0; ++ ++ /* ++ * If the acquire should be aborted, it must be ensured ++ * that the request is removed before returning to caller. ++ */ ++ if (request_err == -EPERM) ++ break; ++ ++ udelay(1); ++ ++ /* Re-read the state because some time has passed. */ ++ nbcon_state_read(con, cur); ++ } ++ ++ /* Timed out or aborted. Carefully remove handover request. */ ++ do { ++ /* ++ * No need to remove request if there is a new waiter. This ++ * can only happen if a higher priority context has taken over ++ * the console or the handover request. ++ */ ++ if (!nbcon_waiter_matches(cur, ctxt->prio)) ++ return -EPERM; ++ ++ /* Unset request for handover. */ ++ new.atom = cur->atom; ++ new.req_prio = NBCON_PRIO_NONE; ++ if (nbcon_state_try_cmpxchg(con, cur, &new)) { ++ /* ++ * Request successfully unset. Report failure of ++ * acquiring via handover. ++ */ ++ cur->atom = new.atom; ++ return request_err; ++ } ++ ++ /* ++ * Unable to remove request. Try to acquire in case ++ * the owner has released the lock. ++ */ ++ } while (nbcon_context_try_acquire_requested(ctxt, cur)); ++ ++ /* Lucky timing. The acquire succeeded while removing the request. */ ++ return 0; ++} ++ ++/** ++ * nbcon_context_try_acquire_hostile - Acquire via unsafe hostile takeover ++ * @ctxt: The context of the caller ++ * @cur: The current console state ++ * ++ * Acquire the console even in the unsafe state. ++ * ++ * It can be permitted by setting the 'allow_unsafe_takeover' field only ++ * by the final attempt to flush messages in panic(). ++ * ++ * Return: 0 on success. -EPERM when not allowed by the context. ++ */ ++static int nbcon_context_try_acquire_hostile(struct nbcon_context *ctxt, ++ struct nbcon_state *cur) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct console *con = ctxt->console; ++ struct nbcon_state new; ++ ++ if (!ctxt->allow_unsafe_takeover) ++ return -EPERM; ++ ++ /* Ensure caller is allowed to perform unsafe hostile takeovers. */ ++ if (WARN_ON_ONCE(ctxt->prio != NBCON_PRIO_PANIC)) ++ return -EPERM; ++ ++ /* ++ * Check that try_acquire_direct() and try_acquire_handover() returned ++ * -EBUSY in the right situation. ++ */ ++ WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio); ++ WARN_ON_ONCE(cur->unsafe != true); ++ ++ do { ++ new.atom = cur->atom; ++ new.cpu = cpu; ++ new.prio = ctxt->prio; ++ new.unsafe |= cur->unsafe_takeover; ++ new.unsafe_takeover |= cur->unsafe; ++ ++ } while (!nbcon_state_try_cmpxchg(con, cur, &new)); ++ ++ return 0; ++} ++ ++static struct printk_buffers panic_nbcon_pbufs; ++ ++/** ++ * nbcon_context_try_acquire - Try to acquire nbcon console ++ * @ctxt: The context of the caller ++ * ++ * Context: Any context which could not be migrated to another CPU. ++ * Return: True if the console was acquired. False otherwise. ++ * ++ * If the caller allowed an unsafe hostile takeover, on success the ++ * caller should check the current console state to see if it is ++ * in an unsafe state. Otherwise, on success the caller may assume ++ * the console is not in an unsafe state. ++ */ ++static bool nbcon_context_try_acquire(struct nbcon_context *ctxt) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct console *con = ctxt->console; ++ struct nbcon_state cur; ++ int err; ++ ++ nbcon_state_read(con, &cur); ++try_again: ++ err = nbcon_context_try_acquire_direct(ctxt, &cur); ++ if (err != -EBUSY) ++ goto out; ++ ++ err = nbcon_context_try_acquire_handover(ctxt, &cur); ++ if (err == -EAGAIN) ++ goto try_again; ++ if (err != -EBUSY) ++ goto out; ++ ++ err = nbcon_context_try_acquire_hostile(ctxt, &cur); ++out: ++ if (err) ++ return false; ++ ++ /* Acquire succeeded. */ ++ ++ /* Assign the appropriate buffer for this context. */ ++ if (atomic_read(&panic_cpu) == cpu) ++ ctxt->pbufs = &panic_nbcon_pbufs; ++ else ++ ctxt->pbufs = con->pbufs; ++ ++ /* Set the record sequence for this context to print. */ ++ ctxt->seq = nbcon_seq_read(ctxt->console); ++ ++ return true; ++} ++ ++static bool nbcon_owner_matches(struct nbcon_state *cur, int expected_cpu, ++ int expected_prio) ++{ ++ /* ++ * Since consoles can only be acquired by higher priorities, ++ * owning contexts are uniquely identified by @prio. However, ++ * since contexts can unexpectedly lose ownership, it is ++ * possible that later another owner appears with the same ++ * priority. For this reason @cpu is also needed. ++ */ ++ ++ if (cur->prio != expected_prio) ++ return false; ++ ++ if (cur->cpu != expected_cpu) ++ return false; ++ ++ return true; ++} ++ ++/** ++ * nbcon_context_release - Release the console ++ * @ctxt: The nbcon context from nbcon_context_try_acquire() ++ */ ++static void nbcon_context_release(struct nbcon_context *ctxt) ++{ ++ unsigned int cpu = smp_processor_id(); ++ struct console *con = ctxt->console; ++ struct nbcon_state cur; ++ struct nbcon_state new; ++ ++ nbcon_state_read(con, &cur); ++ ++ do { ++ if (!nbcon_owner_matches(&cur, cpu, ctxt->prio)) ++ break; ++ ++ new.atom = cur.atom; ++ new.prio = NBCON_PRIO_NONE; ++ ++ /* ++ * If @unsafe_takeover is set, it is kept set so that ++ * the state remains permanently unsafe. ++ */ ++ new.unsafe |= cur.unsafe_takeover; ++ ++ } while (!nbcon_state_try_cmpxchg(con, &cur, &new)); ++ ++ ctxt->pbufs = NULL; ++} ++ ++/** ++ * nbcon_context_can_proceed - Check whether ownership can proceed ++ * @ctxt: The nbcon context from nbcon_context_try_acquire() ++ * @cur: The current console state ++ * ++ * Return: True if this context still owns the console. False if ++ * ownership was handed over or taken. ++ * ++ * Must be invoked when entering the unsafe state to make sure that it still ++ * owns the lock. Also must be invoked when exiting the unsafe context ++ * to eventually free the lock for a higher priority context which asked ++ * for the friendly handover. ++ * ++ * It can be called inside an unsafe section when the console is just ++ * temporary in safe state instead of exiting and entering the unsafe ++ * state. ++ * ++ * Also it can be called in the safe context before doing an expensive ++ * safe operation. It does not make sense to do the operation when ++ * a higher priority context took the lock. ++ * ++ * When this function returns false then the calling context no longer owns ++ * the console and is no longer allowed to go forward. In this case it must ++ * back out immediately and carefully. The buffer content is also no longer ++ * trusted since it no longer belongs to the calling context. ++ */ ++static bool nbcon_context_can_proceed(struct nbcon_context *ctxt, struct nbcon_state *cur) ++{ ++ unsigned int cpu = smp_processor_id(); ++ ++ /* Make sure this context still owns the console. */ ++ if (!nbcon_owner_matches(cur, cpu, ctxt->prio)) ++ return false; ++ ++ /* The console owner can proceed if there is no waiter. */ ++ if (cur->req_prio == NBCON_PRIO_NONE) ++ return true; ++ ++ /* ++ * A console owner within an unsafe region is always allowed to ++ * proceed, even if there are waiters. It can perform a handover ++ * when exiting the unsafe region. Otherwise the waiter will ++ * need to perform an unsafe hostile takeover. ++ */ ++ if (cur->unsafe) ++ return true; ++ ++ /* Waiters always have higher priorities than owners. */ ++ WARN_ON_ONCE(cur->req_prio <= cur->prio); ++ ++ /* ++ * Having a safe point for take over and eventually a few ++ * duplicated characters or a full line is way better than a ++ * hostile takeover. Post processing can take care of the garbage. ++ * Release and hand over. ++ */ ++ nbcon_context_release(ctxt); ++ ++ /* ++ * It is not clear whether the waiter really took over ownership. The ++ * outermost callsite must make the final decision whether console ++ * ownership is needed for it to proceed. If yes, it must reacquire ++ * ownership (possibly hostile) before carefully proceeding. ++ * ++ * The calling context no longer owns the console so go back all the ++ * way instead of trying to implement reacquire heuristics in tons of ++ * places. ++ */ ++ return false; ++} ++ ++/** ++ * nbcon_can_proceed - Check whether ownership can proceed ++ * @wctxt: The write context that was handed to the write function ++ * ++ * Return: True if this context still owns the console. False if ++ * ownership was handed over or taken. ++ * ++ * It is used in nbcon_enter_unsafe() to make sure that it still owns the ++ * lock. Also it is used in nbcon_exit_unsafe() to eventually free the lock ++ * for a higher priority context which asked for the friendly handover. ++ * ++ * It can be called inside an unsafe section when the console is just ++ * temporary in safe state instead of exiting and entering the unsafe state. ++ * ++ * Also it can be called in the safe context before doing an expensive safe ++ * operation. It does not make sense to do the operation when a higher ++ * priority context took the lock. ++ * ++ * When this function returns false then the calling context no longer owns ++ * the console and is no longer allowed to go forward. In this case it must ++ * back out immediately and carefully. The buffer content is also no longer ++ * trusted since it no longer belongs to the calling context. ++ */ ++bool nbcon_can_proceed(struct nbcon_write_context *wctxt) ++{ ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); ++ struct console *con = ctxt->console; ++ struct nbcon_state cur; ++ ++ nbcon_state_read(con, &cur); ++ ++ return nbcon_context_can_proceed(ctxt, &cur); ++} ++EXPORT_SYMBOL_GPL(nbcon_can_proceed); ++ ++#define nbcon_context_enter_unsafe(c) __nbcon_context_update_unsafe(c, true) ++#define nbcon_context_exit_unsafe(c) __nbcon_context_update_unsafe(c, false) ++ ++/** ++ * __nbcon_context_update_unsafe - Update the unsafe bit in @con->nbcon_state ++ * @ctxt: The nbcon context from nbcon_context_try_acquire() ++ * @unsafe: The new value for the unsafe bit ++ * ++ * Return: True if the unsafe state was updated and this context still ++ * owns the console. Otherwise false if ownership was handed ++ * over or taken. ++ * ++ * This function allows console owners to modify the unsafe status of the ++ * console. ++ * ++ * When this function returns false then the calling context no longer owns ++ * the console and is no longer allowed to go forward. In this case it must ++ * back out immediately and carefully. The buffer content is also no longer ++ * trusted since it no longer belongs to the calling context. ++ * ++ * Internal helper to avoid duplicated code. ++ */ ++static bool __nbcon_context_update_unsafe(struct nbcon_context *ctxt, bool unsafe) ++{ ++ struct console *con = ctxt->console; ++ struct nbcon_state cur; ++ struct nbcon_state new; ++ ++ nbcon_state_read(con, &cur); ++ ++ do { ++ /* ++ * The unsafe bit must not be cleared if an ++ * unsafe hostile takeover has occurred. ++ */ ++ if (!unsafe && cur.unsafe_takeover) ++ goto out; ++ ++ if (!nbcon_context_can_proceed(ctxt, &cur)) ++ return false; ++ ++ new.atom = cur.atom; ++ new.unsafe = unsafe; ++ } while (!nbcon_state_try_cmpxchg(con, &cur, &new)); ++ ++ cur.atom = new.atom; ++out: ++ return nbcon_context_can_proceed(ctxt, &cur); ++} ++ ++/** ++ * nbcon_enter_unsafe - Enter an unsafe region in the driver ++ * @wctxt: The write context that was handed to the write function ++ * ++ * Return: True if this context still owns the console. False if ++ * ownership was handed over or taken. ++ * ++ * When this function returns false then the calling context no longer owns ++ * the console and is no longer allowed to go forward. In this case it must ++ * back out immediately and carefully. The buffer content is also no longer ++ * trusted since it no longer belongs to the calling context. ++ */ ++bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) ++{ ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); ++ ++ return nbcon_context_enter_unsafe(ctxt); ++} ++EXPORT_SYMBOL_GPL(nbcon_enter_unsafe); ++ ++/** ++ * nbcon_exit_unsafe - Exit an unsafe region in the driver ++ * @wctxt: The write context that was handed to the write function ++ * ++ * Return: True if this context still owns the console. False if ++ * ownership was handed over or taken. ++ * ++ * When this function returns false then the calling context no longer owns ++ * the console and is no longer allowed to go forward. In this case it must ++ * back out immediately and carefully. The buffer content is also no longer ++ * trusted since it no longer belongs to the calling context. ++ */ ++bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) ++{ ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); ++ ++ return nbcon_context_exit_unsafe(ctxt); ++} ++EXPORT_SYMBOL_GPL(nbcon_exit_unsafe); ++ ++/** ++ * nbcon_reacquire - Reacquire a console after losing ownership ++ * @wctxt: The write context that was handed to the write function ++ * ++ * Since ownership can be lost at any time due to handover or takeover, a ++ * printing context _should_ be prepared to back out immediately and ++ * carefully. However, there are many scenarios where the context _must_ ++ * reacquire ownership in order to finalize or revert hardware changes. ++ * ++ * This function allows a context to reacquire ownership using the same ++ * priority as its previous ownership. ++ * ++ * Note that for printing contexts, after a successful reacquire the ++ * context will have no output buffer because that has been lost. This ++ * function cannot be used to resume printing. ++ */ ++void nbcon_reacquire(struct nbcon_write_context *wctxt) ++{ ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); ++ struct console *con = ctxt->console; ++ struct nbcon_state cur; ++ ++ while (!nbcon_context_try_acquire(ctxt)) ++ cpu_relax(); ++ ++ wctxt->outbuf = NULL; ++ wctxt->len = 0; ++ nbcon_state_read(con, &cur); ++ wctxt->unsafe_takeover = cur.unsafe_takeover; ++} ++EXPORT_SYMBOL_GPL(nbcon_reacquire); ++ ++/** ++ * nbcon_emit_next_record - Emit a record in the acquired context ++ * @wctxt: The write context that will be handed to the write function ++ * @use_atomic: True if the write_atomic callback is to be used ++ * ++ * Return: True if this context still owns the console. False if ++ * ownership was handed over or taken. ++ * ++ * When this function returns false then the calling context no longer owns ++ * the console and is no longer allowed to go forward. In this case it must ++ * back out immediately and carefully. The buffer content is also no longer ++ * trusted since it no longer belongs to the calling context. If the caller ++ * wants to do more it must reacquire the console first. ++ * ++ * When true is returned, @wctxt->ctxt.backlog indicates whether there are ++ * still records pending in the ringbuffer, ++ */ ++static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt, bool use_atomic) ++{ ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); ++ struct console *con = ctxt->console; ++ bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; ++ struct printk_message pmsg = { ++ .pbufs = ctxt->pbufs, ++ }; ++ unsigned long con_dropped; ++ struct nbcon_state cur; ++ unsigned long dropped; ++ bool done = false; ++ ++ /* ++ * The printk buffers are filled within an unsafe section. This ++ * prevents NBCON_PRIO_NORMAL and NBCON_PRIO_EMERGENCY from ++ * clobbering each other. ++ */ ++ ++ if (!nbcon_context_enter_unsafe(ctxt)) ++ return false; ++ ++ ctxt->backlog = printk_get_next_message(&pmsg, ctxt->seq, is_extended, true); ++ if (!ctxt->backlog) ++ return nbcon_context_exit_unsafe(ctxt); ++ ++ /* ++ * @con->dropped is not protected in case of an unsafe hostile ++ * takeover. In that situation the update can be racy so ++ * annotate it accordingly. ++ */ ++ con_dropped = data_race(READ_ONCE(con->dropped)); ++ ++ dropped = con_dropped + pmsg.dropped; ++ if (dropped && !is_extended) ++ console_prepend_dropped(&pmsg, dropped); ++ ++ if (!nbcon_context_exit_unsafe(ctxt)) ++ return false; ++ ++ /* For skipped records just update seq/dropped in @con. */ ++ if (pmsg.outbuf_len == 0) ++ goto update_con; ++ ++ /* Initialize the write context for driver callbacks. */ ++ wctxt->outbuf = &pmsg.pbufs->outbuf[0]; ++ wctxt->len = pmsg.outbuf_len; ++ nbcon_state_read(con, &cur); ++ wctxt->unsafe_takeover = cur.unsafe_takeover; ++ ++ if (use_atomic && ++ con->write_atomic) { ++ done = con->write_atomic(con, wctxt); ++ ++ } else if (!use_atomic && ++ con->write_thread && ++ con->kthread) { ++ WARN_ON_ONCE(con->kthread != current); ++ done = con->write_thread(con, wctxt); ++ } ++ ++ if (!done) { ++ /* ++ * The emit was aborted, probably due to a loss of ownership. ++ * Ensure ownership was lost or released before reporting the ++ * loss. ++ */ ++ nbcon_context_release(ctxt); ++ return false; ++ } ++ ++ /* ++ * Since any dropped message was successfully output, reset the ++ * dropped count for the console. ++ */ ++ dropped = 0; ++update_con: ++ /* ++ * The dropped count and the sequence number are updated within an ++ * unsafe section. This limits update races to the panic context and ++ * allows the panic context to win. ++ */ ++ ++ if (!nbcon_context_enter_unsafe(ctxt)) ++ return false; ++ ++ if (dropped != con_dropped) { ++ /* Counterpart to the READ_ONCE() above. */ ++ WRITE_ONCE(con->dropped, dropped); ++ } ++ ++ nbcon_seq_try_update(ctxt, pmsg.seq + 1); ++ ++ return nbcon_context_exit_unsafe(ctxt); ++} ++ ++/** ++ * nbcon_kthread_should_wakeup - Check whether a printer thread should wakeup ++ * @con: Console to operate on ++ * @ctxt: The acquire context that contains the state ++ * at console_acquire() ++ * ++ * Return: True if the thread should shutdown or if the console is ++ * allowed to print and a record is available. False otherwise. ++ * ++ * After the thread wakes up, it must first check if it should shutdown before ++ * attempting any printing. ++ */ ++static bool nbcon_kthread_should_wakeup(struct console *con, struct nbcon_context *ctxt) ++{ ++ bool is_usable; ++ short flags; ++ int cookie; ++ ++ if (kthread_should_stop()) ++ return true; ++ ++ cookie = console_srcu_read_lock(); ++ flags = console_srcu_read_flags(con); ++ is_usable = console_is_usable(con, flags, false); ++ console_srcu_read_unlock(cookie); ++ ++ if (!is_usable) ++ return false; ++ ++ /* Bring the sequence in @ctxt up to date */ ++ ctxt->seq = nbcon_seq_read(con); ++ ++ return prb_read_valid(prb, ctxt->seq, NULL); ++} ++ ++/** ++ * nbcon_kthread_func - The printer thread function ++ * @__console: Console to operate on ++ */ ++static int nbcon_kthread_func(void *__console) ++{ ++ struct console *con = __console; ++ struct nbcon_write_context wctxt = { ++ .ctxt.console = con, ++ .ctxt.prio = NBCON_PRIO_NORMAL, ++ }; ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); ++ unsigned long flags; ++ short con_flags; ++ bool backlog; ++ int cookie; ++ int ret; ++ ++wait_for_event: ++ /* ++ * Guarantee this task is visible on the rcuwait before ++ * checking the wake condition. ++ * ++ * The full memory barrier within set_current_state() of ++ * ___rcuwait_wait_event() pairs with the full memory ++ * barrier within rcuwait_has_sleeper(). ++ * ++ * This pairs with rcuwait_has_sleeper:A and nbcon_kthread_wake:A. ++ */ ++ ret = rcuwait_wait_event(&con->rcuwait, ++ nbcon_kthread_should_wakeup(con, ctxt), ++ TASK_INTERRUPTIBLE); /* LMM(nbcon_kthread_func:A) */ ++ ++ if (kthread_should_stop()) ++ return 0; ++ ++ /* Wait was interrupted by a spurious signal, go back to sleep. */ ++ if (ret) ++ goto wait_for_event; ++ ++ do { ++ backlog = false; ++ ++ cookie = console_srcu_read_lock(); ++ ++ con_flags = console_srcu_read_flags(con); ++ ++ if (console_is_usable(con, con_flags, false)) { ++ con->driver_enter(con, &flags); ++ ++ /* ++ * Ensure this stays on the CPU to make handover and ++ * takeover possible. ++ */ ++ cant_migrate(); ++ ++ if (nbcon_context_try_acquire(ctxt)) { ++ /* ++ * If the emit fails, this context is no ++ * longer the owner. ++ */ ++ if (nbcon_emit_next_record(&wctxt, false)) { ++ nbcon_context_release(ctxt); ++ backlog = ctxt->backlog; ++ } ++ } ++ ++ con->driver_exit(con, flags); ++ } ++ ++ console_srcu_read_unlock(cookie); ++ cond_resched(); ++ ++ } while (backlog); ++ ++ goto wait_for_event; ++} ++ ++/** ++ * nbcon_irq_work - irq work to wake printk thread ++ * @irq_work: The irq work to operate on ++ */ ++static void nbcon_irq_work(struct irq_work *irq_work) ++{ ++ struct console *con = container_of(irq_work, struct console, irq_work); ++ ++ nbcon_kthread_wake(con); ++} ++ ++static inline bool rcuwait_has_sleeper(struct rcuwait *w) ++{ ++ bool has_sleeper; ++ ++ rcu_read_lock(); ++ /* ++ * Guarantee any new records can be seen by tasks preparing to wait ++ * before this context checks if the rcuwait is empty. ++ * ++ * This full memory barrier pairs with the full memory barrier within ++ * set_current_state() of ___rcuwait_wait_event(), which is called ++ * after prepare_to_rcuwait() adds the waiter but before it has ++ * checked the wait condition. ++ * ++ * This pairs with nbcon_kthread_func:A. ++ */ ++ smp_mb(); /* LMM(rcuwait_has_sleeper:A) */ ++ has_sleeper = !!rcu_dereference(w->task); ++ rcu_read_unlock(); ++ ++ return has_sleeper; ++} ++ ++/** ++ * nbcon_wake_threads - Wake up printing threads using irq_work ++ */ ++void nbcon_wake_threads(void) ++{ ++ struct console *con; ++ int cookie; ++ ++ cookie = console_srcu_read_lock(); ++ for_each_console_srcu(con) { ++ /* ++ * Only schedule irq_work if the printing thread is ++ * actively waiting. If not waiting, the thread will ++ * notice by itself that it has work to do. ++ */ ++ if (con->kthread && rcuwait_has_sleeper(&con->rcuwait)) ++ irq_work_queue(&con->irq_work); ++ } ++ console_srcu_read_unlock(cookie); ++} ++ ++/* Track the nbcon emergency nesting per CPU. */ ++static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting); ++static unsigned int early_nbcon_pcpu_emergency_nesting __initdata; ++ ++/** ++ * nbcon_get_cpu_emergency_nesting - Get the per CPU emergency nesting pointer ++ * ++ * Return: Either a pointer to the per CPU emergency nesting counter of ++ * the current CPU or to the init data during early boot. ++ */ ++static __ref unsigned int *nbcon_get_cpu_emergency_nesting(void) ++{ ++ /* ++ * The value of __printk_percpu_data_ready gets set in normal ++ * context and before SMP initialization. As a result it could ++ * never change while inside an nbcon emergency section. ++ */ ++ if (!printk_percpu_data_ready()) ++ return &early_nbcon_pcpu_emergency_nesting; ++ ++ return this_cpu_ptr(&nbcon_pcpu_emergency_nesting); ++} ++ ++/** ++ * nbcon_atomic_emit_one - Print one record for an nbcon console using the ++ * write_atomic() callback ++ * @wctxt: An initialized write context struct to use ++ * for this context ++ * ++ * Return: False if the given console could not print a record or there ++ * are no more records to print, otherwise true. ++ * ++ * This is an internal helper to handle the locking of the console before ++ * calling nbcon_emit_next_record(). ++ */ ++static bool nbcon_atomic_emit_one(struct nbcon_write_context *wctxt) ++{ ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); ++ ++ if (!nbcon_context_try_acquire(ctxt)) ++ return false; ++ ++ /* ++ * nbcon_emit_next_record() returns false when the console was ++ * handed over or taken over. In both cases the context is no ++ * longer valid. ++ */ ++ if (!nbcon_emit_next_record(wctxt, true)) ++ return false; ++ ++ nbcon_context_release(ctxt); ++ ++ return ctxt->backlog; ++} ++ ++/** ++ * nbcon_get_default_prio - The appropriate nbcon priority to use for nbcon ++ * printing on the current CPU ++ * ++ * Context: Any context which could not be migrated to another CPU. ++ * Return: The nbcon_prio to use for acquiring an nbcon console in this ++ * context for printing. ++ */ ++enum nbcon_prio nbcon_get_default_prio(void) ++{ ++ unsigned int *cpu_emergency_nesting; ++ ++ if (this_cpu_in_panic()) ++ return NBCON_PRIO_PANIC; ++ ++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting(); ++ if (*cpu_emergency_nesting) ++ return NBCON_PRIO_EMERGENCY; ++ ++ return NBCON_PRIO_NORMAL; ++} ++ ++/** ++ * nbcon_atomic_emit_next_record - Print one record for an nbcon console ++ * using the write_atomic() callback ++ * @con: The console to print on ++ * @handover: Will be set to true if a printk waiter has taken over the ++ * console_lock, in which case the caller is no longer holding ++ * both the console_lock and the SRCU read lock. Otherwise it ++ * is set to false. ++ * @cookie: The cookie from the SRCU read lock. ++ * ++ * Context: Any context which could not be migrated to another CPU. ++ * Return: True if a record could be printed, otherwise false. ++ * ++ * This function is meant to be called by console_flush_all() to print records ++ * on nbcon consoles using the write_atomic() callback. Essentially it is the ++ * nbcon version of console_emit_next_record(). ++ */ ++bool nbcon_atomic_emit_next_record(struct console *con, bool *handover, int cookie) ++{ ++ struct nbcon_write_context wctxt = { }; ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); ++ unsigned long driver_flags; ++ bool progress = false; ++ unsigned long flags; ++ ++ *handover = false; ++ ++ /* Use the same locking order as console_emit_next_record(). */ ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ printk_safe_enter_irqsave(flags); ++ console_lock_spinning_enable(); ++ stop_critical_timings(); ++ } ++ ++ con->driver_enter(con, &driver_flags); ++ cant_migrate(); ++ ++ ctxt->console = con; ++ ctxt->prio = nbcon_get_default_prio(); ++ ++ progress = nbcon_atomic_emit_one(&wctxt); ++ ++ con->driver_exit(con, driver_flags); ++ ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ start_critical_timings(); ++ *handover = console_lock_spinning_disable_and_check(cookie); ++ printk_safe_exit_irqrestore(flags); ++ } ++ ++ return progress; ++} ++ ++/** ++ * __nbcon_atomic_flush_all - Flush all nbcon consoles using their ++ * write_atomic() callback ++ * @stop_seq: Flush up until this record ++ * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers ++ */ ++static void __nbcon_atomic_flush_all(u64 stop_seq, bool allow_unsafe_takeover) ++{ ++ struct nbcon_write_context wctxt = { }; ++ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); ++ struct console *con; ++ bool any_progress; ++ int cookie; ++ ++ do { ++ any_progress = false; ++ ++ cookie = console_srcu_read_lock(); ++ for_each_console_srcu(con) { ++ short flags = console_srcu_read_flags(con); ++ unsigned long irq_flags; ++ ++ if (!(flags & CON_NBCON)) ++ continue; ++ ++ if (!console_is_usable(con, flags, true)) ++ continue; ++ ++ if (nbcon_seq_read(con) >= stop_seq) ++ continue; ++ ++ memset(ctxt, 0, sizeof(*ctxt)); ++ ctxt->console = con; ++ ctxt->spinwait_max_us = 2000; ++ ctxt->allow_unsafe_takeover = allow_unsafe_takeover; ++ ++ /* ++ * Atomic flushing does not use console driver ++ * synchronization (i.e. it does not hold the port ++ * lock for uart consoles). Therefore IRQs must be ++ * disabled to avoid being interrupted and then ++ * calling into a driver that will deadlock trying ++ * acquire console ownership. ++ * ++ * This also disables migration in order to get the ++ * current CPU priority. ++ */ ++ local_irq_save(irq_flags); ++ ++ ctxt->prio = nbcon_get_default_prio(); ++ ++ any_progress |= nbcon_atomic_emit_one(&wctxt); ++ ++ local_irq_restore(irq_flags); ++ } ++ console_srcu_read_unlock(cookie); ++ } while (any_progress); ++} ++ ++/** ++ * nbcon_atomic_flush_all - Flush all nbcon consoles using their ++ * write_atomic() callback ++ * ++ * Flush the backlog up through the currently newest record. Any new ++ * records added while flushing will not be flushed. This is to avoid ++ * one CPU printing unbounded because other CPUs continue to add records. ++ */ ++void nbcon_atomic_flush_all(void) ++{ ++ __nbcon_atomic_flush_all(prb_next_reserve_seq(prb), false); ++} ++ ++/** ++ * nbcon_atomic_flush_unsafe - Flush all nbcon consoles using their ++ * write_atomic() callback and allowing unsafe hostile takeovers ++ * ++ * Flush the backlog up through the currently newest record. Unsafe hostile ++ * takeovers will be performed, if necessary. ++ */ ++void nbcon_atomic_flush_unsafe(void) ++{ ++ __nbcon_atomic_flush_all(prb_next_reserve_seq(prb), true); ++} ++ ++/** ++ * nbcon_cpu_emergency_enter - Enter an emergency section where printk() ++ * messages for that CPU are only stored ++ * ++ * Upon exiting the emergency section, all stored messages are flushed. ++ * ++ * Context: Any context. Disables preemption. ++ * ++ * When within an emergency section, no printing occurs on that CPU. This ++ * is to allow all emergency messages to be dumped into the ringbuffer before ++ * flushing the ringbuffer. The actual printing occurs when exiting the ++ * outermost emergency section. ++ */ ++void nbcon_cpu_emergency_enter(void) ++{ ++ unsigned int *cpu_emergency_nesting; ++ ++ preempt_disable(); ++ ++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting(); ++ (*cpu_emergency_nesting)++; ++} ++ ++/** ++ * nbcon_cpu_emergency_exit - Exit an emergency section and flush the ++ * stored messages ++ * ++ * Flushing only occurs when exiting all nesting for the CPU. ++ * ++ * Context: Any context. Enables preemption. ++ */ ++void nbcon_cpu_emergency_exit(void) ++{ ++ unsigned int *cpu_emergency_nesting; ++ bool do_trigger_flush = false; ++ ++ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting(); ++ ++ WARN_ON_ONCE(*cpu_emergency_nesting == 0); ++ ++ if (*cpu_emergency_nesting == 1) ++ do_trigger_flush = true; ++ ++ /* Undo the nesting count of nbcon_cpu_emergency_enter(). */ ++ (*cpu_emergency_nesting)--; ++ ++ preempt_enable(); ++ ++ if (do_trigger_flush) ++ printk_trigger_flush(); ++} ++ ++/** ++ * nbcon_kthread_stop - Stop a printer thread ++ * @con: Console to operate on ++ */ ++static void nbcon_kthread_stop(struct console *con) ++{ ++ lockdep_assert_console_list_lock_held(); ++ ++ if (!con->kthread) ++ return; ++ ++ kthread_stop(con->kthread); ++ con->kthread = NULL; ++} ++ ++/** ++ * nbcon_kthread_create - Create a printer thread ++ * @con: Console to operate on ++ * ++ * If it fails, let the console proceed. The atomic part might ++ * be usable and useful. ++ */ ++void nbcon_kthread_create(struct console *con) ++{ ++ struct task_struct *kt; ++ ++ lockdep_assert_console_list_lock_held(); ++ ++ if (!(con->flags & CON_NBCON) || !con->write_thread) ++ return; ++ ++ if (!printk_threads_enabled || con->kthread) ++ return; ++ ++ /* ++ * Printer threads cannot be started as long as any boot console is ++ * registered because there is no way to synchronize the hardware ++ * registers between boot console code and regular console code. ++ */ ++ if (have_boot_console) ++ return; ++ ++ kt = kthread_run(nbcon_kthread_func, con, "pr/%s%d", con->name, con->index); ++ if (IS_ERR(kt)) { ++ con_printk(KERN_ERR, con, "failed to start printing thread\n"); ++ return; ++ } ++ ++ con->kthread = kt; ++ ++ /* ++ * It is important that console printing threads are scheduled ++ * shortly after a printk call and with generous runtime budgets. ++ */ ++ sched_set_normal(con->kthread, -20); ++} ++ ++static int __init printk_setup_threads(void) ++{ ++ struct console *con; ++ ++ console_list_lock(); ++ printk_threads_enabled = true; ++ for_each_console(con) ++ nbcon_kthread_create(con); ++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && printing_via_unlock) ++ nbcon_legacy_kthread_create(); ++ console_list_unlock(); ++ return 0; ++} ++early_initcall(printk_setup_threads); ++ ++/** ++ * nbcon_alloc - Allocate buffers needed by the nbcon console ++ * @con: Console to allocate buffers for ++ * ++ * Return: True on success. False otherwise and the console cannot ++ * be used. ++ * ++ * This is not part of nbcon_init() because buffer allocation must ++ * be performed earlier in the console registration process. ++ */ ++bool nbcon_alloc(struct console *con) ++{ ++ if (con->flags & CON_BOOT) { ++ /* ++ * Boot console printing is synchronized with legacy console ++ * printing, so boot consoles can share the same global printk ++ * buffers. ++ */ ++ con->pbufs = &printk_shared_pbufs; ++ } else { ++ con->pbufs = kmalloc(sizeof(*con->pbufs), GFP_KERNEL); ++ if (!con->pbufs) { ++ con_printk(KERN_ERR, con, "failed to allocate printing buffer\n"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++/** ++ * nbcon_init - Initialize the nbcon console specific data ++ * @con: Console to initialize ++ * ++ * nbcon_alloc() *must* be called and succeed before this function ++ * is called. ++ * ++ * This function expects that the legacy @con->seq has been set. ++ */ ++void nbcon_init(struct console *con) ++{ ++ struct nbcon_state state = { }; ++ ++ /* nbcon_alloc() must have been called and successful! */ ++ BUG_ON(!con->pbufs); ++ ++ rcuwait_init(&con->rcuwait); ++ init_irq_work(&con->irq_work, nbcon_irq_work); ++ nbcon_seq_force(con, con->seq); ++ nbcon_state_set(con, &state); ++ nbcon_kthread_create(con); ++} ++ ++/** ++ * nbcon_free - Free and cleanup the nbcon console specific data ++ * @con: Console to free/cleanup nbcon data ++ */ ++void nbcon_free(struct console *con) ++{ ++ struct nbcon_state state = { }; ++ ++ nbcon_kthread_stop(con); ++ nbcon_state_set(con, &state); ++ ++ /* Boot consoles share global printk buffers. */ ++ if (!(con->flags & CON_BOOT)) ++ kfree(con->pbufs); ++ ++ con->pbufs = NULL; ++} ++ ++static inline bool uart_is_nbcon(struct uart_port *up) ++{ ++ int cookie; ++ bool ret; ++ ++ if (!uart_console(up)) ++ return false; ++ ++ cookie = console_srcu_read_lock(); ++ ret = (console_srcu_read_flags(up->cons) & CON_NBCON); ++ console_srcu_read_unlock(cookie); ++ return ret; ++} ++ ++/** ++ * nbcon_acquire - The second half of the port locking wrapper ++ * @up: The uart port whose @lock was locked ++ * ++ * The uart_port_lock() wrappers will first lock the spin_lock @up->lock. ++ * Then this function is called to implement nbcon-specific processing. ++ * ++ * If @up is an nbcon console, this console will be acquired and marked as ++ * unsafe. Otherwise this function does nothing. ++ * ++ * nbcon consoles acquired via the port lock wrapper always use priority ++ * NBCON_PRIO_NORMAL. ++ */ ++void nbcon_acquire(struct uart_port *up) ++{ ++ struct console *con = up->cons; ++ struct nbcon_context ctxt; ++ ++ if (!uart_is_nbcon(up)) ++ return; ++ ++ WARN_ON_ONCE(up->nbcon_locked_port); ++ ++ do { ++ do { ++ memset(&ctxt, 0, sizeof(ctxt)); ++ ctxt.console = con; ++ ctxt.prio = NBCON_PRIO_NORMAL; ++ } while (!nbcon_context_try_acquire(&ctxt)); ++ ++ } while (!nbcon_context_enter_unsafe(&ctxt)); ++ ++ up->nbcon_locked_port = true; ++} ++EXPORT_SYMBOL_GPL(nbcon_acquire); ++ ++/** ++ * nbcon_release - The first half of the port unlocking wrapper ++ * @up: The uart port whose @lock is about to be unlocked ++ * ++ * The uart_port_unlock() wrappers will first call this function to implement ++ * nbcon-specific processing. Then afterwards the uart_port_unlock() wrappers ++ * will unlock the spin_lock @up->lock. ++ * ++ * If @up is an nbcon console, the console will be marked as safe and ++ * released. Otherwise this function does nothing. ++ * ++ * nbcon consoles acquired via the port lock wrapper always use priority ++ * NBCON_PRIO_NORMAL. ++ */ ++void nbcon_release(struct uart_port *up) ++{ ++ struct console *con = up->cons; ++ struct nbcon_context ctxt = { ++ .console = con, ++ .prio = NBCON_PRIO_NORMAL, ++ }; ++ ++ if (!up->nbcon_locked_port) ++ return; ++ ++ if (nbcon_context_exit_unsafe(&ctxt)) ++ nbcon_context_release(&ctxt); ++ ++ up->nbcon_locked_port = false; ++} ++EXPORT_SYMBOL_GPL(nbcon_release); ++ ++/** ++ * printk_kthread_shutdown - shutdown all threaded printers ++ * ++ * On system shutdown all threaded printers are stopped. This allows printk ++ * to transition back to atomic printing, thus providing a robust mechanism ++ * for the final shutdown/reboot messages to be output. ++ */ ++static void printk_kthread_shutdown(void) ++{ ++ struct console *con; ++ ++ console_list_lock(); ++ for_each_console(con) { ++ if (con->flags & CON_NBCON) ++ nbcon_kthread_stop(con); ++ } ++ console_list_unlock(); ++} ++ ++static struct syscore_ops printk_syscore_ops = { ++ .shutdown = printk_kthread_shutdown, ++}; ++ ++static int __init printk_init_ops(void) ++{ ++ register_syscore_ops(&printk_syscore_ops); ++ return 0; ++} ++device_initcall(printk_init_ops); +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 0fca282c0..249576a8c 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -102,12 +102,6 @@ DEFINE_STATIC_SRCU(console_srcu); + */ + int __read_mostly suppress_printk; + +-/* +- * During panic, heavy printk by other CPUs can delay the +- * panic and risk deadlock on console resources. +- */ +-static int __read_mostly suppress_panic_printk; +- + #ifdef CONFIG_LOCKDEP + static struct lockdep_map console_lock_dep_map = { + .name = "console_lock" +@@ -288,6 +282,7 @@ EXPORT_SYMBOL(console_list_unlock); + * Return: A cookie to pass to console_srcu_read_unlock(). + */ + int console_srcu_read_lock(void) ++ __acquires(&console_srcu) + { + return srcu_read_lock_nmisafe(&console_srcu); + } +@@ -301,6 +296,7 @@ EXPORT_SYMBOL(console_srcu_read_lock); + * Counterpart to console_srcu_read_lock() + */ + void console_srcu_read_unlock(int cookie) ++ __releases(&console_srcu) + { + srcu_read_unlock_nmisafe(&console_srcu, cookie); + } +@@ -353,6 +349,29 @@ static bool panic_in_progress(void) + return unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID); + } + ++/* Return true if a panic is in progress on the current CPU. */ ++bool this_cpu_in_panic(void) ++{ ++ /* ++ * We can use raw_smp_processor_id() here because it is impossible for ++ * the task to be migrated to the panic_cpu, or away from it. If ++ * panic_cpu has already been set, and we're not currently executing on ++ * that CPU, then we never will be. ++ */ ++ return unlikely(atomic_read(&panic_cpu) == raw_smp_processor_id()); ++} ++ ++/* ++ * Return true if a panic is in progress on a remote CPU. ++ * ++ * On true, the local CPU should immediately release any printing resources ++ * that may be needed by the panic CPU. ++ */ ++bool other_cpu_in_panic(void) ++{ ++ return (panic_in_progress() && !this_cpu_in_panic()); ++} ++ + /* + * This is used for debugging the mess that is the VT code by + * keeping track if we have the console semaphore held. It's +@@ -444,8 +463,33 @@ static int console_msg_format = MSG_FORMAT_DEFAULT; + /* syslog_lock protects syslog_* variables and write access to clear_seq. */ + static DEFINE_MUTEX(syslog_lock); + ++/* ++ * Specifies if a legacy console is registered. If legacy consoles are ++ * present, it is necessary to perform the console_lock/console_unlock dance ++ * whenever console flushing should occur. ++ */ ++bool have_legacy_console; ++ ++/* ++ * Specifies if an nbcon console is registered. If nbcon consoles are present, ++ * synchronous printing of legacy consoles will not occur during panic until ++ * the backtrace has been stored to the ringbuffer. ++ */ ++bool have_nbcon_console; ++ ++/* ++ * Specifies if a boot console is registered. If boot consoles are present, ++ * nbcon consoles cannot print simultaneously and must be synchronized by ++ * the console lock. This is because boot consoles and nbcon consoles may ++ * have mapped the same hardware. ++ */ ++bool have_boot_console; ++ + #ifdef CONFIG_PRINTK + DECLARE_WAIT_QUEUE_HEAD(log_wait); ++ ++static DECLARE_WAIT_QUEUE_HEAD(legacy_wait); ++ + /* All 3 protected by @syslog_lock. */ + /* the next printk record to read by syslog(READ) or /proc/kmsg */ + static u64 syslog_seq; +@@ -494,7 +538,7 @@ _DEFINE_PRINTKRB(printk_rb_static, CONFIG_LOG_BUF_SHIFT - PRB_AVGBITS, + + static struct printk_ringbuffer printk_rb_dynamic; + +-static struct printk_ringbuffer *prb = &printk_rb_static; ++struct printk_ringbuffer *prb = &printk_rb_static; + + /* + * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before +@@ -698,9 +742,6 @@ static ssize_t msg_print_ext_body(char *buf, size_t size, + return len; + } + +-static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, +- bool is_extended, bool may_supress); +- + /* /dev/kmsg - userspace message inject/listen interface */ + struct devkmsg_user { + atomic64_t seq; +@@ -1848,7 +1889,7 @@ static bool console_waiter; + * there may be a waiter spinning (like a spinlock). Also it must be + * ready to hand over the lock at the end of the section. + */ +-static void console_lock_spinning_enable(void) ++void console_lock_spinning_enable(void) + { + /* + * Do not use spinning in panic(). The panic CPU wants to keep the lock. +@@ -1887,7 +1928,7 @@ static void console_lock_spinning_enable(void) + * + * Return: 1 if the lock rights were passed, 0 otherwise. + */ +-static int console_lock_spinning_disable_and_check(int cookie) ++int console_lock_spinning_disable_and_check(int cookie) + { + int waiter; + +@@ -2298,54 +2339,123 @@ int vprintk_store(int facility, int level, + return ret; + } + ++static bool legacy_allow_panic_sync; ++ ++/* ++ * This acts as a one-way switch to allow legacy consoles to print from ++ * the printk() caller context on a panic CPU. ++ */ ++void printk_legacy_allow_panic_sync(void) ++{ ++ legacy_allow_panic_sync = true; ++} ++ + asmlinkage int vprintk_emit(int facility, int level, + const struct dev_printk_info *dev_info, + const char *fmt, va_list args) + { ++ bool do_trylock_unlock = printing_via_unlock && ++ !IS_ENABLED(CONFIG_PREEMPT_RT); + int printed_len; +- bool in_sched = false; + + /* Suppress unimportant messages after panic happens */ + if (unlikely(suppress_printk)) + return 0; + +- if (unlikely(suppress_panic_printk) && other_cpu_in_panic()) ++ /* ++ * The messages on the panic CPU are the most important. If ++ * non-panic CPUs are generating any messages, they will be ++ * silently dropped. ++ */ ++ if (other_cpu_in_panic()) + return 0; + + if (level == LOGLEVEL_SCHED) { + level = LOGLEVEL_DEFAULT; +- in_sched = true; ++ /* If called from the scheduler, we can not call up(). */ ++ do_trylock_unlock = false; + } + + printk_delay(level); + + printed_len = vprintk_store(facility, level, dev_info, fmt, args); + +- /* If called from the scheduler, we can not call up(). */ +- if (!in_sched) { ++ if (!have_boot_console && have_nbcon_console) { ++ bool is_panic_context = this_cpu_in_panic(); ++ ++ /* ++ * In panic, the legacy consoles are not allowed to print from ++ * the printk calling context unless explicitly allowed. This ++ * gives the safe nbcon consoles a chance to print out all the ++ * panic messages first. This restriction only applies if ++ * there are nbcon consoles registered. ++ */ ++ if (is_panic_context) ++ do_trylock_unlock &= legacy_allow_panic_sync; ++ ++ /* ++ * There are situations where nbcon atomic printing should ++ * happen in the printk() caller context: ++ * ++ * - When this CPU is in panic. ++ * ++ * - When booting, before the printing threads have been ++ * started. ++ * ++ * - During shutdown, since the printing threads may not get ++ * a chance to print the final messages. ++ * ++ * Note that if boot consoles are registered, the ++ * console_lock/console_unlock dance must be relied upon ++ * instead because nbcon consoles cannot print simultaneously ++ * with boot consoles. ++ */ ++ if (is_panic_context || ++ !printk_threads_enabled || ++ (system_state > SYSTEM_RUNNING)) { ++ nbcon_atomic_flush_all(); ++ } ++ } ++ ++ nbcon_wake_threads(); ++ ++ if (do_trylock_unlock) { + /* + * The caller may be holding system-critical or + * timing-sensitive locks. Disable preemption during + * printing of all remaining records to all consoles so that + * this context can return as soon as possible. Hopefully + * another printk() caller will take over the printing. ++ * ++ * Also, nbcon_get_default_prio() requires migration disabled. + */ + preempt_disable(); ++ + /* +- * Try to acquire and then immediately release the console +- * semaphore. The release will print out buffers. With the +- * spinning variant, this context tries to take over the +- * printing from another printing context. ++ * Do not emit for EMERGENCY priority. The console will be ++ * explicitly flushed when exiting the emergency section. + */ +- if (console_trylock_spinning()) +- console_unlock(); ++ if (nbcon_get_default_prio() == NBCON_PRIO_EMERGENCY) { ++ do_trylock_unlock = false; ++ } else { ++ /* ++ * Try to acquire and then immediately release the ++ * console semaphore. The release will print out ++ * buffers. With the spinning variant, this context ++ * tries to take over the printing from another ++ * printing context. ++ */ ++ if (console_trylock_spinning()) ++ console_unlock(); ++ } ++ + preempt_enable(); + } + +- if (in_sched) +- defer_console_output(); +- else ++ if (do_trylock_unlock) + wake_up_klogd(); ++ else ++ defer_console_output(); + + return printed_len; + } +@@ -2373,6 +2483,14 @@ EXPORT_SYMBOL(_printk); + static bool pr_flush(int timeout_ms, bool reset_on_progress); + static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress); + ++static struct task_struct *nbcon_legacy_kthread; ++ ++static inline void wake_up_legacy_kthread(void) ++{ ++ if (nbcon_legacy_kthread) ++ wake_up_interruptible(&legacy_wait); ++} ++ + #else /* CONFIG_PRINTK */ + + #define printk_time false +@@ -2383,25 +2501,11 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre + + static u64 syslog_seq; + +-static size_t record_print_text(const struct printk_record *r, +- bool syslog, bool time) +-{ +- return 0; +-} +-static ssize_t info_print_ext_header(char *buf, size_t size, +- struct printk_info *info) +-{ +- return 0; +-} +-static ssize_t msg_print_ext_body(char *buf, size_t size, +- char *text, size_t text_len, +- struct dev_printk_info *dev_info) { return 0; } +-static void console_lock_spinning_enable(void) { } +-static int console_lock_spinning_disable_and_check(int cookie) { return 0; } +-static bool suppress_message_printing(int level) { return false; } + static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; } + static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; } + ++static inline void nbcon_legacy_kthread_create(void) { } ++static inline void wake_up_legacy_kthread(void) { } + #endif /* CONFIG_PRINTK */ + + #ifdef CONFIG_EARLY_PRINTK +@@ -2609,6 +2713,8 @@ void suspend_console(void) + void resume_console(void) + { + struct console *con; ++ short flags; ++ int cookie; + + if (!console_suspend_enabled) + return; +@@ -2625,6 +2731,20 @@ void resume_console(void) + */ + synchronize_srcu(&console_srcu); + ++ /* ++ * Since this runs in task context, wake the threaded printers ++ * directly rather than scheduling irq_work to do it. ++ */ ++ cookie = console_srcu_read_lock(); ++ for_each_console_srcu(con) { ++ flags = console_srcu_read_flags(con); ++ if (flags & CON_NBCON) ++ nbcon_kthread_wake(con); ++ } ++ console_srcu_read_unlock(cookie); ++ ++ wake_up_legacy_kthread(); ++ + pr_flush(1000, true); + } + +@@ -2639,7 +2759,8 @@ void resume_console(void) + */ + static int console_cpu_notify(unsigned int cpu) + { +- if (!cpuhp_tasks_frozen) { ++ if (!cpuhp_tasks_frozen && printing_via_unlock && ++ !IS_ENABLED(CONFIG_PREEMPT_RT)) { + /* If trylock fails, someone else is doing the printing */ + if (console_trylock()) + console_unlock(); +@@ -2647,26 +2768,6 @@ static int console_cpu_notify(unsigned int cpu) + return 0; + } + +-/* +- * Return true if a panic is in progress on a remote CPU. +- * +- * On true, the local CPU should immediately release any printing resources +- * that may be needed by the panic CPU. +- */ +-bool other_cpu_in_panic(void) +-{ +- if (!panic_in_progress()) +- return false; +- +- /* +- * We can use raw_smp_processor_id() here because it is impossible for +- * the task to be migrated to the panic_cpu, or away from it. If +- * panic_cpu has already been set, and we're not currently executing on +- * that CPU, then we never will be. +- */ +- return atomic_read(&panic_cpu) != raw_smp_processor_id(); +-} +- + /** + * console_lock - block the console subsystem from printing + * +@@ -2716,42 +2817,16 @@ int is_console_locked(void) + } + EXPORT_SYMBOL(is_console_locked); + +-/* +- * Check if the given console is currently capable and allowed to print +- * records. +- * +- * Requires the console_srcu_read_lock. +- */ +-static inline bool console_is_usable(struct console *con) +-{ +- short flags = console_srcu_read_flags(con); +- +- if (!(flags & CON_ENABLED)) +- return false; +- +- if ((flags & CON_SUSPENDED)) +- return false; +- +- if (!con->write) +- return false; +- +- /* +- * Console drivers may assume that per-cpu resources have been +- * allocated. So unless they're explicitly marked as being able to +- * cope (CON_ANYTIME) don't call them until this CPU is officially up. +- */ +- if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) +- return false; +- +- return true; +-} +- + static void __console_unlock(void) + { + console_locked = 0; + up_console_sem(); + } + ++static DEFINE_WAIT_OVERRIDE_MAP(printk_legacy_map, LD_WAIT_SLEEP); ++ ++#ifdef CONFIG_PRINTK ++ + /* + * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". This + * is achieved by shifting the existing message over and inserting the dropped +@@ -2766,8 +2841,7 @@ static void __console_unlock(void) + * + * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated. + */ +-#ifdef CONFIG_PRINTK +-static void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) ++void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) + { + struct printk_buffers *pbufs = pmsg->pbufs; + const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf); +@@ -2798,9 +2872,6 @@ static void console_prepend_dropped(struct printk_message *pmsg, unsigned long d + memcpy(outbuf, scratchbuf, len); + pmsg->outbuf_len += len; + } +-#else +-#define console_prepend_dropped(pmsg, dropped) +-#endif /* CONFIG_PRINTK */ + + /* + * Read and format the specified record (or a later record if the specified +@@ -2821,11 +2892,9 @@ static void console_prepend_dropped(struct printk_message *pmsg, unsigned long d + * of @pmsg are valid. (See the documentation of struct printk_message + * for information about the @pmsg fields.) + */ +-static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, +- bool is_extended, bool may_suppress) ++bool printk_get_next_message(struct printk_message *pmsg, u64 seq, ++ bool is_extended, bool may_suppress) + { +- static int panic_console_dropped; +- + struct printk_buffers *pbufs = pmsg->pbufs; + const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf); + const size_t outbuf_sz = sizeof(pbufs->outbuf); +@@ -2853,17 +2922,6 @@ static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, + pmsg->seq = r.info->seq; + pmsg->dropped = r.info->seq - seq; + +- /* +- * Check for dropped messages in panic here so that printk +- * suppression can occur as early as possible if necessary. +- */ +- if (pmsg->dropped && +- panic_in_progress() && +- panic_console_dropped++ > 10) { +- suppress_panic_printk = 1; +- pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n"); +- } +- + /* Skip record that has level above the console loglevel. */ + if (may_suppress && suppress_message_printing(r.info->level)) + goto out; +@@ -2880,6 +2938,13 @@ static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, + return true; + } + ++/* ++ * Used as the printk buffers for non-panic, serialized console printing. ++ * This is for legacy (!CON_NBCON) as well as all boot (CON_BOOT) consoles. ++ * Its usage requires the console_lock held. ++ */ ++struct printk_buffers printk_shared_pbufs; ++ + /* + * Print one record for the given console. The record printed is whatever + * record is the next available record for the given console. +@@ -2897,12 +2962,10 @@ static bool printk_get_next_message(struct printk_message *pmsg, u64 seq, + */ + static bool console_emit_next_record(struct console *con, bool *handover, int cookie) + { +- static struct printk_buffers pbufs; +- + bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; +- char *outbuf = &pbufs.outbuf[0]; ++ char *outbuf = &printk_shared_pbufs.outbuf[0]; + struct printk_message pmsg = { +- .pbufs = &pbufs, ++ .pbufs = &printk_shared_pbufs, + }; + unsigned long flags; + +@@ -2924,35 +2987,59 @@ static bool console_emit_next_record(struct console *con, bool *handover, int co + con->dropped = 0; + } + +- /* +- * While actively printing out messages, if another printk() +- * were to occur on another CPU, it may wait for this one to +- * finish. This task can not be preempted if there is a +- * waiter waiting to take over. +- * +- * Interrupts are disabled because the hand over to a waiter +- * must not be interrupted until the hand over is completed +- * (@console_waiter is cleared). +- */ +- printk_safe_enter_irqsave(flags); +- console_lock_spinning_enable(); ++ /* Write everything out to the hardware. */ + +- /* Do not trace print latency. */ +- stop_critical_timings(); ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ /* ++ * On PREEMPT_RT this function is either in a thread or ++ * panic context. So there is no need for concern about ++ * printk reentrance, handovers, or lockdep complaints. ++ */ + +- /* Write everything out to the hardware. */ +- con->write(con, outbuf, pmsg.outbuf_len); ++ con->write(con, outbuf, pmsg.outbuf_len); ++ con->seq = pmsg.seq + 1; ++ } else { ++ /* ++ * While actively printing out messages, if another printk() ++ * were to occur on another CPU, it may wait for this one to ++ * finish. This task can not be preempted if there is a ++ * waiter waiting to take over. ++ * ++ * Interrupts are disabled because the hand over to a waiter ++ * must not be interrupted until the hand over is completed ++ * (@console_waiter is cleared). ++ */ ++ printk_safe_enter_irqsave(flags); ++ console_lock_spinning_enable(); + +- start_critical_timings(); ++ /* Do not trace print latency. */ ++ stop_critical_timings(); + +- con->seq = pmsg.seq + 1; ++ lock_map_acquire_try(&printk_legacy_map); ++ con->write(con, outbuf, pmsg.outbuf_len); ++ lock_map_release(&printk_legacy_map); + +- *handover = console_lock_spinning_disable_and_check(cookie); +- printk_safe_exit_irqrestore(flags); ++ start_critical_timings(); ++ ++ con->seq = pmsg.seq + 1; ++ ++ *handover = console_lock_spinning_disable_and_check(cookie); ++ printk_safe_exit_irqrestore(flags); ++ } + skip: + return true; + } + ++#else ++ ++static bool console_emit_next_record(struct console *con, bool *handover, int cookie) ++{ ++ *handover = false; ++ return false; ++} ++ ++#endif /* CONFIG_PRINTK */ ++ + /* + * Print out all remaining records to all consoles. + * +@@ -2991,13 +3078,33 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove + + cookie = console_srcu_read_lock(); + for_each_console_srcu(con) { ++ short flags = console_srcu_read_flags(con); ++ u64 printk_seq; + bool progress; + +- if (!console_is_usable(con)) ++ /* ++ * console_flush_all() is only for legacy consoles, ++ * unless the nbcon console has no kthread printer. ++ */ ++ if ((flags & CON_NBCON) && con->kthread) ++ continue; ++ ++ if (!console_is_usable(con, flags, true)) + continue; + any_usable = true; + +- progress = console_emit_next_record(con, handover, cookie); ++ if (flags & CON_NBCON) { ++ ++ lock_map_acquire_try(&printk_legacy_map); ++ progress = nbcon_atomic_emit_next_record(con, handover, cookie); ++ lock_map_release(&printk_legacy_map); ++ ++ printk_seq = nbcon_seq_read(con); ++ } else { ++ progress = console_emit_next_record(con, handover, cookie); ++ ++ printk_seq = con->seq; ++ } + + /* + * If a handover has occurred, the SRCU read lock +@@ -3007,8 +3114,8 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove + return false; + + /* Track the next of the highest seq flushed. */ +- if (con->seq > *next_seq) +- *next_seq = con->seq; ++ if (printk_seq > *next_seq) ++ *next_seq = printk_seq; + + if (!progress) + continue; +@@ -3031,19 +3138,7 @@ static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handove + return false; + } + +-/** +- * console_unlock - unblock the console subsystem from printing +- * +- * Releases the console_lock which the caller holds to block printing of +- * the console subsystem. +- * +- * While the console_lock was held, console output may have been buffered +- * by printk(). If this is the case, console_unlock(); emits +- * the output prior to releasing the lock. +- * +- * console_unlock(); may be called from any context. +- */ +-void console_unlock(void) ++static void console_flush_and_unlock(void) + { + bool do_cond_resched; + bool handover; +@@ -3087,6 +3182,32 @@ void console_unlock(void) + */ + } while (prb_read_valid(prb, next_seq, NULL) && console_trylock()); + } ++ ++/** ++ * console_unlock - unblock the console subsystem from printing ++ * ++ * Releases the console_lock which the caller holds to block printing of ++ * the console subsystem. ++ * ++ * While the console_lock was held, console output may have been buffered ++ * by printk(). If this is the case, console_unlock(); emits ++ * the output prior to releasing the lock. ++ * ++ * console_unlock(); may be called from any context. ++ */ ++void console_unlock(void) ++{ ++ /* ++ * PREEMPT_RT relies on kthread and atomic consoles for printing. ++ * It never attempts to print from console_unlock(). ++ */ ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ __console_unlock(); ++ return; ++ } ++ ++ console_flush_and_unlock(); ++} + EXPORT_SYMBOL(console_unlock); + + /** +@@ -3197,6 +3318,7 @@ void console_flush_on_panic(enum con_flush_mode mode) + + if (mode == CONSOLE_REPLAY_ALL) { + struct console *c; ++ short flags; + int cookie; + u64 seq; + +@@ -3204,16 +3326,25 @@ void console_flush_on_panic(enum con_flush_mode mode) + + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { +- /* +- * This is an unsynchronized assignment, but the +- * kernel is in "hope and pray" mode anyway. +- */ +- c->seq = seq; ++ flags = console_srcu_read_flags(c); ++ ++ if (flags & CON_NBCON) { ++ nbcon_seq_force(c, seq); ++ } else { ++ /* ++ * This is an unsynchronized assignment. On ++ * panic legacy consoles are only best effort. ++ */ ++ c->seq = seq; ++ } + } + console_srcu_read_unlock(cookie); + } + +- console_flush_all(false, &next_seq, &handover); ++ nbcon_atomic_flush_all(); ++ ++ if (printing_via_unlock) ++ console_flush_all(false, &next_seq, &handover); + } + + /* +@@ -3270,13 +3401,122 @@ EXPORT_SYMBOL(console_stop); + + void console_start(struct console *console) + { ++ short flags; ++ + console_list_lock(); + console_srcu_write_flags(console, console->flags | CON_ENABLED); ++ flags = console->flags; + console_list_unlock(); ++ ++ /* ++ * Ensure that all SRCU list walks have completed. The related ++ * printing context must be able to see it is enabled so that ++ * it is guaranteed to wake up and resume printing. ++ */ ++ synchronize_srcu(&console_srcu); ++ ++ if (flags & CON_NBCON) ++ nbcon_kthread_wake(console); ++ else ++ wake_up_legacy_kthread(); ++ + __pr_flush(console, 1000, true); + } + EXPORT_SYMBOL(console_start); + ++#ifdef CONFIG_PRINTK ++static bool printer_should_wake(void) ++{ ++ bool available = false; ++ struct console *con; ++ int cookie; ++ ++ if (kthread_should_stop()) ++ return true; ++ ++ cookie = console_srcu_read_lock(); ++ for_each_console_srcu(con) { ++ short flags = console_srcu_read_flags(con); ++ u64 printk_seq; ++ ++ /* ++ * The legacy printer thread is only for legacy consoles, ++ * unless the nbcon console has no kthread printer. ++ */ ++ if ((flags & CON_NBCON) && con->kthread) ++ continue; ++ ++ if (!console_is_usable(con, flags, true)) ++ continue; ++ ++ if (flags & CON_NBCON) { ++ printk_seq = nbcon_seq_read(con); ++ } else { ++ /* ++ * It is safe to read @seq because only this ++ * thread context updates @seq. ++ */ ++ printk_seq = con->seq; ++ } ++ ++ if (prb_read_valid(prb, printk_seq, NULL)) { ++ available = true; ++ break; ++ } ++ } ++ console_srcu_read_unlock(cookie); ++ ++ return available; ++} ++ ++static int nbcon_legacy_kthread_func(void *unused) ++{ ++ int error; ++ ++ for (;;) { ++ error = wait_event_interruptible(legacy_wait, printer_should_wake()); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ if (error) ++ continue; ++ ++ console_lock(); ++ console_flush_and_unlock(); ++ } ++ ++ return 0; ++} ++ ++void nbcon_legacy_kthread_create(void) ++{ ++ struct task_struct *kt; ++ ++ lockdep_assert_held(&console_mutex); ++ ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) ++ return; ++ ++ if (!printk_threads_enabled || nbcon_legacy_kthread) ++ return; ++ ++ kt = kthread_run(nbcon_legacy_kthread_func, NULL, "pr/legacy"); ++ if (IS_ERR(kt)) { ++ pr_err("unable to start legacy printing thread\n"); ++ return; ++ } ++ ++ nbcon_legacy_kthread = kt; ++ ++ /* ++ * It is important that console printing threads are scheduled ++ * shortly after a printk call and with generous runtime budgets. ++ */ ++ sched_set_normal(nbcon_legacy_kthread, -20); ++} ++#endif /* CONFIG_PRINTK */ ++ + static int __read_mostly keep_bootcon; + + static int __init keep_bootcon_setup(char *str) +@@ -3375,11 +3615,6 @@ static void try_enable_default_console(struct console *newcon) + newcon->flags |= CON_CONSDEV; + } + +-#define con_printk(lvl, con, fmt, ...) \ +- printk(lvl pr_fmt("%sconsole [%s%d] " fmt), \ +- (con->flags & CON_BOOT) ? "boot" : "", \ +- con->name, con->index, ##__VA_ARGS__) +- + static void console_init_seq(struct console *newcon, bool bootcon_registered) + { + struct console *con; +@@ -3428,11 +3663,20 @@ static void console_init_seq(struct console *newcon, bool bootcon_registered) + + newcon->seq = prb_next_seq(prb); + for_each_console(con) { +- if ((con->flags & CON_BOOT) && +- (con->flags & CON_ENABLED) && +- con->seq < newcon->seq) { +- newcon->seq = con->seq; ++ u64 seq; ++ ++ if (!((con->flags & CON_BOOT) && ++ (con->flags & CON_ENABLED))) { ++ continue; + } ++ ++ if (con->flags & CON_NBCON) ++ seq = nbcon_seq_read(con); ++ else ++ seq = con->seq; ++ ++ if (seq < newcon->seq) ++ newcon->seq = seq; + } + } + +@@ -3493,6 +3737,15 @@ void register_console(struct console *newcon) + goto unlock; + } + ++ if (newcon->flags & CON_NBCON) { ++ /* ++ * Ensure the nbcon console buffers can be allocated ++ * before modifying any global data. ++ */ ++ if (!nbcon_alloc(newcon)) ++ goto unlock; ++ } ++ + /* + * See if we want to enable this console driver by default. + * +@@ -3520,8 +3773,11 @@ void register_console(struct console *newcon) + err = try_enable_preferred_console(newcon, false); + + /* printk() messages are not printed to the Braille console. */ +- if (err || newcon->flags & CON_BRL) ++ if (err || newcon->flags & CON_BRL) { ++ if (newcon->flags & CON_NBCON) ++ nbcon_free(newcon); + goto unlock; ++ } + + /* + * If we have a bootconsole, and are switching to a real console, +@@ -3537,6 +3793,17 @@ void register_console(struct console *newcon) + newcon->dropped = 0; + console_init_seq(newcon, bootcon_registered); + ++ if (newcon->flags & CON_NBCON) { ++ have_nbcon_console = true; ++ nbcon_init(newcon); ++ } else { ++ have_legacy_console = true; ++ nbcon_legacy_kthread_create(); ++ } ++ ++ if (newcon->flags & CON_BOOT) ++ have_boot_console = true; ++ + /* + * Put this console in the list - keep the + * preferred driver at the head of the list. +@@ -3589,6 +3856,11 @@ EXPORT_SYMBOL(register_console); + /* Must be called under console_list_lock(). */ + static int unregister_console_locked(struct console *console) + { ++ bool is_boot_con = (console->flags & CON_BOOT); ++ bool found_legacy_con = false; ++ bool found_nbcon_con = false; ++ bool found_boot_con = false; ++ struct console *c; + int res; + + lockdep_assert_console_list_lock_held(); +@@ -3628,11 +3900,50 @@ static int unregister_console_locked(struct console *console) + */ + synchronize_srcu(&console_srcu); + ++ if (console->flags & CON_NBCON) ++ nbcon_free(console); ++ + console_sysfs_notify(); + + if (console->exit) + res = console->exit(console); + ++ /* ++ * With this console gone, the global flags tracking registered ++ * console types may have changed. Update them. ++ */ ++ for_each_console(c) { ++ if (c->flags & CON_BOOT) ++ found_boot_con = true; ++ ++ if (c->flags & CON_NBCON) ++ found_nbcon_con = true; ++ else ++ found_legacy_con = true; ++ } ++ if (!found_boot_con) ++ have_boot_console = false; ++ if (!found_legacy_con) ++ have_legacy_console = false; ++ if (!found_nbcon_con) ++ have_nbcon_console = false; ++ ++ /* ++ * When the last boot console unregisters, start up the ++ * printing threads. ++ */ ++ if (is_boot_con && !have_boot_console) { ++ for_each_console(c) ++ nbcon_kthread_create(c); ++ } ++ ++#ifdef CONFIG_PRINTK ++ if (!printing_via_unlock && nbcon_legacy_kthread) { ++ kthread_stop(nbcon_legacy_kthread); ++ nbcon_legacy_kthread = NULL; ++ } ++#endif ++ + return res; + } + +@@ -3777,69 +4088,94 @@ late_initcall(printk_late_init); + /* If @con is specified, only wait for that console. Otherwise wait for all. */ + static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) + { +- int remaining = timeout_ms; ++ unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms); ++ unsigned long remaining_jiffies = timeout_jiffies; + struct console *c; + u64 last_diff = 0; + u64 printk_seq; ++ short flags; ++ bool locked; + int cookie; + u64 diff; + u64 seq; + + might_sleep(); + +- seq = prb_next_seq(prb); ++ seq = prb_next_reserve_seq(prb); + +- /* Flush the consoles so that records up to @seq are printed. */ +- console_lock(); +- console_unlock(); ++ /* ++ * Flush the consoles so that records up to @seq are printed. ++ * Otherwise this function will just wait for the threaded printers ++ * to print up to @seq. ++ */ ++ if (printing_via_unlock && !IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ console_lock(); ++ console_unlock(); ++ } + + for (;;) { ++ unsigned long begin_jiffies; ++ unsigned long slept_jiffies; ++ ++ locked = false; + diff = 0; + +- /* +- * Hold the console_lock to guarantee safe access to +- * console->seq. Releasing console_lock flushes more +- * records in case @seq is still not printed on all +- * usable consoles. +- */ +- console_lock(); ++ if (printing_via_unlock) { ++ /* ++ * Hold the console_lock to guarantee safe access to ++ * console->seq. Releasing console_lock flushes more ++ * records in case @seq is still not printed on all ++ * usable consoles. ++ */ ++ console_lock(); ++ locked = true; ++ } + + cookie = console_srcu_read_lock(); + for_each_console_srcu(c) { + if (con && con != c) + continue; ++ ++ flags = console_srcu_read_flags(c); ++ + /* + * If consoles are not usable, it cannot be expected + * that they make forward progress, so only increment + * @diff for usable consoles. + */ +- if (!console_is_usable(c)) ++ if (!console_is_usable(c, flags, true) && ++ !console_is_usable(c, flags, false)) { + continue; +- printk_seq = c->seq; ++ } ++ ++ if (flags & CON_NBCON) { ++ printk_seq = nbcon_seq_read(c); ++ } else { ++ WARN_ON_ONCE(!locked); ++ printk_seq = c->seq; ++ } ++ + if (printk_seq < seq) + diff += seq - printk_seq; + } + console_srcu_read_unlock(cookie); + + if (diff != last_diff && reset_on_progress) +- remaining = timeout_ms; ++ remaining_jiffies = timeout_jiffies; + +- console_unlock(); ++ if (locked) ++ console_unlock(); + + /* Note: @diff is 0 if there are no usable consoles. */ +- if (diff == 0 || remaining == 0) ++ if (diff == 0 || remaining_jiffies == 0) + break; + +- if (remaining < 0) { +- /* no timeout limit */ +- msleep(100); +- } else if (remaining < 100) { +- msleep(remaining); +- remaining = 0; +- } else { +- msleep(100); +- remaining -= 100; +- } ++ /* msleep(1) might sleep much longer. Check time by jiffies. */ ++ begin_jiffies = jiffies; ++ msleep(1); ++ slept_jiffies = jiffies - begin_jiffies; ++ ++ remaining_jiffies -= min(slept_jiffies, remaining_jiffies); + + last_diff = diff; + } +@@ -3880,9 +4216,16 @@ 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 trylock fails, someone else is doing the printing */ +- if (console_trylock()) +- console_unlock(); ++ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { ++ wake_up_interruptible(&legacy_wait); ++ } else { ++ /* ++ * If trylock fails, some other context ++ * will do the printing. ++ */ ++ if (console_trylock()) ++ console_unlock(); ++ } + } + + if (pending & PRINTK_PENDING_WAKEUP) +@@ -3950,11 +4293,16 @@ void defer_console_output(void) + * New messages may have been added directly to the ringbuffer + * using vprintk_store(), so wake any waiters as well. + */ +- __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT); ++ int val = PRINTK_PENDING_WAKEUP; ++ ++ if (printing_via_unlock) ++ val |= PRINTK_PENDING_OUTPUT; ++ __wake_up_klogd(val); + } + + void printk_trigger_flush(void) + { ++ nbcon_wake_threads(); + defer_console_output(); + } + +diff --git a/kernel/printk/printk_ringbuffer.c b/kernel/printk/printk_ringbuffer.c +index fde338606..e7b808b82 100644 +--- a/kernel/printk/printk_ringbuffer.c ++++ b/kernel/printk/printk_ringbuffer.c +@@ -6,6 +6,7 @@ + #include + #include + #include "printk_ringbuffer.h" ++#include "internal.h" + + /** + * DOC: printk_ringbuffer overview +@@ -303,6 +304,9 @@ + * + * desc_push_tail:B / desc_reserve:D + * set descriptor reusable (state), then push descriptor tail (id) ++ * ++ * desc_update_last_finalized:A / desc_last_finalized_seq:A ++ * store finalized record, then set new highest finalized sequence number + */ + + #define DATA_SIZE(data_ring) _DATA_SIZE((data_ring)->size_bits) +@@ -1030,9 +1034,13 @@ static char *data_alloc(struct printk_ringbuffer *rb, unsigned int size, + unsigned long next_lpos; + + if (size == 0) { +- /* Specify a data-less block. */ +- blk_lpos->begin = NO_LPOS; +- blk_lpos->next = NO_LPOS; ++ /* ++ * Data blocks are not created for empty lines. Instead, the ++ * reader will recognize these special lpos values and handle ++ * it appropriately. ++ */ ++ blk_lpos->begin = EMPTY_LINE_LPOS; ++ blk_lpos->next = EMPTY_LINE_LPOS; + return NULL; + } + +@@ -1210,10 +1218,18 @@ static const char *get_data(struct prb_data_ring *data_ring, + + /* Data-less data block description. */ + if (BLK_DATALESS(blk_lpos)) { +- if (blk_lpos->begin == NO_LPOS && blk_lpos->next == NO_LPOS) { ++ /* ++ * Records that are just empty lines are also valid, even ++ * though they do not have a data block. For such records ++ * explicitly return empty string data to signify success. ++ */ ++ if (blk_lpos->begin == EMPTY_LINE_LPOS && ++ blk_lpos->next == EMPTY_LINE_LPOS) { + *data_size = 0; + return ""; + } ++ ++ /* Data lost, invalid, or otherwise unavailable. */ + return NULL; + } + +@@ -1441,20 +1457,118 @@ bool prb_reserve_in_last(struct prb_reserved_entry *e, struct printk_ringbuffer + return false; + } + ++/* ++ * @last_finalized_seq value guarantees that all records up to and including ++ * this sequence number are finalized and can be read. The only exception are ++ * too old records which have already been overwritten. ++ * ++ * It is also guaranteed that @last_finalized_seq only increases. ++ * ++ * Be aware that finalized records following non-finalized records are not ++ * reported because they are not yet available to the reader. For example, ++ * a new record stored via printk() will not be available to a printer if ++ * it follows a record that has not been finalized yet. However, once that ++ * non-finalized record becomes finalized, @last_finalized_seq will be ++ * appropriately updated and the full set of finalized records will be ++ * available to the printer. And since each printk() caller will either ++ * directly print or trigger deferred printing of all available unprinted ++ * records, all printk() messages will get printed. ++ */ ++static u64 desc_last_finalized_seq(struct printk_ringbuffer *rb) ++{ ++ struct prb_desc_ring *desc_ring = &rb->desc_ring; ++ unsigned long ulseq; ++ ++ /* ++ * Guarantee the sequence number is loaded before loading the ++ * associated record in order to guarantee that the record can be ++ * seen by this CPU. This pairs with desc_update_last_finalized:A. ++ */ ++ ulseq = atomic_long_read_acquire(&desc_ring->last_finalized_seq ++ ); /* LMM(desc_last_finalized_seq:A) */ ++ ++ return __ulseq_to_u64seq(rb, ulseq); ++} ++ ++static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, ++ struct printk_record *r, unsigned int *line_count); ++ ++/* ++ * Check if there are records directly following @last_finalized_seq that are ++ * finalized. If so, update @last_finalized_seq to the latest of these ++ * records. It is not allowed to skip over records that are not yet finalized. ++ */ ++static void desc_update_last_finalized(struct printk_ringbuffer *rb) ++{ ++ struct prb_desc_ring *desc_ring = &rb->desc_ring; ++ u64 old_seq = desc_last_finalized_seq(rb); ++ unsigned long oldval; ++ unsigned long newval; ++ u64 finalized_seq; ++ u64 try_seq; ++ ++try_again: ++ finalized_seq = old_seq; ++ try_seq = finalized_seq + 1; ++ ++ /* Try to find later finalized records. */ ++ while (_prb_read_valid(rb, &try_seq, NULL, NULL)) { ++ finalized_seq = try_seq; ++ try_seq++; ++ } ++ ++ /* No update needed if no later finalized record was found. */ ++ if (finalized_seq == old_seq) ++ return; ++ ++ oldval = __u64seq_to_ulseq(old_seq); ++ newval = __u64seq_to_ulseq(finalized_seq); ++ ++ /* ++ * Set the sequence number of a later finalized record that has been ++ * seen. ++ * ++ * Guarantee the record data is visible to other CPUs before storing ++ * its sequence number. This pairs with desc_last_finalized_seq:A. ++ * ++ * Memory barrier involvement: ++ * ++ * If desc_last_finalized_seq:A reads from ++ * desc_update_last_finalized:A, then desc_read:A reads from ++ * _prb_commit:B. ++ * ++ * Relies on: ++ * ++ * RELEASE from _prb_commit:B to desc_update_last_finalized:A ++ * matching ++ * ACQUIRE from desc_last_finalized_seq:A to desc_read:A ++ * ++ * Note: _prb_commit:B and desc_update_last_finalized:A can be ++ * different CPUs. However, the desc_update_last_finalized:A ++ * CPU (which performs the release) must have previously seen ++ * _prb_commit:B. ++ */ ++ if (!atomic_long_try_cmpxchg_release(&desc_ring->last_finalized_seq, ++ &oldval, newval)) { /* LMM(desc_update_last_finalized:A) */ ++ old_seq = __ulseq_to_u64seq(rb, oldval); ++ goto try_again; ++ } ++} ++ + /* + * Attempt to finalize a specified descriptor. If this fails, the descriptor + * is either already final or it will finalize itself when the writer commits. + */ +-static void desc_make_final(struct prb_desc_ring *desc_ring, unsigned long id) ++static void desc_make_final(struct printk_ringbuffer *rb, unsigned long id) + { ++ struct prb_desc_ring *desc_ring = &rb->desc_ring; + unsigned long prev_state_val = DESC_SV(id, desc_committed); + struct prb_desc *d = to_desc(desc_ring, id); + +- atomic_long_cmpxchg_relaxed(&d->state_var, prev_state_val, +- DESC_SV(id, desc_finalized)); /* LMM(desc_make_final:A) */ +- +- /* Best effort to remember the last finalized @id. */ +- atomic_long_set(&desc_ring->last_finalized_id, id); ++ if (atomic_long_try_cmpxchg_relaxed(&d->state_var, &prev_state_val, ++ DESC_SV(id, desc_finalized))) { /* LMM(desc_make_final:A) */ ++ desc_update_last_finalized(rb); ++ } + } + + /** +@@ -1550,7 +1664,7 @@ bool prb_reserve(struct prb_reserved_entry *e, struct printk_ringbuffer *rb, + * readers. (For seq==0 there is no previous descriptor.) + */ + if (info->seq > 0) +- desc_make_final(desc_ring, DESC_ID(id - 1)); ++ desc_make_final(rb, DESC_ID(id - 1)); + + r->text_buf = data_alloc(rb, r->text_buf_size, &d->text_blk_lpos, id); + /* If text data allocation fails, a data-less record is committed. */ +@@ -1643,7 +1757,7 @@ void prb_commit(struct prb_reserved_entry *e) + */ + head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_commit:A) */ + if (head_id != e->id) +- desc_make_final(desc_ring, e->id); ++ desc_make_final(e->rb, e->id); + } + + /** +@@ -1663,12 +1777,9 @@ void prb_commit(struct prb_reserved_entry *e) + */ + void prb_final_commit(struct prb_reserved_entry *e) + { +- struct prb_desc_ring *desc_ring = &e->rb->desc_ring; +- + _prb_commit(e, desc_finalized); + +- /* Best effort to remember the last finalized @id. */ +- atomic_long_set(&desc_ring->last_finalized_id, e->id); ++ desc_update_last_finalized(e->rb); + } + + /* +@@ -1746,6 +1857,8 @@ static bool copy_data(struct prb_data_ring *data_ring, + * descriptor. However, it also verifies that the record is finalized and has + * the sequence number @seq. On success, 0 is returned. + * ++ * For the panic CPU, committed descriptors are also considered finalized. ++ * + * Error return values: + * -EINVAL: A finalized record with sequence number @seq does not exist. + * -ENOENT: A finalized record with sequence number @seq exists, but its data +@@ -1764,16 +1877,25 @@ static int desc_read_finalized_seq(struct prb_desc_ring *desc_ring, + + /* + * An unexpected @id (desc_miss) or @seq mismatch means the record +- * does not exist. A descriptor in the reserved or committed state +- * means the record does not yet exist for the reader. ++ * does not exist. A descriptor in the reserved state means the ++ * record does not yet exist for the reader. + */ + if (d_state == desc_miss || + d_state == desc_reserved || +- d_state == desc_committed || + s != seq) { + return -EINVAL; + } + ++ /* ++ * A descriptor in the committed state means the record does not yet ++ * exist for the reader. However, for the panic CPU, committed ++ * records are also handled as finalized records since they contain ++ * message data in a consistent state and may contain additional ++ * hints as to the cause of the panic. ++ */ ++ if (d_state == desc_committed && !this_cpu_in_panic()) ++ return -EINVAL; ++ + /* + * A descriptor in the reusable state may no longer have its data + * available; report it as existing but with lost data. Or the record +@@ -1832,7 +1954,7 @@ static int prb_read(struct printk_ringbuffer *rb, u64 seq, + } + + /* Get the sequence number of the tail descriptor. */ +-static u64 prb_first_seq(struct printk_ringbuffer *rb) ++u64 prb_first_seq(struct printk_ringbuffer *rb) + { + struct prb_desc_ring *desc_ring = &rb->desc_ring; + enum desc_state d_state; +@@ -1875,12 +1997,131 @@ static u64 prb_first_seq(struct printk_ringbuffer *rb) + return seq; + } + ++/** ++ * prb_next_reserve_seq() - Get the sequence number after the most recently ++ * reserved record. ++ * ++ * @rb: The ringbuffer to get the sequence number from. ++ * ++ * This is the public function available to readers to see what sequence ++ * number will be assigned to the next reserved record. ++ * ++ * Note that depending on the situation, this value can be equal to or ++ * higher than the sequence number returned by prb_next_seq(). ++ * ++ * Context: Any context. ++ * Return: The sequence number that will be assigned to the next record ++ * reserved. ++ */ ++u64 prb_next_reserve_seq(struct printk_ringbuffer *rb) ++{ ++ struct prb_desc_ring *desc_ring = &rb->desc_ring; ++ unsigned long last_finalized_id; ++ atomic_long_t *state_var; ++ u64 last_finalized_seq; ++ unsigned long head_id; ++ struct prb_desc desc; ++ unsigned long diff; ++ struct prb_desc *d; ++ int err; ++ ++ /* ++ * It may not be possible to read a sequence number for @head_id. ++ * So the ID of @last_finailzed_seq is used to calculate what the ++ * sequence number of @head_id will be. ++ */ ++ ++try_again: ++ last_finalized_seq = desc_last_finalized_seq(rb); ++ ++ /* ++ * @head_id is loaded after @last_finalized_seq to ensure that it is ++ * at or beyond @last_finalized_seq. ++ * ++ * Memory barrier involvement: ++ * ++ * If desc_last_finalized_seq:A reads from ++ * desc_update_last_finalized:A, then ++ * prb_next_reserve_seq:A reads from desc_reserve:D. ++ * ++ * Relies on: ++ * ++ * RELEASE from desc_reserve:D to desc_update_last_finalized:A ++ * matching ++ * ACQUIRE from desc_last_finalized_seq:A to prb_next_reserve_seq:A ++ * ++ * Note: desc_reserve:D and desc_update_last_finalized:A can be ++ * different CPUs. However, the desc_update_last_finalized:A CPU ++ * (which performs the release) must have previously seen ++ * desc_read:C, which implies desc_reserve:D can be seen. ++ */ ++ head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_next_reserve_seq:A) */ ++ ++ d = to_desc(desc_ring, last_finalized_seq); ++ state_var = &d->state_var; ++ ++ /* Extract the ID, used to specify the descriptor to read. */ ++ last_finalized_id = DESC_ID(atomic_long_read(state_var)); ++ ++ /* Ensure @last_finalized_id is correct. */ ++ err = desc_read_finalized_seq(desc_ring, last_finalized_id, last_finalized_seq, &desc); ++ ++ if (err == -EINVAL) { ++ if (last_finalized_seq == 0) { ++ /* ++ * @last_finalized_seq still contains its initial ++ * value. Probably no record has been finalized yet. ++ * This means the ringbuffer is not yet full and the ++ * @head_id value can be used directly (subtracting ++ * off the id value corresponding to seq=0). ++ */ ++ ++ /* ++ * Because of hack#2 of the bootstrapping phase, the ++ * @head_id initial value must be handled separately. ++ */ ++ if (head_id == DESC0_ID(desc_ring->count_bits)) ++ return 0; ++ ++ /* ++ * The @head_id is initialized such that the first ++ * increment will yield the first record (seq=0). ++ * Therefore use the initial value +1 as the base to ++ * subtract from @head_id. ++ */ ++ last_finalized_id = DESC0_ID(desc_ring->count_bits) + 1; ++ } else { ++ /* Record must have been overwritten. Try again. */ ++ goto try_again; ++ } ++ } ++ ++ /* ++ * @diff is the number of records beyond the last record available ++ * to readers. ++ */ ++ diff = head_id - last_finalized_id; ++ ++ /* ++ * @head_id points to the most recently reserved record, but this ++ * function returns the sequence number that will be assigned to the ++ * next (not yet reserved) record. Thus +1 is needed. ++ */ ++ return (last_finalized_seq + diff + 1); ++} ++ + /* +- * Non-blocking read of a record. Updates @seq to the last finalized record +- * (which may have no data available). ++ * Non-blocking read of a record. + * +- * See the description of prb_read_valid() and prb_read_valid_info() +- * for details. ++ * On success @seq is updated to the record that was read and (if provided) ++ * @r and @line_count will contain the read/calculated data. ++ * ++ * On failure @seq is updated to a record that is not yet available to the ++ * reader, but it will be the next record available to the reader. ++ * ++ * Note: When the current CPU is in panic, this function will skip over any ++ * non-existent/non-finalized records in order to allow the panic CPU ++ * to print any and all records that have been finalized. + */ + static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, + struct printk_record *r, unsigned int *line_count) +@@ -1899,12 +2140,32 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, + *seq = tail_seq; + + } else if (err == -ENOENT) { +- /* Record exists, but no data available. Skip. */ ++ /* Record exists, but the data was lost. Skip. */ + (*seq)++; + + } else { +- /* Non-existent/non-finalized record. Must stop. */ +- return false; ++ /* ++ * Non-existent/non-finalized record. Must stop. ++ * ++ * For panic situations it cannot be expected that ++ * non-finalized records will become finalized. But ++ * there may be other finalized records beyond that ++ * need to be printed for a panic situation. If this ++ * is the panic CPU, skip this ++ * non-existent/non-finalized record unless it is ++ * at or beyond the head, in which case it is not ++ * possible to continue. ++ * ++ * Note that new messages printed on panic CPU are ++ * finalized when we are here. The only exception ++ * might be the last message without trailing newline. ++ * But it would have the sequence number returned ++ * by "prb_next_reserve_seq() - 1". ++ */ ++ if (this_cpu_in_panic() && ((*seq + 1) < prb_next_reserve_seq(rb))) ++ (*seq)++; ++ else ++ return false; + } + } + +@@ -1932,7 +2193,7 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, + * On success, the reader must check r->info.seq to see which record was + * actually read. This allows the reader to detect dropped records. + * +- * Failure means @seq refers to a not yet written record. ++ * Failure means @seq refers to a record not yet available to the reader. + */ + bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq, + struct printk_record *r) +@@ -1962,7 +2223,7 @@ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq, + * On success, the reader must check info->seq to see which record meta data + * was actually read. This allows the reader to detect dropped records. + * +- * Failure means @seq refers to a not yet written record. ++ * Failure means @seq refers to a record not yet available to the reader. + */ + bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq, + struct printk_info *info, unsigned int *line_count) +@@ -2008,7 +2269,9 @@ u64 prb_first_valid_seq(struct printk_ringbuffer *rb) + * newest sequence number available to readers will be. + * + * This provides readers a sequence number to jump to if all currently +- * available records should be skipped. ++ * available records should be skipped. It is guaranteed that all records ++ * previous to the returned value have been finalized and are (or were) ++ * available to the reader. + * + * Context: Any context. + * Return: The sequence number of the next newest (not yet available) record +@@ -2016,34 +2279,19 @@ u64 prb_first_valid_seq(struct printk_ringbuffer *rb) + */ + u64 prb_next_seq(struct printk_ringbuffer *rb) + { +- struct prb_desc_ring *desc_ring = &rb->desc_ring; +- enum desc_state d_state; +- unsigned long id; + u64 seq; + +- /* Check if the cached @id still points to a valid @seq. */ +- id = atomic_long_read(&desc_ring->last_finalized_id); +- d_state = desc_read(desc_ring, id, NULL, &seq, NULL); ++ seq = desc_last_finalized_seq(rb); + +- if (d_state == desc_finalized || d_state == desc_reusable) { +- /* +- * Begin searching after the last finalized record. +- * +- * On 0, the search must begin at 0 because of hack#2 +- * of the bootstrapping phase it is not known if a +- * record at index 0 exists. +- */ +- if (seq != 0) +- seq++; +- } else { +- /* +- * The information about the last finalized sequence number +- * has gone. It should happen only when there is a flood of +- * new messages and the ringbuffer is rapidly recycled. +- * Give up and start from the beginning. +- */ +- seq = 0; +- } ++ /* ++ * Begin searching after the last finalized record. ++ * ++ * On 0, the search must begin at 0 because of hack#2 ++ * of the bootstrapping phase it is not known if a ++ * record at index 0 exists. ++ */ ++ if (seq != 0) ++ seq++; + + /* + * The information about the last finalized @seq might be inaccurate. +@@ -2085,7 +2333,7 @@ void prb_init(struct printk_ringbuffer *rb, + rb->desc_ring.infos = infos; + atomic_long_set(&rb->desc_ring.head_id, DESC0_ID(descbits)); + atomic_long_set(&rb->desc_ring.tail_id, DESC0_ID(descbits)); +- atomic_long_set(&rb->desc_ring.last_finalized_id, DESC0_ID(descbits)); ++ atomic_long_set(&rb->desc_ring.last_finalized_seq, 0); + + rb->text_data_ring.size_bits = textbits; + rb->text_data_ring.data = text_buf; +diff --git a/kernel/printk/printk_ringbuffer.h b/kernel/printk/printk_ringbuffer.h +index 18cd25e48..52626d0f1 100644 +--- a/kernel/printk/printk_ringbuffer.h ++++ b/kernel/printk/printk_ringbuffer.h +@@ -75,7 +75,7 @@ struct prb_desc_ring { + struct printk_info *infos; + atomic_long_t head_id; + atomic_long_t tail_id; +- atomic_long_t last_finalized_id; ++ atomic_long_t last_finalized_seq; + }; + + /* +@@ -127,8 +127,22 @@ enum desc_state { + #define DESC_SV(id, state) (((unsigned long)state << DESC_FLAGS_SHIFT) | id) + #define DESC_ID_MASK (~DESC_FLAGS_MASK) + #define DESC_ID(sv) ((sv) & DESC_ID_MASK) ++ ++/* ++ * Special data block logical position values (for fields of ++ * @prb_desc.text_blk_lpos). ++ * ++ * - Bit0 is used to identify if the record has no data block. (Implemented in ++ * the LPOS_DATALESS() macro.) ++ * ++ * - Bit1 specifies the reason for not having a data block. ++ * ++ * These special values could never be real lpos values because of the ++ * meta data and alignment padding of data blocks. (See to_blk_size() for ++ * details.) ++ */ + #define FAILED_LPOS 0x1 +-#define NO_LPOS 0x3 ++#define EMPTY_LINE_LPOS 0x3 + + #define FAILED_BLK_LPOS \ + { \ +@@ -259,7 +273,7 @@ static struct printk_ringbuffer name = { \ + .infos = &_##name##_infos[0], \ + .head_id = ATOMIC_INIT(DESC0_ID(descbits)), \ + .tail_id = ATOMIC_INIT(DESC0_ID(descbits)), \ +- .last_finalized_id = ATOMIC_INIT(DESC0_ID(descbits)), \ ++ .last_finalized_seq = ATOMIC_INIT(0), \ + }, \ + .text_data_ring = { \ + .size_bits = (avgtextbits) + (descbits), \ +@@ -378,7 +392,41 @@ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq, + bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq, + struct printk_info *info, unsigned int *line_count); + ++u64 prb_first_seq(struct printk_ringbuffer *rb); + u64 prb_first_valid_seq(struct printk_ringbuffer *rb); + u64 prb_next_seq(struct printk_ringbuffer *rb); ++u64 prb_next_reserve_seq(struct printk_ringbuffer *rb); ++ ++#ifdef CONFIG_64BIT ++ ++#define __u64seq_to_ulseq(u64seq) (u64seq) ++#define __ulseq_to_u64seq(rb, ulseq) (ulseq) ++ ++#else /* CONFIG_64BIT */ ++ ++#define __u64seq_to_ulseq(u64seq) ((u32)u64seq) ++ ++static inline u64 __ulseq_to_u64seq(struct printk_ringbuffer *rb, u32 ulseq) ++{ ++ u64 rb_first_seq = prb_first_seq(rb); ++ u64 seq; ++ ++ /* ++ * The provided sequence is only the lower 32 bits of the ringbuffer ++ * sequence. It needs to be expanded to 64bit. Get the first sequence ++ * number from the ringbuffer and fold it. ++ * ++ * Having a 32bit representation in the console is sufficient. ++ * If a console ever gets more than 2^31 records behind ++ * the ringbuffer then this is the least of the problems. ++ * ++ * Also the access to the ring buffer is always safe. ++ */ ++ seq = rb_first_seq - (s32)((u32)rb_first_seq - ulseq); ++ ++ return seq; ++} ++ ++#endif /* CONFIG_64BIT */ + + #endif /* _KERNEL_PRINTK_RINGBUFFER_H */ +diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c +index 6d10927a0..8d9408d65 100644 +--- a/kernel/printk/printk_safe.c ++++ b/kernel/printk/printk_safe.c +@@ -26,6 +26,18 @@ void __printk_safe_exit(void) + this_cpu_dec(printk_context); + } + ++void __printk_deferred_enter(void) ++{ ++ cant_migrate(); ++ this_cpu_inc(printk_context); ++} ++ ++void __printk_deferred_exit(void) ++{ ++ cant_migrate(); ++ this_cpu_dec(printk_context); ++} ++ + asmlinkage int vprintk(const char *fmt, va_list args) + { + #ifdef CONFIG_KGDB_KDB +diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c +index 46612fb15..f893f4cfd 100644 +--- a/kernel/rcu/rcutorture.c ++++ b/kernel/rcu/rcutorture.c +@@ -2409,6 +2409,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/rcu/tree_stall.h b/kernel/rcu/tree_stall.h +index 11a1fac3a..6f085a159 100644 +--- a/kernel/rcu/tree_stall.h ++++ b/kernel/rcu/tree_stall.h +@@ -8,6 +8,7 @@ + */ + + #include ++#include + + ////////////////////////////////////////////////////////////////////////////// + // +@@ -604,6 +605,8 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps) + if (rcu_stall_is_suppressed()) + return; + ++ nbcon_cpu_emergency_enter(); ++ + /* + * OK, time to rat on our buddy... + * See Documentation/RCU/stallwarn.rst for info on how to debug +@@ -658,6 +661,8 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps) + panic_on_rcu_stall(); + + rcu_force_quiescent_state(); /* Kick them all. */ ++ ++ nbcon_cpu_emergency_exit(); + } + + static void print_cpu_stall(unsigned long gps) +diff --git a/kernel/sched/core.c b/kernel/sched/core.c +index 97571d390..1a6f2a90e 100644 +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -897,14 +897,15 @@ static inline void hrtick_rq_init(struct rq *rq) + + #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) + /* +- * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, ++ * Atomically set TIF_NEED_RESCHED[_LAZY] and test for TIF_POLLING_NRFLAG, + * this avoids any races wrt polling state changes and thereby avoids + * spurious IPIs. + */ +-static inline bool set_nr_and_not_polling(struct task_struct *p) ++static inline bool set_nr_and_not_polling(struct task_struct *p, int tif_bit) + { + struct thread_info *ti = task_thread_info(p); +- return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG); ++ ++ return !(fetch_or(&ti->flags, 1 << tif_bit) & _TIF_POLLING_NRFLAG); + } + + /* +@@ -921,7 +922,7 @@ static bool set_nr_if_polling(struct task_struct *p) + for (;;) { + if (!(val & _TIF_POLLING_NRFLAG)) + return false; +- if (val & _TIF_NEED_RESCHED) ++ if (val & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) + return true; + if (try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED)) + break; +@@ -930,9 +931,9 @@ static bool set_nr_if_polling(struct task_struct *p) + } + + #else +-static inline bool set_nr_and_not_polling(struct task_struct *p) ++static inline bool set_nr_and_not_polling(struct task_struct *p, int tif_bit) + { +- set_tsk_need_resched(p); ++ set_tsk_thread_flag(p, tif_bit); + return true; + } + +@@ -1037,28 +1038,47 @@ void wake_up_q(struct wake_q_head *head) + * might also involve a cross-CPU call to trigger the scheduler on + * the target CPU. + */ +-void resched_curr(struct rq *rq) ++static void __resched_curr(struct rq *rq, int lazy) + { ++ int cpu, tif_bit = TIF_NEED_RESCHED + lazy; + struct task_struct *curr = rq->curr; +- int cpu; + + lockdep_assert_rq_held(rq); + +- if (test_tsk_need_resched(curr)) ++ if (unlikely(test_tsk_thread_flag(curr, tif_bit))) + return; + + cpu = cpu_of(rq); + + if (cpu == smp_processor_id()) { +- set_tsk_need_resched(curr); +- set_preempt_need_resched(); ++ set_tsk_thread_flag(curr, tif_bit); ++ if (!lazy) ++ set_preempt_need_resched(); + return; + } + +- if (set_nr_and_not_polling(curr)) +- smp_send_reschedule(cpu); +- else ++ if (set_nr_and_not_polling(curr, tif_bit)) { ++ if (!lazy) ++ smp_send_reschedule(cpu); ++ } else { + trace_sched_wake_idle_without_ipi(cpu); ++ } ++} ++ ++void resched_curr(struct rq *rq) ++{ ++ __resched_curr(rq, 0); ++} ++ ++void resched_curr_lazy(struct rq *rq) ++{ ++ int lazy = IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && !sched_feat(FORCE_NEED_RESCHED) ? ++ TIF_NEED_RESCHED_LAZY_OFFSET : 0; ++ ++ if (lazy && unlikely(test_tsk_thread_flag(rq->curr, TIF_NEED_RESCHED))) ++ return; ++ ++ __resched_curr(rq, lazy); + } + + void resched_cpu(int cpu) +@@ -1131,7 +1151,7 @@ static void wake_up_idle_cpu(int cpu) + if (cpu == smp_processor_id()) + return; + +- if (set_nr_and_not_polling(rq->idle)) ++ if (set_nr_and_not_polling(rq->idle, TIF_NEED_RESCHED)) + smp_send_reschedule(cpu); + else + trace_sched_wake_idle_without_ipi(cpu); +@@ -6721,10 +6741,14 @@ void __noreturn do_task_dead(void) + + static inline void sched_submit_work(struct task_struct *tsk) + { ++ static DEFINE_WAIT_OVERRIDE_MAP(sched_map, LD_WAIT_CONFIG); + unsigned int task_flags; + +- if (task_is_running(tsk)) +- return; ++ /* ++ * Establish LD_WAIT_CONFIG context to ensure none of the code called ++ * will use a blocking primitive -- which would lead to recursion. ++ */ ++ lock_map_acquire_try(&sched_map); + + task_flags = tsk->flags; + /* +@@ -6750,6 +6774,8 @@ static inline void sched_submit_work(struct task_struct *tsk) + * make sure to submit it to avoid deadlocks. + */ + blk_flush_plug(tsk->plug, true); ++ ++ lock_map_release(&sched_map); + } + + static void sched_update_worker(struct task_struct *tsk) +@@ -6762,16 +6788,26 @@ static void sched_update_worker(struct task_struct *tsk) + } + } + +-asmlinkage __visible void __sched schedule(void) ++static __always_inline void __schedule_loop(unsigned int sched_mode) + { +- struct task_struct *tsk = current; +- +- sched_submit_work(tsk); + do { + preempt_disable(); +- __schedule(SM_NONE); ++ __schedule(sched_mode); + sched_preempt_enable_no_resched(); + } while (need_resched()); ++} ++ ++asmlinkage __visible void __sched schedule(void) ++{ ++ struct task_struct *tsk = current; ++ ++#ifdef CONFIG_RT_MUTEXES ++ lockdep_assert(!tsk->sched_rt_mutex); ++#endif ++ ++ if (!task_is_running(tsk)) ++ sched_submit_work(tsk); ++ __schedule_loop(SM_NONE); + sched_update_worker(tsk); + } + EXPORT_SYMBOL(schedule); +@@ -6835,11 +6871,7 @@ void __sched schedule_preempt_disabled(void) + #ifdef CONFIG_PREEMPT_RT + void __sched notrace schedule_rtlock(void) + { +- do { +- preempt_disable(); +- __schedule(SM_RTLOCK_WAIT); +- sched_preempt_enable_no_resched(); +- } while (need_resched()); ++ __schedule_loop(SM_RTLOCK_WAIT); + } + NOKPROBE_SYMBOL(schedule_rtlock); + #endif +@@ -7035,6 +7067,32 @@ static void __setscheduler_prio(struct task_struct *p, int prio) + + #ifdef CONFIG_RT_MUTEXES + ++/* ++ * Would be more useful with typeof()/auto_type but they don't mix with ++ * bit-fields. Since it's a local thing, use int. Keep the generic sounding ++ * name such that if someone were to implement this function we get to compare ++ * notes. ++ */ ++#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; }) ++ ++void rt_mutex_pre_schedule(void) ++{ ++ lockdep_assert(!fetch_and_set(current->sched_rt_mutex, 1)); ++ sched_submit_work(current); ++} ++ ++void rt_mutex_schedule(void) ++{ ++ lockdep_assert(current->sched_rt_mutex); ++ __schedule_loop(SM_NONE); ++} ++ ++void rt_mutex_post_schedule(void) ++{ ++ sched_update_worker(current); ++ lockdep_assert(fetch_and_set(current->sched_rt_mutex, 0)); ++} ++ + static inline int __rt_effective_prio(struct task_struct *pi_task, int prio) + { + if (pi_task) +@@ -8885,6 +8943,21 @@ static inline void preempt_dynamic_init(void) { } + + #endif /* #ifdef CONFIG_PREEMPT_DYNAMIC */ + ++/* ++ * task_is_pi_boosted - Check if task has been PI boosted. ++ * @p: Task to check. ++ * ++ * Return true if task is subject to priority inheritance. ++ */ ++bool task_is_pi_boosted(const struct task_struct *p) ++{ ++ int prio = p->prio; ++ ++ if (!rt_prio(prio)) ++ return false; ++ return prio != p->normal_prio; ++} ++ + /** + * yield - yield the current processor to other threads. + * +diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c +index 4c3d0d9f3..63e19b89c 100644 +--- a/kernel/sched/debug.c ++++ b/kernel/sched/debug.c +@@ -333,6 +333,23 @@ static const struct file_operations sched_debug_fops = { + .release = seq_release, + }; + ++static ssize_t sched_hog_write(struct file *filp, const char __user *ubuf, ++ size_t cnt, loff_t *ppos) ++{ ++ unsigned long end = jiffies + 60 * HZ; ++ ++ for (; time_before(jiffies, end) && !signal_pending(current);) ++ cpu_relax(); ++ ++ return cnt; ++} ++ ++static const struct file_operations sched_hog_fops = { ++ .write = sched_hog_write, ++ .open = simple_open, ++ .llseek = default_llseek, ++}; ++ + static struct dentry *debugfs_sched; + + static __init int sched_init_debug(void) +@@ -374,6 +391,8 @@ static __init int sched_init_debug(void) + + debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops); + ++ debugfs_create_file("hog", 0200, debugfs_sched, NULL, &sched_hog_fops); ++ + return 0; + } + late_initcall(sched_init_debug); +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index b2e1009e5..e7e5569fd 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -1022,8 +1022,10 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se); + * XXX: strictly: vd_i += N*r_i/w_i such that: vd_i > ve_i + * this is probably good enough. + */ +-static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) ++static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se, bool tick) + { ++ struct rq *rq = rq_of(cfs_rq); ++ + if ((s64)(se->vruntime - se->deadline) < 0) + return; + +@@ -1042,10 +1044,19 @@ static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) + /* + * The task has consumed its request, reschedule. + */ +- if (cfs_rq->nr_running > 1) { +- resched_curr(rq_of(cfs_rq)); +- clear_buddies(cfs_rq, se); ++ if (cfs_rq->nr_running < 2) ++ return; ++ ++ if (!IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) || sched_feat(FORCE_NEED_RESCHED)) { ++ resched_curr(rq); ++ } else { ++ /* Did the task ignore the lazy reschedule request? */ ++ if (tick && test_tsk_thread_flag(rq->curr, TIF_NEED_RESCHED_LAZY)) ++ resched_curr(rq); ++ else ++ resched_curr_lazy(rq); + } ++ clear_buddies(cfs_rq, se); + } + + #include "pelt.h" +@@ -1153,7 +1164,7 @@ static void update_tg_load_avg(struct cfs_rq *cfs_rq) + /* + * Update the current task's runtime statistics. + */ +-static void update_curr(struct cfs_rq *cfs_rq) ++static void __update_curr(struct cfs_rq *cfs_rq, bool tick) + { + struct sched_entity *curr = cfs_rq->curr; + u64 now = rq_clock_task(rq_of(cfs_rq)); +@@ -1180,7 +1191,7 @@ static void update_curr(struct cfs_rq *cfs_rq) + schedstat_add(cfs_rq->exec_clock, delta_exec); + + curr->vruntime += calc_delta_fair(delta_exec, curr); +- update_deadline(cfs_rq, curr); ++ update_deadline(cfs_rq, curr, tick); + update_min_vruntime(cfs_rq); + + if (entity_is_task(curr)) { +@@ -1194,6 +1205,11 @@ static void update_curr(struct cfs_rq *cfs_rq) + account_cfs_rq_runtime(cfs_rq, delta_exec); + } + ++static inline void update_curr(struct cfs_rq *cfs_rq) ++{ ++ __update_curr(cfs_rq, false); ++} ++ + static void update_curr_fair(struct rq *rq) + { + update_curr(cfs_rq_of(&rq->curr->se)); +@@ -5403,7 +5419,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued) + /* + * Update run-time statistics of the 'current'. + */ +- update_curr(cfs_rq); ++ __update_curr(cfs_rq, true); + + /* + * Ensure that runnable average is periodically updated. +@@ -5417,7 +5433,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; + } + /* +@@ -5563,7 +5579,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 +@@ -5823,7 +5839,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq) + + /* Determine whether we need to wake up potentially idle CPU: */ + if (rq->curr == rq->idle && rq->cfs.nr_running) +- resched_curr(rq); ++ resched_curr_lazy(rq); + } + + #ifdef CONFIG_SMP +@@ -6528,7 +6544,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); +@@ -8206,7 +8222,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ + * prevents us from potentially nominating it as a false LAST_BUDDY + * below. + */ +- if (test_tsk_need_resched(curr)) ++ if (need_resched()) + return; + + /* Idle tasks are by definition preempted by non-idle tasks. */ +@@ -8248,7 +8264,7 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ + return; + + preempt: +- resched_curr(rq); ++ resched_curr_lazy(rq); + } + + #ifdef CONFIG_SMP +@@ -12394,7 +12410,7 @@ static inline void task_tick_core(struct rq *rq, struct task_struct *curr) + */ + if (rq->core->core_forceidle_count && rq->cfs.nr_running == 1 && + __entity_slice_used(&curr->se, MIN_NR_TASKS_DURING_FORCEIDLE)) +- resched_curr(rq); ++ resched_curr_lazy(rq); + } + + /* +@@ -12559,7 +12575,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 f77016823..dd8b35f67 100644 +--- a/kernel/sched/features.h ++++ b/kernel/sched/features.h +@@ -89,3 +89,5 @@ SCHED_FEAT(UTIL_EST_FASTUP, true) + SCHED_FEAT(LATENCY_WARN, false) + + SCHED_FEAT(HZ_BW, true) ++ ++SCHED_FEAT(FORCE_NEED_RESCHED, false) +diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c +index 5007b25c5..95e1b3df1 100644 +--- a/kernel/sched/idle.c ++++ b/kernel/sched/idle.c +@@ -57,8 +57,7 @@ static noinline int __cpuidle cpu_idle_poll(void) + ct_cpuidle_enter(); + + raw_local_irq_enable(); +- while (!tif_need_resched() && +- (cpu_idle_force_poll || tick_check_broadcast_expired())) ++ while (!need_resched() && (cpu_idle_force_poll || tick_check_broadcast_expired())) + cpu_relax(); + raw_local_irq_disable(); + +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 4ac36eb4c..acd1510e8 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -2253,8 +2253,11 @@ static int rto_next_cpu(struct root_domain *rd) + + rd->rto_cpu = cpu; + +- if (cpu < nr_cpu_ids) ++ if (cpu < nr_cpu_ids) { ++ if (!has_pushable_tasks(cpu_rq(cpu))) ++ continue; + return cpu; ++ } + + rd->rto_cpu = -1; + +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 8cbbbea7f..00cdf0db8 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2438,6 +2438,7 @@ extern void init_sched_fair_class(void); + extern void reweight_task(struct task_struct *p, const struct load_weight *lw); + + extern void resched_curr(struct rq *rq); ++extern void resched_curr_lazy(struct rq *rq); + extern void resched_cpu(int cpu); + + extern struct rt_bandwidth def_rt_bandwidth; +diff --git a/kernel/signal.c b/kernel/signal.c +index 21903f524..9f240d9cb 100644 +--- a/kernel/signal.c ++++ b/kernel/signal.c +@@ -2329,15 +2329,35 @@ static int ptrace_stop(int exit_code, int why, unsigned long message, + do_notify_parent_cldstop(current, false, why); + + /* +- * Don't want to allow preemption here, because +- * sys_ptrace() needs this task to be inactive. ++ * The previous do_notify_parent_cldstop() invocation woke ptracer. ++ * One a PREEMPTION kernel this can result in preemption requirement ++ * which will be fulfilled after read_unlock() and the ptracer will be ++ * put on the CPU. ++ * The ptracer is in wait_task_inactive(, __TASK_TRACED) waiting for ++ * this task wait in schedule(). If this task gets preempted then it ++ * remains enqueued on the runqueue. The ptracer will observe this and ++ * then sleep for a delay of one HZ tick. In the meantime this task ++ * gets scheduled, enters schedule() and will wait for the ptracer. + * +- * XXX: implement read_unlock_no_resched(). ++ * This preemption point is not bad from correctness point of view but ++ * extends the runtime by one HZ tick time due to the ptracer's sleep. ++ * The preempt-disable section ensures that there will be no preemption ++ * between unlock and schedule() and so improving the performance since ++ * the ptracer has no reason to sleep. ++ * ++ * On PREEMPT_RT locking tasklist_lock does not disable preemption. ++ * Therefore the task can be preempted (after ++ * do_notify_parent_cldstop()) before unlocking tasklist_lock so there ++ * is no benefit in doing this. The optimisation is harmful on ++ * PEEMPT_RT because the spinlock_t (in cgroup_enter_frozen()) must not ++ * be acquired with disabled preemption. + */ +- preempt_disable(); ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) ++ preempt_disable(); + read_unlock(&tasklist_lock); + cgroup_enter_frozen(); +- preempt_enable_no_resched(); ++ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) ++ preempt_enable_no_resched(); + schedule(); + cgroup_leave_frozen(true); + +diff --git a/kernel/softirq.c b/kernel/softirq.c +index bd9716d7b..2fde8af88 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -247,6 +247,19 @@ void __local_bh_enable_ip(unsigned long ip, unsigned int cnt) + } + EXPORT_SYMBOL(__local_bh_enable_ip); + ++void softirq_preempt(void) ++{ ++ if (WARN_ON_ONCE(!preemptible())) ++ return; ++ ++ if (WARN_ON_ONCE(__this_cpu_read(softirq_ctrl.cnt) != SOFTIRQ_OFFSET)) ++ return; ++ ++ __local_bh_enable(SOFTIRQ_OFFSET, true); ++ /* preemption point */ ++ __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); ++} ++ + /* + * Invoked from ksoftirqd_run() outside of the interrupt disabled section + * to acquire the per CPU local lock for reentrancy protection. +@@ -623,6 +636,24 @@ static inline void tick_irq_exit(void) + #endif + } + ++#ifdef CONFIG_PREEMPT_RT ++DEFINE_PER_CPU(struct task_struct *, timersd); ++DEFINE_PER_CPU(unsigned long, 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 +@@ -635,6 +666,10 @@ static inline void __irq_exit_rcu(void) + if (!in_interrupt() && local_softirq_pending()) + invoke_softirq(); + ++ if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers() && ++ !(in_nmi() | in_hardirq())) ++ wake_timersd(); ++ + tick_irq_exit(); + } + +@@ -967,12 +1002,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 57e5cb36f..c4ae45701 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -1812,7 +1812,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); +@@ -1925,7 +1925,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/tick-sched.c b/kernel/time/tick-sched.c +index 55cbc49f7..1a0ed106b 100644 +--- a/kernel/time/tick-sched.c ++++ b/kernel/time/tick-sched.c +@@ -795,7 +795,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) +diff --git a/kernel/time/timer.c b/kernel/time/timer.c +index 63a8ce717..b3fbe97d1 100644 +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1470,9 +1470,16 @@ static inline void timer_base_unlock_expiry(struct timer_base *base) + */ + static void timer_sync_wait_running(struct timer_base *base) + { +- if (atomic_read(&base->timer_waiters)) { ++ bool need_preempt; ++ ++ need_preempt = task_is_pi_boosted(current); ++ if (need_preempt || atomic_read(&base->timer_waiters)) { + raw_spin_unlock_irq(&base->lock); + spin_unlock(&base->expiry_lock); ++ ++ if (need_preempt) ++ softirq_preempt(); ++ + spin_lock(&base->expiry_lock); + raw_spin_lock_irq(&base->lock); + } +@@ -2054,7 +2061,7 @@ static void run_local_timers(void) + if (time_before(jiffies, base->next_expiry)) + return; + } +- raise_softirq(TIMER_SOFTIRQ); ++ raise_timer_softirq(); + } + + /* +diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c +index fd398af79..03653fcb3 100644 +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -2708,6 +2708,8 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status) + + if (tif_need_resched()) + trace_flags |= TRACE_FLAG_NEED_RESCHED; ++ if (tif_need_resched_lazy()) ++ trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY; + if (test_preempt_need_resched()) + trace_flags |= TRACE_FLAG_PREEMPT_RESCHED; + return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) | +diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c +index 3b7d3e9eb..5a4fefbc0 100644 +--- a/kernel/trace/trace_output.c ++++ b/kernel/trace/trace_output.c +@@ -460,17 +460,29 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry) + (entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' : + (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : + bh_off ? 'b' : +- (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' : ++ !IS_ENABLED(CONFIG_TRACE_IRQFLAGS_SUPPORT) ? 'X' : + '.'; + +- switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | ++ switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | + TRACE_FLAG_PREEMPT_RESCHED)) { ++ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED: ++ need_resched = 'B'; ++ break; + case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED: + need_resched = 'N'; + break; ++ case TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED: ++ need_resched = 'L'; ++ break; ++ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY: ++ need_resched = 'b'; ++ break; + case TRACE_FLAG_NEED_RESCHED: + need_resched = 'n'; + break; ++ case TRACE_FLAG_NEED_RESCHED_LAZY: ++ need_resched = 'l'; ++ break; + case TRACE_FLAG_PREEMPT_RESCHED: + need_resched = 'p'; + break; +diff --git a/localversion-rt b/localversion-rt +new file mode 100644 +index 000000000..2af6c89ae +--- /dev/null ++++ b/localversion-rt +@@ -0,0 +1 @@ ++-rt40 +diff --git a/net/core/dev.c b/net/core/dev.c +index 5a5bd339f..8f193d7b8 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4705,15 +4705,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); +-} +- + /* + * After we queued a packet into sd->input_pkt_queue, + * we need to make sure this queue is serviced soon. +@@ -6682,6 +6673,32 @@ 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 int napi_threaded_poll(void *data) + { + struct napi_struct *napi = data; +@@ -11619,7 +11636,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 f0a9ef1ae..682175af4 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -6863,8 +6863,13 @@ nodefer: __kfree_skb(skb); + /* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU + * if we are unlucky enough (this seems very unlikely). + */ +- if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) ++ if (unlikely(kick) && !cmpxchg(&sd->defer_ipi_scheduled, 0, 1)) { ++#ifndef CONFIG_PREEMPT_RT + smp_call_function_single_async(cpu, &sd->defer_csd); ++#else ++ schedule_work_on(cpu, &sd->defer_work); ++#endif ++ } + } + + static void skb_splice_csum_page(struct sk_buff *skb, struct page *page, +-- +2.25.1 + diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0011-v6.6-stm32mp-rt-r1.patch b/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0011-v6.6-stm32mp-rt-r1.patch new file mode 100644 index 000000000..490e43afc --- /dev/null +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/0011-v6.6-stm32mp-rt-r1.patch @@ -0,0 +1,386 @@ +From b3f06e85218243adf893ea11fa8010aff110dbe4 Mon Sep 17 00:00:00 2001 +From: Lionel VITTE +Date: Tue, 3 Dec 2024 14:44:47 +0100 +Subject: [PATCH] v6.6-stm32mp-rt-r1 + +--- + .../configs/fragment-07-rt-sysvinit.config | 12 ++++ + arch/arm/configs/fragment-07-rt.config | 32 ++++++++++ + .../configs/fragment-07-rt-sysvinit.config | 12 ++++ + arch/arm64/configs/fragment-07-rt.config | 33 ++++++++++ + drivers/hwtracing/coresight/coresight-cti.h | 10 +++ + drivers/mfd/stm32-lptimer.c | 55 ++++++++++++++++ + drivers/mfd/syscon.c | 3 + + drivers/soc/st/Kconfig | 6 ++ + drivers/soc/st/Makefile | 1 + + drivers/soc/st/stm32_hog.c | 64 +++++++++++++++++++ + drivers/watchdog/stm32_iwdg.c | 2 +- + 11 files changed, 229 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/configs/fragment-07-rt-sysvinit.config + create mode 100644 arch/arm/configs/fragment-07-rt.config + create mode 100644 arch/arm64/configs/fragment-07-rt-sysvinit.config + create mode 100644 arch/arm64/configs/fragment-07-rt.config + create mode 100644 drivers/soc/st/stm32_hog.c + +diff --git a/arch/arm/configs/fragment-07-rt-sysvinit.config b/arch/arm/configs/fragment-07-rt-sysvinit.config +new file mode 100644 +index 000000000..49a4baf60 +--- /dev/null ++++ b/arch/arm/configs/fragment-07-rt-sysvinit.config +@@ -0,0 +1,12 @@ ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_RDMA is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_PERF is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++ +diff --git a/arch/arm/configs/fragment-07-rt.config b/arch/arm/configs/fragment-07-rt.config +new file mode 100644 +index 000000000..98bb8735f +--- /dev/null ++++ b/arch/arm/configs/fragment-07-rt.config +@@ -0,0 +1,32 @@ ++CONFIG_PREEMPT_RT=y ++ ++# disable SCHED_MC ++# CONFIG_MCPM is not set ++ ++# Disable CPUFREQ and CPUIDLE ++# CONFIG_CPU_FREQ is not set ++# CONFIG_CPU_IDLE is not set ++ ++# Force to have HIGH_RES_TIMERS ++CONFIG_HIGH_RES_TIMERS=y ++ ++# force do not go to sleep ++# For multiple core, you should set the specific boot options ++# for isolate the core and render it tickless: "isolcpus=2,3 nohz_full=2,3" ++# Warning: to active only if SMP are present ++# CONFIG_HZ_PERIODIC=y ++ ++# to Enable ftrace, you need to enable the following configuraiton: ++# CONFIG_FTRACE=y ++# CONFIG_IRQSOFF_TRACER=y ++# CONFIG_PREEMPT_TRACER=y ++# CONFIG_SCHED_TRACER=y ++# CONFIG_FUNCTION_TRACER=y ++# By default, the ftrace for RT kernel are disabled ++# CONFIG_FTRACE is not set ++# CONFIG_IRQSOFF_TRACER is not set ++# CONFIG_PREEMPT_TRACER is not set ++# CONFIG_SCHED_TRACER is not set ++# CONFIG_FUNCTION_TRACER is not set ++ ++ +diff --git a/arch/arm64/configs/fragment-07-rt-sysvinit.config b/arch/arm64/configs/fragment-07-rt-sysvinit.config +new file mode 100644 +index 000000000..49a4baf60 +--- /dev/null ++++ b/arch/arm64/configs/fragment-07-rt-sysvinit.config +@@ -0,0 +1,12 @@ ++CONFIG_CGROUPS=y ++# CONFIG_CGROUP_SCHED is not set ++# CONFIG_CGROUP_PIDS is not set ++# CONFIG_CGROUP_RDMA is not set ++# CONFIG_CGROUP_FREEZER is not set ++# CONFIG_CGROUP_DEVICE is not set ++# CONFIG_CGROUP_CPUACCT is not set ++# CONFIG_CGROUP_PERF is not set ++# CONFIG_CGROUP_DEBUG is not set ++# CONFIG_CGROUP_NET_PRIO is not set ++# CONFIG_CGROUP_NET_CLASSID is not set ++ +diff --git a/arch/arm64/configs/fragment-07-rt.config b/arch/arm64/configs/fragment-07-rt.config +new file mode 100644 +index 000000000..8451ff348 +--- /dev/null ++++ b/arch/arm64/configs/fragment-07-rt.config +@@ -0,0 +1,33 @@ ++CONFIG_EXPERT=y ++CONFIG_PREEMPT_RT=y ++ ++# disable SCHED_MC ++# CONFIG_MCPM is not set ++ ++# Disable CPUFREQ and CPUIDLE ++# CONFIG_CPU_FREQ is not set ++# CONFIG_CPU_IDLE is not set ++ ++# Force to have HIGH_RES_TIMERS ++CONFIG_HIGH_RES_TIMERS=y ++ ++# force do not go to sleep ++# For multiple core, you should set the specific boot options ++# for isolate the core and render it tickless: "isolcpus=2,3 nohz_full=2,3" ++# Warning: to active only if SMP are present ++# CONFIG_HZ_PERIODIC=y ++ ++# to Enable ftrace, you need to enable the following configuraiton: ++# CONFIG_FTRACE=y ++# CONFIG_IRQSOFF_TRACER=y ++# CONFIG_PREEMPT_TRACER=y ++# CONFIG_SCHED_TRACER=y ++# CONFIG_FUNCTION_TRACER=y ++# By default, the ftrace for RT kernel are disabled ++# CONFIG_FTRACE is not set ++# CONFIG_IRQSOFF_TRACER is not set ++# CONFIG_PREEMPT_TRACER is not set ++# CONFIG_SCHED_TRACER is not set ++# CONFIG_FUNCTION_TRACER is not set ++ ++ +diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h +index cb9ee616d..9f9eaaf29 100644 +--- a/drivers/hwtracing/coresight/coresight-cti.h ++++ b/drivers/hwtracing/coresight/coresight-cti.h +@@ -17,6 +17,16 @@ + + #include "coresight-priv.h" + ++#ifdef CONFIG_PREEMPT_RT ++#undef spin_lock_init ++#define spin_lock_init raw_spin_lock_init ++#define spin_lock raw_spin_lock ++#define spin_unlock raw_spin_unlock ++#undef spin_lock_irqsave ++#define spin_lock_irqsave raw_spin_lock_irqsave ++#define spin_unlock_irqrestore raw_spin_unlock_irqrestore ++#define spinlock_t raw_spinlock_t ++#endif + /* + * Device registers + * 0x000 - 0x144: CTI programming and status +diff --git a/drivers/mfd/stm32-lptimer.c b/drivers/mfd/stm32-lptimer.c +index 9fc94122f..8df3b70f1 100644 +--- a/drivers/mfd/stm32-lptimer.c ++++ b/drivers/mfd/stm32-lptimer.c +@@ -21,6 +21,9 @@ static const struct regmap_config stm32_lptimer_regmap_cfg = { + .reg_stride = sizeof(u32), + .max_register = STM32_LPTIM_MAX_REGISTER, + .fast_io = true, ++#ifdef CONFIG_PREEMPT_RT ++ .use_raw_spinlock = true, ++#endif + }; + + static int stm32_lptimer_detect_encoder(struct stm32_lptimer *ddata) +@@ -85,6 +88,13 @@ static int stm32_lptimer_detect_hwcfgr(struct device *dev, struct stm32_lptimer + return 0; + } + ++#ifdef CONFIG_PREEMPT_RT ++static void stm32_lptimer_clk_disable_unprepare(void *data) ++{ ++ clk_disable_unprepare(data); ++} ++#endif ++ + static int stm32_lptimer_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; +@@ -100,8 +110,13 @@ static int stm32_lptimer_probe(struct platform_device *pdev) + if (IS_ERR(mmio)) + return PTR_ERR(mmio); + ++#ifdef CONFIG_PREEMPT_RT ++ ddata->regmap = devm_regmap_init_mmio(dev, mmio, ++ &stm32_lptimer_regmap_cfg); ++#else + ddata->regmap = devm_regmap_init_mmio_clk(dev, "mux", mmio, + &stm32_lptimer_regmap_cfg); ++#endif + if (IS_ERR(ddata->regmap)) + return PTR_ERR(ddata->regmap); + +@@ -109,6 +124,16 @@ static int stm32_lptimer_probe(struct platform_device *pdev) + if (IS_ERR(ddata->clk)) + return PTR_ERR(ddata->clk); + ++#ifdef CONFIG_PREEMPT_RT ++ ret = clk_prepare_enable(ddata->clk); ++ if (ret) ++ return ret; ++ ++ ret = devm_add_action_or_reset(dev, stm32_lptimer_clk_disable_unprepare, ddata->clk); ++ if (ret) ++ return ret; ++#endif ++ + ret = stm32_lptimer_detect_hwcfgr(dev, ddata); + if (ret) + return ret; +@@ -122,6 +147,33 @@ static int stm32_lptimer_probe(struct platform_device *pdev) + return devm_of_platform_populate(&pdev->dev); + } + ++#ifdef CONFIG_PREEMPT_RT ++static int stm32_lptimer_suspend(struct device *dev) ++{ ++ struct stm32_lptimer *priv = dev_get_drvdata(dev); ++ ++ clk_disable(priv->clk); ++ ++ return 0; ++} ++ ++static int stm32_lptimer_resume(struct device *dev) ++{ ++ struct stm32_lptimer *priv = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = clk_enable(priv->clk); ++ if (ret) ++ dev_err(dev, "failed to enable clock. Error [%d]\n", ret); ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops stm32_lptim_pm_ops = { ++ SYSTEM_SLEEP_PM_OPS(stm32_lptimer_suspend, stm32_lptimer_resume) ++}; ++#endif ++ + static const struct of_device_id stm32_lptimer_of_match[] = { + { .compatible = "st,stm32-lptimer", }, + { .compatible = "st,stm32mp21-lptimer", }, +@@ -135,6 +187,9 @@ static struct platform_driver stm32_lptimer_driver = { + .driver = { + .name = "stm32-lptimer", + .of_match_table = stm32_lptimer_of_match, ++#ifdef CONFIG_PREEMPT_RT ++ .pm = pm_ptr(&stm32_lptim_pm_ops), ++#endif + }, + }; + module_platform_driver(stm32_lptimer_driver); +diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c +index 7d0e91164..a5746d117 100644 +--- a/drivers/mfd/syscon.c ++++ b/drivers/mfd/syscon.c +@@ -40,6 +40,9 @@ static const struct regmap_config syscon_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, ++#ifdef CONFIG_PREEMPT_RT ++ .use_raw_spinlock = true, ++#endif + }; + + static struct syscon *of_syscon_register(struct device_node *np, bool check_res) +diff --git a/drivers/soc/st/Kconfig b/drivers/soc/st/Kconfig +index 1bde2c16c..704a19692 100644 +--- a/drivers/soc/st/Kconfig ++++ b/drivers/soc/st/Kconfig +@@ -1,5 +1,11 @@ + if ARCH_STM32 + ++config STM32_HOG ++ tristate "STM32 hog" ++ default y ++ help ++ Say y to enable clock(s) at the start of the Kernel. ++ + config STM32_PM_DOMAINS + bool "STM32 PM domains" + depends on MACH_STM32MP157 +diff --git a/drivers/soc/st/Makefile b/drivers/soc/st/Makefile +index 6c71607f6..11f056bfc 100644 +--- a/drivers/soc/st/Makefile ++++ b/drivers/soc/st/Makefile +@@ -1,3 +1,4 @@ ++obj-$(CONFIG_STM32_HOG) += stm32_hog.o + obj-$(CONFIG_STM32_PM_DOMAINS) += stm32_pm_domain.o + obj-$(CONFIG_STM32_RISAB) += stm32_risab.o + obj-$(CONFIG_STM32_RISAF) += stm32_risaf.o +diff --git a/drivers/soc/st/stm32_hog.c b/drivers/soc/st/stm32_hog.c +new file mode 100644 +index 000000000..c8fbf8d5e +--- /dev/null ++++ b/drivers/soc/st/stm32_hog.c +@@ -0,0 +1,64 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (C) 2024, STMicroelectronics - All Rights Reserved ++ */ ++ ++#include ++#include "linux/device.h" ++#include ++#include ++ ++struct stm32_hog_pdata { ++ struct clk_bulk_data *clks; ++ int num_clks; ++}; ++ ++static void stm32_hog_remove(struct platform_device *pdev) ++{ ++ struct stm32_hog_pdata *priv = platform_get_drvdata(pdev); ++ ++ clk_bulk_disable_unprepare(priv->num_clks, priv->clks); ++} ++ ++static int stm32_hog_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct stm32_hog_pdata *priv; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->num_clks = devm_clk_bulk_get_all(dev, &priv->clks); ++ if (priv->num_clks < 1) ++ return -ENODEV; ++ ++ ret = clk_bulk_prepare_enable(priv->num_clks, priv->clks); ++ if (ret) { ++ dev_err(dev, "failed to enable bulk clks %d\n", ret); ++ return ret; ++ } ++ ++ platform_set_drvdata(pdev, priv); ++ ++ return 0; ++} ++ ++static const struct of_device_id stm32_hog_match[] = { ++ { .compatible = "st,stm32-hog", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, stm32_hog_match); ++ ++static struct platform_driver stm32_hog_driver = { ++ .probe = stm32_hog_probe, ++ .remove_new = stm32_hog_remove, ++ .driver = { ++ .name = "stm32-hog", ++ .of_match_table = stm32_hog_match, ++ }, ++}; ++module_platform_driver(stm32_hog_driver); ++MODULE_AUTHOR("Gabriel Fernandez "); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c +index d7dfab2d3..d6a7b74db 100644 +--- a/drivers/watchdog/stm32_iwdg.c ++++ b/drivers/watchdog/stm32_iwdg.c +@@ -320,7 +320,7 @@ static int stm32_iwdg_irq_init(struct platform_device *pdev, + if (!wdt->data->has_early_wakeup) + return 0; + +- irq = platform_get_irq(pdev, 0); ++ irq = platform_get_irq_optional(pdev, 0); + if (irq <= 0) + return 0; + +-- +2.34.1 + diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/fragment-08-deactivate-rng.config b/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/fragment-08-deactivate-rng.config new file mode 100644 index 000000000..5c36fa79a --- /dev/null +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey/stm32mpcommon/fragment-08-deactivate-rng.config @@ -0,0 +1,2 @@ +# Disable RNG to avoid OPTEE Activation +# CONFIG_HW_RANDOM_OPTEE is not set diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb index 84862071a..c4525c2ea 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb @@ -7,6 +7,22 @@ SRCBRANCH:stm32mp2common = "v6.6/stm/dey-5.0/maint" SRCREV = "${AUTOREV}" SRCREV:stm32mp2common = "${AUTOREV}" +STM_RT_FILES = " \ + file://0010-Rebase-on-v6.6.48-rt40.patch \ + file://0011-v6.6-stm32mp-rt-r1.patch \ + file://fragment-08-deactivate-rng.config \ +" +SRC_URI:append:stm32mpcommon = " \ + ${@bb.utils.contains('DISTRO_FEATURES', 'rt', '${STM_RT_FILES}', '', d)} \ +" + +STM_RT_CONFIG_FRAGS = " \ + ${S}/arch/arm64/configs/fragment-07-rt.config \ + ${S}/arch/arm64/configs/fragment-07-rt-sysvinit.config \ + ${WORKDIR}/fragment-08-deactivate-rng.config \ +" +KERNEL_CONFIG_FRAGMENTS:append:stm32mpcommon = " ${@bb.utils.contains('DISTRO_FEATURES', 'rt', '${STM_RT_CONFIG_FRAGS}', '', d)}" + # Blacklist btnxpuart module. It will be managed by the bluetooth-init script KERNEL_MODULE_PROBECONF += "btnxpuart" module_conf_btnxpuart = "blacklist btnxpuart" From cb597d60fb00280e5a44569dc71009c431333e93 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Wed, 26 Feb 2025 17:16:30 +0100 Subject: [PATCH 04/39] Revert "crank: recipe for crank demos" This reverts commit 93e69dfb3e7511e680a3d42613e205a0c3520a77. https://onedigi.atlassian.net/browse/DEL-9527 Signed-off-by: Isaac Hermida --- meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend | 6 ------ 1 file changed, 6 deletions(-) diff --git a/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend b/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend index 090a18c64..58f5fe13b 100644 --- a/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend +++ b/meta-digi-arm/recipes-core/udev/udev-extraconf_1.1.bbappend @@ -53,12 +53,6 @@ do_install:append() { >> ${D}${sysconfdir}/udev/rules.d/localextra.rules fi - # Mouse symlink - printf "%s\n%s\n" \ - "# Symlink to the mouse" \ - "SUBSYSTEM==\"input\", KERNEL==\"event[0-9]*\", ENV{ID_INPUT_MOUSE}==\"1\", SYMLINK+=\"input/mouse0\"" \ - >> ${D}${sysconfdir}/udev/rules.d/localextra.rules - install -d ${D}${sysconfdir}/modprobe.d if ${@bb.utils.contains('MACHINE_FEATURES','gpu','false','true',d)}; then # evbug debug tool From 0885412c26c807ff671f27de60d39c4b04a972f1 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Wed, 26 Feb 2025 17:16:37 +0100 Subject: [PATCH 05/39] Revert "tslib: crank: add 'libts-1.0.so.0' link to the tslib package" This reverts commit 7a06747017368e8b53aace62cb971c510a72b2b0. https://onedigi.atlassian.net/browse/DEL-9527 Signed-off-by: Isaac Hermida --- meta-digi-dey/recipes-graphics/tslib/tslib_1.22.bbappend | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 meta-digi-dey/recipes-graphics/tslib/tslib_1.22.bbappend diff --git a/meta-digi-dey/recipes-graphics/tslib/tslib_1.22.bbappend b/meta-digi-dey/recipes-graphics/tslib/tslib_1.22.bbappend deleted file mode 100644 index e9b7af750..000000000 --- a/meta-digi-dey/recipes-graphics/tslib/tslib_1.22.bbappend +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (C) 2022, Digi International Inc. - -# Crank storyboard engine needs 'libts-1.0.so.0' -do_install:append() { - ln -s libts.so.0 ${D}${libdir}/libts-1.0.so.0 -} - -RPROVIDES:${PN} = "libts-1.0.so.0" From 738588064e42c8be3003bea0951cc9881b3ffba8 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Wed, 26 Feb 2025 17:20:35 +0100 Subject: [PATCH 06/39] Revert "gcnano-userland: fixes for Crank SB engine" This reverts commit c2da31e0b1e01d51769c2f5ee56315905c4a2692. https://onedigi.atlassian.net/browse/DEL-9527 Signed-off-by: Isaac Hermida --- .../gcnano-userland-multi-binary-stm32mp.bbappend | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-graphics/gcnano-userland/gcnano-userland-multi-binary-stm32mp.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-graphics/gcnano-userland/gcnano-userland-multi-binary-stm32mp.bbappend index a121ebfa7..768461012 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-graphics/gcnano-userland/gcnano-userland-multi-binary-stm32mp.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-graphics/gcnano-userland/gcnano-userland-multi-binary-stm32mp.bbappend @@ -1,17 +1,9 @@ -# Copyright (C) 2022,2023, Digi International Inc. - -# -# Workarounds for Crank storyboard engine -# +# Copyright (C) 2022-2025, Digi International Inc. # Put the devel symlink in the normal package -FILES:libegl-gcnano += "${libdir}/libEGL${SOLIBSDEV}" FILES:libgles1-gcnano += "${libdir}/libGLESv1_CM${SOLIBSDEV}" -FILES:libgles2-gcnano += "${libdir}/libGLESv2${SOLIBSDEV}" FILES:libopenvg-gcnano += "${libdir}/libOpenVG${SOLIBSDEV}" -# Add explicit runtime provides for libEGL.so, libGLESv2.so, libGLESv1_CM.so and libOpenVG.so -RPROVIDES:libegl-gcnano:prepend = "libEGL.so " +# Add explicit runtime provides for libGLESv1_CM.so and libOpenVG.so RPROVIDES:libgles1-gcnano:prepend = "libGLESv1_CM.so " -RPROVIDES:libgles2-gcnano:prepend = "libGLESv2.so " RPROVIDES:libopenvg-gcnano:prepend = "libOpenVG.so " From 3422efda373cae58e3fac4f0153be99ea9616141 Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Thu, 6 Mar 2025 15:50:20 +0100 Subject: [PATCH 07/39] nm: remove dnsmasq as DNS manager dnsmaqs is not able to manage DNS from cellular interface. Now, DNS is managed by systemd-resolved on platforms with systemd and by NetworkManager on sysvinit platforms. https://onedigi.atlassian.net/browse/DEL-9353 Signed-off-by: Francisco Gil --- .../networkmanager/networkmanager/NetworkManager.conf | 4 ++-- .../networkmanager/networkmanager_%.bbappend | 6 +++++- meta-digi-dey/recipes-support/dnsmasq/dnsmasq_%.bbappend | 9 --------- 3 files changed, 7 insertions(+), 12 deletions(-) delete mode 100644 meta-digi-dey/recipes-support/dnsmasq/dnsmasq_%.bbappend diff --git a/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager/NetworkManager.conf b/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager/NetworkManager.conf index e79beed5b..141b14d13 100644 --- a/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager/NetworkManager.conf +++ b/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager/NetworkManager.conf @@ -1,8 +1,8 @@ [main] plugins=ifupdown,keyfile no-auto-default=type:ethernet -dns=dnsmasq -rc-manager=file +dns=##DNS_MANAGER## +rc-manager=##RC_MANAGER## [ifupdown] managed=false diff --git a/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager_%.bbappend b/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager_%.bbappend index 4a4aeb376..12160f06f 100644 --- a/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager_%.bbappend +++ b/meta-digi-dey/recipes-connectivity/networkmanager/networkmanager_%.bbappend @@ -23,7 +23,7 @@ SRC_URI += " \ # Adjust compile time options: # * consolekit depends on X11. Disable to allow building framebuffer images. # -PACKAGECONFIG:remove:dey = "consolekit nss" +PACKAGECONFIG:remove:dey = "consolekit dnsmasq nss" PACKAGECONFIG:append = " gnutls modemmanager ppp concheck" # @@ -43,6 +43,8 @@ WLAN0_STATIC_CIDR = "${@ipaddr_to_cidr('wlan0', d)}" UNMANAGED_DEVICES = "interface-name:p2p*;interface-name:wlan1" UNMANAGED_DEVICES:ccimx9 = "interface-name:p2p-wfd0-0;interface-name:wfd0;interface-name:uap0" +DNS_MANAGER = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd','systemd-resolved','default', d)}" +RC_MANAGER = "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'unmanaged', 'file', d)}" inherit update-rc.d @@ -55,6 +57,8 @@ do_install:append() { # Customize NetworkManager # sed -i -e "s,##UNMANAGED_DEVICES##,${UNMANAGED_DEVICES},g" ${D}${sysconfdir}/NetworkManager/NetworkManager.conf + sed -i -e "s,##DNS_MANAGER##,${DNS_MANAGER},g" ${D}${sysconfdir}/NetworkManager/NetworkManager.conf + sed -i -e "s,##RC_MANAGER##,${RC_MANAGER},g" ${D}${sysconfdir}/NetworkManager/NetworkManager.conf # # Connections config files diff --git a/meta-digi-dey/recipes-support/dnsmasq/dnsmasq_%.bbappend b/meta-digi-dey/recipes-support/dnsmasq/dnsmasq_%.bbappend deleted file mode 100644 index be2269f60..000000000 --- a/meta-digi-dey/recipes-support/dnsmasq/dnsmasq_%.bbappend +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) 2017, Digi International Inc. - -# Enable DBUS support so it can be used from NetworkManager -PACKAGECONFIG:append = " dbus" - -# NetworkManager will launch 'dnsmasq' using DBUS, so disable the creation -# of runlevel's symlinks and disable its systemd service. -INHIBIT_UPDATERCD_BBCLASS = "1" -SYSTEMD_AUTO_ENABLE = "disable" From c357bf97f6499e3b8d7ed2e41b25aa5d760208a3 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Thu, 13 Mar 2025 18:04:26 +0100 Subject: [PATCH 08/39] README: add missing CC93 P/Ns to supported platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add to the list of supported platforms missing CC93 variants: - Dual-core, 1GB, non-wireless - Single-core, 512MB, wireless - Single-core, 512MB, non-wireless Reported-by: Miguel Ángel Perez Signed-off-by: Hector Palacios --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4a073651c..b690d887f 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ Software for the following hardware platforms is in production support: ## ConnectCore 93 * ConnectCore 93 System-on-Module (SOM) * [CC-WMX-YC7D-KN](https://www.digi.com/products/models/cc-wmx-yc7d-kn) + * [CC-MX-YC7D-ZN](https://www.digi.com/products/models/cc-mx-yc7d-zn) + * [CC-WMX-ZC6D-L1](https://www.digi.com/products/models/cc-wmx-zc6d-l1) + * [CC-MX-ZC6D-Z1](https://www.digi.com/products/models/cc-mx-zc6d-z1) * ConnectCore 93 Development Kit (DVK) * [CC-WMX93-KIT](https://www.digi.com/products/models/cc-wmx93-kit) ([Get Started](https://www.digi.com/resources/documentation/digidocs/embedded/dey/5.0/cc93/yocto-gs_index)) From 084f45ad0c033e5b2e5e68c2a93cb62762fe5244 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Fri, 4 Apr 2025 10:11:07 +0200 Subject: [PATCH 09/39] kernel-module-nxp-wlan: remove wlan_src_driver_patch_release_lf-6.6.52-2.2.0 The patch was recently added to meta-freescale, remove it from our layer to avoid build errors. Signed-off-by: Gabriel Valcazar (cherry picked from commit 907531b55cb6d421db4454bba5105b71071f6502) --- ...rc_driver_patch_release_lf-6.6.52-2..patch | 1943 ----------------- .../kernel-module-nxp-wlan_git.bbappend | 1 - 2 files changed, 1944 deletions(-) delete mode 100644 meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/0001-issue-fix-wlan_src_driver_patch_release_lf-6.6.52-2..patch diff --git a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/0001-issue-fix-wlan_src_driver_patch_release_lf-6.6.52-2..patch b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/0001-issue-fix-wlan_src_driver_patch_release_lf-6.6.52-2..patch deleted file mode 100644 index adb6f7c9a..000000000 --- a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/0001-issue-fix-wlan_src_driver_patch_release_lf-6.6.52-2..patch +++ /dev/null @@ -1,1943 +0,0 @@ -From: Gonzalo Ruiz -Date: Mon, 10 Feb 2025 09:49:59 +0100 -Subject: [PATCH 1/1] issue fix: wlan_src_driver_patch_release_lf-6.6.52-2.2.0 - -Patch from Wireless_Patch_Release_IW612_W8997_W8801_v0.1. -Incremental patch release based on the Q4-2024 release -"lf-6.6.52-2.2.0". - -[Patch Description] - - Wi-Fi driver patch to fix the issues observed on version 505.p4. - -Signed-off-by: Gonzalo Ruiz ---- - Makefile | 4 +- - mlan/mlan_cmdevt.c | 13 +++- - mlan/mlan_decl.h | 3 +- - mlan/mlan_fw.h | 8 +- - mlan/mlan_join.c | 8 +- - mlan/mlan_main.h | 3 +- - mlan/mlan_pcie.c | 10 ++- - mlan/mlan_shim.c | 3 +- - mlan/mlan_sta_cmd.c | 14 +++- - mlan/mlan_sta_cmdresp.c | 9 ++- - mlan/mlan_uap_cmdevent.c | 3 +- - mlan/mlan_wmm.c | 35 +++++---- - mlinux/mlan_decl.h | 3 +- - mlinux/moal_cfg80211.c | 47 +++++------- - mlinux/moal_cfg80211.h | 32 ++++---- - mlinux/moal_init.c | 30 +++++++- - mlinux/moal_ioctl.c | 11 ++- - mlinux/moal_main.c | 152 ++++++++++++++++++++++++++++++++----- - mlinux/moal_main.h | 8 +- - mlinux/moal_pcie.c | 10 ++- - mlinux/moal_sdio_mmc.c | 65 +++++++++++++--- - mlinux/moal_shim.c | 47 +++--------- - mlinux/moal_sta_cfg80211.c | 92 +++++++++++++--------- - mlinux/moal_uap_cfg80211.c | 58 +++++--------- - 24 files changed, 445 insertions(+), 223 deletions(-) - -diff --git a/Makefile b/Makefile -index 024e977..d61798e 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - # File: Makefile - # --# Copyright 2008-2024 NXP -+# Copyright 2008-2025 NXP - # - # This software file (the File) is distributed by NXP - # under the terms of the GNU General Public License Version 2, June 1991 -@@ -188,7 +188,7 @@ APPDIR= $(shell if test -d "mapp"; then echo mapp; fi) - ############################################################################# - - ccflags-y += -I$(KERNELDIR)/include -- ccflags-y += -DMLAN_RELEASE_VERSION='"505.p4"' -+ ccflags-y += -DMLAN_RELEASE_VERSION='"505.p7.1"' - - ccflags-y += -DFPNUM='"92"' - -diff --git a/mlan/mlan_cmdevt.c b/mlan/mlan_cmdevt.c -index 49c645e..dc0c8ba 100644 ---- a/mlan/mlan_cmdevt.c -+++ b/mlan/mlan_cmdevt.c -@@ -4,7 +4,7 @@ - * @brief This file contains the handling of CMD/EVENT in MLAN - * - * -- * Copyright 2009-2024 NXP -+ * Copyright 2009-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -5272,6 +5272,17 @@ mlan_status wlan_adapter_init_cmd(pmlan_adapter pmadapter) - } - } - #endif -+ if (pmpriv && (pmadapter->init_para.disable_11h_tpc)) { -+ /* Send command to FW to disable 11h tpc */ -+ ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_802_11_SNMP_MIB, -+ HostCmd_ACT_GEN_SET, -+ Dot11h_disable_tpc_i, MNULL, -+ &pmadapter->init_para.disable_11h_tpc); -+ if (ret) { -+ ret = MLAN_STATUS_FAILURE; -+ goto done; -+ } -+ } - #ifdef STA_SUPPORT - if (pmpriv_sta && (pmadapter->ps_mode == Wlan802_11PowerModePSP)) { - ret = wlan_prepare_cmd(pmpriv_sta, -diff --git a/mlan/mlan_decl.h b/mlan/mlan_decl.h -index d1367d6..97bc08f 100644 ---- a/mlan/mlan_decl.h -+++ b/mlan/mlan_decl.h -@@ -3,7 +3,7 @@ - * @brief This file declares the generic data structures and APIs. - * - * -- * Copyright 2008-2022, 2024 NXP -+ * Copyright 2008-2022, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -2782,6 +2782,7 @@ typedef struct _mlan_device { - t_u32 max_tx_pending; - t_u16 tx_budget; - t_u8 mclient_scheduling; -+ t_u8 disable_11h_tpc; - } mlan_device, *pmlan_device; - - /** MLAN API function prototype */ -diff --git a/mlan/mlan_fw.h b/mlan/mlan_fw.h -index 6ce0451..df8efa6 100644 ---- a/mlan/mlan_fw.h -+++ b/mlan/mlan_fw.h -@@ -5,7 +5,7 @@ - * in MLAN module. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -1674,11 +1674,14 @@ typedef MLAN_PACK_START struct _RxPD { - t_u32 rx_info; - - /** Reserved */ -- t_u8 reserved3[8]; -+ t_u8 reserved3[7]; -+ t_u8 rx_pkt_flags; - t_u8 ta_mac[6]; - t_u8 reserved4[2]; - } MLAN_PACK_END RxPD, *PRxPD; - -+#define RX_PKT_FLAG_MEF_MATCH_PKT MBIT(0) -+ - /** IEEEtypes_FrameCtl_t*/ - #ifdef BIG_ENDIAN_SUPPORT - typedef MLAN_PACK_START struct _IEEEtypes_FrameCtl_t { -@@ -3686,6 +3689,7 @@ typedef enum _SNMP_MIB_INDEX { - StopDeauth_i = 44, - Dot11H_fakeRadar = 45, - ChanTrackParam_i = 46, -+ Dot11h_disable_tpc_i = 47, - } SNMP_MIB_INDEX; - - /** max SNMP buf size */ -diff --git a/mlan/mlan_join.c b/mlan/mlan_join.c -index f4c8860..34fe4e7 100644 ---- a/mlan/mlan_join.c -+++ b/mlan/mlan_join.c -@@ -7,7 +7,7 @@ - * to the firmware. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -1046,6 +1046,7 @@ mlan_status wlan_cmd_802_11_associate(mlan_private *pmpriv, - t_u32 rates_size; - t_u16 tmp_cap; - t_u8 *pos; -+ IEEEtypes_CapInfo_t *pcap_info; - t_u8 ft_akm = 0; - t_u8 oper_class; - t_u8 oper_class_flag = MFALSE; -@@ -1524,6 +1525,11 @@ mlan_status wlan_cmd_802_11_associate(mlan_private *pmpriv, - memcpy_ext(pmadapter, &tmp_cap, &pbss_desc->cap_info, - sizeof(passo->cap_info), sizeof(tmp_cap)); - -+ /* retain spectrum_mgmt capability */ -+ pcap_info = &passo->cap_info; -+ if (pcap_info->spectrum_mgmt) -+ SPECTRUM_MGMT_ENABLED(tmp_cap); -+ - if (pmpriv->config_bands == BAND_B) - SHORT_SLOT_TIME_DISABLED(tmp_cap); - -diff --git a/mlan/mlan_main.h b/mlan/mlan_main.h -index 2e41d37..258bd1f 100644 ---- a/mlan/mlan_main.h -+++ b/mlan/mlan_main.h -@@ -5,7 +5,7 @@ - * in MLAN module. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -2042,6 +2042,7 @@ typedef struct _mlan_init_para { - t_u16 tx_budget; - t_u8 mclient_scheduling; - t_u32 reject_addba_req; -+ t_u8 disable_11h_tpc; - } mlan_init_para, *pmlan_init_para; - - #ifdef SDIO -diff --git a/mlan/mlan_pcie.c b/mlan/mlan_pcie.c -index 3575a9a..c29fb6e 100644 ---- a/mlan/mlan_pcie.c -+++ b/mlan/mlan_pcie.c -@@ -3,7 +3,7 @@ - * @brief This file contains PCI-E specific code - * - * -- * Copyright 2008-2021, 2024 NXP -+ * Copyright 2008-2021, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -2134,6 +2134,8 @@ static mlan_status wlan_pcie_send_data_complete(mlan_adapter *pmadapter) - ptx_bd_buf->flags = 0; - ptx_bd_buf->frag_len = 0; - ptx_bd_buf->offset = 0; -+ pcb->moal_spin_lock(pmadapter->pmoal_handle, -+ pmadapter->pmlan_pcie_lock); - pmadapter->pcard_pcie->txbd_rdptr++; - if ((pmadapter->pcard_pcie->txbd_rdptr & - txrx_rw_ptr_mask) == num_tx_buffs) -@@ -2141,6 +2143,8 @@ static mlan_status wlan_pcie_send_data_complete(mlan_adapter *pmadapter) - ((pmadapter->pcard_pcie->txbd_rdptr & - txrx_rw_ptr_rollover_ind) ^ - txrx_rw_ptr_rollover_ind); -+ pcb->moal_spin_unlock(pmadapter->pmoal_handle, -+ pmadapter->pmlan_pcie_lock); - } - #endif - #if defined(PCIE9098) || defined(PCIE9097) || defined(PCIEAW693) || \ -@@ -2154,9 +2158,13 @@ static mlan_status wlan_pcie_send_data_complete(mlan_adapter *pmadapter) - padma_bd_buf->flags = 0; - padma_bd_buf->pkt_size = 0; - padma_bd_buf->reserved = 0; -+ pcb->moal_spin_lock(pmadapter->pmoal_handle, -+ pmadapter->pmlan_pcie_lock); - pmadapter->pcard_pcie->txbd_rdptr++; - pmadapter->pcard_pcie->txbd_rdptr &= - ADMA_RW_PTR_WRAP_MASK; -+ pcb->moal_spin_unlock(pmadapter->pmoal_handle, -+ pmadapter->pmlan_pcie_lock); - } - #endif - } -diff --git a/mlan/mlan_shim.c b/mlan/mlan_shim.c -index 0752d7f..d27ab7e 100644 ---- a/mlan/mlan_shim.c -+++ b/mlan/mlan_shim.c -@@ -3,7 +3,7 @@ - * @brief This file contains APIs to MOAL module. - * - * -- * Copyright 2008-2021, 2024 NXP -+ * Copyright 2008-2021, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -474,6 +474,7 @@ mlan_status mlan_register(pmlan_device pmdevice, t_void **ppmlan_adapter) - #endif - pmadapter->init_para.dfs53cfg = pmdevice->dfs53cfg; - pmadapter->init_para.dfs_offload = pmdevice->dfs_offload; -+ pmadapter->init_para.disable_11h_tpc = pmdevice->disable_11h_tpc; - pmadapter->priv_num = 0; - pmadapter->priv[0] = MNULL; - -diff --git a/mlan/mlan_sta_cmd.c b/mlan/mlan_sta_cmd.c -index 4dd1712..2e16779 100644 ---- a/mlan/mlan_sta_cmd.c -+++ b/mlan/mlan_sta_cmd.c -@@ -5,7 +5,7 @@ - * it is ready. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -242,6 +242,18 @@ static mlan_status wlan_cmd_802_11_snmp_mib(pmlan_private pmpriv, - cmd->size += sizeof(t_u16); - } - break; -+ case Dot11h_disable_tpc_i: -+ psnmp_mib->oid = wlan_cpu_to_le16((t_u16)Dot11h_disable_tpc_i); -+ if (cmd_action == HostCmd_ACT_GEN_SET) { -+ psnmp_mib->query_type = -+ wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); -+ psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16)); -+ ul_temp = *(t_u32 *)pdata_buf; -+ *((t_u16 *)(psnmp_mib->value)) = -+ wlan_cpu_to_le16((t_u16)ul_temp); -+ cmd->size += sizeof(t_u16); -+ } -+ break; - case WwsMode_i: - psnmp_mib->oid = wlan_cpu_to_le16((t_u16)WwsMode_i); - if (cmd_action == HostCmd_ACT_GEN_SET) { -diff --git a/mlan/mlan_sta_cmdresp.c b/mlan/mlan_sta_cmdresp.c -index 116506c..f88f91d 100644 ---- a/mlan/mlan_sta_cmdresp.c -+++ b/mlan/mlan_sta_cmdresp.c -@@ -4,7 +4,7 @@ - * responses generated by firmware. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -643,6 +643,13 @@ static mlan_status wlan_ret_802_11_snmp_mib(pmlan_private pmpriv, - (ul_temp & SLAVE_RADAR_DET_MASK) ? MTRUE : - MFALSE; - } -+ /* Update state for 11h tpc disable */ -+ if (oid == Dot11h_disable_tpc_i) { -+ /* Set 11h tpc to private */ -+ ul_temp = wlan_le16_to_cpu(*((t_u16 *)(psmib->value))); -+ PRINTM(MCMND, "SNMP_RESP: Dot11h_disable_tpc_i =%u\n", -+ ul_temp); -+ } - } - - if (pioctl_buf) { -diff --git a/mlan/mlan_uap_cmdevent.c b/mlan/mlan_uap_cmdevent.c -index 6c50db9..66c01c5 100644 ---- a/mlan/mlan_uap_cmdevent.c -+++ b/mlan/mlan_uap_cmdevent.c -@@ -3,7 +3,7 @@ - * @brief This file contains the handling of AP mode command and event - * - * -- * Copyright 2009-2024 NXP -+ * Copyright 2009-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -3024,6 +3024,7 @@ static mlan_status wlan_uap_cmd_snmp_mib(pmlan_private pmpriv, - switch (cmd_oid) { - case Dot11D_i: - case Dot11H_i: -+ case Dot11h_disable_tpc_i: - psnmp_mib->oid = wlan_cpu_to_le16((t_u16)cmd_oid); - psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u16)); - ul_temp = *(t_u32 *)pdata_buf; -diff --git a/mlan/mlan_wmm.c b/mlan/mlan_wmm.c -index 9a8083a..6da49ea 100644 ---- a/mlan/mlan_wmm.c -+++ b/mlan/mlan_wmm.c -@@ -3,7 +3,7 @@ - * @brief This file contains functions for WMM. - * - * -- * Copyright 2008-2021, 2024 NXP -+ * Copyright 2008-2021, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -840,11 +840,11 @@ static raListTbl *wlan_wmm_get_highest_priolist_ptr(pmlan_adapter pmadapter, - * - * @return byte budget - */ --static t_u32 wlan_wmm_get_byte_budget(pmlan_adapter pmadapter, t_u32 time_budget_us, t_u32 phy_rate_kbps) -+static t_u32 wlan_wmm_get_byte_budget(t_u32 time_budget_us, t_u32 phy_rate_kbps) - { - const t_u32 min_budget = MV_ETH_FRAME_LEN; -- t_u64 byte_budget = pmadapter->callbacks.moal_do_div((t_u64)phy_rate_kbps * time_budget_us, -- 8 * 1000u); -+ t_u64 byte_budget = -+ ((t_u64)phy_rate_kbps * time_budget_us) / (8 * 1000u); - - if (byte_budget > INT_MAX) - return INT_MAX; -@@ -891,7 +891,7 @@ wlan_wmm_allocate_sta_table(pmlan_adapter pmadapter, t_u8 *ra) - - sta_table->budget.time_budget_init_us = pmadapter->init_para.tx_budget; - sta_table->budget.byte_budget_init = wlan_wmm_get_byte_budget( -- pmadapter, sta_table->budget.time_budget_init_us, default_rate); -+ sta_table->budget.time_budget_init_us, default_rate); - sta_table->budget.queue_packets = default_queue_packets; - sta_table->budget.phy_rate_kbps = default_rate; - -@@ -900,14 +900,14 @@ wlan_wmm_allocate_sta_table(pmlan_adapter pmadapter, t_u8 *ra) - sta_table->budget.mpdu_no_amsdu_pps_cap = - pmadapter->tx_mpdu_no_amsdu_pps; - -- sta_table->budget.mpdu_with_amsdu_budget_init = pmadapter->callbacks.moal_do_div( -- (t_u64)sta_table->budget.mpdu_with_amsdu_pps_cap * -- sta_table->budget.time_budget_init_us, -- 1000000); -- sta_table->budget.mpdu_no_amsdu_budget_init = pmadapter->callbacks.moal_do_div( -- (t_u64)sta_table->budget.mpdu_no_amsdu_pps_cap * -- sta_table->budget.time_budget_init_us, -- 1000000); -+ sta_table->budget.mpdu_with_amsdu_budget_init = -+ ((t_u64)sta_table->budget.mpdu_with_amsdu_pps_cap * -+ sta_table->budget.time_budget_init_us) / -+ 1000000; -+ sta_table->budget.mpdu_no_amsdu_budget_init = -+ ((t_u64)sta_table->budget.mpdu_no_amsdu_pps_cap * -+ sta_table->budget.time_budget_init_us) / -+ 1000000; - - for (i = 0; i < NELEMENTS(sta_table->budget.bytes); ++i) { - sta_table->budget.bytes[i] = sta_table->budget.byte_budget_init; -@@ -3142,12 +3142,12 @@ static t_void wlan_wmm_update_queue_packets_budget(pmlan_adapter pmadapter, - list_entry, struct wmm_sta_table, active_sta_entry); - const t_u64 sta_capacity = sta->budget.byte_budget_init; - const t_u32 max_pkts_by_airtime = -- wlan_wmm_get_byte_budget(pmadapter, max_pending_tx_time_us, -+ wlan_wmm_get_byte_budget(max_pending_tx_time_us, - sta->budget.phy_rate_kbps) / - MV_ETH_FRAME_LEN; -- t_u32 sta_share = pmadapter->callbacks.moal_do_div((t_u64)queue_packets_limit * sta_capacity, -- total_capacity); - -+ t_u32 sta_share = -+ queue_packets_limit * sta_capacity / total_capacity; - sta_share = MAX(sta_share, min_sta_share); - sta_share = MIN(sta_share, queue_packets_limit * 7 / 8); - sta_share = MIN(sta_share, max_pkts_by_airtime); -@@ -5183,7 +5183,6 @@ static void wlan_wmm_adjust_sta_tx_budget(pmlan_private priv, - struct wmm_sta_table *sta, - HostCmd_TX_RATE_QUERY *rate) - { -- mlan_adapter *pmadapter = priv->adapter; - const t_u8 ppdu_type_legacy = 0; - const t_u8 ppdu_type_ht = 1; - const t_u8 ppdu_type_vht = 2; -@@ -5211,7 +5210,7 @@ static void wlan_wmm_adjust_sta_tx_budget(pmlan_private priv, - if (phy_rate > 0) { - const t_u32 old_phy_rate = sta->budget.phy_rate_kbps; - sta->budget.byte_budget_init = wlan_wmm_get_byte_budget( -- pmadapter, sta->budget.time_budget_init_us, phy_rate); -+ sta->budget.time_budget_init_us, phy_rate); - sta->budget.phy_rate_kbps = phy_rate; - - if (old_phy_rate / phy_rate >= 2 || -diff --git a/mlinux/mlan_decl.h b/mlinux/mlan_decl.h -index d1367d6..97bc08f 100644 ---- a/mlinux/mlan_decl.h -+++ b/mlinux/mlan_decl.h -@@ -3,7 +3,7 @@ - * @brief This file declares the generic data structures and APIs. - * - * -- * Copyright 2008-2022, 2024 NXP -+ * Copyright 2008-2022, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -2782,6 +2782,7 @@ typedef struct _mlan_device { - t_u32 max_tx_pending; - t_u16 tx_budget; - t_u8 mclient_scheduling; -+ t_u8 disable_11h_tpc; - } mlan_device, *pmlan_device; - - /** MLAN API function prototype */ -diff --git a/mlinux/moal_cfg80211.c b/mlinux/moal_cfg80211.c -index 074fd59..0e54436 100644 ---- a/mlinux/moal_cfg80211.c -+++ b/mlinux/moal_cfg80211.c -@@ -3,7 +3,7 @@ - * @brief This file contains the functions for CFG80211. - * - * -- * Copyright 2011-2024 NXP -+ * Copyright 2011-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -1105,10 +1105,7 @@ void woal_cancel_cac(moal_private *priv) - if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT)) - PRINTM(MERROR, "%s: cancel chan report failed \n", - __func__); --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); - #else -@@ -1203,12 +1200,7 @@ int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, - PRINTM(MERROR, - "%s: cancel chan report failed \n", - __func__); --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, -- &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, -- GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, - &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, -@@ -1322,8 +1314,8 @@ int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, - #endif /* WIFI_DIRECT_SUPPORT */ - #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) - if (priv->bss_type == MLAN_BSS_TYPE_UAP) { --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - woal_cfg80211_del_beacon(wiphy, dev, 0); - #else - woal_cfg80211_del_beacon(wiphy, dev); -@@ -1562,7 +1554,8 @@ fail: - */ - #endif - int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index, -@@ -1638,7 +1631,8 @@ int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, - */ - #endif - int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index, -@@ -1655,13 +1649,9 @@ int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, - LEAVE(); - return -EFAULT; - } -- /* del_key will be trigger from cfg80211_rx_mlme_mgmt funtion -- * where we receive deauth/disassoicate packet in rx_work -- * use MOAL_NO_WAIT to avoid dead lock -- */ - if (MLAN_STATUS_FAILURE == - woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0, key_index, -- mac_addr, 1, 0, MOAL_NO_WAIT)) { -+ mac_addr, 1, 0, MOAL_IOCTL_WAIT)) { - PRINTM(MERROR, "Error deleting the crypto keys\n"); - LEAVE(); - return -EFAULT; -@@ -1697,7 +1687,8 @@ int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, - #endif - int woal_cfg80211_set_default_key(struct wiphy *wiphy, - struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index -@@ -1736,7 +1727,8 @@ int woal_cfg80211_set_default_key(struct wiphy *wiphy, - #if KERNEL_VERSION(2, 6, 30) <= CFG80211_VERSION_CODE - int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, - struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index) -@@ -1750,7 +1742,8 @@ int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, - #if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE - int woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy, - struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index) -@@ -2337,8 +2330,8 @@ done: - * @return 0 -- success, otherwise fail - */ - int woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - unsigned int link_id, - #endif - const u8 *peer, -@@ -5484,11 +5477,11 @@ void woal_cfg80211_notify_channel(moal_private *priv, - CFG80211_VERSION_CODE < KERNEL_VERSION(6, 9, 0) - cfg80211_ch_switch_notify(priv->netdev, &chandef, 0, 0); - #elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && \ -- IMX_ANDROID_13)) && \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33))) && \ - CFG80211_VERSION_CODE < KERNEL_VERSION(6, 9, 0) - cfg80211_ch_switch_notify(priv->netdev, &chandef, 0, 0); - #elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -- IMX_ANDROID_13 || IMX_ANDROID_12_BACKPORT) -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - cfg80211_ch_switch_notify(priv->netdev, &chandef, 0); - #else - cfg80211_ch_switch_notify(priv->netdev, &chandef); -diff --git a/mlinux/moal_cfg80211.h b/mlinux/moal_cfg80211.h -index 3323055..1b8484b 100644 ---- a/mlinux/moal_cfg80211.h -+++ b/mlinux/moal_cfg80211.h -@@ -3,7 +3,7 @@ - * @brief This file contains the CFG80211 specific defines. - * - * -- * Copyright 2011-2022, 2024 NXP -+ * Copyright 2011-2022, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -133,7 +133,8 @@ int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, - int woal_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); - - int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index, -@@ -143,7 +144,8 @@ int woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, - const t_u8 *mac_addr, struct key_params *params); - - int woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index, -@@ -167,8 +169,8 @@ int woal_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); - #endif - - int woal_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - unsigned int link_id, - #endif - const u8 *peer, -@@ -219,7 +221,8 @@ int woal_cfg80211_set_channel(struct wiphy *wiphy, - - #if KERNEL_VERSION(2, 6, 37) < CFG80211_VERSION_CODE - int woal_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *dev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index, bool ucast, bool mcast); -@@ -231,7 +234,8 @@ int woal_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *dev, - #if KERNEL_VERSION(2, 6, 30) <= CFG80211_VERSION_CODE - int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, - struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index); -@@ -240,7 +244,8 @@ int woal_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, - #if KERNEL_VERSION(5, 10, 0) <= CFG80211_VERSION_CODE - int woal_cfg80211_set_default_beacon_key(struct wiphy *wiphy, - struct net_device *netdev, --#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || IMX_ANDROID_13) -+#if ((KERNEL_VERSION(6, 1, 0) <= LINUX_VERSION_CODE) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33)) - int link_id, - #endif - t_u8 key_index); -@@ -453,8 +458,8 @@ int woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, - struct beacon_parameters *params); - #endif - --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev, - unsigned int link_id); - #else -@@ -472,12 +477,7 @@ int woal_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, - #endif - - #if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE --#if KERNEL_VERSION(6, 12, 0) <= CFG80211_VERSION_CODE --int woal_cfg80211_start_radar_detection(struct wiphy *wiphy, -- struct net_device *dev, -- struct cfg80211_chan_def *chandef, -- u32 cac_time_msi, int link_id); --#elif KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE -+#if KERNEL_VERSION(3, 15, 0) <= CFG80211_VERSION_CODE - int woal_cfg80211_start_radar_detection(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_chan_def *chandef, -diff --git a/mlinux/moal_init.c b/mlinux/moal_init.c -index f790666..845d272 100644 ---- a/mlinux/moal_init.c -+++ b/mlinux/moal_init.c -@@ -4,7 +4,7 @@ - * driver. - * - * -- * Copyright 2018-2022, 2024 NXP -+ * Copyright 2018-2022, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -336,6 +336,9 @@ static int mon_filter = DEFAULT_NETMON_FILTER; - - int dual_nb; - -+/** disable 802.11h tpc configuration */ -+static int disable_11h_tpc = 0; -+ - #ifdef DEBUG_LEVEL1 - #ifdef DEBUG_LEVEL2 - #define DEFAULT_DEBUG_MASK (0xffffffff) -@@ -1597,6 +1600,14 @@ static mlan_status parse_cfg_read_block(t_u8 *data, t_u32 size, - params->reject_addba_req = out_data; - PRINTM(MMSG, "reject_addba_req=%x\n", - params->reject_addba_req); -+ } else if (strncmp(line, "disable_11h_tpc", -+ strlen("disable_11h_tpc")) == 0) { -+ if (parse_line_read_int(line, &out_data) != -+ MLAN_STATUS_SUCCESS) -+ goto err; -+ params->disable_11h_tpc = out_data; -+ PRINTM(MMSG, "disable_11h_tpc=%x\n", -+ params->disable_11h_tpc); - } - } - -@@ -2000,6 +2011,13 @@ static void woal_setup_module_param(moal_handle *handle, moal_mod_para *params) - handle->params.dual_nb = dual_nb; - if (params) - handle->params.dual_nb = params->dual_nb; -+ -+ handle->params.disable_11h_tpc = disable_11h_tpc; -+ /* Ignore country IE when 11h tpc is disabled */ -+ if (disable_11h_tpc) -+ moal_extflg_set(handle, EXT_COUNTRY_IE_IGNORE); -+ if (params) -+ handle->params.disable_11h_tpc = params->disable_11h_tpc; - } - - /** -@@ -2568,6 +2586,12 @@ void woal_init_from_dev_tree(void) - data); - reject_addba_req = data; - } -+ } else if (!strncmp(prop->name, "disable_11h_tpc", -+ strlen("disable_11h_tpc"))) { -+ if (!of_property_read_u32(dt_node, prop->name, &data)) { -+ PRINTM(MERROR, "disable_11h_tpc=0x%x\n", data); -+ disable_11h_tpc = data; -+ } - } - #if defined(STA_CFG80211) || defined(UAP_CFG80211) - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) -@@ -3187,3 +3211,7 @@ module_param(reject_addba_req, int, 0); - MODULE_PARM_DESC( - reject_addba_req, - "Bit1: Reject the addba request when FW auto re-connect enabled (STA BSS only); Bit0: Reject the addba request when HS activated"); -+ -+module_param(disable_11h_tpc, int, 0); -+MODULE_PARM_DESC(disable_11h_tpc, -+ "0: Enable 802.11h tpc; 1: Disable 802.11h tpc"); -diff --git a/mlinux/moal_ioctl.c b/mlinux/moal_ioctl.c -index 94b8b2a..49711ea 100644 ---- a/mlinux/moal_ioctl.c -+++ b/mlinux/moal_ioctl.c -@@ -3,7 +3,7 @@ - * @brief This file contains ioctl function to MLAN - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -6101,13 +6101,19 @@ mlan_status woal_cancel_scan(moal_private *priv, t_u8 wait_option) - #ifdef STA_CFG80211 - unsigned long flags; - #endif -+ -+#ifdef STA_CFG80211 -+ // cancel scan timeout -+ if (IS_STA_CFG80211(handle->params.cfg80211_wext) && -+ handle->scan_request) -+ cancel_delayed_work(&handle->scan_timeout_work); -+#endif - /* If scan is in process, cancel the scan command */ - if (!handle->scan_pending_on_block || !scan_priv) { - #ifdef STA_CFG80211 - spin_lock_irqsave(&handle->scan_req_lock, flags); - if (IS_STA_CFG80211(handle->params.cfg80211_wext) && - handle->scan_request) { -- cancel_delayed_work(&handle->scan_timeout_work); - /* some supplicant cannot handle SCAN abort event */ - if (scan_priv && - (scan_priv->bss_type == MLAN_BSS_TYPE_STA)) -@@ -6138,7 +6144,6 @@ mlan_status woal_cancel_scan(moal_private *priv, t_u8 wait_option) - spin_lock_irqsave(&handle->scan_req_lock, flags); - if (IS_STA_CFG80211(handle->params.cfg80211_wext) && - handle->scan_request) { -- cancel_delayed_work(&handle->scan_timeout_work); - /** some supplicant can not handle SCAN abort event */ - if (scan_priv->bss_type == MLAN_BSS_TYPE_STA) - woal_cfg80211_scan_done(handle->scan_request, MTRUE); -diff --git a/mlinux/moal_main.c b/mlinux/moal_main.c -index e7f3242..a478a2c 100644 ---- a/mlinux/moal_main.c -+++ b/mlinux/moal_main.c -@@ -4,7 +4,7 @@ - * driver. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -174,6 +174,7 @@ static struct _card_info card_info_SD8887 = { - .fw_reset_val = 1, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0x90, - .slew_rate_reg = 0x80002328, - .slew_rate_bit_offset = 12, - #endif -@@ -214,6 +215,7 @@ static struct _card_info card_info_SD8897 = { - .fw_reset_val = 1, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xC0, - .slew_rate_reg = 0x80002328, - .slew_rate_bit_offset = 12, - #endif -@@ -299,6 +301,7 @@ static struct _card_info card_info_SD8977 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x80002328, - .slew_rate_bit_offset = 12, - #endif -@@ -342,6 +345,7 @@ static struct _card_info card_info_SD8978 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x80002328, - .slew_rate_bit_offset = 12, - #endif -@@ -385,6 +389,7 @@ static struct _card_info card_info_SD8997 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x80002328, - .slew_rate_bit_offset = 12, - #endif -@@ -429,6 +434,7 @@ static struct _card_info card_info_SD9098 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x90002328, - .slew_rate_bit_offset = 12, - #endif -@@ -473,6 +479,7 @@ static struct _card_info card_info_SD9097 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x90002328, - .slew_rate_bit_offset = 12, - #endif -@@ -517,6 +524,7 @@ static struct _card_info card_info_SDIW624 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x90002328, - .slew_rate_bit_offset = 12, - #endif -@@ -561,6 +569,7 @@ static struct _card_info card_info_SDAW693 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x90002328, - .slew_rate_bit_offset = 12, - #endif -@@ -605,6 +614,7 @@ static struct _card_info card_info_SD9177 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x90002328, - .slew_rate_bit_offset = 12, - #endif -@@ -649,6 +659,7 @@ static struct _card_info card_info_SDIW610 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x45001064, - .slew_rate_bit_offset = 16, - #endif -@@ -976,6 +987,7 @@ static struct _card_info card_info_SD8987 = { - .fw_reset_val = 0x99, - .fw_wakeup_reg = 0, - .fw_wakeup_val = 2, -+ .fw_winner_status_reg = 0xFC, - .slew_rate_reg = 0x80002328, - .slew_rate_bit_offset = 12, - #endif -@@ -989,8 +1001,7 @@ static struct _card_info card_info_SD8987 = { - - /** Driver version */ - char driver_version[] = -- INTF_CARDTYPE KERN_VERSION "--" MLAN_RELEASE_VERSION "-GPL" -- "-(" -+ INTF_CARDTYPE KERN_VERSION "--" MLAN_RELEASE_VERSION "-(" - "FP" FPNUM ")" - #ifdef DEBUG_LEVEL2 - "-dbg" -@@ -1224,11 +1235,7 @@ void woal_clean_up(moal_handle *handle) - handle->cac_period = MFALSE; - priv = handle->priv[handle->cac_bss_index]; - if (priv) { --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, &handle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, -- GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, &handle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, - GFP_KERNEL); -@@ -1259,8 +1266,8 @@ void woal_clean_up(moal_handle *handle) - #ifdef STA_CFG80211 - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) - if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - priv->wdev->connected) { - #else - priv->wdev->current_bss) { -@@ -1305,6 +1312,92 @@ void woal_clean_up(moal_handle *handle) - return; - } - -+/** -+ * @brief This function send the auto recovery failure event to userspace using -+ * netlink -+ * -+ * @param handle Pointer to structure moal_handle -+ * -+ * @return N/A -+ */ -+void woal_send_auto_recovery_failure_event(moal_handle *handle) -+{ -+ mlan_status ret = MLAN_STATUS_SUCCESS; -+ struct sk_buff *skb = NULL; -+ struct nlmsghdr *nlh = NULL; -+ struct sock *sk = handle->nl_sk; -+ int len = strlen(CUS_EVT_FW_RECOVER_FAIL); -+ ENTER(); -+ -+ /* interface name to be prepended to event */ -+ /* NL_MAX_PAYLOAD = 3 * 1024 */ -+ if ((len + IFNAMSIZ) > NL_MAX_PAYLOAD) { -+ PRINTM(MERROR, "event size is too big, len=%d\n", (int)len); -+ ret = MLAN_STATUS_FAILURE; -+ goto done; -+ } -+ if (sk) { -+ /* Allocate skb */ -+ skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC); -+ if (!skb) { -+ PRINTM(MERROR, "Could not allocate skb for netlink\n"); -+ ret = MLAN_STATUS_FAILURE; -+ goto done; -+ } -+ memset(skb->data, 0, NLMSG_SPACE(NL_MAX_PAYLOAD)); -+ -+ nlh = (struct nlmsghdr *)skb->data; -+ nlh->nlmsg_len = NLMSG_SPACE(len + IFNAMSIZ); -+ -+ /* From kernel */ -+ nlh->nlmsg_pid = 0; -+ nlh->nlmsg_flags = 0; -+ -+ /* Data */ -+ skb_put(skb, nlh->nlmsg_len); -+ moal_memcpy_ext(handle, NLMSG_DATA(nlh), "wlan", sizeof("wlan"), -+ nlh->nlmsg_len - NLMSG_LENGTH(0)); -+ -+ moal_memcpy_ext(handle, ((t_u8 *)(NLMSG_DATA(nlh))) + IFNAMSIZ, -+ CUS_EVT_FW_RECOVER_FAIL, len, -+ nlh->nlmsg_len - NLMSG_LENGTH(IFNAMSIZ)); -+ -+ /* From Kernel */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) -+ NETLINK_CB(skb).pid = 0; -+#else -+ NETLINK_CB(skb).portid = 0; -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -+ /* Multicast message */ -+ NETLINK_CB(skb).dst_pid = 0; -+#endif -+ -+ /* Multicast group number */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) -+ NETLINK_CB(skb).dst_groups = NL_MULTICAST_GROUP; -+#else -+ NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP; -+#endif -+ -+ /* Send message */ -+ ret = netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, -+ GFP_ATOMIC); -+ if (ret) { -+ PRINTM(MWARN, "netlink_broadcast failed: ret=%d\n", -+ ret); -+ goto done; -+ } -+ -+ } else { -+ PRINTM(MERROR, -+ "Could not send event through NETLINK. Link down.\n"); -+ } -+done: -+ LEAVE(); -+} -+ - /** - * @brief This function send the auto recovery complete event to kernel - * -@@ -1412,8 +1505,8 @@ static void woal_hang_work_queue(struct work_struct *work) - #ifdef STA_CFG80211 - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) - if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - priv->wdev->connected) { - #else - priv->wdev->current_bss) { -@@ -2603,6 +2696,7 @@ mlan_status woal_init_sw(moal_handle *handle) - handle->rtt_capa.responder_supported = MTRUE; - handle->rtt_capa.mc_version = 60; - handle->is_edmac_enabled = MFALSE; -+ handle->driver_init = MFALSE; - - /* Register to MLAN */ - memset(&device, 0, sizeof(mlan_device)); -@@ -2716,6 +2810,7 @@ mlan_status woal_init_sw(moal_handle *handle) - device.dmcs = handle->params.dmcs; - device.pref_dbc = handle->params.pref_dbc; - device.reject_addba_req = handle->params.reject_addba_req; -+ device.disable_11h_tpc = (t_u32)handle->params.disable_11h_tpc; - - for (i = 0; i < handle->drv_mode.intf_num; i++) { - device.bss_attr[i].bss_type = -@@ -4274,6 +4369,15 @@ err: - #ifdef CONFIG_PROC_FS - woal_proc_exit(handle); - #endif -+ -+#if defined(STA_CFG80211) || defined(UAP_CFG80211) -+ if (handle->wiphy) { -+ wiphy_unregister(handle->wiphy); -+ woal_cfg80211_free_bands(handle->wiphy); -+ wiphy_free(handle->wiphy); -+ handle->wiphy = NULL; -+ } -+#endif - } - LEAVE(); - return ret; -@@ -4770,6 +4874,7 @@ static mlan_status woal_request_fw_dpc(moal_handle *handle, - if (ret) - goto done; - -+ handle->driver_init = MTRUE; - done: - /* We should hold the semaphore until callback finishes execution */ - MOAL_REL_SEMAPHORE(&AddRemoveCardSem); -@@ -4910,6 +5015,9 @@ mlan_status woal_init_fw(moal_handle *handle) - ret = woal_add_card_dpc(handle); - if (ret) - goto done; -+ -+ handle->driver_init = MTRUE; -+ - /* Release semaphore if download is not required */ - MOAL_REL_SEMAPHORE(&AddRemoveCardSem); - done: -@@ -6653,8 +6761,8 @@ int woal_close(struct net_device *dev) - woal_cancel_scan(priv, MOAL_IOCTL_WAIT); - - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && - priv->wdev->connected) { - #else -@@ -10391,8 +10499,8 @@ t_void woal_send_disconnect_to_system(moal_private *priv, - if (IS_STA_CFG80211(cfg80211_wext)) { - spin_lock_irqsave(&priv->connect_lock, flags); - if (!priv->cfg_disconnect && !priv->cfg_connect && priv->wdev && --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - priv->wdev->connected) { - #else - priv->wdev->current_bss) { -@@ -12222,7 +12330,9 @@ t_void woal_scan_timeout_handler(struct work_struct *work) - woal_inform_bss_from_scan_result(priv, NULL, - MOAL_NO_WAIT); - spin_lock_irqsave(&handle->scan_req_lock, flags); -- woal_cfg80211_scan_done(handle->scan_request, MFALSE); -+ if (handle->scan_request) -+ woal_cfg80211_scan_done(handle->scan_request, -+ MFALSE); - handle->scan_request = NULL; - handle->fake_scan_complete = MFALSE; - spin_unlock_irqrestore(&handle->scan_req_lock, flags); -@@ -14035,6 +14145,13 @@ int woal_request_fw_reload(moal_handle *phandle, t_u8 mode) - moal_handle *ref_handle = NULL; - - ENTER(); -+ -+ if (!handle->driver_init) { -+ PRINTM(MMSG, "Ignore fw reload, driver not initialized\n"); -+ LEAVE(); -+ return -EFAULT; -+ } -+ - wifi_status = WIFI_STATUS_FW_RELOAD; - #ifdef PCIE - if (mode == FW_RELOAD_PCIE_RESET) { -@@ -14710,4 +14827,3 @@ MODULE_DESCRIPTION("M-WLAN Driver"); - MODULE_AUTHOR("NXP"); - MODULE_VERSION(MLAN_RELEASE_VERSION); - MODULE_LICENSE("GPL"); --MODULE_LICENSE("GPL"); -diff --git a/mlinux/moal_main.h b/mlinux/moal_main.h -index 6d87dcf..f8941c7 100644 ---- a/mlinux/moal_main.h -+++ b/mlinux/moal_main.h -@@ -3,7 +3,7 @@ - * @brief This file contains wlan driver specific defines etc. - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -408,6 +408,7 @@ typedef enum _MOAL_HARDWARE_STATUS { - #define WIFI_STATUS_SCAN_TIMEOUT 8 - #define WIFI_STATUS_FW_DUMP 9 - #define WIFI_STATUS_FW_RELOAD 10 -+#define WIFI_STATUS_FW_RECOVERY_FAIL 11 - - /** fw cap info 11p */ - #define FW_CAPINFO_80211P MBIT(24) -@@ -2124,6 +2125,7 @@ typedef struct _card_info { - t_u8 func1_reg_end; - t_u32 slew_rate_reg; - t_u8 slew_rate_bit_offset; -+ t_u32 fw_winner_status_reg; - #endif - #if defined(SDIO) || defined(PCIE) - t_u32 fw_stuck_code_reg; -@@ -2724,6 +2726,8 @@ typedef struct _moal_mod_para { - int dual_nb; - /* reject addba req config for HS or FW Auto-reconnect */ - t_u32 reject_addba_req; -+ /** disable_11h_tpc setting */ -+ int disable_11h_tpc; - } moal_mod_para; - - void woal_tp_acnt_timer_func(void *context); -@@ -3265,6 +3269,7 @@ struct _moal_handle { - #endif - t_u32 ips_ctrl; - BOOLEAN is_edmac_enabled; -+ bool driver_init; - }; - - /** -@@ -4330,6 +4335,7 @@ moal_private *woal_add_interface(moal_handle *handle, t_u8 bss_num, - t_u8 bss_type); - void woal_clean_up(moal_handle *handle); - void woal_send_auto_recovery_complete_event(moal_handle *handle); -+void woal_send_auto_recovery_failure_event(moal_handle *handle); - void woal_remove_interface(moal_handle *handle, t_u8 bss_index); - void woal_set_multicast_list(struct net_device *dev); - mlan_status woal_request_fw(moal_handle *handle); -diff --git a/mlinux/moal_pcie.c b/mlinux/moal_pcie.c -index 9034124..f3e8b8c 100644 ---- a/mlinux/moal_pcie.c -+++ b/mlinux/moal_pcie.c -@@ -4,7 +4,7 @@ - * related functions. - * - * -- * Copyright 2008-2022, 2024 NXP -+ * Copyright 2008-2022, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -153,6 +153,8 @@ static const struct pci_device_id wlan_ids[] = { - /* moal interface ops */ - static moal_if_ops pcie_ops; - -+MODULE_DEVICE_TABLE(pci, wlan_ids); -+ - /******************************************************** - Global Variables - ********************************************************/ -@@ -2547,8 +2549,10 @@ static void woal_pcie_dump_fw_info(moal_handle *phandle) - moal_private *priv = NULL; - #ifdef DUMP_TO_PROC - if (phandle->fw_dump_buf) { -- PRINTM(MERROR, "FW dump already exist\n"); -- return; -+ PRINTM(MMSG, "FW dump already exist, free existing dump\n"); -+ moal_vfree(phandle, phandle->fw_dump_buf); -+ phandle->fw_dump_buf = NULL; -+ phandle->fw_dump_len = 0; - } - #endif - mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE); -diff --git a/mlinux/moal_sdio_mmc.c b/mlinux/moal_sdio_mmc.c -index 299829e..44a09f0 100644 ---- a/mlinux/moal_sdio_mmc.c -+++ b/mlinux/moal_sdio_mmc.c -@@ -4,7 +4,7 @@ - * related functions. - * - * -- * Copyright 2008-2022, 2024 NXP -+ * Copyright 2008-2022, 2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -165,6 +165,8 @@ static const struct sdio_device_id wlan_ids[] = { - {}, - }; - -+MODULE_DEVICE_TABLE(sdio, wlan_ids); -+ - int woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id); - void woal_sdio_remove(struct sdio_func *func); - static void woal_sdiommc_work(struct work_struct *work); -@@ -281,7 +283,7 @@ static void woal_sdio_interrupt(struct sdio_func *func) - moal_handle *handle; - sdio_mmc_card *card; - mlan_status status; -- -+ t_u32 host_int_status_reg_val; - ENTER(); - - card = sdio_get_drvdata(func); -@@ -301,6 +303,14 @@ static void woal_sdio_interrupt(struct sdio_func *func) - PRINTM(MINFO, "*** IN SDIO IRQ ***\n"); - PRINTM(MINTR, "*\n"); - -+ if (handle->fw_reseting == MTRUE && (!handle->pmlan_adapter)) { -+ handle->ops.read_reg(handle, 0x0c, &host_int_status_reg_val); -+ PRINTM(MERROR, -+ "*** Recv intr during fw reset, host int status reg value is %d, ignore it ***\n", -+ host_int_status_reg_val); -+ LEAVE(); -+ return; -+ } - /* call mlan_interrupt to read int status */ - status = mlan_interrupt(0, handle->pmlan_adapter); - if (status == MLAN_STATUS_FAILURE) { -@@ -3092,8 +3102,10 @@ static void woal_sdiommc_dump_fw_info(moal_handle *phandle) - } - #ifdef DUMP_TO_PROC - if (phandle->fw_dump_buf) { -- PRINTM(MERROR, "FW dump already exist\n"); -- return; -+ PRINTM(MMSG, "FW dump already exist, free existing dump\n"); -+ moal_vfree(phandle, phandle->fw_dump_buf); -+ phandle->fw_dump_buf = NULL; -+ phandle->fw_dump_len = 0; - } - #endif - /** cancel all pending commands */ -@@ -3298,6 +3310,30 @@ void woal_sdio_reset_hw(moal_handle *handle) - return; - } - -+/** -+ * @brief This function check fw winner status -+ * -+ * @param handle A pointer to moal_handle structure -+ * -+ * @return 1--success, otherwise failure -+ */ -+static BOOLEAN woal_sdiommc_check_winner_status(moal_handle *handle) -+{ -+ t_u32 value = 1; -+ t_u32 winner_status_reg = handle->card_info->fw_winner_status_reg; -+ -+ ENTER(); -+#ifdef SD8801 -+ if (IS_SD8801(handle->card_type)) { -+ LEAVE(); -+ return MTRUE; -+ } -+#endif -+ handle->ops.read_reg(handle, winner_status_reg, &value); -+ LEAVE(); -+ return (value == 0); -+} -+ - /** - * @brief This function reload fw - * -@@ -3322,8 +3358,7 @@ static int woal_sdiommc_reset_fw(moal_handle *handle) - ret = -EFAULT; - goto done; - } -- udelay(2000); -- udelay(2000); -+ udelay(4000); - /** wait SOC fully wake up */ - for (tries = 0; tries < MAX_POLL_TRIES; ++tries) { - ret = handle->ops.write_reg(handle, reset_reg, 0xba); -@@ -3364,6 +3399,13 @@ static int woal_sdiommc_reset_fw(moal_handle *handle) - reset_reg, value); - ret = -EFAULT; - goto done; -+ } else { -+ for (tries = 0; tries < 1000; ++tries) { -+ if (woal_sdiommc_check_winner_status(handle)) { -+ break; -+ } -+ udelay(1000); -+ } - } - PRINTM(MMSG, "SDIO Trigger FW In-band Reset success"); - done: -@@ -3609,13 +3651,19 @@ static void woal_sdiommc_work(struct work_struct *work) - } - if (woal_sdiommc_reset_fw(handle)) { - PRINTM(MERROR, "SDIO In-band Reset Fail\n"); -- goto done; -+ woal_send_auto_recovery_failure_event(handle); -+ wifi_status = WIFI_STATUS_FW_RECOVERY_FAIL; -+ return; - } -+ - handle->surprise_removed = MFALSE; - if (MLAN_STATUS_SUCCESS == woal_do_sdiommc_flr(handle, false, true)) - handle->fw_reseting = MFALSE; -- else -+ else { - handle = NULL; -+ wifi_status = WIFI_STATUS_FW_RECOVERY_FAIL; -+ return; -+ } - - if (ref_handle) { - ref_handle->surprise_removed = MFALSE; -@@ -3624,7 +3672,6 @@ static void woal_sdiommc_work(struct work_struct *work) - ref_handle->fw_reseting = MFALSE; - } - card->work_flags = MFALSE; --done: - wifi_status = WIFI_STATUS_OK; - if (handle) - woal_send_auto_recovery_complete_event(handle); -diff --git a/mlinux/moal_shim.c b/mlinux/moal_shim.c -index 992e6ac..514aa95 100644 ---- a/mlinux/moal_shim.c -+++ b/mlinux/moal_shim.c -@@ -3,7 +3,7 @@ - * @brief This file contains the callback functions registered to MLAN - * - * -- * Copyright 2008-2024 NXP -+ * Copyright 2008-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -3734,12 +3734,7 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - &priv->phandle->cac_timer); - priv->phandle->is_cac_timer_set = MFALSE; - if (radar_detected) { --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, -- &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, -- GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, - &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, -@@ -3761,19 +3756,11 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - // WARN_ON(!time_after_eq(jiffies, - // timeout)); mdelay(100); Using - // optimized delay --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- timeout = -- (priv->wdev->links[0].cac_start_time + -- msecs_to_jiffies( -- priv->wdev -- ->links[0].cac_time_ms)); --#else - timeout = - (priv->wdev->cac_start_time + - msecs_to_jiffies( - priv->wdev - ->cac_time_ms)); --#endif - if (!time_after_eq(jiffies, timeout)) { - /* Exact time to make host and - * device timer in sync */ -@@ -3790,12 +3777,7 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - } - #endif - --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, -- &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_FINISHED, -- GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, - &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_FINISHED, -@@ -3873,12 +3855,7 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - woal_11h_cancel_chan_report_ioctl(priv, - MOAL_NO_WAIT); - /* upstream: inform cfg80211 */ --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, -- &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, -- GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, - &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, -@@ -3980,8 +3957,8 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - || priv->uap_host_based - #endif - #ifdef STA_CFG80211 --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - || priv->wdev->connected - #else - || priv->wdev->current_bss -@@ -4132,12 +4109,12 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0, - 0); - #elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && \ -- IMX_ANDROID_13)) && \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33))) && \ - CFG80211_VERSION_CODE < KERNEL_VERSION(6, 9, 0) - cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0, - 0); - #elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -- IMX_ANDROID_13 || IMX_ANDROID_12_BACKPORT) -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0); - #else - cfg80211_ch_switch_notify(priv->netdev, &priv->chan); -@@ -4486,8 +4463,8 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - PRINTM(MEVENT, - "HostMlme %s: Receive deauth/disassociate\n", - priv->netdev->name); --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - if (!priv->wdev->connected) { - #else - if (!priv->wdev->current_bss) { -@@ -4919,8 +4896,8 @@ mlan_status moal_recv_event(t_void *pmoal, pmlan_event pmevent) - roam_info = - kzalloc(sizeof(struct cfg80211_roam_info), GFP_ATOMIC); - if (roam_info) { --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - roam_info->links[0].bssid = priv->cfg_bssid; - #else - roam_info->bssid = priv->cfg_bssid; -diff --git a/mlinux/moal_sta_cfg80211.c b/mlinux/moal_sta_cfg80211.c -index 3883433..f30134c 100644 ---- a/mlinux/moal_sta_cfg80211.c -+++ b/mlinux/moal_sta_cfg80211.c -@@ -3,7 +3,7 @@ - * @brief This file contains the functions for STA CFG80211. - * - * -- * Copyright 2011-2024 NXP -+ * Copyright 2011-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -135,8 +135,8 @@ static int woal_cfg80211_dump_survey(struct wiphy *wiphy, - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) - static int woal_cfg80211_get_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - unsigned int link_id, - #endif - struct cfg80211_chan_def *chandef); -@@ -2841,7 +2841,9 @@ void woal_host_mlme_process_assoc_timeout(moal_private *priv, - struct cfg80211_bss *bss) - { - /* Send Assoc Failure with Timeout to CFG80211 */ --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) -+#if (CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33 && \ -+ CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 15, 74))) - struct cfg80211_assoc_failure data; - memset(&data, 0, sizeof(struct cfg80211_assoc_failure)); - data.timeout = 1; -@@ -2877,7 +2879,8 @@ void woal_host_mlme_process_assoc_resp(moal_private *priv, - struct cfg80211_rx_assoc_resp_data resp = { - .uapsd_queues = -1, - }; --#elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - struct cfg80211_rx_assoc_resp resp = { - .uapsd_queues = -1, - }; -@@ -2950,7 +2953,8 @@ void woal_host_mlme_process_assoc_resp(moal_private *priv, - } - } - --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - resp.links[0].bss = bss; - resp.buf = assoc_info->assoc_resp_buf; - resp.len = assoc_info->assoc_resp_len; -@@ -5021,7 +5025,9 @@ static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) - scan_req->chan_list[num_chans].scan_time = - INIT_PASSIVE_SCAN_CHAN_TIME; -- else if (priv->bss_type == MLAN_BSS_TYPE_STA) { -+ else if (priv->bss_type == MLAN_BSS_TYPE_STA && -+ scan_req->chan_list[num_chans].scan_type == -+ MLAN_SCAN_TYPE_PASSIVE) { - /* - * Set passive scan time to 110ms to discover - * all nearby AP's, Current 40ms passive scan -@@ -5034,20 +5040,17 @@ static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, - * 1. STA is in connected state - * 2. Scan type is passive - */ -- if (scan_req->chan_list[num_chans].scan_type == -- MLAN_SCAN_TYPE_PASSIVE) -- scan_req->chan_list[num_chans] -- .scan_time = -- PASSIVE_SCAN_CHAN_TIME; -- } else -+ scan_req->chan_list[num_chans].scan_time = -+ PASSIVE_SCAN_CHAN_TIME; -+ } else { - scan_req->chan_list[num_chans].scan_time = MIN( - MIN_SPECIFIC_SCAN_CHAN_TIME, - scan_cfg.scan_time.specific_scan_time); -+ } - } - #endif - #ifdef UAP_CFG80211 - if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) { -- scan_req->scan_chan_gap = 0; - if (!woal_is_uap_scan_result_expired(priv)) - scan_req->chan_list[num_chans].scan_time = - MIN_SPECIFIC_SCAN_CHAN_TIME; -@@ -5850,8 +5853,8 @@ static int woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - if (priv->media_connected == MFALSE) { - PRINTM(MMSG, " Already disconnected\n"); - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - if (priv->wdev->connected && - #else - if (priv->wdev->current_bss && -@@ -6205,8 +6208,8 @@ done: - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) - static int woal_cfg80211_get_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - unsigned int link_id, - #endif - struct cfg80211_chan_def *chandef) -@@ -9277,8 +9280,8 @@ int woal_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, - passoc_rsp = (IEEEtypes_AssocRsp_t *) - assoc_rsp->assoc_resp_buf; - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_14 || IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - roam_info.links[0].bssid = priv->cfg_bssid; - #else - roam_info.bssid = priv->cfg_bssid; -@@ -9757,8 +9760,8 @@ void woal_start_roaming(moal_private *priv) - } - #endif - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_14 || IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - roam_info.links[0].bssid = priv->cfg_bssid; - #else - roam_info.bssid = priv->cfg_bssid; -@@ -9839,7 +9842,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - if (params->ext_capab_len) - req_len += sizeof(MrvlIEtypesHeader_t) + params->ext_capab_len; - #endif --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.supported_rates_len) - req_len += sizeof(MrvlIEtypesHeader_t) + - params->link_sta_params.supported_rates_len; -@@ -9850,14 +9854,16 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - #endif - if (params->uapsd_queues || params->max_sp) - req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(qosinfo); --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.ht_capa) - #else - if (params->ht_capa) - #endif - req_len += sizeof(MrvlIEtypesHeader_t) + - sizeof(struct ieee80211_ht_cap); --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.vht_capa) - #else - if (params->vht_capa) -@@ -9865,7 +9871,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - req_len += sizeof(MrvlIEtypesHeader_t) + - sizeof(struct ieee80211_vht_cap); - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.opmode_notif_used) - req_len += sizeof(MrvlIEtypesHeader_t) + sizeof(u8); - #else -@@ -9875,7 +9882,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - #endif - - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.he_capa_len) - req_len += sizeof(MrvlExtIEtypesHeader_t) + - params->link_sta_params.he_capa_len; -@@ -9931,20 +9939,23 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - tlv = (MrvlIEtypes_Data_t *)pos; - } - #endif --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.supported_rates_len) { - #else - if (params->supported_rates_len) { - #endif - tlv = (MrvlIEtypes_Data_t *)pos; - tlv->header.type = SUPPORTED_RATES; --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - tlv->header.len = params->link_sta_params.supported_rates_len; - #else - tlv->header.len = params->supported_rates_len; - #endif - moal_memcpy_ext(priv->phandle, tlv->data, --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - params->link_sta_params.supported_rates, - tlv->header.len, - #else -@@ -9968,7 +9979,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - sizeof(MrvlIEtypesHeader_t) + tlv->header.len; - tlv = (MrvlIEtypes_Data_t *)pos; - } --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.ht_capa) { - #else - if (params->ht_capa) { -@@ -9976,7 +9988,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - tlv = (MrvlIEtypes_Data_t *)pos; - tlv->header.type = HT_CAPABILITY; - tlv->header.len = sizeof(struct ieee80211_ht_cap); --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - moal_memcpy_ext(priv->phandle, tlv->data, - params->link_sta_params.ht_capa, - #else -@@ -9988,7 +10001,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - sizeof(MrvlIEtypesHeader_t) + tlv->header.len; - tlv = (MrvlIEtypes_Data_t *)pos; - } --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.vht_capa) { - #else - if (params->vht_capa) { -@@ -9996,7 +10010,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - tlv = (MrvlIEtypes_Data_t *)pos; - tlv->header.type = VHT_CAPABILITY; - tlv->header.len = sizeof(struct ieee80211_vht_cap); --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - moal_memcpy_ext(priv->phandle, tlv->data, - params->link_sta_params.vht_capa, - #else -@@ -10009,7 +10024,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - tlv = (MrvlIEtypes_Data_t *)pos; - } - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.opmode_notif_used) { - #else - if (params->opmode_notif_used) { -@@ -10017,7 +10033,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - tlv = (MrvlIEtypes_Data_t *)pos; - tlv->header.type = OPER_MODE_NTF; - tlv->header.len = sizeof(u8); --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - moal_memcpy_ext(priv->phandle, tlv->data, - ¶ms->link_sta_params.opmode_notif, - #else -@@ -10030,7 +10047,8 @@ int woal_cfg80211_uap_add_station(struct wiphy *wiphy, struct net_device *dev, - tlv = (MrvlIEtypes_Data_t *)pos; - } - #endif --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || IMX_ANDROID_14) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 34)) - if (params->link_sta_params.he_capa_len) { - ext_tlv = (MrvlExtIEtypes_Data_t *)pos; - ext_tlv->header.type = EXTENSION; -diff --git a/mlinux/moal_uap_cfg80211.c b/mlinux/moal_uap_cfg80211.c -index 6c40a10..95aaaad 100644 ---- a/mlinux/moal_uap_cfg80211.c -+++ b/mlinux/moal_uap_cfg80211.c -@@ -3,7 +3,7 @@ - * @brief This file contains the functions for uAP CFG80211. - * - * -- * Copyright 2011-2024 NXP -+ * Copyright 2011-2025 NXP - * - * This software file (the File) is distributed by NXP - * under the terms of the GNU General Public License Version 2, June 1991 -@@ -2780,8 +2780,8 @@ int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, - } - } - if (vir_priv && vir_priv->bss_type == MLAN_BSS_TYPE_UAP) { --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - if (woal_cfg80211_del_beacon(wiphy, dev, 0)) - #else - if (woal_cfg80211_del_beacon(wiphy, dev)) -@@ -2789,15 +2789,15 @@ int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, - PRINTM(MERROR, "%s: del_beacon failed\n", - __func__); - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - vir_priv->wdev->links[0].ap.beacon_interval = 0; - #else - vir_priv->wdev->beacon_interval = 0; - #endif - #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - memset(&vir_priv->wdev->links[0].ap.chandef, 0, - sizeof(vir_priv->wdev->links[0].ap.chandef)); - #else -@@ -2806,8 +2806,8 @@ int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, - #endif - #endif - #endif --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - vir_priv->wdev->u.ap.ssid_len = 0; - #else - vir_priv->wdev->ssid_len = 0; -@@ -3101,8 +3101,8 @@ done: - * - * @return 0 -- success, otherwise fail - */ --#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13 || \ -- IMX_ANDROID_12_BACKPORT) -+#if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev, - unsigned int link_id) - #else -@@ -3168,10 +3168,7 @@ int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) - if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT)) - PRINTM(MERROR, "%s: cancel chan report failed \n", - __func__); --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); - #else -@@ -3851,10 +3848,7 @@ void woal_cac_timer_func(void *context) - moal_private *priv = handle->priv[handle->cac_bss_index]; - - PRINTM(MEVENT, "cac_timer fired.\n"); --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, &handle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, &handle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); - #else -@@ -3957,11 +3951,11 @@ static void woal_switch_uap_channel(moal_private *priv, t_u8 wait_option) - CFG80211_VERSION_CODE < KERNEL_VERSION(6, 9, 0) - cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0, 0); - #elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && \ -- IMX_ANDROID_13)) && \ -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 33))) && \ - CFG80211_VERSION_CODE < KERNEL_VERSION(6, 9, 0) - cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0, 0); - #elif ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || \ -- IMX_ANDROID_13 || IMX_ANDROID_12_BACKPORT) -+ (defined(ANDROID_SDK_VERSION) && ANDROID_SDK_VERSION >= 31)) - cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0); - #else - cfg80211_ch_switch_notify(priv->netdev, &priv->chan); -@@ -4013,10 +4007,7 @@ void woal_process_cancel_chanrpt_event(moal_private *priv) - if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT)) - PRINTM(MERROR, "%s: cancel chan report failed \n", - __func__); --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) -- cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel, -- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0); --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) - cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel, - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); - #else -@@ -4030,22 +4021,7 @@ void woal_process_cancel_chanrpt_event(moal_private *priv) - } - #endif - --#if CFG80211_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) --/** -- * @brief start radar detection -- * -- * @param wiphy A pointer to wiphy structure -- * @param dev A pointer to net_device structure -- * @param chandef A pointer to cfg80211_chan_def structure -- * @param cac_time_ms A cac dwell time -- * @param link_id valid link_id for MLO operation or 0 otherwise. -- * @return 0 -- success, otherwise fail -- */ --int woal_cfg80211_start_radar_detection(struct wiphy *wiphy, -- struct net_device *dev, -- struct cfg80211_chan_def *chandef, -- u32 cac_time_ms, int link_id) --#elif CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) -+#if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) - /** - * @brief start radar detection - * diff --git a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan_git.bbappend b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan_git.bbappend index 77a7a55d0..4c5b73ed1 100644 --- a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan_git.bbappend +++ b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan_git.bbappend @@ -5,7 +5,6 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}:" SRC_URI:append = " \ file://81-iw612-wifi.rules \ file://load_iw612.sh \ - file://0001-issue-fix-wlan_src_driver_patch_release_lf-6.6.52-2..patch \ " do_install:append () { From ee8075bfa78ec1ee203d8f1aae03af6de1496610 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Mon, 7 Apr 2025 11:39:47 +0200 Subject: [PATCH 10/39] build-github.sh: remove not supported platforms These platforms are not officially supported in the first DEY-5.0 release. Signed-off-by: Javier Viguera --- sdk/build-github.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sdk/build-github.sh b/sdk/build-github.sh index be51ffa75..10d1495a9 100755 --- a/sdk/build-github.sh +++ b/sdk/build-github.sh @@ -147,15 +147,9 @@ while read -r _pl _tgt; do # the fly with underscores. eval "${_pl//-/_}_tgt=\"${_tgt//,/ }\"" done<<-_EOF_ - ccimx8mm-dvk dey-image-qt - ccimx8mn-dvk dey-image-qt ccimx8x-sbc-pro dey-image-qt - ccimx6qpsbc dey-image-qt - ccimx6sbc dey-image-qt ccimx6ulsbc dey-image-qt ccimx6ulstarter core-image-base - ccmp15-dvk dey-image-webkit - ccmp13-dvk core-image-base ccmp25-dvk dey-image-webkit ccimx91-dvk core-image-base ccimx93-dvk dey-image-qt From ed1013e87a408a97a1ded00dd72c44128320a389 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Tue, 25 Feb 2025 18:00:30 +0100 Subject: [PATCH 11/39] linux-virtualization: expand lxc config support enable the kernel BTRFS filesystem support for better support with LXC incremental snapshots. Signed-off-by: Isaac Hermida --- meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg b/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg index 08c1f7a76..bcfdb4c0c 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg @@ -60,3 +60,5 @@ CONFIG_UNIX_DIAG=m CONFIG_NETFILTER_XT_MATCH_COMMENT=m CONFIG_NETLINK_DIAG=m CONFIG_MACVLAN=y +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y From 15ef826cb205cc9727f4c7f8ffcd2ffcb591ac56 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Tue, 22 Apr 2025 12:32:19 +0200 Subject: [PATCH 12/39] linux-virtualization: add more defconfig options for docker Enable CONFIG_BPF_SYSCALL and CONFIG_CGROUP_BPF when using docker, as it is needed for a correct network interoperability. Some kernels may have it enabled by default, but others not, so just enable it for any platform. https://onedigi.atlassian.net/browse/DEL-9592 Signed-off-by: Isaac Hermida --- meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg b/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg index bcfdb4c0c..686f2a30f 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey/docker_conf.cfg @@ -62,3 +62,5 @@ CONFIG_NETLINK_DIAG=m CONFIG_MACVLAN=y CONFIG_BTRFS_FS=y CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_BPF_SYSCALL=y +CONFIG_CGROUP_BPF=y From 1dd83ed1658dfea89b7b1e2eeb5c293bfd808269 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Tue, 22 Apr 2025 16:00:41 +0200 Subject: [PATCH 13/39] x-linux-ai: update support for new X-LINUX-AI v6.0.1 release This commit introduces the necessary changes in the Digi Embedded Yocto layer to support the X-LINUX-AI v6.0.1 software package from the meta-st-x-linux-ai layer. The update removes support that is now provided directly by the ST layer in this new version and adapts existing recipes to align with the updated mechanisms for AI application integration. These changes ensure compatibility with platforms that feature hardware acceleration (NPU), as well as those that rely solely on CPU-based inference. Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/layer.conf | 5 +- ...6.0.0.bbappend => stai-mpu_6.0.1.bbappend} | 0 ...tion-remove-weston-user-check-from-l.patch | 18 +++-- ...-remove-weston-user-check-from-launc.patch | 18 +++-- ...remove-weston-user-check-from-launch.patch | 20 +++--- .../resources/application-resources.bbappend | 7 +- ...-add-support-to-STM32MP255-processor.patch | 62 ---------------- ...-support-for-web-camera-with-STM32MP.patch | 70 +++++++++++++++++++ ...-support-for-web-camera-with-STM32MP.patch | 68 ------------------ ...main_isp-fix-support-for-web-camera.patch} | 0 ..._isp-fix-support-for-CSI-DCMIPP-cam.patch} | 0 ...ation-remove-weston-user-check-from-.patch | 16 +++-- .../packagegroup-dey-x-linux-ai.bb | 30 ++++---- 13 files changed, 135 insertions(+), 179 deletions(-) rename meta-digi-dey/dynamic-layers/x-linux-ai/recipes-frameworks/stai-mpu/{stai-mpu_6.0.0.bbappend => stai-mpu_6.0.1.bbappend} (100%) delete mode 100644 meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-add-support-to-STM32MP255-processor.patch create mode 100644 meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch delete mode 100644 meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0002-config_board-fix-support-for-web-camera-with-STM32MP.patch rename meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/{0003-setup_camera_main_isp-fix-support-for-web-camera.patch => 0002-setup_camera_main_isp-fix-support-for-web-camera.patch} (100%) rename meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/{0004-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch => 0003-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch} (100%) diff --git a/meta-digi-arm/conf/layer.conf b/meta-digi-arm/conf/layer.conf index 49a615cc7..d0991aeb1 100644 --- a/meta-digi-arm/conf/layer.conf +++ b/meta-digi-arm/conf/layer.conf @@ -53,8 +53,9 @@ BBMASK += " \ # Tweak x-linux-ai dependencies to use ST's machine learning packages LAYERDEPENDS_x-linux-ai:remove = "st-openstlinux" BBMASK += " \ - meta-st-x-linux-ai/recipes-st/images/st-image-ai-userfs.bb \ - meta-st-x-linux-ai/recipes-st/images/st-image-ai.bb \ + meta-st-x-linux-ai/recipes-st/images/st-image-ai-npu-userfs.bb \ + meta-st-x-linux-ai/recipes-st/images/st-image-ai-npu.bb \ + meta-st-x-linux-ai/recipes-st/images/st-image-ai-cpu.bb \ " # Digi's General and Open Source license agreements diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-frameworks/stai-mpu/stai-mpu_6.0.0.bbappend b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-frameworks/stai-mpu/stai-mpu_6.0.1.bbappend similarity index 100% rename from meta-digi-dey/dynamic-layers/x-linux-ai/recipes-frameworks/stai-mpu/stai-mpu_6.0.0.bbappend rename to meta-digi-dey/dynamic-layers/x-linux-ai/recipes-frameworks/stai-mpu/stai-mpu_6.0.1.bbappend diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/image-classification/files/patches/0001-image-classification-remove-weston-user-check-from-l.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/image-classification/files/patches/0001-image-classification-remove-weston-user-check-from-l.patch index 883b27d94..07953017a 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/image-classification/files/patches/0001-image-classification-remove-weston-user-check-from-l.patch +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/image-classification/files/patches/0001-image-classification-remove-weston-user-check-from-l.patch @@ -10,17 +10,20 @@ Signed-off-by: David Escalona 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/stai-mpu/launch_python_image_classification.sh b/stai-mpu/launch_python_image_classification.sh -index ac5efb5..ab0ed4b 100755 +index 3cb5259..afbedf8 100755 --- a/stai-mpu/launch_python_image_classification.sh +++ b/stai-mpu/launch_python_image_classification.sh -@@ -7,15 +7,9 @@ +@@ -5,18 +5,12 @@ + # + # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + CONFIG=$(find /usr/local/x-linux-ai -name "config_board_*.sh") + source $CONFIG cmd="python3 /usr/local/x-linux-ai/image-classification/stai_mpu_image_classification.py -m /usr/local/x-linux-ai/image-classification/models/$IMAGE_CLASSIFICATION_MODEL -l /usr/local/x-linux-ai/image-classification/models/$IMAGE_CLASSIFICATION_LABEL.txt --framerate $DFPS --frame_width $DWIDTH --frame_height $DHEIGHT $OPTIONS" -if [ "$weston_user" != "root" ]; then @@ -31,17 +34,20 @@ index ac5efb5..ab0ed4b 100755 -fi +$cmd diff --git a/stai-mpu/launch_python_image_classification_testdata.sh b/stai-mpu/launch_python_image_classification_testdata.sh -index 31ac124..a35f615 100755 +index 25388cd..9d68e90 100755 --- a/stai-mpu/launch_python_image_classification_testdata.sh +++ b/stai-mpu/launch_python_image_classification_testdata.sh -@@ -7,15 +7,9 @@ +@@ -5,18 +5,12 @@ + # + # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + CONFIG=$(find /usr/local/x-linux-ai -name "config_board_*.sh") + source $CONFIG cmd="python3 /usr/local/x-linux-ai/image-classification/stai_mpu_image_classification.py -m /usr/local/x-linux-ai/image-classification/models/$IMAGE_CLASSIFICATION_MODEL -l /usr/local/x-linux-ai/image-classification/models/$IMAGE_CLASSIFICATION_LABEL.txt -i /usr/local/x-linux-ai/image-classification/models/$IMAGE_CLASSIF_DATA" -if [ "$weston_user" != "root" ]; then diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/object-detection/files/patches/0001-object-detection-remove-weston-user-check-from-launc.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/object-detection/files/patches/0001-object-detection-remove-weston-user-check-from-launc.patch index d29b3d9e1..aa3a07f8f 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/object-detection/files/patches/0001-object-detection-remove-weston-user-check-from-launc.patch +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/object-detection/files/patches/0001-object-detection-remove-weston-user-check-from-launc.patch @@ -9,17 +9,20 @@ Signed-off-by: David Escalona 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/stai-mpu/launch_python_object_detection.sh b/stai-mpu/launch_python_object_detection.sh -index d0332dc..54f5e54 100755 +index e460fb3..b595f7f 100755 --- a/stai-mpu/launch_python_object_detection.sh +++ b/stai-mpu/launch_python_object_detection.sh -@@ -7,15 +7,9 @@ +@@ -5,18 +5,12 @@ + # + # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai_mpu wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + CONFIG=$(find /usr/local/x-linux-ai -name "config_board_*.sh") + source $CONFIG cmd="/usr/local/x-linux-ai/object-detection/stai_mpu_object_detection.py -m /usr/local/x-linux-ai/object-detection/models/$OBJ_DETEC_MODEL -l /usr/local/x-linux-ai/object-detection/models/$OBJ_DETEC_MODEL_LABEL.txt --framerate $DFPS --frame_width $DWIDTH --frame_height $DHEIGHT $OPTIONS" -if [ "$weston_user" != "root" ]; then @@ -30,17 +33,20 @@ index d0332dc..54f5e54 100755 -fi +$cmd diff --git a/stai-mpu/launch_python_object_detection_testdata.sh b/stai-mpu/launch_python_object_detection_testdata.sh -index c8e4d5b..bd9a9b9 100755 +index 7c5a6e5..ca547a4 100755 --- a/stai-mpu/launch_python_object_detection_testdata.sh +++ b/stai-mpu/launch_python_object_detection_testdata.sh -@@ -7,15 +7,9 @@ +@@ -5,18 +5,12 @@ + # + # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai_mpu wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + CONFIG=$(find /usr/local/x-linux-ai -name "config_board_*.sh") + source $CONFIG cmd="/usr/local/x-linux-ai/object-detection/stai_mpu_object_detection.py -m /usr/local/x-linux-ai/object-detection/models/$OBJ_DETEC_MODEL -l /usr/local/x-linux-ai/object-detection/models/$OBJ_DETEC_MODEL_LABEL.txt -i /usr/local/x-linux-ai/object-detection/models/$OBJ_DETECT_DATA" -if [ "$weston_user" != "root" ]; then diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/pose-estimation/files/patches/0001-pose-estimation-remove-weston-user-check-from-launch.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/pose-estimation/files/patches/0001-pose-estimation-remove-weston-user-check-from-launch.patch index 22b00d4fa..27b56f469 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/pose-estimation/files/patches/0001-pose-estimation-remove-weston-user-check-from-launch.patch +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/pose-estimation/files/patches/0001-pose-estimation-remove-weston-user-check-from-launch.patch @@ -4,12 +4,12 @@ Subject: [PATCH 1/3] pose-estimation: remove weston user check from launch Signed-off-by: David Escalona --- - stai-mpu/launch_python_pose_estimation.sh | 8 +------- - stai-mpu/launch_python_pose_estimation_testdata.sh | 8 +------- + .../files/stai-mpu/launch_python_pose_estimation.sh | 8 +------- + .../stai-mpu/launch_python_pose_estimation_testdata.sh | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/stai-mpu/launch_python_pose_estimation.sh b/stai-mpu/launch_python_pose_estimation.sh -index a317b58..7c41246 100644 +index 61952cf..6c8b5b8 100644 --- a/stai-mpu/launch_python_pose_estimation.sh +++ b/stai-mpu/launch_python_pose_estimation.sh @@ -5,17 +5,11 @@ @@ -17,13 +17,13 @@ index a317b58..7c41246 100644 # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. - + -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + source /usr/local/x-linux-ai/resources/config_board_npu.sh cmd="python3 /usr/local/x-linux-ai/pose-estimation/stai_mpu_pose_estimation.py -m /usr/local/x-linux-ai/pose-estimation/models/$POSE_ESTIMATION_MODEL --framerate $DFPS --frame_width $DWIDTH --frame_height $DHEIGHT $OPTIONS" - + -if [ "$weston_user" != "root" ]; then - echo "user : "$weston_user - script -qc "su -l $weston_user -c '$cmd'" @@ -33,7 +33,7 @@ index a317b58..7c41246 100644 \ No newline at end of file +$cmd diff --git a/stai-mpu/launch_python_pose_estimation_testdata.sh b/stai-mpu/launch_python_pose_estimation_testdata.sh -index 9992666..cc2f0b6 100644 +index 6ba035b..9a4448e 100644 --- a/stai-mpu/launch_python_pose_estimation_testdata.sh +++ b/stai-mpu/launch_python_pose_estimation_testdata.sh @@ -5,17 +5,11 @@ @@ -41,13 +41,13 @@ index 9992666..cc2f0b6 100644 # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. - + -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + source /usr/local/x-linux-ai/resources/config_board_npu.sh cmd="python3 /usr/local/x-linux-ai/pose-estimation/stai_mpu_pose_estimation.py -m /usr/local/x-linux-ai/pose-estimation/models/$POSE_ESTIMATION_MODEL -i /usr/local/x-linux-ai/pose-estimation/models/$POSE_ESTIMATION_DATA" - + -if [ "$weston_user" != "root" ]; then - echo "user : "$weston_user - script -qc "su -l $weston_user -c '$cmd'" diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend index 4db3150ba..bdc044640 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend @@ -3,8 +3,7 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI += " \ - file://patches/0001-config_board-add-support-to-STM32MP255-processor.patch \ - file://patches/0002-config_board-fix-support-for-web-camera-with-STM32MP.patch \ - file://patches/0003-setup_camera_main_isp-fix-support-for-web-camera.patch \ - file://patches/0004-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch \ + file://patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch \ + file://patches/0002-setup_camera_main_isp-fix-support-for-web-camera.patch \ + file://patches/0003-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch \ " diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-add-support-to-STM32MP255-processor.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-add-support-to-STM32MP255-processor.patch deleted file mode 100644 index 90b0e5724..000000000 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-add-support-to-STM32MP255-processor.patch +++ /dev/null @@ -1,62 +0,0 @@ -From: Arturo Buzarra -Date: Wed, 11 Dec 2024 17:20:22 +0100 -Subject: [PATCH] config_board: add support to STM32MP255 processor - -Signed-off-by: Arturo Buzarra ---- - .../files/resources-files/config_board.sh | 32 +++++++++++++++++++ - 1 file changed, 32 insertions(+) - -diff --git a/resources-files/config_board.sh b/resources-files/config_board.sh -index a9ce24b..a37981a 100644 ---- a/resources-files/config_board.sh -+++ b/resources-files/config_board.sh -@@ -13,6 +13,7 @@ STM32MP2="stm32mp2" - STM32MP135="stm32mp135" - STM32MP157="stm32mp157" - STM32MP157FEV1="stm32mp157f-ev1st" -+STM32MP255="stm32mp255" - STM32MP257="stm32mp257" - STM32MP257FEV1="stm32mp257f-ev1st" - -@@ -79,6 +80,37 @@ if [[ "$COMPATIBLE" == *"$STM32MP157"* ]]; then - fi - fi - -+if [[ "$COMPATIBLE" == *"$STM32MP255"* ]]; then -+ SEMANTIC_SEGMENTATION_MODEL="deeplabv3/deeplabv3_257_int8_per_tensor$NN_EXT" -+ SEMANTIC_SEGMENTATION_LABEL="deeplabv3/labels_pascalvoc" -+ SEMANTIC_SEGMENTATION_DATA="deeplabv3/testdata/" -+ POSE_ESTIMATION_DATA="yolov8n_pose/testdata/" -+ POSE_ESTIMATION_MODEL="yolov8n_pose/yolov8n_256_quant_pt_uf_pose_coco-st$NN_EXT" -+ FACE_DETECTION_MODEL="blazeface/blazeface_128x128_quant$NN_EXT" -+ FACE_DETECTION_DATA="blazeface/testdata/" -+ FACE_RECO_MODEL="facenet/facenet512_160x160_quant$NN_EXT" -+ FACE_RECO_DATA="facenet/testdata/" -+ FACE_DATABASE="database/" -+ # STM32MP255 settings -+ MACHINE=$STM32MP255 -+ DWIDTH=640 -+ DHEIGHT=480 -+ DFPS=30 -+ COMPUTE_ENGINE="--npu" -+ IMAGE_CLASSIFICATION_MODEL="mobilenet/mobilenet_v2_1.0_224_int8_per_tensor$NN_EXT" -+ IMAGE_CLASSIFICATION_LABEL="mobilenet/labels_imagenet_2012" -+ IMAGE_CLASSIF_DATA="mobilenet/testdata/" -+ if [[ "$NN_EXT" == ".nb" ]]; then -+ OBJ_DETEC_MODEL="coco_ssd_mobilenet/ssd_mobilenet_v2_fpnlite_10_256_int8_per_tensor$NN_EXT" -+ OBJ_DETEC_MODEL_LABEL="coco_ssd_mobilenet/labels_coco_dataset_80" -+ else -+ OBJ_DETEC_MODEL="coco_ssd_mobilenet/ssd_mobilenet_v2_fpnlite_10_256_int8$NN_EXT" -+ OBJ_DETEC_MODEL_LABEL="coco_ssd_mobilenet/labels_coco_dataset_80" -+ fi -+ OBJ_DETECT_DATA="coco_ssd_mobilenet/testdata/" -+ OPTIONS="--dual_camera_pipeline" -+fi -+ - if [[ "$COMPATIBLE" == *"$STM32MP257"* ]]; then - SEMANTIC_SEGMENTATION_MODEL="deeplabv3/deeplabv3_257_int8_per_tensor$NN_EXT" - SEMANTIC_SEGMENTATION_LABEL="deeplabv3/labels_pascalvoc" --- -2.47.1 - diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch new file mode 100644 index 000000000..8dea1d258 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch @@ -0,0 +1,70 @@ +From: Arturo Buzarra +Date: Tue, 22 Apr 2025 14:01:12 +0200 +Subject: [PATCH] config_board: fix support for web camera with STM32MP255 + processor + +This commit disables the dual camera pipeline support for USB cameras, as it is +exclusive to cameras using the DCMIPP peripheral. + +Signed-off-by: Arturo Buzarra +--- + .../files/resources-files/config_board_npu.sh | 29 ++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/resources-files/config_board_npu.sh b/resources-files/config_board_npu.sh +index c89b5ca..38dda50 100644 +--- a/resources-files/config_board_npu.sh ++++ b/resources-files/config_board_npu.sh +@@ -16,10 +16,28 @@ STM32MP251="stm32mp251" + STM32MP235="stm32mp235" + STM32MP233="stm32mp233" + STM32MP231="stm32mp231" + STM32MP2_NPU="stm32mp2x with GPU/NPU" + ++function is_dcmipp_present() { ++ DCMIPP_SENSOR="NOTFOUND" ++ # ov5640 or imx335 camera can be present on csi connector ++ for video in $(find /sys/class/video4linux -name "video*" -type l); ++ do ++ if [ "$(cat $video/name)" = "dcmipp_main_capture" ]; then ++ for sub in $(find /sys/class/video4linux -name "v4l-subdev*" -type l); ++ do ++ subdev_name=$(tr -d '\0' < $sub/name | awk '{print $1}') ++ if [ "$subdev_name" = "ov5640" ] || [ "$subdev_name" = "imx335" ]; then ++ DCMIPP_SENSOR=$subdev_name ++ break; ++ fi ++ done ++ fi ++ done ++} ++ + if [[ "$COMPATIBLE" == *"$STM32MP253"* ]] || [[ "$COMPATIBLE" == *"$STM32MP251"* ]] || [[ "$COMPATIBLE" == *"$STM32MP233"* ]] || [[ "$COMPATIBLE" == *"$STM32MP231"* ]]; then + if [[ "$SOFTWARE" == "AI_NPU" ]]; then + echo "Software X-LINUX-AI installed is not compatible with the board, please install X-LINUX-AI CPU version for plateform without hardware accelerator" + exit 1 + fi +@@ -54,11 +72,20 @@ if [[ "$COMPATIBLE" == *"$STM32MP257"* ]] || [[ "$COMPATIBLE" == *"$STM32MP255"* + MACHINE=$STM32MP2_NPU + DWIDTH=760 + DHEIGHT=568 + DFPS=30 + COMPUTE_ENGINE="--npu" +- OPTIONS="--dual_camera_pipeline" ++ ++ is_dcmipp_present ++ if [ "$DCMIPP_SENSOR" != "NOTFOUND" ]; then ++ # DCMIPP camera ++ OPTIONS="--dual_camera_pipeline" ++ else ++ # Web camera ++ OPTIONS="" ++ fi ++ + IMAGE_CLASSIFICATION_MODEL="mobilenet/mobilenet_v2_1.0_224_int8_per_tensor$NN_EXT" + IMAGE_CLASSIFICATION_LABEL="mobilenet/labels_imagenet_2012" + IMAGE_CLASSIF_DATA="mobilenet/testdata/" + if [[ "$NN_EXT" == ".nb" ]]; then + OBJ_DETEC_MODEL="coco_ssd_mobilenet/ssd_mobilenet_v2_fpnlite_10_256_int8_per_tensor$NN_EXT" +-- +2.34.1 diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0002-config_board-fix-support-for-web-camera-with-STM32MP.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0002-config_board-fix-support-for-web-camera-with-STM32MP.patch deleted file mode 100644 index f101e2873..000000000 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0002-config_board-fix-support-for-web-camera-with-STM32MP.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: Arturo Buzarra -Date: Tue, 21 Jan 2025 12:04:52 +0100 -Subject: [PATCH] config_board: fix support for web camera with STM32MP255 - processor - -This commit disables the dual camera pipeline support for USB cameras, as it is -exclusive to cameras using the DCMIPP peripheral. - -Signed-off-by: Arturo Buzarra ---- - .../files/resources-files/config_board.sh | 27 +++++++++++++++++++ - 1 file changed, 27 insertions(+) - -diff --git a/resources-files/config_board.sh b/resources-files/config_board.sh -index a623086..e7e8b00 100644 ---- a/resources-files/config_board.sh -+++ b/resources-files/config_board.sh -@@ -15,10 +15,28 @@ STM32MP157="stm32mp157" - STM32MP157FEV1="stm32mp157f-ev1st" - STM32MP255="stm32mp255" - STM32MP257="stm32mp257" - STM32MP257FEV1="stm32mp257f-ev1st" - -+function is_dcmipp_present() { -+ DCMIPP_SENSOR="NOTFOUND" -+ # ov5640 or imx335 camera can be present on csi connector -+ for video in $(find /sys/class/video4linux -name "video*" -type l); -+ do -+ if [ "$(cat $video/name)" = "dcmipp_main_capture" ]; then -+ for sub in $(find /sys/class/video4linux -name "v4l-subdev*" -type l); -+ do -+ subdev_name=$(tr -d '\0' < $sub/name | awk '{print $1}') -+ if [ "$subdev_name" = "ov5640" ] || [ "$subdev_name" = "imx335" ]; then -+ DCMIPP_SENSOR=$subdev_name -+ break; -+ fi -+ done -+ fi -+ done -+} -+ - if [[ "$FRAMEWORK" == "nbg" ]]; then - NN_EXT=".nb" - elif [[ "$FRAMEWORK" == "tflite" ]]; then - NN_EXT=".tflite" - elif [[ "$FRAMEWORK" == "onnx" ]]; then -@@ -107,10 +125,19 @@ if [[ "$COMPATIBLE" == *"$STM32MP255"* ]]; then - OBJ_DETEC_MODEL="coco_ssd_mobilenet/ssd_mobilenet_v2_fpnlite_10_256_int8$NN_EXT" - OBJ_DETEC_MODEL_LABEL="coco_ssd_mobilenet/labels_coco_dataset_80" - fi - OBJ_DETECT_DATA="coco_ssd_mobilenet/testdata/" - OPTIONS="--dual_camera_pipeline" -+ -+ is_dcmipp_present -+ if [ "$DCMIPP_SENSOR" != "NOTFOUND" ]; then -+ # DCMIPP camera -+ OPTIONS="--dual_camera_pipeline" -+ else -+ # Web camera -+ OPTIONS="" -+ fi - fi - - if [[ "$COMPATIBLE" == *"$STM32MP257"* ]]; then - SEMANTIC_SEGMENTATION_MODEL="deeplabv3/deeplabv3_257_int8_per_tensor$NN_EXT" - SEMANTIC_SEGMENTATION_LABEL="deeplabv3/labels_pascalvoc" --- -2.34.1 diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0003-setup_camera_main_isp-fix-support-for-web-camera.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0002-setup_camera_main_isp-fix-support-for-web-camera.patch similarity index 100% rename from meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0003-setup_camera_main_isp-fix-support-for-web-camera.patch rename to meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0002-setup_camera_main_isp-fix-support-for-web-camera.patch diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0004-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0003-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch similarity index 100% rename from meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0004-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch rename to meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0003-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/semantic-segmentation/files/patches/0001-semantic-segmentation-remove-weston-user-check-from-.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/semantic-segmentation/files/patches/0001-semantic-segmentation-remove-weston-user-check-from-.patch index b94de0be2..8910c2339 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/semantic-segmentation/files/patches/0001-semantic-segmentation-remove-weston-user-check-from-.patch +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/semantic-segmentation/files/patches/0001-semantic-segmentation-remove-weston-user-check-from-.patch @@ -10,17 +10,19 @@ Signed-off-by: David Escalona 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/stai-mpu/launch_python_semantic_segmentation.sh b/stai-mpu/launch_python_semantic_segmentation.sh -index e3c3a6c..e008572 100755 +index a1c2479..94cd540 100755 --- a/stai-mpu/launch_python_semantic_segmentation.sh +++ b/stai-mpu/launch_python_semantic_segmentation.sh -@@ -7,15 +7,9 @@ +@@ -5,17 +5,11 @@ + # + # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai-mpu wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + source /usr/local/x-linux-ai/resources/config_board_npu.sh cmd="python3 /usr/local/x-linux-ai/semantic-segmentation/stai_mpu_semantic_segmentation.py -m /usr/local/x-linux-ai/semantic-segmentation/models/$SEMANTIC_SEGMENTATION_MODEL -l /usr/local/x-linux-ai/semantic-segmentation/models/$SEMANTIC_SEGMENTATION_LABEL.txt --framerate $DFPS --frame_width $DWIDTH --frame_height $DHEIGHT $OPTIONS" -if [ "$weston_user" != "root" ]; then @@ -31,17 +33,19 @@ index e3c3a6c..e008572 100755 -fi +$cmd diff --git a/stai-mpu/launch_python_semantic_segmentation_testdata.sh b/stai-mpu/launch_python_semantic_segmentation_testdata.sh -index 2d3db4b..5375e0f 100755 +index bf3ac5e..a02de8f 100755 --- a/stai-mpu/launch_python_semantic_segmentation_testdata.sh +++ b/stai-mpu/launch_python_semantic_segmentation_testdata.sh -@@ -7,15 +7,9 @@ +@@ -5,17 +5,11 @@ + # + # This software is licensed under terms that can be found in the LICENSE file # in the root directory of this software component. # If no LICENSE file comes with this software, it is provided AS-IS. -weston_user=$(ps aux | grep '/usr/bin/weston '|grep -v 'grep'|awk '{print $1}') FRAMEWORK=$1 echo "stai-mpu wrapper used : "$FRAMEWORK - source /usr/local/x-linux-ai/resources/config_board.sh + source /usr/local/x-linux-ai/resources/config_board_npu.sh cmd="python3 /usr/local/x-linux-ai/semantic-segmentation/stai_mpu_semantic_segmentation.py -m /usr/local/x-linux-ai/semantic-segmentation/models/$SEMANTIC_SEGMENTATION_MODEL -l /usr/local/x-linux-ai/semantic-segmentation/models/$SEMANTIC_SEGMENTATION_LABEL.txt -i /usr/local/x-linux-ai/semantic-segmentation/models/$SEMANTIC_SEGMENTATION_DATA" -if [ "$weston_user" != "root" ]; then diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-st/packagegroups/packagegroup-dey-x-linux-ai.bb b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-st/packagegroups/packagegroup-dey-x-linux-ai.bb index dd096fe12..a7ce9a6d4 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-st/packagegroups/packagegroup-dey-x-linux-ai.bb +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-st/packagegroups/packagegroup-dey-x-linux-ai.bb @@ -11,30 +11,30 @@ COMMON_PACKAGES = " \ " TFLITE_PACKAGES = " \ - stai-mpu-image-classification-cpp-tfl \ - stai-mpu-image-classification-python-tfl \ - stai-mpu-object-detection-cpp-tfl \ - stai-mpu-object-detection-python-tfl \ + stai-mpu-image-classification-cpp-tfl-npu \ + stai-mpu-image-classification-python-tfl-npu \ + stai-mpu-object-detection-cpp-tfl-npu \ + stai-mpu-object-detection-python-tfl-npu \ tflite-vx-delegate-example \ " ONNX_PACKAGES = " \ onnxruntime-tools \ - stai-mpu-image-classification-cpp-ort \ - stai-mpu-image-classification-python-ort \ - stai-mpu-object-detection-python-ort \ - stai-mpu-object-detection-cpp-ort \ + stai-mpu-image-classification-cpp-ort-npu \ + stai-mpu-image-classification-python-ort-npu \ + stai-mpu-object-detection-python-ort-npu \ + stai-mpu-object-detection-cpp-ort-npu \ " OPENVX_PACKAGES = " \ nbg-benchmark \ - stai-mpu-image-classification-cpp-ovx \ - stai-mpu-image-classification-python-ovx \ - stai-mpu-object-detection-cpp-ovx \ - stai-mpu-object-detection-python-ovx \ - stai-mpu-semantic-segmentation-python-ovx \ - stai-mpu-pose-estimation-python-ovx \ - stai-mpu-face-recognition-cpp-ovx \ + stai-mpu-image-classification-cpp-ovx-npu \ + stai-mpu-image-classification-python-ovx-npu \ + stai-mpu-object-detection-cpp-ovx-npu \ + stai-mpu-object-detection-python-ovx-npu \ + stai-mpu-semantic-segmentation-python-ovx-npu \ + stai-mpu-pose-estimation-python-ovx-npu \ + stai-mpu-face-recognition-cpp-ovx-npu \ " RDEPENDS:${PN} += " \ From 7614d4ab39abdca4961618ee6158202ecc53c291 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Fri, 9 May 2025 14:16:01 +0200 Subject: [PATCH 14/39] swupdate: fix regression in 2024.12.1 This version of swupdate has a bug that happens if the root of sw-description is redirected via a link, which is the case is some of our sw-description templates (such as the one we use for file updates). Backport a fix from v2025.05. https://onedigi.atlassian.net/browse/ADK4A-1957 Signed-off-by: Gabriel Valcazar (cherry picked from commit 5bdd59a6473257bbbe69f2b81fd70ba4fa26dcfd) --- ...t_find_path-properly-return-to-free-.patch | 170 ++++++++++++++++++ .../swupdate/swupdate_2024.12.bbappend | 5 + 2 files changed, 175 insertions(+) create mode 100644 meta-digi-dey/recipes-support/swupdate/swupdate/0004-Revert-parser-set_find_path-properly-return-to-free-.patch create mode 100644 meta-digi-dey/recipes-support/swupdate/swupdate_2024.12.bbappend diff --git a/meta-digi-dey/recipes-support/swupdate/swupdate/0004-Revert-parser-set_find_path-properly-return-to-free-.patch b/meta-digi-dey/recipes-support/swupdate/swupdate/0004-Revert-parser-set_find_path-properly-return-to-free-.patch new file mode 100644 index 000000000..222684302 --- /dev/null +++ b/meta-digi-dey/recipes-support/swupdate/swupdate/0004-Revert-parser-set_find_path-properly-return-to-free-.patch @@ -0,0 +1,170 @@ +From: Stefano Babic +Date: Fri, 28 Feb 2025 17:19:05 +0100 +Subject: [PATCH] Revert "parser: set_find_path: properly return to-free string + array" + +This reverts commit cefc5ae2e43c78697281c529a29b61c4bdb3c037. + +The commit causes a regression bug by following links in the +sw-description if the root of the tree is redirected via a link. An +example to create the issue is: + + stable : { + copy1: { + partitions: ( + .......... + ); + images: ( + .......... + ); + scripts: ( + .......... + ); + }; + + copy2: { + ref = "#./copy1"; + }; + }; + +An update with -e stable,copy1 works, while -e stable,copy2 does not +find anything to be installed because the link is not followed. + +Signed-off-by: Stefano Babic +Reported-by: Konstantin Shabalovski +Reported-by: Florian Amstutz +(cherry picked from commit 4294da8b720ac9bbf25001fddb0ee63d39207dc1) + +parser: fix issues related to commit cefc5ae2 + +The commit above fixes a memory leak, but on a structure that was mainly +used for debugging and points to used node array in case of links. If +this structure is freed, links recursion does not work anymore. + +After reverting the commit above, remove the structure causing the +regression bug because it is not really used. + +Signed-off-by: Stefano Babic +(cherry picked from commit 93fd657cd2fd4a396cd903bfcd576f6475d1dcdf) +--- + core/parsing_library.c | 4 ++-- + corelib/parsing_library_libconfig.c | 4 +--- + corelib/parsing_library_libjson.c | 4 +--- + include/parselib.h | 2 +- + parser/parser.c | 4 +--- + 5 files changed, 6 insertions(+), 12 deletions(-) + +diff --git a/core/parsing_library.c b/core/parsing_library.c +index 1dc0c42a..a1fcfdd8 100644 +--- a/core/parsing_library.c ++++ b/core/parsing_library.c +@@ -239,7 +239,7 @@ void get_hash_value(parsertype p, void *elem, unsigned char *hash) + ascii_to_hash(hash, hash_ascii); + } + +-bool set_find_path(const char **nodes, const char *newpath, char ***tmp) ++bool set_find_path(const char **nodes, const char *newpath) + { + char **paths; + unsigned int count; +@@ -329,7 +329,7 @@ bool set_find_path(const char **nodes, const char *newpath, char ***tmp) + } + + free(ref); +- *tmp = paths; ++ free(paths); + + return true; + } +diff --git a/corelib/parsing_library_libconfig.c b/corelib/parsing_library_libconfig.c +index 35ae903e..bcb72a11 100644 +--- a/corelib/parsing_library_libconfig.c ++++ b/corelib/parsing_library_libconfig.c +@@ -182,7 +182,6 @@ void *find_root_libconfig(config_t *cfg, const char **nodes, unsigned int depth) + config_setting_t *elem; + char *root; + const char *ref; +- char **tmp = NULL; + + /* + * check for deadlock links, block recursion +@@ -204,12 +203,11 @@ void *find_root_libconfig(config_t *cfg, const char **nodes, unsigned int depth) + if (elem && config_setting_is_group(elem) == CONFIG_TRUE) { + ref = get_field_string_libconfig(elem, "ref"); + if (ref) { +- if (!set_find_path(nodes, ref, &tmp)) { ++ if (!set_find_path(nodes, ref)) { + free(root); + return NULL; + } + elem = find_root_libconfig(cfg, nodes, depth); +- free_string_array(tmp); + } + } + +diff --git a/corelib/parsing_library_libjson.c b/corelib/parsing_library_libjson.c +index e78ed000..99b60f55 100644 +--- a/corelib/parsing_library_libjson.c ++++ b/corelib/parsing_library_libjson.c +@@ -220,7 +220,6 @@ void *find_root_json(json_object *root, const char **nodes, unsigned int depth) + { + json_object *node; + enum json_type type; +- char **tmp = NULL; + const char *str; + + /* +@@ -237,10 +236,9 @@ void *find_root_json(json_object *root, const char **nodes, unsigned int depth) + if (type == json_type_object || type == json_type_array) { + str = get_field_string_json(node, "ref"); + if (str) { +- if (!set_find_path(nodes, str, &tmp)) ++ if (!set_find_path(nodes, str)) + return NULL; + node = find_root_json(root, nodes, depth); +- free_string_array(tmp); + } + } + } +diff --git a/include/parselib.h b/include/parselib.h +index 2837dc33..40e98f68 100644 +--- a/include/parselib.h ++++ b/include/parselib.h +@@ -63,7 +63,7 @@ void get_hash_value(parsertype p, void *elem, unsigned char *hash); + void check_field_string(const char *src, char *dst, const size_t max_len); + void *find_root(parsertype p, void *root, const char **nodes); + void *get_node(parsertype p, void *root, const char **nodes); +-bool set_find_path(const char **nodes, const char *newpath, char ***tmp); ++bool set_find_path(const char **nodes, const char *newpath); + + static inline void get_field_bool(parsertype p, void *e, const char *path, bool *dest) + { +diff --git a/parser/parser.c b/parser/parser.c +index 99c3396e..a8f4a691 100644 +--- a/parser/parser.c ++++ b/parser/parser.c +@@ -132,7 +132,6 @@ static int parser_follow_link(parsertype p, void *cfg, void *elem, + { + const char *ref; + void *link; +- char **tmp = NULL; /* to store temporary link path */ + const char **linknodes; + int result = 0; + +@@ -144,7 +143,7 @@ static int parser_follow_link(parsertype p, void *cfg, void *elem, + for (int j = 0; j < count_string_array(nodes); j++) { + linknodes[j] = nodes[j]; + } +- if (!set_find_path(linknodes, ref, &tmp)) { ++ if (!set_find_path(linknodes, ref)) { + free(linknodes); + return -1; + } +@@ -153,7 +152,6 @@ static int parser_follow_link(parsertype p, void *cfg, void *elem, + if (link) { + result = fn(p, cfg, link, linknodes, swcfg, L); + } +- free_string_array(tmp); + free(linknodes); + return result; + } diff --git a/meta-digi-dey/recipes-support/swupdate/swupdate_2024.12.bbappend b/meta-digi-dey/recipes-support/swupdate/swupdate_2024.12.bbappend new file mode 100644 index 000000000..a7f99ed9e --- /dev/null +++ b/meta-digi-dey/recipes-support/swupdate/swupdate_2024.12.bbappend @@ -0,0 +1,5 @@ +# Copyright (C) 2025, Digi International Inc. + +SRC_URI += " \ + file://0004-Revert-parser-set_find_path-properly-return-to-free-.patch \ +" From b154154a7ee87470ffaf887fa8b0f1ee270a62af Mon Sep 17 00:00:00 2001 From: Tatiana Leon Date: Mon, 19 May 2025 10:54:11 +0200 Subject: [PATCH 15/39] cccs: switch daemon init method to inittab for sysvinit-based systems This commit updates the CCCS recipe to support `inittab`-based daemon initialization for platforms using `sysvinit`, such as ConnectCore 6UL. By switching to `inittab` for daemon control in these systems, we guarantee automatic relaunch of `cccsd` if it exits unexpectedly (this functionality was previously only available with `systemd`) This improves reliability and aligns behavior across `systemd` and non-`systemd` platforms. See Confluence question "Why won't CC6-UL rejoin DRM after a planned DRM outage?" (https://onedigi.atlassian.net/wiki/plugins/servlet/ac/com.atlassian.confluence.plugins.confluence-questions/globalQuestionsViewer?ac.com.atlassian.confluence.plugins.confluence-questions.path=/questions/236710985798) Signed-off-by: Tatiana Leon (cherry picked from commit 5c667641a88437795fea3097ca5cf76c22de47c1) --- meta-digi-dey/recipes-digi/cccs/cccs_git.bb | 17 +++++++++++------ meta-digi-dey/recipes-digi/cccs/files/cccsd.tab | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 meta-digi-dey/recipes-digi/cccs/files/cccsd.tab diff --git a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb index 694d2ac1c..dc62ab2a0 100644 --- a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb +++ b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb @@ -22,6 +22,7 @@ SRC_URI = " \ ${CC_GIT_URI};branch=${SRCBRANCH} \ file://cccsd-init \ file://cccsd.service \ + file://cccsd.tab \ file://cccs-gs-demo-init \ file://cccs-gs-demo.service \ " @@ -50,16 +51,21 @@ inherit pkgconfig systemd update-rc.d do_install() { oe_runmake DESTDIR=${D} install + install -d ${D}${sysconfdir}/init.d/ + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then # Install systemd unit files install -d ${D}${systemd_unitdir}/system install -m 0644 ${WORKDIR}/cccsd.service ${D}${systemd_unitdir}/system/ install -m 0644 ${WORKDIR}/cccs-gs-demo.service ${D}${systemd_unitdir}/system/ + + install -m 755 ${WORKDIR}/cccsd-init ${D}${sysconfdir}/cccsd + ln -sf /etc/cccsd ${D}${sysconfdir}/init.d/cccsd + else + install -d ${D}${sysconfdir}/inittab.d/ + install -m 755 ${WORKDIR}/cccsd.tab ${D}${sysconfdir}/inittab.d/cccsd.tab fi - install -d ${D}${sysconfdir}/init.d/ - install -m 755 ${WORKDIR}/cccsd-init ${D}${sysconfdir}/cccsd - ln -sf /etc/cccsd ${D}${sysconfdir}/init.d/cccsd install -m 755 ${WORKDIR}/cccs-gs-demo-init ${D}${sysconfdir}/cccs-gs-demo ln -sf /etc/cccs-gs-demo ${D}${sysconfdir}/init.d/cccs-gs-demo @@ -100,9 +106,7 @@ REMOVE_POSTINST_RPN = "${PN}-daemon" inherit ${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", "remove-pkg-postinst-ontarget", \ oe.utils.ifelse(d.getVar("CCCS_CONF_PATH"), "remove-pkg-postinst-ontarget", ""), d)} -INITSCRIPT_PACKAGES = "${PN}-daemon ${PN}-gs-demo" -INITSCRIPT_NAME:${PN}-daemon = "cccsd" -INITSCRIPT_PARAMS:${PN}-daemon = "defaults 19 81" +INITSCRIPT_PACKAGES = "${PN}-gs-demo" INITSCRIPT_NAME:${PN}-gs-demo = "cccs-gs-demo" INITSCRIPT_PARAMS:${PN}-gs-demo = "defaults 81 19" @@ -127,6 +131,7 @@ FILES:${PN}-daemon = " \ ${sysconfdir}/cccsd \ ${sysconfdir}/cccs.conf \ ${sysconfdir}/init.d/cccsd \ + ${sysconfdir}/inittab/cccsd.tab \ " FILES:${PN}-gs-demo = " \ diff --git a/meta-digi-dey/recipes-digi/cccs/files/cccsd.tab b/meta-digi-dey/recipes-digi/cccs/files/cccsd.tab new file mode 100644 index 000000000..db9558e19 --- /dev/null +++ b/meta-digi-dey/recipes-digi/cccs/files/cccsd.tab @@ -0,0 +1 @@ +cccs:2345:respawn:/usr/bin/cccsd -d > /dev/null 2>&1 From 1038192b11bd641feeff8cda7362818ad5bb9803 Mon Sep 17 00:00:00 2001 From: Isaac Hermida Date: Tue, 1 Jul 2025 17:07:24 +0200 Subject: [PATCH 16/39] linux-dey: tsn: fix tsn kernel support fix missing option to include the required kernel options for tsn support. That support was added in commit 37f5db42ac6d for kernel 6.1, but it was missed for kernel 6.6. Add the support to include the required fragment, regardless the kernel version. While on it, update the tsn config to match kernel 6.6. Signed-off-by: Isaac Hermida --- meta-digi-arm/recipes-kernel/linux/linux-dey.inc | 1 + .../recipes-kernel/linux/linux-dey/tsn_conf.cfg | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc index fdcbb9e77..3ad4a7016 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc @@ -13,6 +13,7 @@ SRC_URI = " \ ${LINUX_GIT_URI};branch=${SRCBRANCH} \ ${@oe.utils.conditional('KERNEL_DEFCONFIG', '', 'file://defconfig', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'virtualization', 'file://docker_conf.cfg', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'tsn', 'file://tsn_conf.cfg', '', d)} \ ${@oe.utils.vartrue('TRUSTFENCE_FILE_BASED_ENCRYPT', 'file://fscrypt.cfg', '', d)} \ " S = "${WORKDIR}/git" diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey/tsn_conf.cfg b/meta-digi-arm/recipes-kernel/linux/linux-dey/tsn_conf.cfg index cdc21fd88..dc1c2cb9f 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey/tsn_conf.cfg +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey/tsn_conf.cfg @@ -10,18 +10,24 @@ . consult the product documentation. . .......................................................................... +CONFIG_TSN=y CONFIG_NET_SCH_MULTIQ=m -CONFIG_NET_SCH_CBS=m +CONFIG_NET_SCH_CBS=y CONFIG_NET_SCH_ETF=m -CONFIG_NET_SCH_TAPRIO=m -CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_TAPRIO=y +CONFIG_NET_SCH_MQPRIO=y CONFIG_NET_SCH_INGRESS=m CONFIG_NET_CLS_BASIC=m CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_FLOWER=m CONFIG_NET_CLS_ACT=y CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y CONFIG_NET_ACT_MIRRED=m -CONFIG_NET_ACT_GATE=m CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_GATE=m +CONFIG_FSL_ENETC=y CONFIG_FSL_ENETC_QOS=y +CONFIG_IFB=m From 01107a1d87a4806f8bb276ab11422057a5bb905b Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Fri, 27 Jun 2025 21:21:06 +0200 Subject: [PATCH 17/39] uuu installer: remove -t option and determine by filename The `-t` option to program images with TrustFence didn't make much sense because the install script is dynamically generated at build-time with the name of the boot artifacts containing "signed/encrypted" on their filenames. This commit: - Removes `-t` option to simplify the script. - Determines if programming a signed/encrypted bootloader by looking at the bootloader filename. - For NXP platforms, reworks the function that updates the bootloader to properly program only-signed bootloaders (currently wrongly using `trustfence update`) Signed-off-by: Hector Palacios --- .../ccimx6qpsbc/install_linux_fw_uuu.sh | 46 ++++++++++------- .../ccimx6sbc/install_linux_fw_uuu.sh | 48 +++++++++++------- .../ccimx6ul/install_linux_fw_uuu.sh | 21 +++++--- .../ccimx8m/install_linux_fw_uuu.sh | 48 +++++++++++------- .../ccimx8x/install_linux_fw_uuu.sh | 48 +++++++++++------- .../u-boot-dey/ccimx9/install_linux_fw_uuu.sh | 50 +++++++++++-------- .../u-boot-dey/ccmp1/install_linux_fw_uuu.sh | 11 ++-- .../u-boot-dey/ccmp2/install_linux_fw_uuu.sh | 13 +++-- 8 files changed, 175 insertions(+), 110 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh index dc411dae2..20859dc0d 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2021-2024 by Digi International Inc. +# Copyright (C) 2021-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ show_usage() echo " -k Update includes dek file." echo " (implies -t)." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install Trustfence artifacts." echo " -u U-Boot filename." echo " Auto-determined by variant if not provided." exit 2 @@ -61,23 +60,27 @@ part_update() echo "=====================================================================================" echo "\033[0m" - if [ "${TRUSTFENCE}" = "true" ] && [ "${1}" = "bootloader" ]; then - uuu fb: download -f "${2}" - if [ -n "${DEK_FILE}" ]; then - uuu fb: ucmd setenv uboot_size \${filesize} - uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} - uuu fb: download -f "${3}" - uuu fb: ucmd setenv dek_size \${filesize} - uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + if [ "${1}" = "bootloader" ]; then + if [ "${ENCRYPTED}" = "true" ]; then + uuu fb: download -f "${2}" + if [ -n "${DEK_FILE}" ]; then + # Encrypted bootloader + dek + uuu fb: ucmd setenv uboot_size \${filesize} + uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} + uuu fb: download -f "${3}" + uuu fb: ucmd setenv dek_size \${filesize} + uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + else + # Encrypted bootloader (re-use existing dek) + uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + fi else - uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + # Non-encrypted bootloader (can be signed or not) + uuu fb: flash "${1}" "${2}" fi else - if [ "${1}" = "bootloader" ]; then - uuu fb: flash "${1}" "${2}" - else - uuu fb: flash -raw2sparse "${1}" "${2}" - fi + # Non-bootloader image + uuu fb: flash -raw2sparse "${1}" "${2}" fi } @@ -91,7 +94,7 @@ echo "############################################################" # -i # -u # -k -while getopts ':bdhi:k:ntu:' c +while getopts ':bdhi:k:nu:' c do if [ "${c}" = ":" ]; then c="${OPTARG}" @@ -107,7 +110,6 @@ do i) IMAGE_NAME=${OPTARG} ;; k) DEK_FILE=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; u) INSTALL_UBOOT_FILENAME=${OPTARG} ;; esac done @@ -161,6 +163,14 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then fi fi +# Determine if bootloader is signed and/or encrypted +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed"; then + SIGNED=true +fi +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then + ENCRYPTED=true +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh index a818ad60b..0301f8a87 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2021-2024 by Digi International Inc. +# Copyright (C) 2021-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ show_usage() echo " -k Update includes dek file." echo " (implies -t)." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install TrustFence artifacts." echo " -u U-Boot filename." echo " Auto-determined by variant if not provided." exit 2 @@ -61,23 +60,27 @@ part_update() echo "=====================================================================================" echo "\033[0m" - if [ "${TRUSTFENCE}" = "true" ] && [ "${1}" = "bootloader" ]; then - uuu fb: download -f "${2}" - if [ -n "${DEK_FILE}" ]; then - uuu fb: ucmd setenv uboot_size \${filesize} - uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} - uuu fb: download -f "${3}" - uuu fb: ucmd setenv dek_size \${filesize} - uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + if [ "${1}" = "bootloader" ]; then + if [ "${ENCRYPTED}" = "true" ]; then + uuu fb: download -f "${2}" + if [ -n "${DEK_FILE}" ]; then + # Encrypted bootloader + dek + uuu fb: ucmd setenv uboot_size \${filesize} + uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} + uuu fb: download -f "${3}" + uuu fb: ucmd setenv dek_size \${filesize} + uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + else + # Encrypted bootloader (re-use existing dek) + uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + fi else - uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + # Non-encrypted bootloader (can be signed or not) + uuu fb: flash "${1}" "${2}" fi else - if [ "${1}" = "bootloader" ]; then - uuu fb: flash "${1}" "${2}" - else - uuu fb: flash -raw2sparse "${1}" "${2}" - fi + # Non-bootloader image + uuu fb: flash -raw2sparse "${1}" "${2}" fi } @@ -91,7 +94,7 @@ echo "############################################################" # -i # -u # -k -while getopts ':bdhi:k:ntu:' c +while getopts ':bdhi:k:nu:' c do if [ "${c}" = ":" ]; then c="${OPTARG}" @@ -105,9 +108,8 @@ do d) INSTALL_DUALBOOT=true && BOOTCOUNT=true ;; h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; - k) DEK_FILE=${OPTARG} && TRUSTFENCE=true ;; + k) DEK_FILE=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; u) INSTALL_UBOOT_FILENAME=${OPTARG} ;; esac done @@ -180,6 +182,14 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then fi fi +# Determine if bootloader is signed and/or encrypted +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed"; then + SIGNED=true +fi +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then + ENCRYPTED=true +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh index b3c3f862d..9bfe9888d 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2020-2024 by Digi International Inc. +# Copyright (C) 2020-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ show_usage() echo " -k Update includes dek file." echo " (implies -t)." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install TrustFence artifacts." echo " -u U-Boot filename." echo " Auto-determined by variant if not provided." exit 2 @@ -74,17 +73,20 @@ part_update() ERASE="-e" fi uuu fb: download -f "${2}" - if [ "${TRUSTFENCE}" = "true" ] && [ "${1}" = "uboot" ]; then + if [ "${1}" = "bootloader" ] && [ "${ENCRYPTED}" = "true" ]; then if [ -n "${DEK_FILE}" ]; then + # Encrypted bootloader + dek uuu fb: ucmd setenv uboot_size \${filesize} uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} uuu fb: download -f "${4}" uuu fb: ucmd setenv dek_size \${filesize} uuu "fb[-t ${3}]:" ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} else + # Encrypted bootloader (re-use existing dek) uuu "fb[-t ${3}]:" ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} fi else + # Rest of images (including non-encrypted bootloader) uuu "fb[-t ${3}]:" ucmd update "${1}" ram \${fastboot_buffer} \${fastboot_bytes} ${ERASE} fi } @@ -99,7 +101,7 @@ echo "############################################################" # -i # -u # -k -while getopts ':bdhi:k:ntu:' c +while getopts ':bdhi:k:nu:' c do if [ "${c}" = ":" ]; then c="${OPTARG}" @@ -113,9 +115,8 @@ do d) INSTALL_DUALBOOT=true && BOOTCOUNT=true ;; h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; - k) DEK_FILE=${OPTARG} && TRUSTFENCE=true ;; + k) DEK_FILE=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; u) INSTALL_UBOOT_FILENAME=${OPTARG} ;; esac done @@ -184,6 +185,14 @@ if [ -z "${INSTALL_UBOOT_FILENAME}" ]; then fi fi +# Determine if bootloader is signed and/or encrypted +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed"; then + SIGNED=true +fi +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then + ENCRYPTED=true +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh index f6fbdcd81..bf19752de 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2020-2024 by Digi International Inc. +# Copyright (C) 2020-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ show_usage() echo " -k Update includes dek file." echo " (implies -t)." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install TrustFence artifacts." echo " -u U-Boot filename." echo " Auto-determined by variant if not provided." exit 2 @@ -61,23 +60,27 @@ part_update() echo "=====================================================================================" echo "\033[0m" - if [ "${TRUSTFENCE}" = "true" ] && [ "${1}" = "bootloader" ]; then - uuu fb: download -f "${2}" - if [ -n "${DEK_FILE}" ]; then - uuu fb: ucmd setenv uboot_size \${filesize} - uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} - uuu fb: download -f "${3}" - uuu fb: ucmd setenv dek_size \${filesize} - uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + if [ "${1}" = "bootloader" ]; then + if [ "${ENCRYPTED}" = "true" ]; then + uuu fb: download -f "${2}" + if [ -n "${DEK_FILE}" ]; then + # Encrypted bootloader + dek + uuu fb: ucmd setenv uboot_size \${filesize} + uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} + uuu fb: download -f "${3}" + uuu fb: ucmd setenv dek_size \${filesize} + uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + else + # Encrypted bootloader (re-use existing dek) + uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + fi else - uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + # Non-encrypted bootloader (can be signed or not) + uuu fb: flash "${1}" "${2}" fi else - if [ "${1}" = "bootloader" ]; then - uuu fb: flash "${1}" "${2}" - else - uuu fb: flash -raw2sparse "${1}" "${2}" - fi + # Non-bootloader image + uuu fb: flash -raw2sparse "${1}" "${2}" fi } @@ -91,7 +94,7 @@ echo "############################################################" # -i # -u # -k -while getopts ':bdhi:k:ntu:' c +while getopts ':bdhi:k:nu:' c do if [ "${c}" = ":" ]; then c="${OPTARG}" @@ -105,9 +108,8 @@ do d) INSTALL_DUALBOOT=true && BOOTCOUNT=true ;; h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; - k) DEK_FILE=${OPTARG} && TRUSTFENCE=true ;; + k) DEK_FILE=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; u) INSTALL_UBOOT_FILENAME=${OPTARG} ;; esac done @@ -132,6 +134,14 @@ if [ -z "${INSTALL_UBOOT_FILENAME}" ]; then INSTALL_UBOOT_FILENAME="imx-boot-##SIGNED##-##MACHINE##.bin" fi +# Determine if bootloader is signed and/or encrypted +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed"; then + SIGNED=true +fi +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then + ENCRYPTED=true +fi + # Determine linux, recovery, and rootfs image filenames to update if [ -z "${IMAGE_NAME}" ]; then IMAGE_NAME="##DEFAULT_IMAGE_NAME##" diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh index 88b258932..cf7a797e8 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2020-2024 by Digi International Inc. +# Copyright (C) 2020-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -42,7 +42,6 @@ show_usage() echo " -k Update includes dek file." echo " (implies -t)." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install TrustFence artifacts." echo " -u U-Boot filename." echo " Auto-determined by variant if not provided." exit 2 @@ -61,23 +60,27 @@ part_update() echo "=====================================================================================" echo "\033[0m" - if [ "${TRUSTFENCE}" = "true" ] && [ "${1}" = "bootloader" ]; then - uuu fb: download -f "${2}" - if [ -n "${DEK_FILE}" ]; then - uuu fb: ucmd setenv uboot_size \${filesize} - uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} - uuu fb: download -f "${3}" - uuu fb: ucmd setenv dek_size \${filesize} - uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + if [ "${1}" = "bootloader" ]; then + if [ "${ENCRYPTED}" = "true" ]; then + uuu fb: download -f "${2}" + if [ -n "${DEK_FILE}" ]; then + # Encrypted bootloader + dek + uuu fb: ucmd setenv uboot_size \${filesize} + uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} + uuu fb: download -f "${3}" + uuu fb: ucmd setenv dek_size \${filesize} + uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + else + # Encrypted bootloader (re-use existing dek) + uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + fi else - uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + # Non-encrypted bootloader (can be signed or not) + uuu fb: flash "${1}" "${2}" fi else - if [ "${1}" = "bootloader" ]; then - uuu fb: flash "${1}" "${2}" - else - uuu fb: flash -raw2sparse "${1}" "${2}" - fi + # Non-bootloader image + uuu fb: flash -raw2sparse "${1}" "${2}" fi } @@ -91,7 +94,7 @@ echo "############################################################" # -i # -u # -k -while getopts ':bdhi:k:ntu:' c +while getopts ':bdhi:k:nu:' c do if [ "${c}" = ":" ]; then c="${OPTARG}" @@ -105,9 +108,8 @@ do d) INSTALL_DUALBOOT=true && BOOTCOUNT=true ;; h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; - k) DEK_FILE=${OPTARG} && TRUSTFENCE=true ;; + k) DEK_FILE=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; u) INSTALL_UBOOT_FILENAME=${OPTARG} ;; esac done @@ -136,6 +138,14 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then INSTALL_UBOOT_FILENAME="imx-boot-##SIGNED##-##MACHINE##-${soc_rev}.bin" fi +# Determine if bootloader is signed and/or encrypted +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed"; then + SIGNED=true +fi +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then + ENCRYPTED=true +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh index bcf92552b..c8aad3f3e 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2020-2024 by Digi International Inc. +# Copyright (C) 2020-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ show_usage() echo " (implies -t)." echo " -n No wait. Skips 10 seconds delay to stop script." echo " -u U-Boot filename." - echo " -t Install TrustFence artifacts." echo " Auto-determined by variant if not provided." echo " -U Update redundant bootloader partition." @@ -63,23 +62,27 @@ part_update() echo "=====================================================================================" echo "\033[0m" - if [ "${TRUSTFENCE}" = "true" ] && [ "${1}" = "bootloader" ]; then - uuu fb: download -f "${2}" - if [ -n "${DEK_FILE}" ]; then - uuu fb: ucmd setenv uboot_size \${filesize} - uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} - uuu fb: download -f "${3}" - uuu fb: ucmd setenv dek_size \${filesize} - uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + if [ "${1}" = "bootloader" ] || [ "${1}" = "bootloader_redundant" ]; then + if [ "${ENCRYPTED}" = "true" ]; then + uuu fb: download -f "${2}" + if [ -n "${DEK_FILE}" ]; then + # Encrypted bootloader + dek + uuu fb: ucmd setenv uboot_size \${filesize} + uuu fb: ucmd setenv fastboot_buffer \${initrd_addr} + uuu fb: download -f "${3}" + uuu fb: ucmd setenv dek_size \${filesize} + uuu fb: ucmd trustfence update ram \${loadaddr} \${uboot_size} \${initrd_addr} \${dek_size} + else + # Encrypted bootloader (re-use existing dek) + uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + fi else - uuu fb: ucmd trustfence update ram \${fastboot_buffer} \${fastboot_bytes} + # Non-encrypted bootloader (can be signed or not) + uuu fb: flash "${1}" "${2}" fi else - if [ "${1}" = "bootloader" ] || [ "${1}" = "bootloader_redundant" ]; then - uuu fb: flash "${1}" "${2}" - else - uuu fb: flash -raw2sparse "${1}" "${2}" - fi + # Non-bootloader image + uuu fb: flash -raw2sparse "${1}" "${2}" fi } @@ -93,7 +96,7 @@ echo "############################################################" # -i # -u # -k -while getopts ':bdhti:nu:Uk:' c +while getopts ':bdhi:nu:Uk:' c do if [ "${c}" = ":" ]; then c="${OPTARG}" @@ -107,10 +110,9 @@ do d) INSTALL_DUALBOOT=true && BOOTCOUNT=true ;; h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; - k) DEK_FILE=${OPTARG} && TRUSTFENCE=true ;; + k) DEK_FILE=${OPTARG} ;; n) NOWAIT=true ;; u) INSTALL_UBOOT_FILENAME=${OPTARG} ;; - t) TRUSTFENCE=true ;; U) INSTALL_REDUNDANT_UBOOT=true ;; esac done @@ -145,6 +147,14 @@ if [ -z "${INSTALL_UBOOT_FILENAME}" ]; then INSTALL_UBOOT_FILENAME="imx-boot-##SIGNED##-##MACHINE##${SOCREV}.bin" fi +# Determine if bootloader is signed and/or encrypted +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed"; then + SIGNED=true +fi +if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then + ENCRYPTED=true +fi + # remove redirect uuu fb: ucmd setenv stdout serial @@ -344,7 +354,7 @@ if [ -f ${COMPRESSED_ROOTFS_IMAGE} ] && [ -f ${INSTALL_ROOTFS_FILENAME} ]; then rm -f "${INSTALL_ROOTFS_FILENAME}" fi # Set the dboot_kernel_var to fitimage if Trustfence is enabled -if [ "${TRUSTFENCE}" = "true" ] || echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "signed" -e "encrypted"; then +if [ "${SIGNED}" = "true" || "${ENCRYPTED}" = "true" ]; then uuu fb: ucmd setenv dboot_kernel_var fitimage fi diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_uuu.sh index 4df790ea4..a2ab168dc 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_uuu.sh @@ -50,7 +50,6 @@ show_usage() echo " 'dey-image-webkit', 'core-image-base'..." echo " Defaults to '##DEFAULT_IMAGE_NAME##' if not provided." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install TrustFence artifacts." exit 2 } @@ -84,7 +83,7 @@ echo "############################################################" # -b, -d, -n (booleans) # -f # -i -while getopts 'a:bdf:hi:nt' c +while getopts 'a:bdf:hi:n' c do case $c in a) INSTALL_ATF_FILENAME=${OPTARG} ;; @@ -94,7 +93,6 @@ do h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; esac done @@ -137,6 +135,11 @@ if [ -z "${INSTALL_FIP_FILENAME}" ]; then INSTALL_FIP_FILENAME="fip-##MACHINE##-${module_ram}-##BOOTSCHEME_DEFAULT##-nand##SIGNED##.bin" fi +# Determine if boot artifacts are signed +if echo "$INSTALL_FIP_FILENAME" | grep -q -e "Signed"; then + SIGNED=true +fi + # Determine linux, recovery, and rootfs image filenames to update if [ -z "${IMAGE_NAME}" ]; then IMAGE_NAME="##DEFAULT_IMAGE_NAME##" @@ -320,7 +323,7 @@ else fi # Set the dboot_kernel_var to fitimage if Trustfence is enabled -if [ "${TRUSTFENCE}" = "true" ] || echo "${INSTALL_FIP_FILENAME}" | grep -q -e "Signed"; then +if [ "${SIGNED}" = "true" ]; then uuu fb: ucmd setenv dboot_kernel_var fitimage uuu fb: ucmd saveenv fi diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_uuu.sh index dc2c4b0f0..046fb0557 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_uuu.sh @@ -1,7 +1,7 @@ #!/bin/sh #=============================================================================== # -# Copyright (C) 2024 by Digi International Inc. +# Copyright (C) 2024, 2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it @@ -44,7 +44,6 @@ show_usage() echo " 'dey-image-webkit', 'core-image-base'..." echo " Defaults to '##DEFAULT_IMAGE_NAME##' if not provided." echo " -n No wait. Skips 10 seconds delay to stop script." - echo " -t Install TrustFence artifacts." exit 2 } @@ -80,7 +79,7 @@ echo "############################################################" # -b, -d, -n (booleans) # -f # -i -while getopts 'a:bdf:hi:nt' c +while getopts 'a:bdf:hi:n' c do case $c in a) INSTALL_ATF_FILENAME=${OPTARG} ;; @@ -90,7 +89,6 @@ do h) show_usage ;; i) IMAGE_NAME=${OPTARG} ;; n) NOWAIT=true ;; - t) TRUSTFENCE=true ;; esac done @@ -117,6 +115,11 @@ if [ -z "${INSTALL_FIP_FILENAME}" ]; then INSTALL_FIP_FILENAME="fip-##MACHINE##-optee-emmc##SIGNED##.bin" fi +# Determine if boot artifacts are signed +if echo "$INSTALL_FIP_FILENAME" | grep -q -e "Signed"; then + SIGNED=true +fi + # remove redirect uuu fb: ucmd setenv stdout serial @@ -306,7 +309,7 @@ else fi # Set the dboot_kernel_var to fitimage if Trustfence is enabled -if [ "${TRUSTFENCE}" = "true" ] || echo "${INSTALL_FIP_FILENAME}" | grep -q -e "Signed"; then +if [ "${SIGNED}" = "true" ]; then uuu fb: ucmd setenv dboot_kernel_var fitimage uuu fb: ucmd saveenv fi From 9672b2a80addcfeb81c4d83ebf29758512579739 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Mon, 30 Jun 2025 17:34:29 +0200 Subject: [PATCH 18/39] installer: uuu: prevent installing encrypted uboot on open device Programming an encrypted bootloader can only be done after the secure keys have been programed on the OTP bits, and the device has been closed. Programming on an open device would result in a non-secure configuration or a non-bootable device after the close operation. Create functions to detect the current TrustFence status and exit the install script if the device is open and the artifacts are encrypted. Signed-off-by: Hector Palacios https://onedigi.atlassian.net/browse/DEL-9699 --- .../ccimx6qpsbc/install_linux_fw_uuu.sh | 30 ++++++++++++++++ .../ccimx6sbc/install_linux_fw_uuu.sh | 30 ++++++++++++++++ .../ccimx6ul/install_linux_fw_uuu.sh | 30 ++++++++++++++++ .../ccimx8m/install_linux_fw_uuu.sh | 36 +++++++++++++++++-- .../ccimx8x/install_linux_fw_uuu.sh | 30 ++++++++++++++++ .../u-boot-dey/ccimx9/install_linux_fw_uuu.sh | 32 ++++++++++++++++- 6 files changed, 184 insertions(+), 4 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh index 20859dc0d..bdbe07e51 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh @@ -27,6 +27,15 @@ getenv() uuu -v fb: ucmd printenv "${1}" | sed -ne "s,^${1}=,,g;T;p" } +# Grep for string in command output +# Params: +# 1. Command +# 2. String to grep +grep_string() +{ + uuu -v fb: ucmd ${1} | grep "${2}" +} + show_usage() { echo "Usage: $0 [options]" @@ -171,6 +180,27 @@ if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then ENCRYPTED=true fi +if [ "${ENCRYPTED}" = "true" ]; then + tf_status=$(grep_string "trustfence status" "Secure boot:") + if echo "${tf_status}" | grep -q -e "OPEN"; then + echo "\033[93m" + echo "WARNING!" + echo "You are trying to program encrypted images but the device status is OPEN." + echo "An OPEN device requires manual procedure for installing an encrypted bootloader," + echo "programming the secure keys, and closing the device." + echo "Continuing would result in a non-secure setup or a non-bootable device after the" + echo "close operation." + echo "" + echo "Check the online documentation for manual steps at:" + echo "https://docs.digi.com/resources/documentation/digidocs/embedded/trustfence_home.html" + echo "" + echo "You can run this installer to program encrypted artifacts when the device has been closed." + echo "\033[0m" + echo "Exiting." + exit 1 + fi +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh index 0301f8a87..56c34d53f 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh @@ -27,6 +27,15 @@ getenv() uuu -v fb: ucmd printenv "${1}" | sed -ne "s,^${1}=,,g;T;p" } +# Grep for string in command output +# Params: +# 1. Command +# 2. String to grep +grep_string() +{ + uuu -v fb: ucmd ${1} | grep "${2}" +} + show_usage() { echo "Usage: $0 [options]" @@ -190,6 +199,27 @@ if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then ENCRYPTED=true fi +if [ "${ENCRYPTED}" = "true" ]; then + tf_status=$(grep_string "trustfence status" "Secure boot:") + if echo "${tf_status}" | grep -q -e "OPEN"; then + echo "\033[93m" + echo "WARNING!" + echo "You are trying to program encrypted images but the device status is OPEN." + echo "An OPEN device requires manual procedure for installing an encrypted bootloader," + echo "programming the secure keys, and closing the device." + echo "Continuing would result in a non-secure setup or a non-bootable device after the" + echo "close operation." + echo "" + echo "Check the online documentation for manual steps at:" + echo "https://docs.digi.com/resources/documentation/digidocs/embedded/trustfence_home.html" + echo "" + echo "You can run this installer to program encrypted artifacts when the device has been closed." + echo "\033[0m" + echo "Exiting." + exit 1 + fi +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh index 9bfe9888d..552bb4a9a 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh @@ -27,6 +27,15 @@ getenv() uuu -v fb: ucmd printenv "${1}" | sed -ne "s,^${1}=,,g;T;p" } +# Grep for string in command output +# Params: +# 1. Command +# 2. String to grep +grep_string() +{ + uuu -v fb: ucmd ${1} | grep "${2}" +} + show_usage() { echo "Usage: $0 [options]" @@ -193,6 +202,27 @@ if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then ENCRYPTED=true fi +if [ "${ENCRYPTED}" = "true" ]; then + tf_status=$(grep_string "trustfence status" "Secure boot:") + if echo "${tf_status}" | grep -q -e "OPEN"; then + echo "\033[93m" + echo "WARNING!" + echo "You are trying to program encrypted images but the device status is OPEN." + echo "An OPEN device requires manual procedure for installing an encrypted bootloader," + echo "programming the secure keys, and closing the device." + echo "Continuing would result in a non-secure setup or a non-bootable device after the" + echo "close operation." + echo "" + echo "Check the online documentation for manual steps at:" + echo "https://docs.digi.com/resources/documentation/digidocs/embedded/trustfence_home.html" + echo "" + echo "You can run this installer to program encrypted artifacts when the device has been closed." + echo "\033[0m" + echo "Exiting." + exit 1 + fi +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh index bf19752de..41234a8d2 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_uuu.sh @@ -27,6 +27,15 @@ getenv() uuu -v fb: ucmd printenv "${1}" | sed -ne "s,^${1}=,,g;T;p" } +# Grep for string in command output +# Params: +# 1. Command +# 2. String to grep +grep_string() +{ + uuu -v fb: ucmd ${1} | grep "${2}" +} + show_usage() { echo "Usage: $0 [options]" @@ -123,9 +132,6 @@ if [ "${dualboot}" = "yes" ]; then DUALBOOT=true; fi -# remove redirect -uuu fb: ucmd setenv stdout serial - echo "" echo "Determining image files to use..." @@ -142,6 +148,30 @@ if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then ENCRYPTED=true fi +if [ "${ENCRYPTED}" = "true" ]; then + tf_status=$(grep_string "trustfence status" "Secure boot:") + if echo "${tf_status}" | grep -q -e "OPEN"; then + echo "\033[93m" + echo "WARNING!" + echo "You are trying to program encrypted images but the device status is OPEN." + echo "An OPEN device requires manual procedure for installing an encrypted bootloader," + echo "programming the secure keys, and closing the device." + echo "Continuing would result in a non-secure setup or a non-bootable device after the" + echo "close operation." + echo "" + echo "Check the online documentation for manual steps at:" + echo "https://docs.digi.com/resources/documentation/digidocs/embedded/trustfence_home.html" + echo "" + echo "You can run this installer to program encrypted artifacts when the device has been closed." + echo "\033[0m" + echo "Exiting." + exit 1 + fi +fi + +# remove redirect +uuu fb: ucmd setenv stdout serial + # Determine linux, recovery, and rootfs image filenames to update if [ -z "${IMAGE_NAME}" ]; then IMAGE_NAME="##DEFAULT_IMAGE_NAME##" diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh index cf7a797e8..c87a4e718 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_uuu.sh @@ -27,6 +27,15 @@ getenv() uuu -v fb: ucmd printenv "${1}" | sed -ne "s,^${1}=,,g;T;p" } +# Grep for string in command output +# Params: +# 1. Command +# 2. String to grep +grep_string() +{ + uuu -v fb: ucmd ${1} | grep "${2}" +} + show_usage() { echo "Usage: $0 [options]" @@ -146,6 +155,27 @@ if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then ENCRYPTED=true fi +if [ "${ENCRYPTED}" = "true" ]; then + tf_status=$(grep_string "trustfence status" "Secure boot:") + if echo "${tf_status}" | grep -q -e "OPEN"; then + echo "\033[93m" + echo "WARNING!" + echo "You are trying to program encrypted images but the device status is OPEN." + echo "An OPEN device requires manual procedure for installing an encrypted bootloader," + echo "programming the secure keys, and closing the device." + echo "Continuing would result in a non-secure setup or a non-bootable device after the" + echo "close operation." + echo "" + echo "Check the online documentation for manual steps at:" + echo "https://docs.digi.com/resources/documentation/digidocs/embedded/trustfence_home.html" + echo "" + echo "You can run this installer to program encrypted artifacts when the device has been closed." + echo "\033[0m" + echo "Exiting." + exit 1 + fi +fi + # remove redirect uuu fb: ucmd setenv stdout serial diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh index c8aad3f3e..924469283 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_uuu.sh @@ -27,6 +27,15 @@ getenv() uuu -v fb: ucmd printenv "${1}" | sed -ne "s,^${1}=,,g;T;p" } +# Grep for string in command output +# Params: +# 1. Command +# 2. String to grep +grep_string() +{ + uuu -v fb: ucmd ${1} | grep "${2}" +} + show_usage() { echo "Usage: $0 [options]" @@ -155,6 +164,27 @@ if echo "$INSTALL_UBOOT_FILENAME" | grep -q -e "encrypted"; then ENCRYPTED=true fi +if [ "${ENCRYPTED}" = "true" ]; then + tf_status=$(grep_string "trustfence status" "Secure boot:") + if echo "${tf_status}" | grep -q -e "OPEN"; then + echo "\033[93m" + echo "WARNING!" + echo "You are trying to program encrypted images but the device status is OPEN." + echo "An OPEN device requires manual procedure for installing an encrypted bootloader," + echo "programming the secure keys, and closing the device." + echo "Continuing would result in a non-secure setup or a non-bootable device after the" + echo "close operation." + echo "" + echo "Check the online documentation for manual steps at:" + echo "https://docs.digi.com/resources/documentation/digidocs/embedded/trustfence_home.html" + echo "" + echo "You can run this installer to program encrypted artifacts when the device has been closed." + echo "\033[0m" + echo "Exiting." + exit 1 + fi +fi + # remove redirect uuu fb: ucmd setenv stdout serial @@ -354,7 +384,7 @@ if [ -f ${COMPRESSED_ROOTFS_IMAGE} ] && [ -f ${INSTALL_ROOTFS_FILENAME} ]; then rm -f "${INSTALL_ROOTFS_FILENAME}" fi # Set the dboot_kernel_var to fitimage if Trustfence is enabled -if [ "${SIGNED}" = "true" || "${ENCRYPTED}" = "true" ]; then +if [ "${SIGNED}" = "true" ] || [ "${ENCRYPTED}" = "true" ]; then uuu fb: ucmd setenv dboot_kernel_var fitimage fi From 41810d5c17e39246ebfae86893719fd7a7f14c53 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Wed, 2 Jul 2025 21:15:13 +0200 Subject: [PATCH 19/39] installers: add missing ##SIGNED## placeholder to uboot filenames This gets substituted when TrustFence is enabled to "signed/encrypted" or removed when TrustFence is disabled. Signed-off-by: Hector Palacios --- .../ccimx6qpsbc/install_linux_fw_media.txt | 8 ++++---- .../ccimx6qpsbc/install_linux_fw_uuu.sh | 8 ++++---- .../ccimx6sbc/install_linux_fw_media.txt | 16 ++++++++-------- .../u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh | 16 ++++++++-------- .../ccimx6ul/install_linux_fw_media.txt | 12 ++++++------ .../u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh | 10 +++++----- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt index 5b62ef222..597183fcc 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt @@ -10,9 +10,9 @@ BASEFILENAME=0 # Determine U-Boot file to program basing on module variant # If module_variant is unknown or not set, return error asking the user if test "${module_variant}" = "0x01" || test "${module_variant}" = "0x02"; then - setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##2GB.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##2GB.imx; elif test "${module_variant}" = "0x03"; then - setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##1GB.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##1GB.imx; fi # Use 'test -n ...' because 'test -z ...' does not work well on old versions of @@ -25,9 +25,9 @@ else echo ""; echo "1. Set variable 'INSTALL_UBOOT_FILENAME' depending on your ConnectCore 6 QuadPlus variant:"; echo " - For a QuadPlus CPU with 2GB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##2GB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##2GB.imx"; echo " - For a DualPlus CPU with 1GB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##1GB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##1GB.imx"; echo ""; echo ""; echo "2. Run the install script again."; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh index bdbe07e51..a358e6d92 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_uuu.sh @@ -142,9 +142,9 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then # If module_variant is unknown or not set, return error asking the user if [ "$module_variant" = "0x01" ] || \ [ "$module_variant" = "0x02" ]; then - INSTALL_UBOOT_FILENAME="u-boot-##MACHINE##2GB.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-##MACHINE##2GB.imx" elif [ "$module_variant" = "0x03" ]; then - INSTALL_UBOOT_FILENAME="u-boot-##MACHINE##1GB.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-##MACHINE##1GB.imx" fi # U-Boot when the checked value is empty. @@ -159,9 +159,9 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then echo "" echo "1. Set variable 'INSTALL_UBOOT_FILENAME' depending on your ConnectCore 6 QuadPlus variant:" echo " - For a QuadPlus CPU with 2GB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##2GB.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##2GB.imx" echo " - For a DualPlus CPU with 1GB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##1GB.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##1GB.imx" echo "" echo "" echo "2. Run the install script again." diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt index 6fcefb035..42c771a51 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt @@ -10,11 +10,11 @@ BASEFILENAME=0 # Determine U-Boot file to program basing on module variant # If module_variant is unknown or not set, return error asking the user if test "${module_variant}" = "0x12"; then - setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc2GB.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc2GB.imx; elif test "${module_variant}" = "0x02" || test "${module_variant}" = "0x04" || test "${module_variant}" = "0x05" || test "${module_variant}" = "0x0b" || test "${module_variant}" = "0x11" || test "${module_variant}" = "0x14" || test "${module_variant}" = "0x15" || test "${module_variant}" = "0x16"; then - setenv INSTALL_UBOOT_FILENAME u-boot-cc${soc_family}sbc.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-cc${soc_family}sbc.imx; elif test "${module_variant}" = "0x03" || test "${module_variant}" = "0x0c" || test "${module_variant}" = "0x0e" || test "${module_variant}" = "0x0f" || test "${module_variant}" = "0x13"; then - setenv INSTALL_UBOOT_FILENAME u-boot-cc${soc_family}sbc512MB.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-cc${soc_family}sbc512MB.imx; fi # Use 'test -n ...' because 'test -z ...' does not work well on old versions of @@ -27,15 +27,15 @@ else echo ""; echo "1. Set variable 'INSTALL_UBOOT_FILENAME' depending on your ConnectCore 6 variant:"; echo " - For a Quad/Dual CPU with 2GB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc2GB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc2GB.imx"; echo " - For a Quad/Dual CPU with 1GB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc.imx"; echo " - For a Quad/Dual CPU with 512MB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc512MB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc512MB.imx"; echo " - For a DualLite/Solo CPU with 1GB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6dlsbc.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6dlsbc.imx"; echo " - For a DualLite/Solo CPU with 512MB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6dlsbc512MB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6dlsbc512MB.imx"; echo ""; echo "2. Run the install script again."; echo ""; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh index 56c34d53f..1c358dd80 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_uuu.sh @@ -142,7 +142,7 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then module_variant=$(getenv "module_variant") # Determine U-Boot file to program basing on SOM's variant if [ "$module_variant" = "0x12" ]; then - INSTALL_UBOOT_FILENAME="u-boot-cc${soc_family}sbc2GB.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-cc${soc_family}sbc2GB.imx" elif [ "$module_variant" = "0x02" ] || \ [ "$module_variant" = "0x04" ] || \ [ "$module_variant" = "0x05" ] || \ @@ -151,13 +151,13 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then [ "$module_variant" = "0x14" ] || \ [ "$module_variant" = "0x15" ] || \ [ "$module_variant" = "0x16" ]; then - INSTALL_UBOOT_FILENAME="u-boot-cc${soc_family}sbc.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-cc${soc_family}sbc.imx" elif [ "$module_variant" = "0x03" ] || \ [ "$module_variant" = "0x0c" ] || \ [ "$module_variant" = "0x0e" ] || \ [ "$module_variant" = "0x0f" ] || \ [ "$module_variant" = "0x13" ]; then - INSTALL_UBOOT_FILENAME="u-boot-cc${soc_family}sbc512MB.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-cc${soc_family}sbc512MB.imx" fi fi @@ -173,15 +173,15 @@ if [ -z ${INSTALL_UBOOT_FILENAME} ]; then echo "" echo "1. Set variable 'INSTALL_UBOOT_FILENAME' depending on your ConnectCore 6 variant:" echo " - For a Quad/Dual CPU with 2GB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc2GB.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc2GB.imx" echo " - For a Quad/Dual CPU with 1GB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc.imx" echo " - For a Quad/Dual CPU with 512MB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6qsbc512MB.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6qsbc512MB.imx" echo " - For a DualLite/Solo CPU with 1GB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6dlsbc.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6dlsbc.imx" echo " - For a DualLite/Solo CPU with 512MB DDR3, run:" - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-ccimx6dlsbc512MB.imx" + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-ccimx6dlsbc512MB.imx" echo "" echo "2. Run the install script again." echo "" diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt index e18af43ff..7f6ea886b 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt @@ -10,11 +10,11 @@ BASEFILENAME=0 # Determine U-Boot file to program basing on module variant # If module_variant is unknown or not set, return error asking the user if test "${module_variant}" = "0x02" || test "${module_variant}" = "0x03" || test "${module_variant}" = "0x06" || test "${module_variant}" = "0x09"; then - setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##.imx; elif test "${module_variant}" = "0x04" || test "${module_variant}" = "0x05" || test "${module_variant}" = "0x07"; then - setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##1GB.imx; + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##1GB.imx; elif test "${module_variant}" = "0x08" || test "${module_variant}" = "0x0a"; then - setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##512MB.imx + setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##512MB.imx fi setenv INSTALL_MEDIA_INDEX ##INSTALL_MEDIA_INDEX## @@ -30,11 +30,11 @@ else echo ""; echo "1. Set variable 'INSTALL_UBOOT_FILENAME' depending on your ConnectCore 6UL variant:"; echo " - For a SOM with 1GB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##1GB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##1GB.imx"; echo " - For a SOM with 512MB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##512MB.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##512MB.imx"; echo " - For a SOM with 256MB DDR3, run:"; - echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##MACHINE##.imx"; + echo " => setenv INSTALL_UBOOT_FILENAME u-boot-##SIGNED##-##MACHINE##.imx"; echo ""; echo "2. Run the install script again."; echo ""; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh index 552bb4a9a..affc09f88 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh @@ -159,12 +159,12 @@ if [ -z "${INSTALL_UBOOT_FILENAME}" ]; then elif [ "$module_variant" = "0x04" ] || \ [ "$module_variant" = "0x05" ] || \ [ "$module_variant" = "0x07" ]; then - INSTALL_UBOOT_FILENAME="u-boot-##MACHINE##1GB.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-##MACHINE##1GB.imx" elif [ "$module_variant" = "0x02" ] || \ [ "$module_variant" = "0x03" ] || \ [ "$module_variant" = "0x06" ] || \ [ "$module_variant" = "0x09" ]; then - INSTALL_UBOOT_FILENAME="u-boot-##MACHINE##.imx" + INSTALL_UBOOT_FILENAME="u-boot-##SIGNED##-##MACHINE##.imx" fi fi @@ -180,11 +180,11 @@ if [ -z "${INSTALL_UBOOT_FILENAME}" ]; then echo "" echo "1. Add U-boot file name, depending on your ConnectCore 6UL variant, to script command line:" echo " - For a SOM with 1GB DDR3, run:" - echo " => ./install_linux_fw_uuu.sh -u u-boot-##MACHINE##1GB.imx" + echo " => ./install_linux_fw_uuu.sh -u u-boot-##SIGNED##-##MACHINE##1GB.imx" echo " - For a SOM with 512MB DDR3, run:" - echo " => ./install_linux_fw_uuu.sh -u u-boot-##MACHINE##512MB.imx" + echo " => ./install_linux_fw_uuu.sh -u u-boot-##SIGNED##-##MACHINE##512MB.imx" echo " - For a SOM with 256MB DDR3, run:" - echo " => ./install_linux_fw_uuu.sh -u u-boot-##MACHINE##.imx" + echo " => ./install_linux_fw_uuu.sh -u u-boot-##SIGNED##-##MACHINE##.imx" echo "" echo "2. Run the install script again." echo "" From 318374f11dd913bebd2fc39ba6323fe922f0d175 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Mon, 30 Jun 2025 17:33:37 +0200 Subject: [PATCH 20/39] dey-installer: add signed/encrypted bootloader to installer zip On NXP platforms, the signed/encrypted bootloader images are not included on the installer ZIP. This prevents from using the installer when TrustFence is enabled. This commit adds to the installer: - If encryption is enabled - encrypted bootloader - signed bootloader (for USB recovery boot) - If encryption is disabled - signed bootloader - If TrustFence is disabled - non-signed bootloader It also treats the ccimx6ul special, as this has a dedicated file for USB recovery boot. Signed-off-by: Hector Palacios https://onedigi.atlassian.net/browse/DEL-9698 --- meta-digi-arm/conf/machine/ccimx6qpsbc.conf | 4 +- meta-digi-arm/conf/machine/ccimx6sbc.conf | 10 ++-- meta-digi-arm/conf/machine/ccimx6ulsbc.conf | 6 +-- .../conf/machine/ccimx6ulstarter.conf | 6 +-- meta-digi-arm/conf/machine/ccimx8mm-dvk.conf | 2 +- meta-digi-arm/conf/machine/ccimx8mn-dvk.conf | 2 +- .../conf/machine/ccimx8x-sbc-express.conf | 4 +- .../conf/machine/ccimx8x-sbc-pro.conf | 4 +- meta-digi-arm/conf/machine/ccimx91-dvk.conf | 2 +- meta-digi-arm/conf/machine/ccimx93-dvk.conf | 4 +- .../imx-mkimage/imx-boot_1.0.bbappend | 4 +- .../classes/dey-image-installer.bbclass | 49 ++++++++++++++++++- 12 files changed, 73 insertions(+), 24 deletions(-) diff --git a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf index 73be213f8..243e82f50 100644 --- a/meta-digi-arm/conf/machine/ccimx6qpsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6qpsbc.conf @@ -49,8 +49,8 @@ XBEE_TTY ?= "ttymxc4" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - u-boot-ccimx6qpsbc1GB.imx \ - u-boot-ccimx6qpsbc2GB.imx \ + u-boot##SIGNED##-ccimx6qpsbc1GB.imx \ + u-boot##SIGNED##-ccimx6qpsbc2GB.imx \ " # Default overlayfs_etc mount point and type diff --git a/meta-digi-arm/conf/machine/ccimx6sbc.conf b/meta-digi-arm/conf/machine/ccimx6sbc.conf index 232a9c350..d832c16f6 100644 --- a/meta-digi-arm/conf/machine/ccimx6sbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6sbc.conf @@ -51,11 +51,11 @@ XBEE_TTY ?= "ttymxc4" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - u-boot-ccimx6dlsbc512MB.imx \ - u-boot-ccimx6dlsbc.imx \ - u-boot-ccimx6qsbc2GB.imx \ - u-boot-ccimx6qsbc512MB.imx \ - u-boot-ccimx6qsbc.imx \ + u-boot##SIGNED##-ccimx6dlsbc512MB.imx \ + u-boot##SIGNED##-ccimx6dlsbc.imx \ + u-boot##SIGNED##-ccimx6qsbc2GB.imx \ + u-boot##SIGNED##-ccimx6qsbc512MB.imx \ + u-boot##SIGNED##-ccimx6qsbc.imx \ " # Default overlayfs_etc mount point and type diff --git a/meta-digi-arm/conf/machine/ccimx6ulsbc.conf b/meta-digi-arm/conf/machine/ccimx6ulsbc.conf index 5daf216bf..7a6f98339 100644 --- a/meta-digi-arm/conf/machine/ccimx6ulsbc.conf +++ b/meta-digi-arm/conf/machine/ccimx6ulsbc.conf @@ -36,7 +36,7 @@ XBEE_TTY ?= "ttymxc1" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - u-boot-ccimx6ulsbc1GB.imx \ - u-boot-ccimx6ulsbc512MB.imx \ - u-boot-ccimx6ulsbc.imx \ + u-boot##SIGNED##-ccimx6ulsbc1GB.imx \ + u-boot##SIGNED##-ccimx6ulsbc512MB.imx \ + u-boot##SIGNED##-ccimx6ulsbc.imx \ " diff --git a/meta-digi-arm/conf/machine/ccimx6ulstarter.conf b/meta-digi-arm/conf/machine/ccimx6ulstarter.conf index 6771aafdd..c89bcb477 100644 --- a/meta-digi-arm/conf/machine/ccimx6ulstarter.conf +++ b/meta-digi-arm/conf/machine/ccimx6ulstarter.conf @@ -35,7 +35,7 @@ DEFAULT_IMAGE_NAME ?= "core-image-base" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - u-boot-ccimx6ulstarter1GB.imx \ - u-boot-ccimx6ulstarter512MB.imx \ - u-boot-ccimx6ulstarter.imx \ + u-boot##SIGNED##-ccimx6ulstarter1GB.imx \ + u-boot##SIGNED##-ccimx6ulstarter512MB.imx \ + u-boot##SIGNED##-ccimx6ulstarter.imx \ " diff --git a/meta-digi-arm/conf/machine/ccimx8mm-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mm-dvk.conf index 4f296ec50..6ea18d62d 100644 --- a/meta-digi-arm/conf/machine/ccimx8mm-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx8mm-dvk.conf @@ -55,7 +55,7 @@ XBEE_SLEEP_RQ_GPIO ?= "mca-gpio@11,gpio1@7" XBEE_TTY ?= "ttymxc3" # Boot artifacts to be copied from the deploy dir to the installer ZIP -BOOTABLE_ARTIFACTS = "imx-boot-ccimx8mm-dvk.bin" +BOOTABLE_ARTIFACTS = "imx-boot##SIGNED##-ccimx8mm-dvk.bin" # Default overlayfs_etc mount point and type OVERLAYFS_ETC_MOUNT_POINT ?= "/mnt/data" diff --git a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf index 3270b8096..5966e7529 100644 --- a/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx8mn-dvk.conf @@ -56,7 +56,7 @@ XBEE_SLEEP_RQ_GPIO ?= "mca-gpio@11,gpio1@7" XBEE_TTY ?= "ttymxc3" # Boot artifacts to be copied from the deploy dir to the installer ZIP -BOOTABLE_ARTIFACTS = "imx-boot-ccimx8mn-dvk.bin" +BOOTABLE_ARTIFACTS = "imx-boot##SIGNED##-ccimx8mn-dvk.bin" # Default overlayfs_etc mount point and type OVERLAYFS_ETC_MOUNT_POINT ?= "/mnt/data" diff --git a/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf b/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf index ffd76bad3..6dd90992a 100644 --- a/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf +++ b/meta-digi-arm/conf/machine/ccimx8x-sbc-express.conf @@ -34,6 +34,6 @@ XBEE_TTY ?= "ttyLP0" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - imx-boot-ccimx8x-sbc-express-B0.bin \ - imx-boot-ccimx8x-sbc-express-C0.bin \ + imx-boot##SIGNED##-ccimx8x-sbc-express-B0.bin \ + imx-boot##SIGNED##-ccimx8x-sbc-express-C0.bin \ " diff --git a/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf b/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf index fd55f8cb2..b7d2aa33b 100644 --- a/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf +++ b/meta-digi-arm/conf/machine/ccimx8x-sbc-pro.conf @@ -49,8 +49,8 @@ XBEE_TTY ?= "ttyMCA0" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - imx-boot-ccimx8x-sbc-pro-B0.bin \ - imx-boot-ccimx8x-sbc-pro-C0.bin \ + imx-boot##SIGNED##-ccimx8x-sbc-pro-B0.bin \ + imx-boot##SIGNED##-ccimx8x-sbc-pro-C0.bin \ " # Default overlayfs_etc mount point and type diff --git a/meta-digi-arm/conf/machine/ccimx91-dvk.conf b/meta-digi-arm/conf/machine/ccimx91-dvk.conf index 1dbc47989..f0c0ba895 100644 --- a/meta-digi-arm/conf/machine/ccimx91-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx91-dvk.conf @@ -47,7 +47,7 @@ IS_HEADLESS = "true" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - imx-boot-ccimx91-dvk.bin \ + imx-boot##SIGNED##-ccimx91-dvk.bin \ " # Add secure enclave diff --git a/meta-digi-arm/conf/machine/ccimx93-dvk.conf b/meta-digi-arm/conf/machine/ccimx93-dvk.conf index b139b792d..03de79998 100644 --- a/meta-digi-arm/conf/machine/ccimx93-dvk.conf +++ b/meta-digi-arm/conf/machine/ccimx93-dvk.conf @@ -53,6 +53,6 @@ WKS_FILE_DEPENDS:append = " imx-m33-demos" # Boot artifacts to be copied from the deploy dir to the installer ZIP BOOTABLE_ARTIFACTS = " \ - imx-boot-ccimx93-dvk.bin \ - imx-boot-ccimx93-dvk-A0.bin \ + imx-boot##SIGNED##-ccimx93-dvk.bin \ + imx-boot##SIGNED##-ccimx93-dvk-A0.bin \ " diff --git a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-bsp/imx-mkimage/imx-boot_1.0.bbappend b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-bsp/imx-mkimage/imx-boot_1.0.bbappend index 5cab81e18..f73e80ea6 100644 --- a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-bsp/imx-mkimage/imx-boot_1.0.bbappend +++ b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-bsp/imx-mkimage/imx-boot_1.0.bbappend @@ -118,7 +118,9 @@ do_compile:ccimx8x() { do_install:ccimx8x () { install -d ${D}/boot - for bin in ${BOOTABLE_ARTIFACTS}; do + # Remove ##SIGNED## placeholder from variable (signing takes place later) + BOOT_ARTIFACTS=$(echo "${BOOTABLE_ARTIFACTS}" | sed -e 's,##SIGNED##,,g') + for bin in ${BOOT_ARTIFACTS}; do for target in ${IMXBOOT_TARGETS}; do install -m 0644 ${S}/${bin}-${target} ${D}/boot/ done diff --git a/meta-digi-dey/classes/dey-image-installer.bbclass b/meta-digi-dey/classes/dey-image-installer.bbclass index c44b5417f..191a0b05a 100644 --- a/meta-digi-dey/classes/dey-image-installer.bbclass +++ b/meta-digi-dey/classes/dey-image-installer.bbclass @@ -31,6 +31,50 @@ HAS_USB_DRIVER:ccimx9 = "true" HAS_USB_DRIVER:ccmp1 = "true" HAS_USB_DRIVER:ccmp2 = "true" +BOOTLOADER_SIGNED_STRING ?= "-signed" +BOOTLOADER_ENCRYPTED_STRING ?= "-encrypted" +BOOTLOADER_SIGNED_USB_STRING ?= "-usb-signed" + +curate_bootloader_artifacts() { + for artifact in ${BOOTABLE_ARTIFACTS}; do + # NXP platforms may have a ##SIGNED## placeholder to replace + if [ "${DEY_SOC_VENDOR}" = "NXP" ] && echo "${artifact}" | grep -q -e "##SIGNED##"; then + if [ "${TRUSTFENCE_SIGN}" = "1" ]; then + if [ "${DIGI_SOM}" = "ccimx6ul" ]; then + if [ "${TRUSTFENCE_DEK_PATH}" != "0" ]; then + # Encrypted bootloader + curated_artifact=$(echo "${artifact}" | sed "s,##SIGNED##,${BOOTLOADER_ENCRYPTED_STRING},") + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${curated_artifact}" + else + # Signed, non-encrypted bootloader + curated_artifact=$(echo "${artifact}" | sed "s,##SIGNED##,${BOOTLOADER_SIGNED_STRING},") + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${curated_artifact}" + fi + # Signed, non-encrypted bootloader for USB recovery + curated_artifact=$(echo "${artifact}" | sed "s,##SIGNED##,${BOOTLOADER_SIGNED_USB_STRING},") + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${curated_artifact}" + else + if [ "${TRUSTFENCE_DEK_PATH}" != "0" ]; then + # Encrypted bootloader + curated_artifact=$(echo "${artifact}" | sed "s,##SIGNED##,${BOOTLOADER_ENCRYPTED_STRING},") + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${curated_artifact}" + fi + # Signed, non-encrypted bootloader for USB recovery + curated_artifact=$(echo "${artifact}" | sed "s,##SIGNED##,${BOOTLOADER_SIGNED_STRING},") + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${curated_artifact}" + fi + else + # Non-signed bootloader + curated_artifact=$(echo "${artifact}" | sed 's,##SIGNED##,,') + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${curated_artifact}" + fi + else + CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS} ${artifact}" + fi + done + export CURATED_BOOTABLE_ARTIFACTS="${CURATED_BOOTABLE_ARTIFACTS}" +} + generate_installer_zip () { # Get list of files to pack INSTALLER_FILELIST="${DEPLOY_DIR_IMAGE}/install_linux_fw_sd.scr \ @@ -53,7 +97,10 @@ generate_installer_zip () { INSTALLER_FILELIST="${INSTALLER_FILELIST} ${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.${ext}" fi done - for artifact in ${BOOTABLE_ARTIFACTS}; do + + # Add bootable artifacts to installer + curate_bootloader_artifacts + for artifact in ${CURATED_BOOTABLE_ARTIFACTS}; do if readlink -e "${DEPLOY_DIR_IMAGE}/${artifact}" >/dev/null; then INSTALLER_FILELIST="${INSTALLER_FILELIST} ${DEPLOY_DIR_IMAGE}/${artifact}" fi From 6997b8aa57c1e646c0aa960d4c2a09bd421dcb59 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Tue, 1 Jul 2025 23:25:23 +0200 Subject: [PATCH 21/39] README: dey-5.0-r2 release notes https://onedigi.atlassian.net/browse/DEL-9688 Signed-off-by: Arturo Buzarra --- README.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cf0406762..dee189fa6 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,37 @@ Documentation is available online at https://www.digi.com/resources/documentatio ## 5.0-r2 -TODO +* ST-based platforms + * Added support to ConnectCore MP13 + * Added support to ConnectCore MP15 + * Updated BSP + * Trusted Firmware ARM v2.8 (based on tag 'v2.10-stm32mp-r1.2' by ST) + * OP-TEE v4.0.0 (based on tag '4.0.0-stm32mp-r1.2' by ST) + * U-Boot v2023.10 (based on tag 'v2023.10-stm32mp-r1.2' by ST) + * Updated X-LINUX-AI software package (based on tag 'v6.0.1' by ST) + * Updated Wifi driver (based on 'v6.1.110-2025_0602' release from Cypress) + * Updated Wifi firmware to 'imx-scarthgap-jaculus_r1.1' release from Murata + * 2FY Wireless chip: v28.10.387.16 + * 2AE Wireless chip: v13.10.246.356 + * Added initial TrustFence support for ConnectCore MP2 + * Added Qt 6.8.4 support for ConnectCore MP1 platforms + * Added support to new countries on ConnectCore MP1 World CLM blob file + * Added real-time support +* NXP-based platforms + * Added support to ConnectCore 8M Mini + * Added support to ConnectCore 8M Nano + * Added real-time support + * Updated i.MX GStreamer stack to 1.24.7.imx +* TrustFence + * Added support to install signed/encrypted images from uuu install script +* Added support to Flutter framework + * Added new image recipe for Flutter graphical applications +* Removed Crank framework support +* Added UBI health monitor service (for NAND-based SOMs) +* BTRFS filesystem support for LXC incremental snapshots +* Created installer ZIP by default, and not *.sdcard image +* Enabled SSL/TLS support on vsftpd daemon by default +* General bug fixing and improvements ## 5.0-r1 From b581ac2a3bfb8056422bd0651819e6b253bb0dfa Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Thu, 3 Jul 2025 10:26:43 +0200 Subject: [PATCH 22/39] u-boot: rework deploy symlinks using uboot_deploy_config Use the existing uboot_deploy(_spl)_config function to clean up and rework the symlinks created in the deploy directory. Signed-off-by: Javier Viguera --- .../recipes-bsp/u-boot/u-boot-dey.inc | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc index 9276797af..dc0cc52d2 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc @@ -72,7 +72,6 @@ SIGN_UBOOT:ccimx6 = "sign_uboot" SIGN_UBOOT:ccimx6ul = "sign_uboot" do_deploy[postfuncs] += " \ - adapt_uboot_filenames \ ${@oe.utils.ifelse(d.getVar('BUILD_UBOOT_SCRIPTS') == 'true', 'build_uboot_scripts', '')} \ ${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', '${SIGN_UBOOT}', '', d)} \ " @@ -140,29 +139,31 @@ build_uboot_scripts() { fi } -adapt_uboot_filenames() { - # Remove canonical U-Boot symlinks for ${UBOOT_CONFIG} currently in the form: - # u-boot-.- - # u-boot- - # and add a more suitable symlink in the form: - # u-boot--. - if [ -n "${UBOOT_CONFIG}" ] - then - for config in ${UBOOT_MACHINE}; do - i=$(expr $i + 1); - for type in ${UBOOT_CONFIG}; do - j=$(expr $j + 1); - if [ $j -eq $i ] - then - cd ${DEPLOYDIR} - rm -f ${UBOOT_BINARY}-${type} - ln -sf ${UBOOT_BINARYNAME}-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${UBOOT_BINARYNAME}-${type}.${UBOOT_SUFFIX} - fi - done - unset j - done - unset i - fi +# +# Clean Yocto generated u-boot symlinks. +# +# Left: +# u-boot-. +# u-boot-.- (needed for imx-boot) +# u-boot-spl.bin-- (needed for imx-boot) +# +uboot_deploy_config:append() { + rm -f ${DEPLOYDIR}/${UBOOT_SYMLINK} \ + ${DEPLOYDIR}/${UBOOT_BINARY}-${type} \ + ${DEPLOYDIR}/${UBOOT_BINARY} + ln -sf ${UBOOT_BINARYNAME}-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${DEPLOYDIR}/${UBOOT_BINARYNAME}-${type}.${UBOOT_SUFFIX} +} +uboot_deploy_spl_config:append() { + rm -f ${DEPLOYDIR}/${SPL_BINARYFILE}-${type} \ + ${DEPLOYDIR}/${SPL_BINARYFILE} \ + ${DEPLOYDIR}/${SPL_SYMLINK} +} +# Further cleaning for platforms not generating imx-boot +uboot_deploy_config:append:ccimx6ul() { + rm -f ${DEPLOYDIR}/${UBOOT_SYMLINK}-${type} +} +uboot_deploy_spl_config:append:ccimx6ul() { + rm -f ${DEPLOYDIR}/${SPL_SYMLINK}-${type} } sign_uboot() { From 5c96ae3ecdb4e654161e5dd9a747ae3abe22c543 Mon Sep 17 00:00:00 2001 From: Javier Viguera Date: Thu, 3 Jul 2025 10:27:26 +0200 Subject: [PATCH 23/39] base-files: fix sysctl config installation on systemd-based systems Systemd-based systems do not use the global /etc/sysctl.conf file. Instead, they read configuration from individual files under /etc/sysctl.d. This change installs our sysctl settings as /etc/sysctl.d/console.conf when systemd is enabled. For systems that do not use systemd, the configuration file is still installed at /etc/sysctl.conf. The CONFFILES entry is also updated. Signed-off-by: Javier Viguera --- .../recipes-core/base-files/base-files/sysctl.conf | 1 - .../base-files/base-files_3.0.14.bbappend | 11 ++++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/meta-digi-dey/recipes-core/base-files/base-files/sysctl.conf b/meta-digi-dey/recipes-core/base-files/base-files/sysctl.conf index f2466a457..6f98ffd98 100644 --- a/meta-digi-dey/recipes-core/base-files/base-files/sysctl.conf +++ b/meta-digi-dey/recipes-core/base-files/base-files/sysctl.conf @@ -1,3 +1,2 @@ # Console log-level kernel.printk = 4 4 1 7 - diff --git a/meta-digi-dey/recipes-core/base-files/base-files_3.0.14.bbappend b/meta-digi-dey/recipes-core/base-files/base-files_3.0.14.bbappend index 6c165d9e9..a8c58b6c5 100644 --- a/meta-digi-dey/recipes-core/base-files/base-files_3.0.14.bbappend +++ b/meta-digi-dey/recipes-core/base-files/base-files_3.0.14.bbappend @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2024, Digi International Inc. +# Copyright (C) 2013-2025, Digi International Inc. FILESEXTRAPATHS:prepend := "${THISDIR}/${BPN}:" @@ -7,7 +7,12 @@ SRC_URI:append:dey = " \ " do_install:append:dey() { - install -m 0644 ${WORKDIR}/sysctl.conf ${D}${sysconfdir}/ + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then + install -d ${D}${sysconfdir}/sysctl.d + install -m 0644 ${WORKDIR}/sysctl.conf ${D}${sysconfdir}/sysctl.d/console.conf + else + install -m 0644 ${WORKDIR}/sysctl.conf ${D}${sysconfdir}/ + fi } pkg_postinst_ontarget:${PN}() { @@ -56,4 +61,4 @@ pkg_postinst_ontarget:${PN}() { inherit ${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", "remove-pkg-postinst-ontarget", "", d)} -CONFFILES:${PN}:dey += "${sysconfdir}/sysctl.conf" +CONFFILES:${PN}:dey += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', '', '${sysconfdir}/sysctl.conf', d)}" From 51e97057c9815122e6e98135f498074a35768132 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Thu, 3 Jul 2025 11:30:45 +0200 Subject: [PATCH 24/39] ccmp15-dvk: enable support for dey-image-flutter This commit enables building dey-image-flutter for the ConnectCore MP15 platform. It integrates the necessary configurations to support Flutter-based graphical applications on this platform. Signed-off-by: Arturo Buzarra --- meta-digi-arm/conf/templates/ccmp15-dvk/bblayers.conf.sample | 2 ++ meta-digi-arm/conf/templates/ccmp15-dvk/conf-notes.txt | 5 +++++ sdk/build.sh | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/meta-digi-arm/conf/templates/ccmp15-dvk/bblayers.conf.sample b/meta-digi-arm/conf/templates/ccmp15-dvk/bblayers.conf.sample index bdbe740ee..615bee8ea 100644 --- a/meta-digi-arm/conf/templates/ccmp15-dvk/bblayers.conf.sample +++ b/meta-digi-arm/conf/templates/ccmp15-dvk/bblayers.conf.sample @@ -20,6 +20,8 @@ BBLAYERS ?= " \ ##DIGIBASE##/meta-timesys \ ##DIGIBASE##/meta-st-stm32mp \ ##DIGIBASE##/meta-st-x-linux-ai \ + ##DIGIBASE##/meta-flutter \ + ##DIGIBASE##/meta-flutter/meta-flutter-apps \ ##DIGIBASE##/meta-digi/meta-digi-arm \ ##DIGIBASE##/meta-digi/meta-digi-dey \ " diff --git a/meta-digi-arm/conf/templates/ccmp15-dvk/conf-notes.txt b/meta-digi-arm/conf/templates/ccmp15-dvk/conf-notes.txt index a0a98b6e5..ed9e5d62f 100644 --- a/meta-digi-arm/conf/templates/ccmp15-dvk/conf-notes.txt +++ b/meta-digi-arm/conf/templates/ccmp15-dvk/conf-notes.txt @@ -15,6 +15,11 @@ Digi Embedded Yocto provides the following image recipes: By default the image is Wayland-based so it provides a full Weston desktop environment. + * dey-image-flutter: graphical Flutter image + + Expansion of custom Digi core-image-base including full Flutter + framework support. + * core-image-base: a console-only image Expansion of native core-image-base by including all the support for the diff --git a/sdk/build.sh b/sdk/build.sh index 6d7d59fca..73407d508 100755 --- a/sdk/build.sh +++ b/sdk/build.sh @@ -189,7 +189,7 @@ done<<-_EOF_ ccimx6ulstarter core-image-base ccimx6ulsom dey-image-mft-module-min ccimx6ulrftest dey-image-mft-module-rf - ccmp15-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl + ccmp15-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccmp13-dvk core-image-base ccmp25-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccimx91-dvk core-image-base From 15dee0005e88ec5fd69a60f7b468aabae6523c4a Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 4 Jul 2025 10:36:47 +0200 Subject: [PATCH 25/39] meta-digi: update revisions for dey-5.0-r2.1 Signed-off-by: Arturo Buzarra --- .../recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend | 4 ++-- .../recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend | 4 ++-- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb | 2 +- .../recipes-digi/trustfence/trustfence-sign-tools.inc | 4 ++-- .../kernel-module-qualcomm/kernel-module-qualcomm.bb | 4 ++-- meta-digi-arm/recipes-kernel/linux/linux-dey.inc | 2 +- meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb | 4 ++-- meta-digi-dey/recipes-digi/cccs/cccs_git.bb | 4 ++-- meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc | 4 ++-- meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend index 36f5e376b..fa7594510 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend @@ -11,10 +11,10 @@ TFA_URI_GITHUB = "${DIGI_GITHUB_GIT}/arm-trusted-firmware.git;protocol=https" TFA_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${TFA_URI_STASH}', '${TFA_URI_GITHUB}', d)}" SRCBRANCH = "v2.10/stm32mp/maint" -SRCREV = "${AUTOREV}" +SRCREV = "e22f7d89868db1d909d582be9bdd73679648a438" SRC_URI = " \ - ${TFA_GIT_URI};branch=${SRCBRANCH} \ + ${TFA_GIT_URI};nobranch=1 \ " # stm32mp15 = header-version 1 diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend index 244c79843..4e758e280 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend @@ -11,9 +11,9 @@ OPTEE_URI_GITHUB = "${DIGI_GITHUB_GIT}/optee_os.git;protocol=https" OPTEE_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${OPTEE_URI_STASH}', '${OPTEE_URI_GITHUB}', d)}" SRCBRANCH = "4.0.0/stm/maint" -SRCREV = "${AUTOREV}" +SRCREV = "5548d8a97f85c144685e510c02ad79a5fd4f8298" SRC_URI = " \ - ${OPTEE_GIT_URI};branch=${SRCBRANCH};name=os \ + ${OPTEE_GIT_URI};nobranch=1;name=os \ file://fonts.tar.gz;subdir=git;name=fonts \ " diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc index dc0cc52d2..1fe0a3d8f 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc @@ -27,7 +27,7 @@ INSTALL_FW_UBOOT_SCRIPTS = " \ " SRC_URI = " \ - ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ + ${UBOOT_GIT_URI};nobranch=1 \ file://boot.txt \ file://install_linux_fw_media.txt \ file://install_linux_fw_uuu.sh \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb index 32bd7b349..910ea1125 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb @@ -7,7 +7,7 @@ DEPENDS += "flex-native bison-native" DEPENDS += "python3-setuptools-native" SRCBRANCH = "v2023.10/maint" -SRCREV = "${AUTOREV}" +SRCREV = "24d88c49b38399c6d20325c586587b992717c006" SRC_URI += " \ ${@oe.utils.conditional('TRUSTFENCE_SIGN_FIT_STM', '1', 'file://fit_signature.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb index 902616a60..c596ec66c 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb @@ -7,6 +7,6 @@ LIC_FILES_CHKSUM = "file://Licenses/README;md5=2ca5f2c35c8cc335f0a19756634782f1" DEPENDS += "flex-native bison-native" SRCBRANCH = "v2024.04/maint" -SRCREV = "${AUTOREV}" +SRCREV = "dc2bd5d288ca472cb200c4c4e40c098ce14e84d5" COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8m|ccimx8x|ccimx9)" diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc index d27e2b2e6..f066aaf33 100644 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc @@ -5,7 +5,7 @@ LICENSE = "GPL-2.0-only" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6" SRCBRANCH = "v2024.04/maint" -SRCREV = "${AUTOREV}" +SRCREV = "dc2bd5d288ca472cb200c4c4e40c098ce14e84d5" S = "${WORKDIR}" @@ -15,7 +15,7 @@ UBOOT_URI_GITHUB = "${DIGI_GITHUB_GIT}/u-boot.git;protocol=https" UBOOT_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${UBOOT_URI_STASH}', '${UBOOT_URI_GITHUB}', d)}" SRC_URI = " \ - ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ + ${UBOOT_GIT_URI};nobranch=1 \ file://trustfence-sign-artifact-nxp.sh \ file://trustfence-sign-artifact-stm.sh \ file://trustfence-gen-pki-stm.sh \ diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index 6b2061aeb..47d37d0c8 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -9,12 +9,12 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca PV = "v4.0.11.213X" SRCBRANCH = "qca65X4/dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "81f2e6d27c127f7bce54d348310919e6b3e3972a" QCOM_GIT_URI = "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DIGI_MTK_GIT}/linux/qcacld-2.0.git;protocol=ssh', '${DIGI_GITHUB_GIT}/qcacld-2.0.git;protocol=https', d)}" SRC_URI = " \ - ${QCOM_GIT_URI};branch=${SRCBRANCH} \ + ${QCOM_GIT_URI};nobranch=1 \ " # Selects whether the interface is SDIO or PCI diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc index 3ad4a7016..029cf1bcd 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc @@ -10,7 +10,7 @@ require ${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'recipes-kernel/linux/li DEPENDS += "${@oe.utils.conditional('DEY_SOC_VENDOR', 'NXP', 'lzop-native', '', d)}" SRC_URI = " \ - ${LINUX_GIT_URI};branch=${SRCBRANCH} \ + ${LINUX_GIT_URI};nobranch=1 \ ${@oe.utils.conditional('KERNEL_DEFCONFIG', '', 'file://defconfig', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'virtualization', 'file://docker_conf.cfg', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'tsn', 'file://tsn_conf.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb index b8d792fc2..0566a75b4 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb @@ -4,8 +4,8 @@ require recipes-kernel/linux/linux-dey.inc SRCBRANCH = "v6.6/nxp/dey-5.0/maint" SRCBRANCH:stm32mpcommon = "v6.6/stm/dey-5.0/maint" -SRCREV = "${AUTOREV}" -SRCREV:stm32mpcommon = "${AUTOREV}" +SRCREV = "2559992b9749b3cc8a6dcc407c1c3cf57c0c0466" +SRCREV:stm32mpcommon = "7a25283f18f9ad39c4e27a93542b90546f872be6" # Define RT patches per machine RT_FILES:use-nxp-bsp = " \ diff --git a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb index dc62ab2a0..b5251362e 100644 --- a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb +++ b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb @@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7 DEPENDS = "libconfuse libdigiapix openssl recovery-utils swupdate zlib json-c" SRCBRANCH = "dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "7f1a3c54fbc1536872fc87390104414e41b92f49" CC_STASH = "gitsm://git@stash.digi.com/cc/cc_dey.git;protocol=ssh" CC_GITHUB = "gitsm://github.com/digi-embedded/cc_dey.git;protocol=https" @@ -19,7 +19,7 @@ CCCS_DEVICE_TYPE ?= "${MACHINE}" CCCS_CONF_PATH ?= "" SRC_URI = " \ - ${CC_GIT_URI};branch=${SRCBRANCH} \ + ${CC_GIT_URI};nobranch=1 \ file://cccsd-init \ file://cccsd.service \ file://cccsd.tab \ diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc index 852a67bee..307aedc1f 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc @@ -1,11 +1,11 @@ # Copyright (C) 2019-2025, Digi International Inc. SRCBRANCH = "dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "f1849282b0d2f25eb64abc68065414344e0eb343" DEY_EXAMPLES_STASH = "${DIGI_MTK_GIT}/dey/dey-examples.git;protocol=ssh" DEY_EXAMPLES_GITHUB = "${DIGI_GITHUB_GIT}/dey-examples.git;protocol=https" DEY_EXAMPLES_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DEY_EXAMPLES_STASH}', '${DEY_EXAMPLES_GITHUB}', d)}" -SRC_URI = "${DEY_EXAMPLES_GIT_URI};branch=${SRCBRANCH}" +SRC_URI = "${DEY_EXAMPLES_GIT_URI};nobranch=1" diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb index 3e4f5b7a8..f142b8250 100644 --- a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb @@ -7,7 +7,7 @@ LICENSE = "ISC" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d" SRCBRANCH ?= "dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "59ffac2b50fa48a06046a3267e0ec8219081ef39" LIBDIGIAPIX_URI_STASH = "${DIGI_MTK_GIT}/dey/libdigiapix.git;protocol=ssh" LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" @@ -15,7 +15,7 @@ LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" LIBDIGIAPIX_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${LIBDIGIAPIX_URI_STASH}', '${LIBDIGIAPIX_URI_GITHUB}', d)}" SRC_URI = " \ - ${LIBDIGIAPIX_GIT_URI};branch=${SRCBRANCH} \ + ${LIBDIGIAPIX_GIT_URI};nobranch=1 \ file://99-digiapix.rules \ file://libdigiapix.conf \ file://digiapix.sh \ From 6858f8aa253bb60ec07b0160617b966b636119ee Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Fri, 4 Jul 2025 11:15:42 +0200 Subject: [PATCH 26/39] meta-digi: revert revisions to AUTOREV Signed-off-by: Arturo Buzarra --- .../recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend | 4 ++-- .../recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend | 4 ++-- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb | 2 +- .../recipes-digi/trustfence/trustfence-sign-tools.inc | 4 ++-- .../kernel-module-qualcomm/kernel-module-qualcomm.bb | 4 ++-- meta-digi-arm/recipes-kernel/linux/linux-dey.inc | 2 +- meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb | 4 ++-- meta-digi-dey/recipes-digi/cccs/cccs_git.bb | 4 ++-- meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc | 4 ++-- meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend index fa7594510..36f5e376b 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend @@ -11,10 +11,10 @@ TFA_URI_GITHUB = "${DIGI_GITHUB_GIT}/arm-trusted-firmware.git;protocol=https" TFA_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${TFA_URI_STASH}', '${TFA_URI_GITHUB}', d)}" SRCBRANCH = "v2.10/stm32mp/maint" -SRCREV = "e22f7d89868db1d909d582be9bdd73679648a438" +SRCREV = "${AUTOREV}" SRC_URI = " \ - ${TFA_GIT_URI};nobranch=1 \ + ${TFA_GIT_URI};branch=${SRCBRANCH} \ " # stm32mp15 = header-version 1 diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend index 4e758e280..244c79843 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend @@ -11,9 +11,9 @@ OPTEE_URI_GITHUB = "${DIGI_GITHUB_GIT}/optee_os.git;protocol=https" OPTEE_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${OPTEE_URI_STASH}', '${OPTEE_URI_GITHUB}', d)}" SRCBRANCH = "4.0.0/stm/maint" -SRCREV = "5548d8a97f85c144685e510c02ad79a5fd4f8298" +SRCREV = "${AUTOREV}" SRC_URI = " \ - ${OPTEE_GIT_URI};nobranch=1;name=os \ + ${OPTEE_GIT_URI};branch=${SRCBRANCH};name=os \ file://fonts.tar.gz;subdir=git;name=fonts \ " diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc index 1fe0a3d8f..dc0cc52d2 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc @@ -27,7 +27,7 @@ INSTALL_FW_UBOOT_SCRIPTS = " \ " SRC_URI = " \ - ${UBOOT_GIT_URI};nobranch=1 \ + ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ file://boot.txt \ file://install_linux_fw_media.txt \ file://install_linux_fw_uuu.sh \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb index 910ea1125..32bd7b349 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb @@ -7,7 +7,7 @@ DEPENDS += "flex-native bison-native" DEPENDS += "python3-setuptools-native" SRCBRANCH = "v2023.10/maint" -SRCREV = "24d88c49b38399c6d20325c586587b992717c006" +SRCREV = "${AUTOREV}" SRC_URI += " \ ${@oe.utils.conditional('TRUSTFENCE_SIGN_FIT_STM', '1', 'file://fit_signature.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb index c596ec66c..902616a60 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb @@ -7,6 +7,6 @@ LIC_FILES_CHKSUM = "file://Licenses/README;md5=2ca5f2c35c8cc335f0a19756634782f1" DEPENDS += "flex-native bison-native" SRCBRANCH = "v2024.04/maint" -SRCREV = "dc2bd5d288ca472cb200c4c4e40c098ce14e84d5" +SRCREV = "${AUTOREV}" COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8m|ccimx8x|ccimx9)" diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc index f066aaf33..d27e2b2e6 100644 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc @@ -5,7 +5,7 @@ LICENSE = "GPL-2.0-only" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6" SRCBRANCH = "v2024.04/maint" -SRCREV = "dc2bd5d288ca472cb200c4c4e40c098ce14e84d5" +SRCREV = "${AUTOREV}" S = "${WORKDIR}" @@ -15,7 +15,7 @@ UBOOT_URI_GITHUB = "${DIGI_GITHUB_GIT}/u-boot.git;protocol=https" UBOOT_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${UBOOT_URI_STASH}', '${UBOOT_URI_GITHUB}', d)}" SRC_URI = " \ - ${UBOOT_GIT_URI};nobranch=1 \ + ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ file://trustfence-sign-artifact-nxp.sh \ file://trustfence-sign-artifact-stm.sh \ file://trustfence-gen-pki-stm.sh \ diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index 47d37d0c8..6b2061aeb 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -9,12 +9,12 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca PV = "v4.0.11.213X" SRCBRANCH = "qca65X4/dey-5.0/maint" -SRCREV = "81f2e6d27c127f7bce54d348310919e6b3e3972a" +SRCREV = "${AUTOREV}" QCOM_GIT_URI = "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DIGI_MTK_GIT}/linux/qcacld-2.0.git;protocol=ssh', '${DIGI_GITHUB_GIT}/qcacld-2.0.git;protocol=https', d)}" SRC_URI = " \ - ${QCOM_GIT_URI};nobranch=1 \ + ${QCOM_GIT_URI};branch=${SRCBRANCH} \ " # Selects whether the interface is SDIO or PCI diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc index 029cf1bcd..3ad4a7016 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc @@ -10,7 +10,7 @@ require ${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'recipes-kernel/linux/li DEPENDS += "${@oe.utils.conditional('DEY_SOC_VENDOR', 'NXP', 'lzop-native', '', d)}" SRC_URI = " \ - ${LINUX_GIT_URI};nobranch=1 \ + ${LINUX_GIT_URI};branch=${SRCBRANCH} \ ${@oe.utils.conditional('KERNEL_DEFCONFIG', '', 'file://defconfig', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'virtualization', 'file://docker_conf.cfg', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'tsn', 'file://tsn_conf.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb index 0566a75b4..b8d792fc2 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb @@ -4,8 +4,8 @@ require recipes-kernel/linux/linux-dey.inc SRCBRANCH = "v6.6/nxp/dey-5.0/maint" SRCBRANCH:stm32mpcommon = "v6.6/stm/dey-5.0/maint" -SRCREV = "2559992b9749b3cc8a6dcc407c1c3cf57c0c0466" -SRCREV:stm32mpcommon = "7a25283f18f9ad39c4e27a93542b90546f872be6" +SRCREV = "${AUTOREV}" +SRCREV:stm32mpcommon = "${AUTOREV}" # Define RT patches per machine RT_FILES:use-nxp-bsp = " \ diff --git a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb index b5251362e..dc62ab2a0 100644 --- a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb +++ b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb @@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7 DEPENDS = "libconfuse libdigiapix openssl recovery-utils swupdate zlib json-c" SRCBRANCH = "dey-5.0/maint" -SRCREV = "7f1a3c54fbc1536872fc87390104414e41b92f49" +SRCREV = "${AUTOREV}" CC_STASH = "gitsm://git@stash.digi.com/cc/cc_dey.git;protocol=ssh" CC_GITHUB = "gitsm://github.com/digi-embedded/cc_dey.git;protocol=https" @@ -19,7 +19,7 @@ CCCS_DEVICE_TYPE ?= "${MACHINE}" CCCS_CONF_PATH ?= "" SRC_URI = " \ - ${CC_GIT_URI};nobranch=1 \ + ${CC_GIT_URI};branch=${SRCBRANCH} \ file://cccsd-init \ file://cccsd.service \ file://cccsd.tab \ diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc index 307aedc1f..852a67bee 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc @@ -1,11 +1,11 @@ # Copyright (C) 2019-2025, Digi International Inc. SRCBRANCH = "dey-5.0/maint" -SRCREV = "f1849282b0d2f25eb64abc68065414344e0eb343" +SRCREV = "${AUTOREV}" DEY_EXAMPLES_STASH = "${DIGI_MTK_GIT}/dey/dey-examples.git;protocol=ssh" DEY_EXAMPLES_GITHUB = "${DIGI_GITHUB_GIT}/dey-examples.git;protocol=https" DEY_EXAMPLES_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DEY_EXAMPLES_STASH}', '${DEY_EXAMPLES_GITHUB}', d)}" -SRC_URI = "${DEY_EXAMPLES_GIT_URI};nobranch=1" +SRC_URI = "${DEY_EXAMPLES_GIT_URI};branch=${SRCBRANCH}" diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb index f142b8250..3e4f5b7a8 100644 --- a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb @@ -7,7 +7,7 @@ LICENSE = "ISC" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d" SRCBRANCH ?= "dey-5.0/maint" -SRCREV = "59ffac2b50fa48a06046a3267e0ec8219081ef39" +SRCREV = "${AUTOREV}" LIBDIGIAPIX_URI_STASH = "${DIGI_MTK_GIT}/dey/libdigiapix.git;protocol=ssh" LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" @@ -15,7 +15,7 @@ LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" LIBDIGIAPIX_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${LIBDIGIAPIX_URI_STASH}', '${LIBDIGIAPIX_URI_GITHUB}', d)}" SRC_URI = " \ - ${LIBDIGIAPIX_GIT_URI};nobranch=1 \ + ${LIBDIGIAPIX_GIT_URI};branch=${SRCBRANCH} \ file://99-digiapix.rules \ file://libdigiapix.conf \ file://digiapix.sh \ From 1e726ebcf515a903dc595ac1b4dc61a32b055f7e Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Fri, 4 Jul 2025 17:54:08 +0200 Subject: [PATCH 27/39] installer media: use INSTALL_MEDIA variable value, not name At the point of saving the bootcmd for the second stage of the install process we want to use the variable value, not the variable name since this variable doesn't exist after the environment is reset. Signed-off-by: Hector Palacios https://onedigi.atlassian.net/browse/DEL-9711 --- .../u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccmp1/install_linux_fw_media.txt | 4 ++-- .../u-boot/u-boot-dey/ccmp2/install_linux_fw_media.txt | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt index 597183fcc..36b04b269 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6qpsbc/install_linux_fw_media.txt @@ -173,7 +173,7 @@ setenv bootcmd " echo \"Aborted.\"; exit; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -203,7 +203,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt index 42c771a51..58c1830fb 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6sbc/install_linux_fw_media.txt @@ -180,7 +180,7 @@ setenv bootcmd " echo \"Aborted.\"; exit; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -210,7 +210,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt index 7f6ea886b..807a52bc5 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt @@ -174,7 +174,7 @@ setenv bootcmd " else force_erase=\"-e\"; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -204,7 +204,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt index cdde62c74..ba4810e6b 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt @@ -149,7 +149,7 @@ setenv bootcmd " echo \"Aborted.\"; exit; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -179,7 +179,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt index 5fb16dbda..c0b48ea3b 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt @@ -160,7 +160,7 @@ setenv bootcmd " echo \"Aborted.\"; exit; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -190,7 +190,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt index 8667432f6..571592da4 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt @@ -183,7 +183,7 @@ setenv bootcmd " echo \"Aborted.\"; exit; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -213,7 +213,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_media.txt index b22e9dbf4..85b68f4f7 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp1/install_linux_fw_media.txt @@ -191,7 +191,7 @@ setenv bootcmd " setenv rootfstype ${rootfstype}; setenv install_dualboot ${install_dualboot}; run ubivolscript; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -221,7 +221,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_media.txt index b05dda55f..281586866 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccmp2/install_linux_fw_media.txt @@ -198,7 +198,7 @@ setenv bootcmd " echo \"Aborted.\"; exit; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb start; fi; if test \"\$\{dualboot\}\" = yes; then @@ -228,7 +228,7 @@ setenv bootcmd " exit; fi; fi; - if test \"\$\{INSTALL_MEDIA\}\" = "usb"; then + if test "${INSTALL_MEDIA}" = "usb"; then usb reset; fi; echo \"\"; From 9bf8359a3d48f19264925447165511edcfe7f99d Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Mon, 7 Jul 2025 18:18:01 +0200 Subject: [PATCH 28/39] installer-media: restore INSTALL_UBOOT_FILENAME variable Commit ac69566ecdbda1d5183dd5618fb9fb0356a479b6 mistakenly removed the command of cc9, cc8x, and cc8m media installers that sets the variable that contains the U-Boot file to install. Signed-off-by: Hector Palacios https://onedigi.atlassian.net/browse/DEL-9720 --- .../u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt | 1 + .../u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt | 1 + .../u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt | 1 + 3 files changed, 3 insertions(+) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt index ba4810e6b..9887d1a8c 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8m/install_linux_fw_media.txt @@ -7,6 +7,7 @@ install_abort=0 BASEFILENAME=0 +setenv INSTALL_UBOOT_FILENAME imx-boot-##MACHINE##.bin setenv INSTALL_MEDIA_INDEX ##INSTALL_MEDIA_INDEX## setenv INSTALL_MEDIA ##INSTALL_MEDIA## diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt index c0b48ea3b..161b91a7a 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx8x/install_linux_fw_media.txt @@ -18,6 +18,7 @@ fi # the necessary logic to choose the correct imx-boot file for the target's SOC. setenv skip-uboot-check "yes" +setenv INSTALL_UBOOT_FILENAME imx-boot-##MACHINE##-${soc_rev}.bin setenv INSTALL_MEDIA_INDEX ##INSTALL_MEDIA_INDEX## setenv INSTALL_MEDIA ##INSTALL_MEDIA## diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt index 571592da4..be42a5eef 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx9/install_linux_fw_media.txt @@ -23,6 +23,7 @@ if test "${soc_type}" = "imx93"; then fi fi +setenv INSTALL_UBOOT_FILENAME imx-boot-##MACHINE##${SOCREV}.bin setenv INSTALL_MEDIA_INDEX ##INSTALL_MEDIA_INDEX## setenv INSTALL_MEDIA ##INSTALL_MEDIA## From bf15b1ae9167be813a51e5d80c17a0c0d1a2fab5 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Tue, 8 Jul 2025 15:34:11 +0200 Subject: [PATCH 29/39] x-linux-ai: recipes-samples: move Digi webcam patch to config-npu bbappend Since the release of X-LINUX-AI v6.0.1, AI support has been split between devices with NPU and those relying solely on CPU. As a result, the Digi custom patch to enable USB webcam support was no longer applied, because the config_board_npu.sh script is now handled by the new config-npu.bb recipe. This commit addresses the issue by introducing a new bbappend for config-npu, ensuring that the webcam-related patch is correctly applied for NPU-enabled platforms. https://onedigi.atlassian.net/browse/DEL-9721 Signed-off-by: Arturo Buzarra --- .../resources/application-resources.bbappend | 1 - .../recipes-samples/resources/config-npu.bbappend | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/config-npu.bbappend diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend index bdc044640..0b3f5d21e 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/application-resources.bbappend @@ -3,7 +3,6 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI += " \ - file://patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch \ file://patches/0002-setup_camera_main_isp-fix-support-for-web-camera.patch \ file://patches/0003-setup_camera_main_isp-fix-support-for-CSI-DCMIPP-cam.patch \ " diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/config-npu.bbappend b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/config-npu.bbappend new file mode 100644 index 000000000..4413c3167 --- /dev/null +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/config-npu.bbappend @@ -0,0 +1,7 @@ +# Copyright (C) 2025, Digi International Inc. + +FILESEXTRAPATHS:prepend := "${THISDIR}/files:" + +SRC_URI += " \ + file://patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch \ +" From 756957e2803665edab74a54e8031d4d75c64e038 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Tue, 8 Jul 2025 15:43:00 +0200 Subject: [PATCH 30/39] x-linux-ai: recipes-samples: fix broken webcam support after latest release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latest X-LINUX-AI v6.0.1 release consolidated the config_board_npu.sh script across all STM32MP2x platforms with NPU support. As part of this consolidation, the supported video resolutions were unified under a single default setting, which does not work correctly with USB webcams. This commit updates Digi’s custom patch to adjust the internal resolution used for processing video streams from webcams, ensuring proper support and functionality. https://onedigi.atlassian.net/browse/DEL-9721 Signed-off-by: Arturo Buzarra --- ...board-fix-support-for-web-camera-with-STM32MP.patch | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch index 8dea1d258..48984e0c9 100644 --- a/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch +++ b/meta-digi-dey/dynamic-layers/x-linux-ai/recipes-samples/resources/files/patches/0001-config_board-fix-support-for-web-camera-with-STM32MP.patch @@ -8,11 +8,11 @@ exclusive to cameras using the DCMIPP peripheral. Signed-off-by: Arturo Buzarra --- - .../files/resources-files/config_board_npu.sh | 29 ++++++++++++++++++- - 1 file changed, 28 insertions(+), 1 deletion(-) + .../files/resources-files/config_board_npu.sh | 31 ++++++++++++++++++- + 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/resources-files/config_board_npu.sh b/resources-files/config_board_npu.sh -index c89b5ca..38dda50 100644 +index c89b5ca..af95558 100644 --- a/resources-files/config_board_npu.sh +++ b/resources-files/config_board_npu.sh @@ -16,10 +16,28 @@ STM32MP251="stm32mp251" @@ -44,7 +44,7 @@ index c89b5ca..38dda50 100644 echo "Software X-LINUX-AI installed is not compatible with the board, please install X-LINUX-AI CPU version for plateform without hardware accelerator" exit 1 fi -@@ -54,11 +72,20 @@ if [[ "$COMPATIBLE" == *"$STM32MP257"* ]] || [[ "$COMPATIBLE" == *"$STM32MP255"* +@@ -54,11 +72,22 @@ if [[ "$COMPATIBLE" == *"$STM32MP257"* ]] || [[ "$COMPATIBLE" == *"$STM32MP255"* MACHINE=$STM32MP2_NPU DWIDTH=760 DHEIGHT=568 @@ -59,6 +59,8 @@ index c89b5ca..38dda50 100644 + else + # Web camera + OPTIONS="" ++ DWIDTH=640 ++ DHEIGHT=480 + fi + IMAGE_CLASSIFICATION_MODEL="mobilenet/mobilenet_v2_1.0_224_int8_per_tensor$NN_EXT" From bd31fd3ef464cb732f2f6866a1f7100eec5caf74 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 8 Jul 2025 10:06:52 +0200 Subject: [PATCH 31/39] firmware-murata-nxp: cc9: add rgpower files Do not install 'txpower' and 'rutxpower' files from the Murata repo, which are used for the V1 TX power method, and replace them with custom 'rgpower' files, required for the V2 TX power method. These files encode the TxPower limitations obtained during the ConnectCore 93 Certification tests, and there is one file per supported country. There is a common file for all the European countries, so create links for each of them, based on the CEPT REC7003E recommendation. New 'rgpower' files: - rgpower_CA.bin (MD5SUM: 7c012351f0521a02e3d78615fed5eb54) - rgpower_EU.bin (MD5SUM: 4d1a54b3c1f12a7d0bb44d0337786a0b) - rgpower_JP.bin (MD5SUM: b7706bb2718997d933b2bdf1e53e64b4) - rgpower_US.bin (MD5SUM: 16555f962b025e0426098decd0147f1f) - rgpower_WW.bin (MD5SUM: 505223c56527e849d4b1e5800c8613b5) Take the opportunity to just install bt_power_config scripts and prevent the installation of other unused files (db.txt, ed_mac_ctrl_V2_nw61x.conf and regulatory.db) from the Murata repository. https://onedigi.atlassian.net/browse/DEL-8974 Signed-off-by: Gonzalo Ruiz --- .../firmware-murata-nxp.bb | 25 ++++++++++-- .../firmware-murata-nxp/rgpower_CA.bin | 39 +++++++++++++++++++ .../firmware-murata-nxp/rgpower_EU.bin | 27 +++++++++++++ .../firmware-murata-nxp/rgpower_JP.bin | 26 +++++++++++++ .../firmware-murata-nxp/rgpower_US.bin | 37 ++++++++++++++++++ .../firmware-murata-nxp/rgpower_WW.bin | 33 ++++++++++++++++ 6 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_CA.bin create mode 100644 meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_EU.bin create mode 100644 meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_JP.bin create mode 100644 meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_US.bin create mode 100644 meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_WW.bin diff --git a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp.bb b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp.bb index 253394e52..3d3d7d56e 100644 --- a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp.bb +++ b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp.bb @@ -1,4 +1,4 @@ -# Copyright (C) 2023,2024, Digi International Inc. +# Copyright (C) 2023-2025, Digi International Inc. SUMMARY = "Murata NXP firmware binaries" LICENSE = "GPL-2.0-only" @@ -6,7 +6,14 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=ffa10f40b98be2c2bc9608f56827ed23" SRCBRANCH = "imx-6-1-1" SRCREV = "6103e224be638f5b421c323993f29bb6c0ada44a" -SRC_URI = "git://github.com/murata-wireless/nxp-linux-calibration;protocol=http;branch=${SRCBRANCH}" +SRC_URI = "\ + git://github.com/murata-wireless/nxp-linux-calibration;protocol=http;branch=${SRCBRANCH} \ + file://rgpower_CA.bin \ + file://rgpower_EU.bin \ + file://rgpower_JP.bin \ + file://rgpower_US.bin \ + file://rgpower_WW.bin \ +" S = "${WORKDIR}/git" @@ -15,13 +22,25 @@ do_compile[noexec] = "1" do_install () { install -d ${D}${nonarch_base_libdir}/firmware/nxp - install -m 0644 murata/files/2DL/* ${D}${nonarch_base_libdir}/firmware/nxp + install -m 0644 murata/files/2DL/bt_power_config* ${D}${nonarch_base_libdir}/firmware/nxp # For the EU BT power file, set the baudrate to 3Mbps (as used by the btnxpuart driver) sed -i -e "s,00 C2 01 00 00 00 00 00 00 00 00 00,C0 C6 2D 00 00 00 00 00 00 00 00 00,g" \ ${D}${nonarch_base_libdir}/firmware/nxp/bt_power_config_EU.sh # For all the BT power scripts, replace the hcitool reset command to avoid misleading BT behaviour. sed -i -e "s,hcitool -i hci0 cmd 0x03 0x003,hciconfig hci0 reset,g" \ ${D}${nonarch_base_libdir}/firmware/nxp/bt_power_config*.sh + + # Install TX power level management V2 rgpower files + install -m 444 ${WORKDIR}/rgpower_*.bin ${D}${nonarch_base_libdir}/firmware/nxp/ + + # Generate links for countries that share the Europe file + EU_COUNTRIES="AD AL AT BA BE BG CH CY CZ DE DK EE ES FI FR GB \ + GE GR HR HU IE IS IT LI LT LU LV MC MD ME MK MT \ + NL NO PL PT RO RS SE SI SK SM TR VA" + + for country in $EU_COUNTRIES; do + ln -sf rgpower_EU.bin ${D}${nonarch_base_libdir}/firmware/nxp/rgpower_${country}.bin + done } FILES:${PN} = "${nonarch_base_libdir}/firmware" diff --git a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_CA.bin b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_CA.bin new file mode 100644 index 000000000..f73d7326c --- /dev/null +++ b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_CA.bin @@ -0,0 +1,39 @@ + +region_pwr_cfg = { +49 02 64 01 00 00 00 00 01 00 ee 01 06 00 43 41 +20 20 00 01 06 02 4c 01 a1 a1 04 01 0b a0 00 00 +00 00 43 41 20 20 a3 13 00 02 08 05 ab 40 61 00 +08 44 02 12 03 84 40 40 00 18 30 02 0d 00 83 80 +20 f0 10 40 06 0e 01 43 a1 90 e8 84 4a 29 16 8c +46 a1 b0 f8 8c 4e 2b 17 8c 80 61 80 b0 0c 3a 3c +05 89 44 25 92 b9 6c 94 1f 30 92 4c c0 72 c9 74 +4e 71 32 95 00 c1 40 b8 65 0e 8b 44 9d cd 65 f3 +10 0c ea 8c 3b 9e 43 e0 14 1a 88 36 a7 47 00 04 +40 00 40 18 20 1e 01 57 80 ec 55 b8 72 b0 06 8c +07 00 e5 42 a0 70 10 20 02 b6 c5 a1 96 f8 84 82 +16 11 82 5c 6e 16 e0 1d cc 05 75 94 56 6f 36 eb +dd ca 07 7f 00 dd b0 54 db d8 2c 09 69 86 46 01 +51 19 dd de 24 0b c6 e3 ef b2 8c 9d a7 31 59 cb +e6 72 19 cc a6 7c 23 12 05 63 40 5a 98 c5 6c 1b +70 ca 80 02 5a 8d 56 b2 16 04 d7 e7 a1 7b 30 0e +b0 09 98 db 6b b6 19 fd e6 62 db 8e d1 e4 b4 b9 +6d ec 67 7f ab 8c ed c1 80 5e 24 38 15 bf 02 01 +c0 95 bb 48 27 b7 bc eb e3 bb 5d c0 1f 7b 65 a8 +ec 78 f3 5e 6f 07 a7 b6 04 06 79 7b f0 ec c0 33 +b1 f1 8d ea e5 bb 10 8f 58 1b 45 08 00 04 41 40 +d0 00 10 14 07 00 04 81 40 90 38 12 0a 0a 01 82 +61 d0 a0 08 +} +ed_mac_ctrl_v3 = { +30 01 1b 00 00 00 00 00 01 00 0a 00 01 00 0a 00 +ff 00 00 00 64 02 03 00 a1 a1 a0 +} +subband_ru_power_cfg = { +6d 02 6c 00 00 00 00 00 01 00 18 01 09 0a 0a 0a +06 00 00 0a 0a 0a 0a 08 00 00 0a 0a 0a 0a 07 00 +00 08 0a 0a 0a 07 07 00 08 0a 0a 0a 0a 00 00 0a +0a 0a 0a 0a 0a 00 07 07 07 07 03 05 00 07 0a 0a +0a 0a 00 00 0a 0a 0a 0a 0a 0a 00 09 09 09 09 09 +09 00 0a 0a 0a 0a 0a 00 00 00 00 00 00 00 00 00 +05 05 05 05 05 64 02 03 00 a1 a1 a0 +} \ No newline at end of file diff --git a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_EU.bin b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_EU.bin new file mode 100644 index 000000000..32da16468 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_EU.bin @@ -0,0 +1,27 @@ + +region_pwr_cfg = { +49 02 a3 00 00 00 00 00 01 00 ee 01 06 00 45 55 +20 30 00 02 06 02 8b 00 a1 a1 04 01 0b a0 00 00 +00 00 45 55 20 30 93 07 00 02 08 06 ab 40 20 c0 +68 00 02 0d 82 c1 e1 30 88 34 32 15 0d 85 c4 62 +11 38 78 e6 1d 17 82 83 c0 00 40 18 30 16 02 07 +80 63 60 80 12 b0 04 8c 07 2b e4 42 a0 70 4c 06 +06 00 04 65 b2 f9 8c ce 60 11 06 cb a6 f3 99 a4 +e2 75 31 06 84 a0 d3 da 0d 0e 77 42 00 d1 27 e1 +10 65 22 88 10 00 00 c0 60 40 00 4c 1b 50 a9 55 +2a d5 8a 9d 54 19 5c ad 03 29 60 ab 1d 3a 6e 0a +b0 55 40 +} +ed_mac_ctrl_v3 = { +30 01 1b 00 00 00 00 00 01 00 0a 00 01 00 0a 00 +ff 00 00 00 64 02 03 00 a1 a1 a0 +} +subband_ru_power_cfg = { +6d 02 6c 00 00 00 00 00 01 00 18 01 06 08 0b 0d +0d 00 00 06 08 0b 0d 0d 00 00 06 08 0b 0d 0d 00 +00 06 08 0a 0a 0a 0a 00 06 08 0a 0a 0a 00 00 06 +08 0a 0a 0a 0a 00 06 08 0a 0a 0a 0a 00 06 08 0a +0a 0a 0a 00 00 00 00 00 00 00 00 03 03 03 03 03 +03 00 03 03 03 03 03 00 00 00 00 00 00 00 00 00 +03 03 03 03 03 64 02 03 00 a1 a1 a0 +} \ No newline at end of file diff --git a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_JP.bin b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_JP.bin new file mode 100644 index 000000000..9dde3a253 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_JP.bin @@ -0,0 +1,26 @@ + +region_pwr_cfg = { +49 02 99 00 00 00 00 00 01 00 ee 01 06 00 4a 50 +20 40 00 03 06 02 81 00 a1 a1 04 01 0b a0 00 00 +00 00 4a 50 20 40 f3 06 00 02 08 06 ab 40 20 f0 +68 00 02 0e 00 83 41 90 68 44 2a 19 09 85 c0 c0 +e0 e0 34 18 1f 13 8a c4 a2 91 68 2c 0e 3b 04 8b +46 20 c0 d8 28 e6 49 23 8e c9 c1 e0 00 20 0c 1e +ac 04 23 01 c0 30 08 00 54 0e 09 80 02 c0 e0 a4 +ea 79 3e 84 ce 42 c0 d9 ed 0e 8b 44 9d 52 28 d4 +9a 38 04 19 42 06 50 69 95 3a 1d 3a a1 45 a8 82 +a8 40 aa 2d 72 74 0a 00 80 +} +ed_mac_ctrl_v3 = { +30 01 1b 00 00 00 00 00 01 00 0a 00 01 00 0a 00 +ff 00 00 00 64 02 03 00 a1 a1 a0 +} +subband_ru_power_cfg = { +6d 02 6c 00 00 00 00 00 01 00 18 01 06 07 0a 0c +0d 00 00 06 07 0a 0c 0d 00 00 06 07 0a 0c 0d 00 +00 fe 01 04 07 0a 0a 00 01 04 07 0a 0a 00 00 fe +01 04 07 0a 0a 00 fe 01 04 07 0a 0a 00 fe 01 04 +07 0a 0a 00 fe 01 04 07 0a 0a 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +fe fe fe fe fe 64 02 03 00 a1 a1 a0 +} \ No newline at end of file diff --git a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_US.bin b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_US.bin new file mode 100644 index 000000000..bd7dcbe63 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_US.bin @@ -0,0 +1,37 @@ + +region_pwr_cfg = { +49 02 40 01 00 00 00 00 01 00 ee 01 06 00 55 53 +20 10 00 01 06 02 28 01 a1 a1 04 01 0b a0 00 00 +00 00 55 53 20 10 63 11 00 02 08 05 ab 40 61 00 +08 44 02 12 03 84 40 40 00 18 30 02 0d 00 83 80 +20 f0 10 40 06 0e 01 43 a1 90 e8 84 4a 29 16 8c +46 a1 b0 f8 8c 4e 2b 17 8c 80 61 80 b0 0c 3a 3c +05 89 44 25 92 b9 6c 94 1f 30 92 4c c0 72 c9 74 +4e 71 32 95 00 c1 40 b8 65 0e 8b 44 9d cd 65 f3 +10 0c ea 8c 3b 9e 43 e0 14 1a 88 36 a7 47 00 04 +40 00 40 18 3e b7 0e 56 00 d1 80 e0 1c a8 55 18 +08 01 01 c0 40 80 22 21 20 85 84 60 96 8b 55 b2 +dc 01 b8 56 6e 71 5b ad b6 df 28 bd 53 40 56 b0 +5d a8 10 0a 88 ce ee 31 20 5e 0c 09 85 07 61 f1 +38 da ce 33 1d 90 c9 59 32 81 18 90 2b 2e 02 cf +03 80 c0 dc 1e 28 00 12 ce e7 f4 3a 3d 2e 53 50 +01 d0 e3 f4 18 3d 66 6a 17 af c6 e1 30 d8 8d b6 +57 61 19 d9 67 81 80 bd 74 38 15 8f 02 01 ed 40 +70 48 13 4f 9d e4 72 81 dc ce 76 bf 8f 85 e9 75 +39 fb 0e 88 10 19 da 09 43 b1 a0 ce 40 33 24 0c +d3 04 78 c1 8a c8 2b d8 12 05 02 79 40 af 06 20 + +} +ed_mac_ctrl_v3 = { +30 01 1b 00 00 00 00 00 01 00 0a 00 01 00 0a 00 +ff 00 00 00 64 02 03 00 a1 a1 a0 +} +subband_ru_power_cfg = { +6d 02 6c 00 00 00 00 00 01 00 18 01 09 0a 0a 0a +06 00 00 0a 0a 0a 0a 08 00 00 0a 0a 0a 0a 07 00 +00 0a 0a 0a 0a 07 07 00 0a 0a 0a 0a 0a 00 00 0a +0a 0a 0a 0a 0a 00 07 07 07 07 03 05 00 07 0a 0a +0a 0a 0a 00 0a 0a 0a 0a 0a 0a 00 09 09 09 09 09 +09 00 0a 0a 0a 0a 0a 00 00 00 00 00 00 00 00 00 +05 05 05 05 05 64 02 03 00 a1 a1 a0 +} \ No newline at end of file diff --git a/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_WW.bin b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_WW.bin new file mode 100644 index 000000000..7d05c0b11 --- /dev/null +++ b/meta-digi-arm/recipes-bsp/firmware-murata-nxp/firmware-murata-nxp/rgpower_WW.bin @@ -0,0 +1,33 @@ + +region_pwr_cfg = { +49 02 07 01 00 00 00 00 01 00 ee 01 06 00 57 57 +20 00 00 00 06 02 ef 00 a1 a1 04 01 0b a0 00 00 +00 00 57 57 20 00 d3 0d 00 02 08 05 83 40 4a d0 +08 30 1a 00 82 80 41 a0 90 64 28 05 08 86 c2 e2 +30 f8 4c 4a 1d 08 05 c5 60 11 70 0c 66 23 1b 81 +46 23 51 99 08 04 14 0b 00 00 e4 f2 99 58 0e 3d +0a 90 45 25 63 b9 78 36 63 22 8f c9 26 52 80 88 +04 08 03 07 cf 81 20 25 60 09 18 0e 01 80 40 02 +a0 70 48 1a 01 01 81 80 01 00 70 4e 9f 51 a9 d5 +6a f5 2a a4 74 04 0d 02 02 c0 93 60 55 42 b9 4f +05 d7 ec 36 30 45 96 b0 10 b4 5a ac 56 4b 35 4e +9e 0a b9 00 af 10 bb 7d de f3 7b 04 df 64 d7 fa +fe 06 cf 5e b0 5c ed b7 5b 86 0c 19 61 bd 00 81 +98 6a 9c 34 15 6b 03 d8 c0 e0 30 20 02 9d 26 cc +66 b3 99 eb be 84 1b 9b ce e7 f2 f6 2c c8 33 51 +9e 86 da 71 f6 20 66 2e df 96 09 db c1 41 4d d0 +27 32 0a d7 84 ac a0 +} +ed_mac_ctrl_v3 = { +30 01 1b 00 00 00 00 00 01 00 0a 00 01 00 0a 00 +ff 00 00 00 64 02 03 00 a1 a1 a0 +} +subband_ru_power_cfg = { +6d 02 6c 00 00 00 00 00 01 00 18 01 06 07 0a 0a +06 00 00 06 07 0a 0a 08 00 00 06 07 0a 0a 07 00 +00 fe 01 04 07 07 07 00 01 04 07 0a 0a 00 00 fe +01 04 07 0a 0a 00 fe 01 04 07 03 05 00 fe 01 04 +07 0a 0a 00 fe 01 04 07 0a 0a 00 03 03 03 03 03 +03 00 03 03 03 03 03 00 00 00 00 00 00 00 00 00 +fe fe fe fe fe 64 02 03 00 a1 a1 a0 +} \ No newline at end of file From 822f38e1d0dab8457b3716e2923e9a7821db3a2d Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 8 Jul 2025 10:09:22 +0200 Subject: [PATCH 32/39] kernel-module-nxp-wlan: cc9: select V2 TX power method Set V2 TX power method for regulatory management on the iw612 init and remove the 'txpwrlimit_cfg' and 'init_hostcmd_cfg' driver parameters which are only used for V1 TX power method. This allows the driver to load a specific rgpower_XX.bin binary file contained in the rootfs whenever command "iw reg set XX" is executed, updating the TX power settings and allowed frequencies list to those contained in the file. 'XX' stands for the 2-character ISO3166-1 alpha-2 country code. If the selected rgpower_XX.bin file does not exist, or no country is selected, the driver will load rgpower_WW.bin (Worldwide) by default. https://onedigi.atlassian.net/browse/DEL-8974 Signed-off-by: Gonzalo Ruiz --- .../kernel-modules/kernel-module-nxp-wlan/load_iw612.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/load_iw612.sh b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/load_iw612.sh index d3526cdff..d2467d3a5 100644 --- a/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/load_iw612.sh +++ b/meta-digi-arm/dynamic-layers/freescale-layer/recipes-kernel/kernel-modules/kernel-module-nxp-wlan/load_iw612.sh @@ -21,8 +21,7 @@ drv_mode=${DRIVER_MODE} \ drvdbg=${DRIVER_DEBUG} \ sta_name=wlan \ country_ie_ignore=1 \ -txpwrlimit_cfg=nxp/txpower_US.bin \ -init_hostcmd_cfg=nxp/rutxpower_US.bin \ +cntry_txpwr=2 \ fw_name=nxp/sd_w61x_v1.bin.se \ " From 850f75f238669ba4b6190019f498ff1ed0df8e98 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz Date: Tue, 8 Jul 2025 11:04:03 +0200 Subject: [PATCH 33/39] README: add comment about CC9 rgpower files https://onedigi.atlassian.net/browse/DEL-8974 Signed-off-by: Gonzalo Ruiz --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dee189fa6..d74e80f48 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ Documentation is available online at https://www.digi.com/resources/documentatio * Added support to ConnectCore 8M Nano * Added real-time support * Updated i.MX GStreamer stack to 1.24.7.imx + * Applied certified power limits on ConnectCore 93 and 91 * TrustFence * Added support to install signed/encrypted images from uuu install script * Added support to Flutter framework From c17af3fd4754f78f5fee1c5803a3b5c2837b3bee Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Tue, 8 Jul 2025 13:15:10 +0200 Subject: [PATCH 34/39] installers: cc6ul: format 'update' and 'data' partitions On the multi-MTD layout (default) the 'data' UBI volume is never created and thus not mounted by the system. This is because with this layout, the creation of the UBI volume is done by the 'update' command, but nobody updates this partition cause DEY doesn't generate an image for it. We want the 'data' UBI volume to be created so that the CC6UL can connect to the regular Remote Manager URI and store the certificate in it. As long as a UBI volume is created, Linux will mount it, so this commit erases the partition and creates the UBI volume. The same goes for the 'update' partition. The installer was relying on the recovery mechanism to wipe this partition, but this is not longer required with UBI. As long as the installer erases the partition and creates the volume, Linux will be able to mount it, so the boot in recovery mode has been removed from the script. Note: the formatting is only done for multi-MTD layout; the ubivolscript creates all volumes for single-MTD layout. Signed-off-by: Hector Palacios --- .../ccimx6ul/install_linux_fw_media.txt | 33 ++++++++++---- .../ccimx6ul/install_linux_fw_uuu.sh | 44 ++++++++++++++----- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt index 807a52bc5..3a0bc4120 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_media.txt @@ -112,7 +112,9 @@ else echo " linux ${INSTALL_LINUX_FILENAME}" echo " recovery ${INSTALL_RECOVERY_FILENAME}" echo " rootfs ${INSTALL_ROOTFS_FILENAME}" + echo " update --format--" fi +echo " data --format--" echo "" echo " Press CTRL+C now if you wish to abort or wait 10 seconds" echo " to continue." @@ -158,9 +160,8 @@ fi # - Set bootlimit to 3 # - If Normal Boot: # - Update the system partitions: linux, recovery, rootfs -# - Erase the 'update' partition -# - Configure recovery to wipe 'update' partition -# - Run 'recovery' and let the system boot after +# - Format the 'update' partition +# - Format the 'data' partition setenv bootcmd " env default -a; setenv singlemtdsys ${singlemtdsys}; @@ -272,19 +273,33 @@ setenv bootcmd " exit; fi; echo \"\"; - if test \"\$\{singlemtdsys\}\" != yes; then + fi; + if test \"\$\{singlemtdsys\}\" != yes; then + if test \"\$\{dualboot\}\" != yes; then + echo \"\"; + echo \"\"; + echo \">> Formatting 'update' partition\"; + echo \"\"; + echo \"\"; nand erase.part update; + if ubi part update; then + ubi createvol update; + fi; + fi; + echo \"\"; + echo \"\"; + echo \">> Formatting 'data' partition\"; + echo \"\"; + echo \"\"; + nand erase.part data; + if ubi part data; then + ubi createvol data; fi; - setenv boot_recovery yes; - setenv recovery_command wipe_update; fi; saveenv; echo \"\"; echo \"\"; echo \">> Firmware installation complete.\"; - if test \"\$\{dualboot\}\" != yes; then - echo \"Rebooting into recovery mode for final deployment.\"; - fi; echo \"\"; echo \"\"; sleep 1; diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh index affc09f88..6be65a0d2 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey/ccimx6ul/install_linux_fw_uuu.sh @@ -100,6 +100,24 @@ part_update() fi } +# Format a partition +# Params: +# 1. partition +# Description: +# - erases a partition +# - creates UBI volume with the same name as the partition +format_part() +{ + echo "\033[36m" + echo "=====================================================================================" + echo "Formatting '${1}' partition" + echo "=====================================================================================" + echo "\033[0m" + + uuu "fb[-t 20000]:" ucmd nand erase.part "${1}" + uuu "fb[-t 20000]:" ucmd if ubi part "${1}"\; then ubi createvol "${1}"\;fi +} + clear echo "############################################################" echo "# Linux firmware install through USB OTG #" @@ -278,6 +296,9 @@ fi LINUX_NAME="linux" RECOVERY_NAME="recovery" ROOTFS_NAME="rootfs" +UPDATE_NAME="update" +DATA_NAME="data" + # Print warning about storage media being deleted if [ "${NOWAIT}" != true ]; then WAIT=10 @@ -305,6 +326,12 @@ if [ "${NOWAIT}" != true ]; then printf " ${RECOVERY_NAME}\t${INSTALL_RECOVERY_FILENAME}\n" printf " ${ROOTFS_NAME}\t${INSTALL_ROOTFS_FILENAME}\n" fi + if [ "${SINGLEMTDSYS}" != true ]; then + if [ "${DUALBOOT}" != true ]; then + printf " ${UPDATE_NAME}\t--format--\n" + fi + printf " ${DATA_NAME}\t\t--format--\n" + fi printf "\n" printf " Press CTRL+C now if you wish to abort.\n" printf "\n" @@ -334,7 +361,8 @@ part_update "uboot" "${INSTALL_UBOOT_FILENAME}" 5000 "${DEK_FILE}" # - Update the 'linux' partition # - Update the 'recovery' partition # - Update the 'rootfs' partition -# - Erase the 'update' partition +# - Format the 'update' partition +# - Format the 'data' partition uuu fb: ucmd setenv bootcmd " env default -a; setenv dualboot \${dualboot}; @@ -388,15 +416,11 @@ else part_update "${ROOTFS_NAME}" "${INSTALL_ROOTFS_FILENAME}" 120000 fi -if [ "${SINGLEMTDSYS}" != true ] && [ "${DUALBOOT}" != true ]; then - # Erase the 'Update' partition - uuu "fb[-t 20000]:" ucmd nand erase.part update -fi - -if [ "${DUALBOOT}" != true ]; then - # Configure u-boot to boot into recovery mode - uuu fb: ucmd setenv boot_recovery yes - uuu fb: ucmd setenv recovery_command wipe_update +if [ "${SINGLEMTDSYS}" != true ]; then + if [ "${DUALBOOT}" != true ]; then + format_part "${UPDATE_NAME}" + fi + format_part "${DATA_NAME}" fi # Set the rootfstype if squashfs From 4f8ed2d4348d9b2c08de43fb46490f9e304a5c88 Mon Sep 17 00:00:00 2001 From: Tatiana Leon Date: Tue, 8 Jul 2025 10:24:38 +0200 Subject: [PATCH 35/39] cccs: ccimx6ul: drop exception for `data` partition and client certificates Until DEY 5.0, the ccimx6ul platform was the only one that did not include a `data` partition. As a result, `cccsd` had to store the client certificate from Remote Manager in the root filesystem, under `/etc/ssl/certs` by default. This setup caused issues after a software update, as the received client certificate would be lost, making the device unable to reconnect to the server until the certificate was manually reset from Remote Manager. The same problem occurred in dual-boot systems, since the certificate was stored in the rootfs of the current bank and was not accessible from the other bank. To avoid this situation, the ccimx6ul used the `remotemanager.digi.com` endpoint instead of `edp12.devicecloud.com`, as the former does not support or deliver client certificates. Now that DEY 5.0 includes a `data` partition in the ccimx6ul partition table, we can remove this exception and allow the use of `edp12.devicecloud.com`, storing the certificates persistently in the `data` partition. Signed-off-by: Tatiana Leon --- meta-digi-dey/recipes-digi/cccs/cccs_git.bb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb index dc62ab2a0..7e623890c 100644 --- a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb +++ b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb @@ -87,13 +87,6 @@ do_install() { fi } -do_install:append:ccimx6ul() { - if [ -z "${CCCS_CONF_PATH}" ]; then - sed -i "/url = \"edp12.devicecloud.com\"/c\url = \"remotemanager.digi.com\"" ${D}${sysconfdir}/cccs.conf - sed -i "/client_cert_path = \"\/mnt\/data\/drm_cert.pem\"/c\client_cert_path = \"\/etc\/ssl\/certs\/drm_cert.pem\"" ${D}${sysconfdir}/cccs.conf - fi -} - pkg_postinst_ontarget:${PN}-daemon() { # If dualboot is enabled, change the CCCSD download path and set on the fly to yes on the first boot if [ "$(fw_printenv -n dualboot 2>/dev/null)" = "yes" ]; then From 656a23cd4288da5b549579b3808143ff35504cb8 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Tue, 8 Jul 2025 15:33:52 +0200 Subject: [PATCH 36/39] sysinfo: properly format table header row for markdown Signed-off-by: Hector Palacios --- meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo b/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo index 970026150..54e7df828 100755 --- a/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo +++ b/meta-digi-dey/recipes-digi/sysinfo/sysinfo/sysinfo @@ -342,7 +342,7 @@ REPORT_PATH="/tmp/sysinfo-${DEY_VERSION}-${BOARD_SN}-${DATE}" echo "-------------------------------------" echo "" - echo "||*Component*||*Version*" + echo "|||:Component|:Version" DUT_HEADER="SN-${BOARD_SN}, ${MACHINE} ${BOARD_VARIANT} ${BOARD_TYPE}v${BOARD_VERSION}" if [ -n "${BOARD_ID}" ]; then DUT_HEADER="${DUT_HEADER} board_ID=${BOARD_ID}" From afe37daf9871f4ff5813e4b781eaa8453639c9a9 Mon Sep 17 00:00:00 2001 From: Francisco Gil Date: Tue, 15 Jul 2025 13:49:28 +0200 Subject: [PATCH 37/39] README: update known issues and limitations for dey-5.0-r2 Signed-off-by: Francisco Gil --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index d74e80f48..04725c29b 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,18 @@ updated list can be found on the online documentation. not supported. * For P2P connections Digi recommends "Negotiated GO" modes. The QCA6564 devices fail to join autonomous groups. +* Mouse input does not work in Flutter-based applications. When launching + Flutter applications, the system fails to register mouse input. This + prevents interaction with graphical elements and UI components, impacting + use cases that rely on pointer input. + Using a panel with a touchscreen prevents the issue from appearing. + This issue has been reported to the community, and we are waiting for a fix. +* Mouse clicks stop working in WebKit after running the Aquarium demo or + video settings icon. After executing the Aquarium WebGL demo in WebKit, + mouse click events are no longer recognized in subsequent browsing sessions. + An application restart is required to recover proper mouse functionality. + This issue has been reported to the community, and we are working together + on a fix. ## ConnectCore 93 @@ -225,6 +237,20 @@ updated list can be found on the online documentation. reducing the maximum throughput of this interface. * The QCA6564 wireless chip does not support Wake On Wireless LAN. +## ConnectCore MP25 + +* MMC0 input/output errors may appear during extended suspend/resume cycles. +* The system may fail to power off correctly, eventually falling back to a watchdog + reset. + +## ConnectCore MP13 + +* The power button becomes unresponsive after one power-off/power-on cycle. + A system reboot is required to restore normal functionality. + The issue originates from the OP-TEE/ATF firmware and will be addressed in + the next DEY release. + If you need further assistance, please contact Digi Technical Support. + # Support Contact Information For support questions please contact Digi Technical Support: From 915b235f5a4bef79281adab8cd9c1da636e01735 Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Tue, 15 Jul 2025 22:10:11 +0200 Subject: [PATCH 38/39] meta-digi-dey: bump distro version to 5.0-r2.2 Signed-off-by: Arturo Buzarra --- meta-digi-dey/conf/distro/dey.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta-digi-dey/conf/distro/dey.conf b/meta-digi-dey/conf/distro/dey.conf index 5e21cf0ef..fd7399dee 100644 --- a/meta-digi-dey/conf/distro/dey.conf +++ b/meta-digi-dey/conf/distro/dey.conf @@ -4,7 +4,7 @@ require conf/distro/poky.conf YOCTO_MAJOR = "5" YOCTO_MINOR = "0" DEY_RELEASE = "2" -DEY_BUILD = "1" +DEY_BUILD = "2" # Firmware version of the system. DEY_FIRMWARE_VERSION ?= "${YOCTO_MAJOR}.${YOCTO_MINOR}.${DEY_RELEASE}.${DEY_BUILD}" From b2eb7a5825f4871293fe86801a29a08f98c6e90a Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Tue, 15 Jul 2025 22:10:11 +0200 Subject: [PATCH 39/39] meta-digi: update revisions for dey-5.0-r2.2 Signed-off-by: Arturo Buzarra --- .../recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend | 4 ++-- .../recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend | 4 ++-- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb | 2 +- meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb | 2 +- .../recipes-digi/trustfence/trustfence-sign-tools.inc | 4 ++-- .../kernel-module-qualcomm/kernel-module-qualcomm.bb | 4 ++-- meta-digi-arm/recipes-kernel/linux/linux-dey.inc | 2 +- meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb | 4 ++-- meta-digi-dey/recipes-digi/cccs/cccs_git.bb | 4 ++-- meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc | 4 ++-- meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb | 4 ++-- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend index 36f5e376b..fa7594510 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-bsp/trusted-firmware-a/tf-a-stm32mp_2.10.bbappend @@ -11,10 +11,10 @@ TFA_URI_GITHUB = "${DIGI_GITHUB_GIT}/arm-trusted-firmware.git;protocol=https" TFA_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${TFA_URI_STASH}', '${TFA_URI_GITHUB}', d)}" SRCBRANCH = "v2.10/stm32mp/maint" -SRCREV = "${AUTOREV}" +SRCREV = "e22f7d89868db1d909d582be9bdd73679648a438" SRC_URI = " \ - ${TFA_GIT_URI};branch=${SRCBRANCH} \ + ${TFA_GIT_URI};nobranch=1 \ " # stm32mp15 = header-version 1 diff --git a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend index 244c79843..a2c9d912d 100644 --- a/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend +++ b/meta-digi-arm/dynamic-layers/stm-st-stm32mp/recipes-security/optee/optee-os-stm32mp_4.0.0.bbappend @@ -11,9 +11,9 @@ OPTEE_URI_GITHUB = "${DIGI_GITHUB_GIT}/optee_os.git;protocol=https" OPTEE_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${OPTEE_URI_STASH}', '${OPTEE_URI_GITHUB}', d)}" SRCBRANCH = "4.0.0/stm/maint" -SRCREV = "${AUTOREV}" +SRCREV = "da06ccf751938a642805f11b7aae3d7cde5f6917" SRC_URI = " \ - ${OPTEE_GIT_URI};branch=${SRCBRANCH};name=os \ + ${OPTEE_GIT_URI};nobranch=1;name=os \ file://fonts.tar.gz;subdir=git;name=fonts \ " diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc index dc0cc52d2..1fe0a3d8f 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey.inc @@ -27,7 +27,7 @@ INSTALL_FW_UBOOT_SCRIPTS = " \ " SRC_URI = " \ - ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ + ${UBOOT_GIT_URI};nobranch=1 \ file://boot.txt \ file://install_linux_fw_media.txt \ file://install_linux_fw_uuu.sh \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb index 32bd7b349..910ea1125 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2023.10.bb @@ -7,7 +7,7 @@ DEPENDS += "flex-native bison-native" DEPENDS += "python3-setuptools-native" SRCBRANCH = "v2023.10/maint" -SRCREV = "${AUTOREV}" +SRCREV = "24d88c49b38399c6d20325c586587b992717c006" SRC_URI += " \ ${@oe.utils.conditional('TRUSTFENCE_SIGN_FIT_STM', '1', 'file://fit_signature.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb index 902616a60..c596ec66c 100644 --- a/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb +++ b/meta-digi-arm/recipes-bsp/u-boot/u-boot-dey_2024.04.bb @@ -7,6 +7,6 @@ LIC_FILES_CHKSUM = "file://Licenses/README;md5=2ca5f2c35c8cc335f0a19756634782f1" DEPENDS += "flex-native bison-native" SRCBRANCH = "v2024.04/maint" -SRCREV = "${AUTOREV}" +SRCREV = "dc2bd5d288ca472cb200c4c4e40c098ce14e84d5" COMPATIBLE_MACHINE = "(ccimx6ul|ccimx8m|ccimx8x|ccimx9)" diff --git a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc index d27e2b2e6..f066aaf33 100644 --- a/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc +++ b/meta-digi-arm/recipes-digi/trustfence/trustfence-sign-tools.inc @@ -5,7 +5,7 @@ LICENSE = "GPL-2.0-only" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0-only;md5=801f80980d171dd6425610833a22dbe6" SRCBRANCH = "v2024.04/maint" -SRCREV = "${AUTOREV}" +SRCREV = "dc2bd5d288ca472cb200c4c4e40c098ce14e84d5" S = "${WORKDIR}" @@ -15,7 +15,7 @@ UBOOT_URI_GITHUB = "${DIGI_GITHUB_GIT}/u-boot.git;protocol=https" UBOOT_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${UBOOT_URI_STASH}', '${UBOOT_URI_GITHUB}', d)}" SRC_URI = " \ - ${UBOOT_GIT_URI};branch=${SRCBRANCH} \ + ${UBOOT_GIT_URI};nobranch=1 \ file://trustfence-sign-artifact-nxp.sh \ file://trustfence-sign-artifact-stm.sh \ file://trustfence-gen-pki-stm.sh \ diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index 6b2061aeb..47d37d0c8 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -9,12 +9,12 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca PV = "v4.0.11.213X" SRCBRANCH = "qca65X4/dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "81f2e6d27c127f7bce54d348310919e6b3e3972a" QCOM_GIT_URI = "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DIGI_MTK_GIT}/linux/qcacld-2.0.git;protocol=ssh', '${DIGI_GITHUB_GIT}/qcacld-2.0.git;protocol=https', d)}" SRC_URI = " \ - ${QCOM_GIT_URI};branch=${SRCBRANCH} \ + ${QCOM_GIT_URI};nobranch=1 \ " # Selects whether the interface is SDIO or PCI diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc index 3ad4a7016..029cf1bcd 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey.inc +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey.inc @@ -10,7 +10,7 @@ require ${@oe.utils.conditional('TRUSTFENCE_SIGN', '1', 'recipes-kernel/linux/li DEPENDS += "${@oe.utils.conditional('DEY_SOC_VENDOR', 'NXP', 'lzop-native', '', d)}" SRC_URI = " \ - ${LINUX_GIT_URI};branch=${SRCBRANCH} \ + ${LINUX_GIT_URI};nobranch=1 \ ${@oe.utils.conditional('KERNEL_DEFCONFIG', '', 'file://defconfig', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'virtualization', 'file://docker_conf.cfg', '', d)} \ ${@bb.utils.contains('DISTRO_FEATURES', 'tsn', 'file://tsn_conf.cfg', '', d)} \ diff --git a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb index b8d792fc2..7e33e65e7 100644 --- a/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb +++ b/meta-digi-arm/recipes-kernel/linux/linux-dey_6.6.bb @@ -4,8 +4,8 @@ require recipes-kernel/linux/linux-dey.inc SRCBRANCH = "v6.6/nxp/dey-5.0/maint" SRCBRANCH:stm32mpcommon = "v6.6/stm/dey-5.0/maint" -SRCREV = "${AUTOREV}" -SRCREV:stm32mpcommon = "${AUTOREV}" +SRCREV = "480779ca1cae17cb9de0af0f185634e5529c7c2e" +SRCREV:stm32mpcommon = "dd850e7ac5870c41055d5e4c37694f86135a3e67" # Define RT patches per machine RT_FILES:use-nxp-bsp = " \ diff --git a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb index 7e623890c..29c0f3f15 100644 --- a/meta-digi-dey/recipes-digi/cccs/cccs_git.bb +++ b/meta-digi-dey/recipes-digi/cccs/cccs_git.bb @@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MPL-2.0;md5=815ca599c9df247a0c7 DEPENDS = "libconfuse libdigiapix openssl recovery-utils swupdate zlib json-c" SRCBRANCH = "dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "7f1a3c54fbc1536872fc87390104414e41b92f49" CC_STASH = "gitsm://git@stash.digi.com/cc/cc_dey.git;protocol=ssh" CC_GITHUB = "gitsm://github.com/digi-embedded/cc_dey.git;protocol=https" @@ -19,7 +19,7 @@ CCCS_DEVICE_TYPE ?= "${MACHINE}" CCCS_CONF_PATH ?= "" SRC_URI = " \ - ${CC_GIT_URI};branch=${SRCBRANCH} \ + ${CC_GIT_URI};nobranch=1 \ file://cccsd-init \ file://cccsd.service \ file://cccsd.tab \ diff --git a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc index 852a67bee..fd0f96a03 100644 --- a/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc +++ b/meta-digi-dey/recipes-digi/dey-examples/dey-examples-src.inc @@ -1,11 +1,11 @@ # Copyright (C) 2019-2025, Digi International Inc. SRCBRANCH = "dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "4250a5e09885284764620c6defa9fc42affee0ab" DEY_EXAMPLES_STASH = "${DIGI_MTK_GIT}/dey/dey-examples.git;protocol=ssh" DEY_EXAMPLES_GITHUB = "${DIGI_GITHUB_GIT}/dey-examples.git;protocol=https" DEY_EXAMPLES_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${DEY_EXAMPLES_STASH}', '${DEY_EXAMPLES_GITHUB}', d)}" -SRC_URI = "${DEY_EXAMPLES_GIT_URI};branch=${SRCBRANCH}" +SRC_URI = "${DEY_EXAMPLES_GIT_URI};nobranch=1" diff --git a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb index 3e4f5b7a8..f142b8250 100644 --- a/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb +++ b/meta-digi-dey/recipes-digi/libdigiapix/libdigiapix_git.bb @@ -7,7 +7,7 @@ LICENSE = "ISC" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d" SRCBRANCH ?= "dey-5.0/maint" -SRCREV = "${AUTOREV}" +SRCREV = "59ffac2b50fa48a06046a3267e0ec8219081ef39" LIBDIGIAPIX_URI_STASH = "${DIGI_MTK_GIT}/dey/libdigiapix.git;protocol=ssh" LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" @@ -15,7 +15,7 @@ LIBDIGIAPIX_URI_GITHUB = "${DIGI_GITHUB_GIT}/libdigiapix.git;protocol=https" LIBDIGIAPIX_GIT_URI ?= "${@oe.utils.conditional('DIGI_INTERNAL_GIT', '1' , '${LIBDIGIAPIX_URI_STASH}', '${LIBDIGIAPIX_URI_GITHUB}', d)}" SRC_URI = " \ - ${LIBDIGIAPIX_GIT_URI};branch=${SRCBRANCH} \ + ${LIBDIGIAPIX_GIT_URI};nobranch=1 \ file://99-digiapix.rules \ file://libdigiapix.conf \ file://digiapix.sh \